Sign In

@linkedctl/cli

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@linkedctl/cli - npm Package Compare versions

Comparing version
0.0.0
to
0.1.0
assets/logo.png

Sorry, the diff of this file is not supported yet

+17
export interface CallbackResult {
code: string;
state: string;
}
/**
* Start a local HTTP server on a random available port and wait for the
* OAuth2 callback from LinkedIn.
*
* Returns an object containing the port, a promise that resolves with the
* authorization code and state, and a stop function to shut down the server.
*/
export declare function startCallbackServer(port: number): Promise<{
port: number;
result: Promise<CallbackResult>;
stop: () => Promise<void>;
}>;
//# sourceMappingURL=callback-server.d.ts.map
{"version":3,"file":"callback-server.d.ts","sourceRoot":"","sources":["../../../src/commands/auth/callback-server.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B,CAAC,CA0DD"}
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Oleksii PELYKH
import { createServer } from "node:http";
const SUCCESS_HTML = `<!DOCTYPE html>
<html><head><title>LinkedCtl</title></head>
<body style="font-family:system-ui;text-align:center;padding:4rem">
<h1>Authorization successful</h1>
<p>You may close this window and return to your terminal.</p>
</body></html>`;
const ERROR_HTML = `<!DOCTYPE html>
<html><head><title>LinkedCtl</title></head>
<body style="font-family:system-ui;text-align:center;padding:4rem">
<h1>Authorization failed</h1>
<p>Something went wrong. Please check your terminal for details.</p>
</body></html>`;
/**
* Start a local HTTP server on a random available port and wait for the
* OAuth2 callback from LinkedIn.
*
* Returns an object containing the port, a promise that resolves with the
* authorization code and state, and a stop function to shut down the server.
*/
export async function startCallbackServer(port) {
let resolveResult;
let rejectResult;
const result = new Promise((resolve, reject) => {
resolveResult = resolve;
rejectResult = reject;
});
const server = createServer((req, res) => {
const url = new URL(req.url ?? "/", `http://localhost`);
if (url.pathname !== "/callback") {
res.writeHead(404, { "Content-Type": "text/plain" });
res.end("Not Found");
return;
}
const code = url.searchParams.get("code");
const state = url.searchParams.get("state");
const error = url.searchParams.get("error");
const errorDescription = url.searchParams.get("error_description");
if (error !== null) {
res.writeHead(200, { "Content-Type": "text/html" });
res.end(ERROR_HTML);
rejectResult(new Error(`Authorization denied: ${errorDescription ?? error}`));
return;
}
if (code === null || state === null) {
res.writeHead(400, { "Content-Type": "text/html" });
res.end(ERROR_HTML);
rejectResult(new Error("Missing code or state in callback. " +
'The OAuth2 flow may have been interrupted. Run "linkedctl auth login" to try again.'));
return;
}
res.writeHead(200, { "Content-Type": "text/html" });
res.end(SUCCESS_HTML);
resolveResult({ code, state });
});
const actualPort = await listen(server, port);
const stop = async () => {
await new Promise((resolve, reject) => {
server.close((err) => {
if (err)
reject(err);
else
resolve();
});
});
};
return { port: actualPort, result, stop };
}
function listen(server, port) {
return new Promise((resolve, reject) => {
server.on("error", reject);
server.listen(port, "127.0.0.1", () => {
const addr = server.address();
if (addr === null || typeof addr === "string") {
reject(new Error("Unexpected server address type"));
return;
}
resolve(addr.port);
});
});
}
//# sourceMappingURL=callback-server.js.map
{"version":3,"file":"callback-server.js","sourceRoot":"","sources":["../../../src/commands/auth/callback-server.ts"],"names":[],"mappings":"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"}
import { Command } from "commander";
export declare function authCommand(): Command;
//# sourceMappingURL=index.d.ts.map
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/auth/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,wBAAgB,WAAW,IAAI,OAAO,CAarC"}
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Oleksii PELYKH
import { Command } from "commander";
import { setupCommand } from "./setup.js";
import { tokenCommand } from "./token.js";
import { statusCommand } from "./status.js";
import { logoutCommand } from "./logout.js";
import { revokeCommand } from "./revoke.js";
import { loginCommand } from "./login.js";
import { refreshCommand } from "./refresh.js";
export function authCommand() {
const cmd = new Command("auth");
cmd.description("Manage authentication");
cmd.addCommand(setupCommand());
cmd.addCommand(tokenCommand());
cmd.addCommand(statusCommand());
cmd.addCommand(logoutCommand());
cmd.addCommand(revokeCommand());
cmd.addCommand(loginCommand());
cmd.addCommand(refreshCommand());
return cmd;
}
//# sourceMappingURL=index.js.map
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/auth/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,MAAM,UAAU,WAAW;IACzB,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAChC,GAAG,CAAC,WAAW,CAAC,uBAAuB,CAAC,CAAC;IAEzC,GAAG,CAAC,UAAU,CAAC,YAAY,EAAE,CAAC,CAAC;IAC/B,GAAG,CAAC,UAAU,CAAC,YAAY,EAAE,CAAC,CAAC;IAC/B,GAAG,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;IAChC,GAAG,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;IAChC,GAAG,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;IAChC,GAAG,CAAC,UAAU,CAAC,YAAY,EAAE,CAAC,CAAC;IAC/B,GAAG,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC,CAAC;IAEjC,OAAO,GAAG,CAAC;AACb,CAAC"}
import { Command } from "commander";
export declare const DEFAULT_REDIRECT_PORT = 18920;
export declare function loginCommand(): Command;
//# sourceMappingURL=login.d.ts.map
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../src/commands/auth/login.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBpC,eAAO,MAAM,qBAAqB,QAAQ,CAAC;AAE3C,wBAAgB,YAAY,IAAI,OAAO,CAiItC"}
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Oleksii PELYKH
import { randomUUID } from "node:crypto";
import { execFile } from "node:child_process";
import { platform } from "node:os";
import { Command } from "commander";
import { loadConfigFile, validateConfig, saveOAuthTokens, saveOAuthClientCredentials, buildAuthorizationUrl, exchangeAuthorizationCode, refreshAccessToken, generateCodeVerifier, computeCodeChallenge, } from "@linkedctl/core";
import { startCallbackServer } from "./callback-server.js";
export const DEFAULT_REDIRECT_PORT = 18920;
export function loginCommand() {
const cmd = new Command("login");
cmd.description("Authenticate with LinkedIn via OAuth2");
cmd.option("--client-id <id>", "OAuth2 client ID (overrides config value)");
cmd.option("--client-secret <secret>", "OAuth2 client secret (overrides config value)");
cmd.option("--scope <scopes>", "OAuth2 scopes (space-separated)");
cmd.option("--port <number>", "local callback server port", String(DEFAULT_REDIRECT_PORT));
cmd.option("--pkce", "use PKCE flow (requires LinkedIn to enable it for your app)");
cmd.action(async (opts) => {
const program = cmd.parent?.parent;
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const profileFlag = program?.opts()["profile"];
const { raw } = await loadConfigFile({ profile: profileFlag });
const { config } = validateConfig(raw);
// Resolve client credentials: CLI flags > config
const clientId = opts.clientId ?? config.oauth?.clientId;
const clientSecret = opts.clientSecret ?? config.oauth?.clientSecret;
if (clientId === undefined || clientSecret === undefined) {
throw new Error("Missing OAuth2 credentials. Provide --client-id and --client-secret, " +
'or run "linkedctl auth setup" to configure them interactively.');
}
// Resolve scope: CLI flag > config
const scope = opts.scope ?? config.oauth?.scope;
if (scope === undefined) {
throw new Error("Missing OAuth2 scope. Provide --scope, " + 'or run "linkedctl auth setup" to configure it interactively.');
}
const writeOpts = { profile: profileFlag };
// Check for existing refresh token and attempt refresh first
const existingRefreshToken = config.oauth?.refreshToken;
if (existingRefreshToken !== undefined) {
console.error("Attempting token refresh...");
const refreshConfig = {
clientId,
clientSecret,
redirectUri: "", // not used for refresh
scope,
};
try {
const tokens = await refreshAccessToken(refreshConfig, existingRefreshToken);
const expiry = new Date(Date.now() + tokens.expiresIn * 1000).toISOString();
await saveOAuthTokens({
accessToken: tokens.accessToken,
refreshToken: tokens.refreshToken,
tokenExpiresAt: expiry,
}, writeOpts);
await saveOAuthClientCredentials({ clientId, clientSecret }, writeOpts);
if (profileFlag !== undefined) {
console.error(`Token refreshed for profile "${profileFlag}".`);
}
else {
console.error("Token refreshed.");
}
return;
}
catch {
console.error("Token refresh failed, starting full authorization flow...");
}
}
// Full OAuth2 authorization code flow
const port = Number.parseInt(opts.port, 10);
const { result, stop } = await startCallbackServer(port);
const redirectUri = `http://127.0.0.1:${port}/callback`;
const state = randomUUID();
const usePkce = opts.pkce === true || config.oauth?.pkce === true;
let codeVerifier;
let codeChallenge;
if (usePkce) {
codeVerifier = generateCodeVerifier();
codeChallenge = computeCodeChallenge(codeVerifier);
}
const oauth2Config = {
clientId,
clientSecret,
redirectUri,
scope,
};
const authUrl = buildAuthorizationUrl(oauth2Config, state, codeChallenge);
console.error("Opening browser for LinkedIn authorization...");
console.error(`If the browser does not open, visit:\n${authUrl}`);
openBrowser(authUrl);
try {
const callback = await result;
if (callback.state !== state) {
throw new Error("OAuth2 state mismatch — possible CSRF attack. " +
'The authorization response may have been tampered with. Run "linkedctl auth login" to try again.');
}
const tokens = await exchangeAuthorizationCode(oauth2Config, callback.code, codeVerifier);
const expiry = new Date(Date.now() + tokens.expiresIn * 1000).toISOString();
await saveOAuthTokens({
accessToken: tokens.accessToken,
refreshToken: tokens.refreshToken,
tokenExpiresAt: expiry,
}, writeOpts);
await saveOAuthClientCredentials({ clientId, clientSecret }, writeOpts);
if (profileFlag !== undefined) {
console.error(`Authenticated and saved to profile "${profileFlag}".`);
}
else {
console.error("Authenticated successfully.");
}
}
finally {
await stop();
}
});
return cmd;
}
function openBrowser(url) {
switch (platform()) {
case "darwin":
execFile("open", [url]);
break;
case "win32":
execFile("cmd", ["/c", "start", "", url]);
break;
default:
execFile("xdg-open", [url]);
break;
}
}
//# sourceMappingURL=login.js.map
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/commands/auth/login.ts"],"names":[],"mappings":"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"}
import { Command } from "commander";
export declare function logoutCommand(): Command;
//# sourceMappingURL=logout.d.ts.map
{"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../../src/commands/auth/logout.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,wBAAgB,aAAa,IAAI,OAAO,CAwBvC"}
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Oleksii PELYKH
import { Command } from "commander";
import { loadConfigFile, validateConfig, clearOAuthTokens } from "@linkedctl/core";
export function logoutCommand() {
const cmd = new Command("logout");
cmd.description("Clear stored credentials from the active config");
cmd.action(async (_opts, actionCmd) => {
const rootOpts = actionCmd.optsWithGlobals();
const profileFlag = typeof rootOpts["profile"] === "string" ? rootOpts["profile"] : undefined;
const { raw } = await loadConfigFile({ profile: profileFlag });
const { config } = validateConfig(raw);
if (config.oauth === undefined) {
throw new Error('No OAuth credentials configured. Run "linkedctl auth setup" to configure credentials, ' +
'or "linkedctl auth login" to authenticate.');
}
await clearOAuthTokens({ profile: profileFlag });
const label = profileFlag ?? "default";
console.log(`Credentials cleared for profile "${label}".`);
});
return cmd;
}
//# sourceMappingURL=logout.js.map
{"version":3,"file":"logout.js","sourceRoot":"","sources":["../../../src/commands/auth/logout.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnF,MAAM,UAAU,aAAa;IAC3B,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClC,GAAG,CAAC,WAAW,CAAC,iDAAiD,CAAC,CAAC;IAEnE,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,KAA8B,EAAE,SAAkB,EAAE,EAAE;QACtE,MAAM,QAAQ,GAAG,SAAS,CAAC,eAAe,EAAE,CAAC;QAC7C,MAAM,WAAW,GAAG,OAAO,QAAQ,CAAC,SAAS,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAE9F,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,cAAc,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;QAC/D,MAAM,EAAE,MAAM,EAAE,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;QAEvC,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CACb,wFAAwF;gBACtF,4CAA4C,CAC/C,CAAC;QACJ,CAAC;QAED,MAAM,gBAAgB,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;QACjD,MAAM,KAAK,GAAG,WAAW,IAAI,SAAS,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,oCAAoC,KAAK,IAAI,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC"}
import { Command } from "commander";
export declare function refreshCommand(): Command;
//# sourceMappingURL=refresh.d.ts.map
{"version":3,"file":"refresh.d.ts","sourceRoot":"","sources":["../../../src/commands/auth/refresh.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,wBAAgB,cAAc,IAAI,OAAO,CA6DxC"}
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Oleksii PELYKH
import { Command } from "commander";
import { loadConfigFile, validateConfig, saveOAuthTokens, saveOAuthClientCredentials, refreshAccessToken, } from "@linkedctl/core";
export function refreshCommand() {
const cmd = new Command("refresh");
cmd.description("Refresh the access token using a stored refresh token");
cmd.action(async (_opts, actionCmd) => {
const rootOpts = actionCmd.optsWithGlobals();
const profileFlag = typeof rootOpts["profile"] === "string" ? rootOpts["profile"] : undefined;
const { raw } = await loadConfigFile({ profile: profileFlag });
const { config } = validateConfig(raw);
const clientId = config.oauth?.clientId;
const clientSecret = config.oauth?.clientSecret;
if (clientId === undefined || clientSecret === undefined) {
throw new Error("Missing OAuth2 credentials in config. " +
'Run "linkedctl auth login --client-id <id> --client-secret <secret>" first.');
}
const existingRefreshToken = config.oauth?.refreshToken;
if (existingRefreshToken === undefined) {
throw new Error("No refresh token available. " +
"Refresh tokens are only available for approved LinkedIn Marketing Developer Platform (MDP) partners. " +
'Run "linkedctl auth login" to re-authenticate.');
}
const oauth2Config = {
clientId,
clientSecret,
redirectUri: "",
scope: "",
};
const writeOpts = { profile: profileFlag };
try {
const tokens = await refreshAccessToken(oauth2Config, existingRefreshToken);
const expiry = new Date(Date.now() + tokens.expiresIn * 1000).toISOString();
await saveOAuthTokens({
accessToken: tokens.accessToken,
refreshToken: tokens.refreshToken ?? existingRefreshToken,
tokenExpiresAt: expiry,
}, writeOpts);
await saveOAuthClientCredentials({ clientId, clientSecret }, writeOpts);
const label = profileFlag ?? "default";
console.log(`Token refreshed for profile "${label}".`);
}
catch (error) {
const message = error instanceof Error ? error.message : String(error);
throw new Error(`Token refresh failed: ${message}. ` + 'Run "linkedctl auth login" to re-authenticate.');
}
});
return cmd;
}
//# sourceMappingURL=refresh.js.map
{"version":3,"file":"refresh.js","sourceRoot":"","sources":["../../../src/commands/auth/refresh.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EACL,cAAc,EACd,cAAc,EACd,eAAe,EACf,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AAGzB,MAAM,UAAU,cAAc;IAC5B,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC;IACnC,GAAG,CAAC,WAAW,CAAC,uDAAuD,CAAC,CAAC;IAEzE,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,KAA8B,EAAE,SAAkB,EAAE,EAAE;QACtE,MAAM,QAAQ,GAAG,SAAS,CAAC,eAAe,EAAE,CAAC;QAC7C,MAAM,WAAW,GAAG,OAAO,QAAQ,CAAC,SAAS,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAE9F,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,cAAc,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;QAC/D,MAAM,EAAE,MAAM,EAAE,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;QAEvC,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC;QACxC,MAAM,YAAY,GAAG,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC;QAEhD,IAAI,QAAQ,KAAK,SAAS,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YACzD,MAAM,IAAI,KAAK,CACb,wCAAwC;gBACtC,6EAA6E,CAChF,CAAC;QACJ,CAAC;QAED,MAAM,oBAAoB,GAAG,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC;QAExD,IAAI,oBAAoB,KAAK,SAAS,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CACb,8BAA8B;gBAC5B,uGAAuG;gBACvG,gDAAgD,CACnD,CAAC;QACJ,CAAC;QAED,MAAM,YAAY,GAAiB;YACjC,QAAQ;YACR,YAAY;YACZ,WAAW,EAAE,EAAE;YACf,KAAK,EAAE,EAAE;SACV,CAAC;QAEF,MAAM,SAAS,GAAG,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;QAE3C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,YAAY,EAAE,oBAAoB,CAAC,CAAC;YAC5E,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;YAC5E,MAAM,eAAe,CACnB;gBACE,WAAW,EAAE,MAAM,CAAC,WAAW;gBAC/B,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,oBAAoB;gBACzD,cAAc,EAAE,MAAM;aACvB,EACD,SAAS,CACV,CAAC;YACF,MAAM,0BAA0B,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,SAAS,CAAC,CAAC;YACxE,MAAM,KAAK,GAAG,WAAW,IAAI,SAAS,CAAC;YACvC,OAAO,CAAC,GAAG,CAAC,gCAAgC,KAAK,IAAI,CAAC,CAAC;QACzD,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,MAAM,IAAI,KAAK,CAAC,yBAAyB,OAAO,IAAI,GAAG,gDAAgD,CAAC,CAAC;QAC3G,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC"}
import { Command } from "commander";
export declare function revokeCommand(): Command;
//# sourceMappingURL=revoke.d.ts.map
{"version":3,"file":"revoke.d.ts","sourceRoot":"","sources":["../../../src/commands/auth/revoke.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,wBAAgB,aAAa,IAAI,OAAO,CAsCvC"}
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Oleksii PELYKH
import { Command } from "commander";
import { loadConfigFile, validateConfig, clearOAuthTokens, revokeAccessToken } from "@linkedctl/core";
export function revokeCommand() {
const cmd = new Command("revoke");
cmd.description("Revoke the access token server-side and clear local credentials");
cmd.action(async (_opts, actionCmd) => {
const rootOpts = actionCmd.optsWithGlobals();
const profileFlag = typeof rootOpts["profile"] === "string" ? rootOpts["profile"] : undefined;
const { raw } = await loadConfigFile({ profile: profileFlag });
const { config } = validateConfig(raw);
const accessToken = config.oauth?.accessToken;
const clientId = config.oauth?.clientId;
const clientSecret = config.oauth?.clientSecret;
const label = profileFlag ?? "default";
if (accessToken === undefined || accessToken === "" || clientId === undefined || clientSecret === undefined) {
await clearOAuthTokens({ profile: profileFlag });
console.log(`No complete credentials for server-side revocation (missing access token, client ID, or client secret). Local credentials cleared for profile "${label}".`);
return;
}
try {
await revokeAccessToken(clientId, clientSecret, accessToken);
console.log(`Access token revoked server-side for profile "${label}".`);
}
catch (error) {
const message = error instanceof Error ? error.message : String(error);
console.warn(`Warning: Server-side revocation failed: ${message}`);
console.warn("Local credentials will still be cleared.");
}
await clearOAuthTokens({ profile: profileFlag });
console.log(`Local credentials cleared for profile "${label}".`);
});
return cmd;
}
//# sourceMappingURL=revoke.js.map
{"version":3,"file":"revoke.js","sourceRoot":"","sources":["../../../src/commands/auth/revoke.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEtG,MAAM,UAAU,aAAa;IAC3B,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClC,GAAG,CAAC,WAAW,CAAC,iEAAiE,CAAC,CAAC;IAEnF,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,KAA8B,EAAE,SAAkB,EAAE,EAAE;QACtE,MAAM,QAAQ,GAAG,SAAS,CAAC,eAAe,EAAE,CAAC;QAC7C,MAAM,WAAW,GAAG,OAAO,QAAQ,CAAC,SAAS,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAE9F,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,cAAc,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;QAC/D,MAAM,EAAE,MAAM,EAAE,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;QAEvC,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,EAAE,WAAW,CAAC;QAC9C,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC;QACxC,MAAM,YAAY,GAAG,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC;QAChD,MAAM,KAAK,GAAG,WAAW,IAAI,SAAS,CAAC;QAEvC,IAAI,WAAW,KAAK,SAAS,IAAI,WAAW,KAAK,EAAE,IAAI,QAAQ,KAAK,SAAS,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YAC5G,MAAM,gBAAgB,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;YACjD,OAAO,CAAC,GAAG,CACT,kJAAkJ,KAAK,IAAI,CAC5J,CAAC;YACF,OAAO;QACT,CAAC;QAED,IAAI,CAAC;YACH,MAAM,iBAAiB,CAAC,QAAQ,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;YAC7D,OAAO,CAAC,GAAG,CAAC,iDAAiD,KAAK,IAAI,CAAC,CAAC;QAC1E,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,OAAO,CAAC,IAAI,CAAC,2CAA2C,OAAO,EAAE,CAAC,CAAC;YACnE,OAAO,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;QAC3D,CAAC;QAED,MAAM,gBAAgB,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;QACjD,OAAO,CAAC,GAAG,CAAC,0CAA0C,KAAK,IAAI,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC"}
import { Command } from "commander";
export declare function setupCommand(): Command;
//# sourceMappingURL=setup.d.ts.map
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/commands/auth/setup.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC,wBAAgB,YAAY,IAAI,OAAO,CA8HtC"}
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Oleksii PELYKH
import { copyFile } from "node:fs/promises";
import { dirname, join } from "node:path";
import { homedir } from "node:os";
import { fileURLToPath } from "node:url";
import { createInterface } from "node:readline/promises";
import { Command } from "commander";
import { saveOAuthClientCredentials, saveOAuthScope, saveOAuthPkce, saveApiVersion, DEFAULT_API_VERSION, } from "@linkedctl/core";
import { DEFAULT_REDIRECT_PORT } from "./login.js";
export function setupCommand() {
const cmd = new Command("setup");
cmd.description("Configure OAuth client credentials interactively");
cmd.addHelpText("after", "\nLinkedIn Developer Portal: https://www.linkedin.com/developers/apps");
cmd.action(async () => {
const program = cmd.parent?.parent;
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const profileFlag = program?.opts()["profile"];
const rl = createInterface({ input: process.stdin, output: process.stderr });
// Offer to save logo to ~/Downloads for easy upload during app registration
const logoSource = join(dirname(fileURLToPath(import.meta.url)), "..", "..", "..", "assets", "logo.png");
const logoDestination = join(homedir(), "Downloads", "linkedctl-logo.png");
let logoSaved = false;
const saveLogo = await rl.question("Save LinkedCtl logo to ~/Downloads for app registration? [y/N] ");
if (saveLogo.trim().toLowerCase() === "y" || saveLogo.trim().toLowerCase() === "yes") {
try {
await copyFile(logoSource, logoDestination);
logoSaved = true;
}
catch {
process.stderr.write(" Could not save logo (file not available).\n");
}
}
process.stderr.write("\n");
process.stderr.write("To use OAuth authentication, you need a LinkedIn OAuth application.\n");
process.stderr.write("\n");
process.stderr.write('1. Go to https://www.linkedin.com/developers/apps and click "Create app"\n');
process.stderr.write("2. Fill in the app details:\n");
process.stderr.write(' - App name: "LinkedCtl - <your name>"\n');
process.stderr.write(" - LinkedIn Page: select your company page (or personal default page)\n");
if (logoSaved) {
process.stderr.write(` - App logo: use the file saved to ${logoDestination}\n`);
}
else {
process.stderr.write(" - App logo: use the LinkedCtl logo from the repository (square, >= 100px)\n");
}
process.stderr.write('3. Under the "Auth" tab, note your Client ID and Primary Client Secret\n');
process.stderr.write(`4. Add a redirect URL: http://127.0.0.1:${DEFAULT_REDIRECT_PORT}/callback\n`);
process.stderr.write('5. Under "Products", request access to the products you need\n');
process.stderr.write(" (e.g. Share on LinkedIn, Sign In with LinkedIn using OpenID Connect)\n");
process.stderr.write("6. Copy the Client ID and Client Secret below\n");
process.stderr.write("\n");
try {
const clientId = await rl.question("Client ID: ");
if (clientId.trim() === "") {
throw new Error("Client ID cannot be empty. " +
'Find your Client ID in the "Auth" tab of your app at https://www.linkedin.com/developers/apps');
}
const clientSecret = await rl.question("Client Secret: ");
if (clientSecret.trim() === "") {
throw new Error("Client Secret cannot be empty. " +
'Find your Client Secret in the "Auth" tab of your app at https://www.linkedin.com/developers/apps');
}
const writeOpts = profileFlag !== undefined ? { profile: profileFlag } : undefined;
await saveOAuthClientCredentials({ clientId: clientId.trim(), clientSecret: clientSecret.trim() }, writeOpts);
process.stderr.write("\n");
process.stderr.write("Which LinkedIn products have you enabled for this app?\n");
process.stderr.write("\n");
const scopes = [];
const signIn = await rl.question("Sign In with LinkedIn using OpenID Connect? [y/N] ");
if (signIn.trim().toLowerCase() === "y" || signIn.trim().toLowerCase() === "yes") {
scopes.push("openid", "profile", "email");
}
const share = await rl.question("Share on LinkedIn? [y/N] ");
if (share.trim().toLowerCase() === "y" || share.trim().toLowerCase() === "yes") {
scopes.push("w_member_social");
// Posting requires the author's person URN, which is only available via
// the /v2/userinfo endpoint. That endpoint needs openid scopes, so we
// force-enable them when Share on LinkedIn is selected.
if (!scopes.includes("openid")) {
scopes.push("openid", "profile", "email");
process.stderr.write(' → Also enabling "Sign In with LinkedIn" scopes (required to resolve author identity for posts)\n');
}
}
if (scopes.length === 0) {
throw new Error("At least one LinkedIn product must be enabled for OAuth to work. " +
'Enable products under the "Products" tab of your app at https://www.linkedin.com/developers/apps ' +
"and then re-run this setup.");
}
const scope = [...new Set(scopes)].join(" ");
await saveOAuthScope(scope, writeOpts);
process.stderr.write("\n");
process.stderr.write("PKCE (Proof Key for Code Exchange) improves security for native OAuth apps.\n");
process.stderr.write("LinkedIn requires PKCE to be enabled for your app by LinkedIn support.\n");
const pkceAnswer = await rl.question("Is PKCE enabled for your app? [y/N] ");
const pkce = pkceAnswer.trim().toLowerCase() === "y" || pkceAnswer.trim().toLowerCase() === "yes";
await saveOAuthPkce(pkce, writeOpts);
await saveApiVersion(DEFAULT_API_VERSION, writeOpts);
if (profileFlag !== undefined) {
process.stderr.write(`\nOAuth client credentials and scope saved to profile "${profileFlag}".\n`);
}
else {
process.stderr.write("\nOAuth client credentials and scope saved.\n");
}
process.stderr.write(`Scope: ${scope}\n`);
if (pkce) {
process.stderr.write("PKCE: enabled\n");
}
process.stderr.write('Run "linkedctl auth login" to authenticate.\n');
}
finally {
rl.close();
}
});
return cmd;
}
//# sourceMappingURL=setup.js.map
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../../src/commands/auth/setup.ts"],"names":[],"mappings":"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"}
import { Command } from "commander";
export declare function statusCommand(): Command;
//# sourceMappingURL=status.d.ts.map
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/commands/auth/status.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuBpC,wBAAgB,aAAa,IAAI,OAAO,CA0CvC"}
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Oleksii PELYKH
import { Command } from "commander";
import { loadConfigFile, validateConfig, getTokenExpiry } from "@linkedctl/core";
/**
* Format remaining time until token expiry as a human-readable string.
*/
function formatTimeRemaining(expiresAt) {
const diffMs = expiresAt.getTime() - Date.now();
const totalMinutes = Math.floor(diffMs / 60_000);
const totalHours = Math.floor(totalMinutes / 60);
const days = Math.floor(totalHours / 24);
const hours = totalHours % 24;
if (days > 0) {
return hours > 0 ? `${String(days)}d ${String(hours)}h` : `${String(days)}d`;
}
if (totalHours > 0) {
const minutes = totalMinutes % 60;
return minutes > 0 ? `${String(totalHours)}h ${String(minutes)}m` : `${String(totalHours)}h`;
}
return `${String(totalMinutes)}m`;
}
export function statusCommand() {
const cmd = new Command("status");
cmd.description("Show authentication status for the active profile");
cmd.action(async (_opts, actionCmd) => {
const rootOpts = actionCmd.optsWithGlobals();
const profileFlag = typeof rootOpts["profile"] === "string" ? rootOpts["profile"] : undefined;
const { raw } = await loadConfigFile({ profile: profileFlag });
const { config } = validateConfig(raw);
const label = profileFlag ?? "default";
if (config.oauth?.accessToken === undefined || config.oauth.accessToken === "") {
console.log(`Profile: ${label}`);
console.log("Status: not configured");
console.error('Run "linkedctl auth login" to set up authentication.');
return;
}
const expiry = getTokenExpiry(config.oauth.accessToken);
console.log(`Profile: ${label}`);
if (expiry === undefined) {
console.log("Status: authenticated");
console.log("Expiry: unknown (token is not a JWT)");
return;
}
if (expiry.isExpired) {
console.log("Status: expired");
console.log(`Expired: ${expiry.expiresAt.toISOString()}`);
console.error('Run "linkedctl auth login" to re-authenticate.');
return;
}
const remaining = formatTimeRemaining(expiry.expiresAt);
console.log("Status: authenticated");
console.log(`Expires: ${expiry.expiresAt.toISOString()} (${remaining} remaining)`);
});
return cmd;
}
//# sourceMappingURL=status.js.map
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/commands/auth/status.ts"],"names":[],"mappings":"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"}
import { Command } from "commander";
export declare function tokenCommand(): Command;
//# sourceMappingURL=token.d.ts.map
{"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../../src/commands/auth/token.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,wBAAgB,YAAY,IAAI,OAAO,CAetC"}
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Oleksii PELYKH
import { Command } from "commander";
import { saveOAuthTokens } from "@linkedctl/core";
export function tokenCommand() {
const cmd = new Command("token");
cmd.description("Store a direct access token in the active profile");
cmd.requiredOption("--access-token <token>", "access token to store");
cmd.action(async (_opts, command) => {
const globals = command.optsWithGlobals();
const profileFlag = globals.profile;
await saveOAuthTokens({ accessToken: globals.accessToken }, { profile: profileFlag });
const label = profileFlag ?? "default";
console.log(`Access token stored in profile "${label}".`);
});
return cmd;
}
//# sourceMappingURL=token.js.map
{"version":3,"file":"token.js","sourceRoot":"","sources":["../../../src/commands/auth/token.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,UAAU,YAAY;IAC1B,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACjC,GAAG,CAAC,WAAW,CAAC,mDAAmD,CAAC,CAAC;IACrE,GAAG,CAAC,cAAc,CAAC,wBAAwB,EAAE,uBAAuB,CAAC,CAAC;IAEtE,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,KAA8B,EAAE,OAAgB,EAAE,EAAE;QACpE,MAAM,OAAO,GAAG,OAAO,CAAC,eAAe,EAAyD,CAAC;QACjG,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;QAEpC,MAAM,eAAe,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;QACtF,MAAM,KAAK,GAAG,WAAW,IAAI,SAAS,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,mCAAmC,KAAK,IAAI,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC"}
import { Command } from "commander";
export declare function completionCommand(program: Command): Command;
//# sourceMappingURL=completion.d.ts.map
{"version":3,"file":"completion.d.ts","sourceRoot":"","sources":["../../src/commands/completion.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6MpC,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAiC3D"}
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Oleksii PELYKH
import { Command } from "commander";
function collectCommands(cmd, prefix) {
const result = [];
const name = prefix ? `${prefix} ${cmd.name()}` : cmd.name();
const subcommands = cmd.commands.map((c) => c.name());
const options = cmd.options.map((o) => o.long).filter((o) => o !== undefined);
result.push({ name, subcommands, options });
for (const sub of cmd.commands) {
result.push(...collectCommands(sub, name));
}
return result;
}
function generateBash(program) {
const commands = collectCommands(program, "");
const rootName = program.name();
const d = "$";
const cases = commands
.map((cmd) => {
const words = [...cmd.subcommands, ...cmd.options].join(" ");
const pattern = cmd.name === rootName ? rootName : cmd.name.replace(`${rootName} `, "").replace(/ /g, "__");
return ` ${pattern})\n COMPREPLY=(${d}(compgen -W "${words}" -- "${d}{cur}"))\n return 0\n ;;`;
})
.join("\n");
const cmdLookup = commands
.filter((cmd) => cmd.name !== rootName)
.map((cmd) => {
const parts = cmd.name.replace(`${rootName} `, "").split(" ");
return ` ${parts.join("__")}) cmd="${parts.join("__")}" ;;`;
})
.join("\n");
return `# bash completion for ${rootName}
# eval "${d}(${rootName} completion bash)"
_${rootName}_completions() {
local cur prev words cword cmd
_init_completion || return
cmd="${rootName}"
for ((i=1; i < cword; i++)); do
case "${d}{words[i]}" in
-*) ;;
*)
local subcmd
if [ "${d}{cmd}" = "${rootName}" ]; then
subcmd="${d}{words[i]}"
else
subcmd="${d}{cmd}__${d}{words[i]}"
fi
case "${d}{subcmd}" in
${cmdLookup}
*) ;;
esac
;;
esac
done
case "${d}{cmd}" in
${cases}
esac
}
complete -F _${rootName}_completions ${rootName}
`;
}
function generateZsh(program) {
const commands = collectCommands(program, "");
const rootName = program.name();
const d = "$";
const helperPrefix = `__${rootName}`;
const functions = [];
for (const cmd of commands) {
const fnName = cmd.name.replace(/ /g, "_");
const optionArgs = cmd.options.map((opt) => `'${opt}[option]'`);
if (cmd.subcommands.length > 0) {
const subcmds = cmd.subcommands.map((s) => `'${s}:${s} command'`);
functions.push(`${helperPrefix}_${fnName}() {
local -a commands options
commands=(${subcmds.join(" ")})
options=(${optionArgs.join(" ")})
_describe -t commands 'commands' commands
_describe -t options 'options' options
}`);
}
else if (optionArgs.length > 0) {
functions.push(`${helperPrefix}_${fnName}() {
local -a options
options=(${optionArgs.join(" ")})
_describe -t options 'options' options
}`);
}
}
// Build routing cases for root subcommands
const rootCmd = commands.find((c) => c.name === rootName);
const rootSubcases = (rootCmd?.subcommands ?? [])
.map((sub) => {
const childCmd = commands.find((c) => c.name === `${rootName} ${sub}`);
if (!childCmd || (childCmd.subcommands.length === 0 && childCmd.options.length === 0))
return null;
const childSubcases = childCmd.subcommands
.map((subsub) => {
const leafFn = `${rootName}_${sub}_${subsub}`;
const exists = functions.some((f) => f.includes(`${helperPrefix}_${leafFn}()`));
return exists ? ` ${subsub}) ${helperPrefix}_${leafFn} ;;` : null;
})
.filter(Boolean)
.join("\n");
if (childCmd.subcommands.length > 0 && childSubcases) {
return ` ${sub})
if (( CURRENT == 2 )); then
${helperPrefix}_${rootName}_${sub}
else
case "${d}{line[2]}" in
${childSubcases}
esac
fi
;;`;
}
return ` ${sub}) ${helperPrefix}_${rootName}_${sub} ;;`;
})
.filter(Boolean)
.join("\n");
return `#compdef ${rootName}
# eval "${d}(${rootName} completion zsh)"
${functions.join("\n\n")}
_${rootName}() {
local curcontext="${d}curcontext" state line
typeset -A opt_args
_arguments -C \\
'1:command:->command' \\
'*::arg:->args'
case "${d}state" in
command)
${helperPrefix}_${rootName}
;;
args)
case "${d}{line[1]}" in
${rootSubcases}
esac
;;
esac
}
_${rootName} "${d}@"
`;
}
function generateFish(program) {
const commands = collectCommands(program, "");
const rootName = program.name();
const lines = [`# fish completion for ${rootName}`, `# ${rootName} completion fish | source`];
for (const cmd of commands) {
const parts = cmd.name.split(" ");
if (cmd.name === rootName) {
for (const sub of cmd.subcommands) {
lines.push(`complete -c ${rootName} -n "__fish_use_subcommand" -a "${sub}" -d "${sub} command"`);
}
for (const opt of cmd.options) {
const longFlag = opt.replace(/^--/, "");
lines.push(`complete -c ${rootName} -n "__fish_use_subcommand" -l "${longFlag}"`);
}
}
else {
const parentArgs = parts.slice(1);
const condition = parentArgs.length === 1
? `__fish_seen_subcommand_from ${parentArgs[0]}`
: parentArgs.map((a) => `__fish_seen_subcommand_from ${a}`).join("; and ");
for (const sub of cmd.subcommands) {
lines.push(`complete -c ${rootName} -n "${condition}" -a "${sub}" -d "${sub} command"`);
}
for (const opt of cmd.options) {
const longFlag = opt.replace(/^--/, "");
lines.push(`complete -c ${rootName} -n "${condition}" -l "${longFlag}"`);
}
}
}
return lines.join("\n") + "\n";
}
export function completionCommand(program) {
const cmd = new Command("completion");
cmd.description("Generate shell completion scripts");
cmd.argument("<shell>", "shell type (bash, zsh, fish)");
cmd.addHelpText("after", `
Examples:
eval "$(linkedctl completion bash)"
linkedctl completion zsh > ~/.zsh/completions/_linkedctl
linkedctl completion fish | source`);
cmd.action((shell) => {
switch (shell) {
case "bash":
process.stdout.write(generateBash(program));
break;
case "zsh":
process.stdout.write(generateZsh(program));
break;
case "fish":
process.stdout.write(generateFish(program));
break;
default:
console.error(`Unsupported shell: ${shell}. Supported shells: bash, zsh, fish`);
process.exitCode = 1;
break;
}
});
return cmd;
}
//# sourceMappingURL=completion.js.map
{"version":3,"file":"completion.js","sourceRoot":"","sources":["../../src/commands/completion.ts"],"names":[],"mappings":"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"}
import { Command } from "commander";
interface CreateOpts {
text?: string | undefined;
visibility?: string | undefined;
format?: string | undefined;
}
/**
* Shared action handler for creating a text post.
*/
export declare function createPostAction(textArg: string | undefined, opts: CreateOpts, cmd: Command): Promise<void>;
export declare function createCommand(): Command;
export {};
//# sourceMappingURL=create.d.ts.map
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/commands/post/create.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAO5C,UAAU,UAAU;IAClB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AA0BD;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAiCjH;AAED,wBAAgB,aAAa,IAAI,OAAO,CAiBvC"}
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Oleksii PELYKH
import { Command, Option } from "commander";
import { resolveConfig, LinkedInClient, getCurrentPersonUrn, createTextPost, LinkedInApiError } from "@linkedctl/core";
import { resolveFormat, formatOutput } from "../../output/index.js";
import { readStdin } from "./stdin.js";
/**
* Resolve the post text from --text option, positional argument, or stdin.
*
* Precedence: --text > positional argument > stdin.
*/
async function resolveText(textOpt, textArg) {
if (textOpt !== undefined && textOpt !== "") {
return textOpt;
}
if (textArg !== undefined && textArg !== "") {
return textArg;
}
if (!process.stdin.isTTY) {
const stdin = await readStdin();
if (stdin !== "") {
return stdin;
}
}
throw new Error('No text provided. Use --text "message", pass text as an argument, or pipe text via stdin.');
}
/**
* Shared action handler for creating a text post.
*/
export async function createPostAction(textArg, opts, cmd) {
const text = await resolveText(opts.text, textArg);
const globals = cmd.optsWithGlobals();
const { config } = await resolveConfig({
profile: globals.profile,
requiredScopes: ["openid", "profile", "email", "w_member_social"],
});
// resolveConfig guarantees oauth.accessToken and apiVersion are defined
const accessToken = config.oauth?.accessToken ?? "";
const apiVersion = config.apiVersion ?? "";
const client = new LinkedInClient({ accessToken, apiVersion });
const authorUrn = await getCurrentPersonUrn(client);
const visibility = opts.visibility ?? "PUBLIC";
try {
const postUrn = await createTextPost(client, {
author: authorUrn,
text,
visibility,
});
const format = resolveFormat(opts.format, process.stdout);
const output = formatOutput({ urn: postUrn }, format);
console.log(output);
}
catch (error) {
if (error instanceof LinkedInApiError) {
throw new Error(`Failed to create post: ${error.message}`);
}
throw error;
}
}
export function createCommand() {
const cmd = new Command("create");
cmd.description("Create a text post on LinkedIn (text: --text > positional > stdin)");
cmd.argument("[text]", "text content of the post");
cmd.option("--text <text>", "text content of the post (takes precedence over positional argument)");
cmd.addOption(new Option("--visibility <visibility>", "post visibility (PUBLIC or CONNECTIONS)")
.choices(["PUBLIC", "CONNECTIONS"])
.default("PUBLIC"));
cmd.addOption(new Option("--format <format>", "output format (json or table)").choices(["json", "table"]));
cmd.action(async (text, opts, actionCmd) => {
await createPostAction(text, opts, actionCmd);
});
return cmd;
}
//# sourceMappingURL=create.js.map
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../../src/commands/post/create.ts"],"names":[],"mappings":"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"}
import { Command } from "commander";
export declare function postCommand(): Command;
//# sourceMappingURL=index.d.ts.map
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/post/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAG5C,wBAAgB,WAAW,IAAI,OAAO,CAsBrC"}
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Oleksii PELYKH
import { Command, Option } from "commander";
import { createCommand, createPostAction } from "./create.js";
export function postCommand() {
const cmd = new Command("post");
cmd.description("Manage LinkedIn posts");
cmd.enablePositionalOptions();
cmd.argument("[text]", "shorthand: create a post with the given text (text > stdin)");
cmd.option("--text <text>", "text content of the post (takes precedence over positional argument)");
cmd.addOption(new Option("--visibility <visibility>", "post visibility (PUBLIC or CONNECTIONS)")
.choices(["PUBLIC", "CONNECTIONS"])
.default("PUBLIC"));
cmd.addOption(new Option("--format <format>", "output format (json or table)").choices(["json", "table"]));
cmd.action(async (text, opts, actionCmd) => {
await createPostAction(text, opts, actionCmd);
});
cmd.addCommand(createCommand());
return cmd;
}
//# sourceMappingURL=index.js.map
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/post/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE9D,MAAM,UAAU,WAAW;IACzB,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAChC,GAAG,CAAC,WAAW,CAAC,uBAAuB,CAAC,CAAC;IAEzC,GAAG,CAAC,uBAAuB,EAAE,CAAC;IAE9B,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,6DAA6D,CAAC,CAAC;IACtF,GAAG,CAAC,MAAM,CAAC,eAAe,EAAE,sEAAsE,CAAC,CAAC;IACpG,GAAG,CAAC,SAAS,CACX,IAAI,MAAM,CAAC,2BAA2B,EAAE,yCAAyC,CAAC;SAC/E,OAAO,CAAC,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;SAClC,OAAO,CAAC,QAAQ,CAAC,CACrB,CAAC;IACF,GAAG,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,mBAAmB,EAAE,+BAA+B,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAE3G,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,IAAwB,EAAE,IAA6B,EAAE,SAAkB,EAAE,EAAE;QAC/F,MAAM,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;IAEhC,OAAO,GAAG,CAAC;AACb,CAAC"}
/**
* Read all available data from stdin and return it as a trimmed string.
*/
export declare function readStdin(): Promise<string>;
//# sourceMappingURL=stdin.d.ts.map
{"version":3,"file":"stdin.d.ts","sourceRoot":"","sources":["../../../src/commands/post/stdin.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAc3C"}
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Oleksii PELYKH
/**
* Read all available data from stdin and return it as a trimmed string.
*/
export function readStdin() {
return new Promise((resolve, reject) => {
const chunks = [];
process.stdin.on("data", (chunk) => {
chunks.push(chunk);
});
process.stdin.on("end", () => {
resolve(Buffer.concat(chunks).toString("utf-8").trim());
});
process.stdin.on("error", reject);
});
}
//# sourceMappingURL=stdin.js.map
{"version":3,"file":"stdin.js","sourceRoot":"","sources":["../../../src/commands/post/stdin.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC;;GAEG;AACH,MAAM,UAAU,SAAS;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YACzC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YAC3B,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC"}
import { Command } from "commander";
export declare function createCommand(): Command;
//# sourceMappingURL=create.d.ts.map
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/commands/profile/create.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,wBAAgB,aAAa,IAAI,OAAO,CAgCvC"}
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Oleksii PELYKH
import { join } from "node:path";
import { homedir } from "node:os";
import { writeFile, mkdir } from "node:fs/promises";
import { Command } from "commander";
import { loadConfigFile, isValidProfileName, saveOAuthTokens, CONFIG_DIR, DEFAULT_API_VERSION } from "@linkedctl/core";
export function createCommand() {
const cmd = new Command("create");
cmd.description("Create a new profile");
cmd.argument("<name>", "profile name");
cmd.requiredOption("--access-token <token>", "OAuth2 access token");
cmd.option("--api-version <version>", "LinkedIn API version", DEFAULT_API_VERSION);
cmd.action(async (name, opts) => {
if (!isValidProfileName(name)) {
throw new Error(`Invalid profile name "${name}". Names must not contain path separators or be empty.`);
}
const { path } = await loadConfigFile({ profile: name });
if (path !== undefined) {
throw new Error(`Profile "${name}" already exists. Delete it first or use a different name.`);
}
// Ensure the profile directory exists
const profileDir = join(homedir(), CONFIG_DIR);
await mkdir(profileDir, { recursive: true });
// Write the initial config with api-version
const profilePath = join(profileDir, `${name}.yaml`);
await writeFile(profilePath, `api-version: "${opts.apiVersion}"\n`, { mode: 0o600 });
// Save the access token (merges into existing file)
await saveOAuthTokens({ accessToken: opts.accessToken }, { profile: name });
console.log(`Profile "${name}" created.`);
});
return cmd;
}
//# sourceMappingURL=create.js.map
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../../src/commands/profile/create.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,eAAe,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEvH,MAAM,UAAU,aAAa;IAC3B,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClC,GAAG,CAAC,WAAW,CAAC,sBAAsB,CAAC,CAAC;IACxC,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;IACvC,GAAG,CAAC,cAAc,CAAC,wBAAwB,EAAE,qBAAqB,CAAC,CAAC;IACpE,GAAG,CAAC,MAAM,CAAC,yBAAyB,EAAE,sBAAsB,EAAE,mBAAmB,CAAC,CAAC;IAEnF,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,IAAiD,EAAE,EAAE;QACnF,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,wDAAwD,CAAC,CAAC;QACzG,CAAC;QAED,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,cAAc,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,YAAY,IAAI,4DAA4D,CAAC,CAAC;QAChG,CAAC;QAED,sCAAsC;QACtC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC,CAAC;QAC/C,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE7C,4CAA4C;QAC5C,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,GAAG,IAAI,OAAO,CAAC,CAAC;QACrD,MAAM,SAAS,CAAC,WAAW,EAAE,iBAAiB,IAAI,CAAC,UAAU,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAErF,oDAAoD;QACpD,MAAM,eAAe,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAE5E,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,YAAY,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC"}
import { Command } from "commander";
export declare function deleteCommand(): Command;
//# sourceMappingURL=delete.d.ts.map
{"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["../../../src/commands/profile/delete.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,wBAAgB,aAAa,IAAI,OAAO,CAyBvC"}
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Oleksii PELYKH
import { join } from "node:path";
import { homedir } from "node:os";
import { unlink } from "node:fs/promises";
import { Command } from "commander";
import { isValidProfileName, CONFIG_DIR } from "@linkedctl/core";
export function deleteCommand() {
const cmd = new Command("delete");
cmd.description("Delete a profile");
cmd.argument("<name>", "profile name");
cmd.action(async (name) => {
if (!isValidProfileName(name)) {
throw new Error(`Invalid profile name "${name}". Names must not contain path separators or be empty.`);
}
const profilePath = join(homedir(), CONFIG_DIR, `${name}.yaml`);
try {
await unlink(profilePath);
}
catch (error) {
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
throw new Error(`Profile "${name}" not found. Run "linkedctl profile list" to see available profiles.`);
}
throw error;
}
console.log(`Profile "${name}" deleted.`);
});
return cmd;
}
//# sourceMappingURL=delete.js.map
{"version":3,"file":"delete.js","sourceRoot":"","sources":["../../../src/commands/profile/delete.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEjE,MAAM,UAAU,aAAa;IAC3B,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClC,GAAG,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC;IACpC,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;IAEvC,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,EAAE;QAChC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,wDAAwD,CAAC,CAAC;QACzG,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,GAAG,IAAI,OAAO,CAAC,CAAC;QAEhE,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;QAC5B,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,IAAI,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACpG,MAAM,IAAI,KAAK,CAAC,YAAY,IAAI,sEAAsE,CAAC,CAAC;YAC1G,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,YAAY,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC"}
import { Command } from "commander";
export declare function profileCommand(): Command;
//# sourceMappingURL=index.d.ts.map
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/profile/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,cAAc,IAAI,OAAO,CAUxC"}
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Oleksii PELYKH
import { Command } from "commander";
import { createCommand } from "./create.js";
import { listCommand } from "./list.js";
import { showCommand } from "./show.js";
import { deleteCommand } from "./delete.js";
export function profileCommand() {
const cmd = new Command("profile");
cmd.description("Manage configuration profiles");
cmd.addCommand(createCommand());
cmd.addCommand(listCommand());
cmd.addCommand(showCommand());
cmd.addCommand(deleteCommand());
return cmd;
}
//# sourceMappingURL=index.js.map
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/profile/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,UAAU,cAAc;IAC5B,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC;IACnC,GAAG,CAAC,WAAW,CAAC,+BAA+B,CAAC,CAAC;IAEjD,GAAG,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;IAChC,GAAG,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;IAC9B,GAAG,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;IAC9B,GAAG,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;IAEhC,OAAO,GAAG,CAAC;AACb,CAAC"}
import { Command } from "commander";
export declare function listCommand(): Command;
//# sourceMappingURL=list.d.ts.map
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/commands/profile/list.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,wBAAgB,WAAW,IAAI,OAAO,CA8BrC"}
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Oleksii PELYKH
import { join } from "node:path";
import { homedir } from "node:os";
import { readdir } from "node:fs/promises";
import { Command } from "commander";
import { CONFIG_DIR } from "@linkedctl/core";
export function listCommand() {
const cmd = new Command("list");
cmd.description("List all profiles");
cmd.action(async () => {
const profileDir = join(homedir(), CONFIG_DIR);
let entries;
try {
entries = await readdir(profileDir);
}
catch (error) {
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
console.log("No profiles configured.");
return;
}
throw error;
}
const names = entries.filter((e) => e.endsWith(".yaml")).map((e) => e.replace(/\.yaml$/, ""));
if (names.length === 0) {
console.log("No profiles configured.");
return;
}
for (const name of names) {
console.log(name);
}
});
return cmd;
}
//# sourceMappingURL=list.js.map
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/commands/profile/list.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,MAAM,UAAU,WAAW;IACzB,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAChC,GAAG,CAAC,WAAW,CAAC,mBAAmB,CAAC,CAAC;IAErC,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE;QACpB,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC,CAAC;QAC/C,IAAI,OAAiB,CAAC;QACtB,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC;QACtC,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,IAAI,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACpG,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;gBACvC,OAAO;YACT,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;QAED,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC;QAE9F,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;YACvC,OAAO;QACT,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC"}
import { Command } from "commander";
export declare function showCommand(): Command;
//# sourceMappingURL=show.d.ts.map
{"version":3,"file":"show.d.ts","sourceRoot":"","sources":["../../../src/commands/profile/show.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,wBAAgB,WAAW,IAAI,OAAO,CA2CrC"}
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Oleksii PELYKH
import { Command } from "commander";
import { loadConfigFile, validateConfig, isValidProfileName } from "@linkedctl/core";
function redactSecret(value) {
if (value.length <= 8) {
return "****";
}
return value.slice(0, 4) + "****" + value.slice(-4);
}
export function showCommand() {
const cmd = new Command("show");
cmd.description("Show profile details (secrets redacted)");
cmd.argument("<name>", "profile name");
cmd.action(async (name) => {
if (!isValidProfileName(name)) {
throw new Error(`Invalid profile name "${name}". Names must not contain path separators or be empty.`);
}
const { raw, path } = await loadConfigFile({ profile: name });
if (path === undefined) {
throw new Error(`Profile "${name}" not found. Run "linkedctl profile list" to see available profiles.`);
}
const { config } = validateConfig(raw);
console.log(`Profile: ${name}`);
if (config.oauth !== undefined) {
if (config.oauth.clientId !== undefined) {
console.log(` client-id: ${redactSecret(config.oauth.clientId)}`);
}
if (config.oauth.clientSecret !== undefined) {
console.log(` client-secret: ${redactSecret(config.oauth.clientSecret)}`);
}
if (config.oauth.accessToken !== undefined) {
console.log(` access-token: ${redactSecret(config.oauth.accessToken)}`);
}
if (config.oauth.refreshToken !== undefined) {
console.log(` refresh-token: ${redactSecret(config.oauth.refreshToken)}`);
}
if (config.oauth.tokenExpiresAt !== undefined) {
console.log(` token-expires-at: ${config.oauth.tokenExpiresAt}`);
}
}
if (config.apiVersion !== undefined) {
console.log(` api-version: ${config.apiVersion}`);
}
});
return cmd;
}
//# sourceMappingURL=show.js.map
{"version":3,"file":"show.js","sourceRoot":"","sources":["../../../src/commands/profile/show.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErF,SAAS,YAAY,CAAC,KAAa;IACjC,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACtB,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAChC,GAAG,CAAC,WAAW,CAAC,yCAAyC,CAAC,CAAC;IAC3D,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;IAEvC,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,EAAE;QAChC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,wDAAwD,CAAC,CAAC;QACzG,CAAC;QAED,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,MAAM,cAAc,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9D,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,YAAY,IAAI,sEAAsE,CAAC,CAAC;QAC1G,CAAC;QAED,MAAM,EAAE,MAAM,EAAE,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;QAEvC,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;QAEhC,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAC/B,IAAI,MAAM,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;gBACxC,OAAO,CAAC,GAAG,CAAC,gBAAgB,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YACrE,CAAC;YACD,IAAI,MAAM,CAAC,KAAK,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;gBAC5C,OAAO,CAAC,GAAG,CAAC,oBAAoB,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;YAC7E,CAAC;YACD,IAAI,MAAM,CAAC,KAAK,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;gBAC3C,OAAO,CAAC,GAAG,CAAC,mBAAmB,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;YAC3E,CAAC;YACD,IAAI,MAAM,CAAC,KAAK,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;gBAC5C,OAAO,CAAC,GAAG,CAAC,oBAAoB,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;YAC7E,CAAC;YACD,IAAI,MAAM,CAAC,KAAK,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;gBAC9C,OAAO,CAAC,GAAG,CAAC,uBAAuB,MAAM,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC;YACpE,CAAC;QACH,CAAC;QAED,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YACpC,OAAO,CAAC,GAAG,CAAC,kBAAkB,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;QACrD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC"}
import { Command } from "commander";
export declare function whoamiCommand(): Command;
//# sourceMappingURL=whoami.d.ts.map
{"version":3,"file":"whoami.d.ts","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAK5C,wBAAgB,aAAa,IAAI,OAAO,CA6BvC"}
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Oleksii PELYKH
import { Command, Option } from "commander";
import { resolveConfig, LinkedInClient, getUserInfo } from "@linkedctl/core";
import { resolveFormat, formatOutput } from "../output/index.js";
export function whoamiCommand() {
const cmd = new Command("whoami");
cmd.description("Display the current authenticated user's profile");
cmd.addOption(new Option("--format <format>", "output format (json or table)").choices(["json", "table"]));
cmd.action(async (opts, actionCmd) => {
const rootOpts = actionCmd.optsWithGlobals();
const profileFlag = typeof rootOpts["profile"] === "string" ? rootOpts["profile"] : undefined;
const { config } = await resolveConfig({ profile: profileFlag, requiredScopes: ["openid", "profile", "email"] });
// resolveConfig guarantees oauth.accessToken and apiVersion are defined
const accessToken = config.oauth?.accessToken ?? "";
const apiVersion = config.apiVersion ?? "";
const client = new LinkedInClient({ accessToken, apiVersion });
const userInfo = await getUserInfo(client);
const format = resolveFormat(opts["format"], process.stdout);
const data = {
name: userInfo.name,
email: userInfo.email,
picture: userInfo.picture,
};
console.log(formatOutput(data, format));
});
return cmd;
}
//# sourceMappingURL=whoami.js.map
{"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE7E,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEjE,MAAM,UAAU,aAAa;IAC3B,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClC,GAAG,CAAC,WAAW,CAAC,kDAAkD,CAAC,CAAC;IACpE,GAAG,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,mBAAmB,EAAE,+BAA+B,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAE3G,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,IAA6B,EAAE,SAAkB,EAAE,EAAE;QACrE,MAAM,QAAQ,GAAG,SAAS,CAAC,eAAe,EAAE,CAAC;QAC7C,MAAM,WAAW,GAAG,OAAO,QAAQ,CAAC,SAAS,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAE9F,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;QACjH,wEAAwE;QACxE,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,EAAE,WAAW,IAAI,EAAE,CAAC;QACpD,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;QAC3C,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC;QAE/D,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC;QAE3C,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,QAAQ,CAA6B,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAEzF,MAAM,IAAI,GAAG;YACX,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,OAAO,EAAE,QAAQ,CAAC,OAAO;SAC1B,CAAC;QAEF,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC"}
/**
* Determine whether color output is enabled.
*
* Color is disabled when:
* - The `NO_COLOR` environment variable is set (any value, per https://no-color.org/)
* - The `noColor` flag is `true` (from `--no-color` CLI flag)
*
* @param options.noColor - Whether the `--no-color` CLI flag was provided
* @param options.env - Environment variables to check (defaults to `process.env`)
*/
export declare function isColorEnabled(options?: {
noColor?: boolean | undefined;
env?: Record<string, string | undefined> | undefined;
}): boolean;
//# sourceMappingURL=color.d.ts.map
{"version":3,"file":"color.d.ts","sourceRoot":"","sources":["../../src/output/color.ts"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE;IACvC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;CACtD,GAAG,OAAO,CAYV"}
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Oleksii PELYKH
/**
* Determine whether color output is enabled.
*
* Color is disabled when:
* - The `NO_COLOR` environment variable is set (any value, per https://no-color.org/)
* - The `noColor` flag is `true` (from `--no-color` CLI flag)
*
* @param options.noColor - Whether the `--no-color` CLI flag was provided
* @param options.env - Environment variables to check (defaults to `process.env`)
*/
export function isColorEnabled(options) {
const env = options?.env ?? process.env;
if ("NO_COLOR" in env) {
return false;
}
if (options?.noColor === true) {
return false;
}
return true;
}
//# sourceMappingURL=color.js.map
{"version":3,"file":"color.js","sourceRoot":"","sources":["../../src/output/color.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAAC,OAG9B;IACC,MAAM,GAAG,GAAG,OAAO,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IAExC,IAAI,UAAU,IAAI,GAAG,EAAE,CAAC;QACtB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,OAAO,EAAE,OAAO,KAAK,IAAI,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
/**
* Supported output formats.
*/
export type OutputFormat = "json" | "table";
/**
* Detect the default output format based on whether the stream is a TTY.
* TTY streams default to "table"; piped streams default to "json".
*/
export declare function detectFormat(stream: {
isTTY?: boolean;
}): OutputFormat;
/**
* Resolve the effective output format: an explicit choice overrides TTY detection.
*/
export declare function resolveFormat(explicit: OutputFormat | undefined, stream: {
isTTY?: boolean;
}): OutputFormat;
//# sourceMappingURL=format.d.ts.map
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/output/format.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,OAAO,CAAC;AAE5C;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,YAAY,CAEtE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,YAAY,GAAG,SAAS,EAAE,MAAM,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,YAAY,CAE3G"}
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Oleksii PELYKH
/**
* Detect the default output format based on whether the stream is a TTY.
* TTY streams default to "table"; piped streams default to "json".
*/
export function detectFormat(stream) {
return stream.isTTY === true ? "table" : "json";
}
/**
* Resolve the effective output format: an explicit choice overrides TTY detection.
*/
export function resolveFormat(explicit, stream) {
return explicit ?? detectFormat(stream);
}
//# sourceMappingURL=format.js.map
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/output/format.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAOpC;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,MAA2B;IACtD,OAAO,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;AAClD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,QAAkC,EAAE,MAA2B;IAC3F,OAAO,QAAQ,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC;AAC1C,CAAC"}
import type { OutputFormat } from "./format.js";
/**
* Format data according to the specified output format.
*/
export declare function formatOutput(data: unknown, format: OutputFormat): string;
//# sourceMappingURL=formatter.d.ts.map
{"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../../src/output/formatter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIhD;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,GAAG,MAAM,CAOxE"}
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Oleksii PELYKH
import { formatJson } from "./json-formatter.js";
import { formatTable } from "./table-formatter.js";
/**
* Format data according to the specified output format.
*/
export function formatOutput(data, format) {
switch (format) {
case "json":
return formatJson(data);
case "table":
return formatTable(data);
}
}
//# sourceMappingURL=formatter.js.map
{"version":3,"file":"formatter.js","sourceRoot":"","sources":["../../src/output/formatter.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAGpC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,IAAa,EAAE,MAAoB;IAC9D,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,MAAM;YACT,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC;QAC1B,KAAK,OAAO;YACV,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;AACH,CAAC"}
export type { OutputFormat } from "./format.js";
export { detectFormat, resolveFormat } from "./format.js";
export { formatJson } from "./json-formatter.js";
export { formatTable } from "./table-formatter.js";
export { formatOutput } from "./formatter.js";
export { isColorEnabled } from "./color.js";
//# sourceMappingURL=index.d.ts.map
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/output/index.ts"],"names":[],"mappings":"AAGA,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Oleksii PELYKH
export { detectFormat, resolveFormat } from "./format.js";
export { formatJson } from "./json-formatter.js";
export { formatTable } from "./table-formatter.js";
export { formatOutput } from "./formatter.js";
export { isColorEnabled } from "./color.js";
//# sourceMappingURL=index.js.map
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/output/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAGpC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
/**
* Format data as a pretty-printed JSON string.
*/
export declare function formatJson(data: unknown): string;
//# sourceMappingURL=json-formatter.d.ts.map
{"version":3,"file":"json-formatter.d.ts","sourceRoot":"","sources":["../../src/output/json-formatter.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAEhD"}
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Oleksii PELYKH
/**
* Format data as a pretty-printed JSON string.
*/
export function formatJson(data) {
return JSON.stringify(data, null, 2);
}
//# sourceMappingURL=json-formatter.js.map
{"version":3,"file":"json-formatter.js","sourceRoot":"","sources":["../../src/output/json-formatter.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,IAAa;IACtC,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACvC,CAAC"}
/**
* Format data as a human-readable table string.
*
* - Array of objects: columnar table with headers derived from object keys.
* - Single object: two-column key/value table.
* - Primitive: stringified value.
*/
export declare function formatTable(data: unknown): string;
//# sourceMappingURL=table-formatter.d.ts.map
{"version":3,"file":"table-formatter.d.ts","sourceRoot":"","sources":["../../src/output/table-formatter.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAQjD"}
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Oleksii PELYKH
/**
* Format data as a human-readable table string.
*
* - Array of objects: columnar table with headers derived from object keys.
* - Single object: two-column key/value table.
* - Primitive: stringified value.
*/
export function formatTable(data) {
if (Array.isArray(data)) {
return data.length === 0 ? "" : formatArrayTable(data);
}
if (typeof data === "object" && data !== null) {
return formatRecordTable(data);
}
return String(data);
}
function formatArrayTable(rows) {
const records = rows.map(toRecord);
const columns = deriveColumns(records);
if (columns.length === 0) {
return "";
}
const widths = computeColumnWidths(columns, records);
const header = columns.map((col, i) => pad(col, widths[i] ?? 0)).join(" ");
const separator = widths.map((w) => "\u2500".repeat(w)).join(" ");
const body = records
.map((row) => columns.map((col, i) => pad(cellValue(row[col]), widths[i] ?? 0)).join(" "))
.join("\n");
return `${header}\n${separator}\n${body}`;
}
function formatRecordTable(record) {
const entries = Object.entries(record);
if (entries.length === 0) {
return "";
}
const keyWidth = Math.max(...entries.map(([key]) => key.length));
return entries.map(([key, value]) => `${pad(key, keyWidth)} ${cellValue(value)}`).join("\n");
}
function deriveColumns(records) {
const seen = new Set();
const columns = [];
for (const record of records) {
for (const key of Object.keys(record)) {
if (!seen.has(key)) {
seen.add(key);
columns.push(key);
}
}
}
return columns;
}
function computeColumnWidths(columns, records) {
return columns.map((col) => {
const headerLen = col.length;
const maxValueLen = records.reduce((max, row) => Math.max(max, cellValue(row[col]).length), 0);
return Math.max(headerLen, maxValueLen);
});
}
function cellValue(value) {
if (value === null || value === undefined) {
return "";
}
if (typeof value === "object") {
return JSON.stringify(value);
}
return String(value);
}
function pad(value, width) {
return value.padEnd(width);
}
function toRecord(value) {
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
return value;
}
return { value };
}
//# sourceMappingURL=table-formatter.js.map
{"version":3,"file":"table-formatter.js","sourceRoot":"","sources":["../../src/output/table-formatter.ts"],"names":[],"mappings":"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"}
import { Command } from "commander";
/**
* Build and return the top-level Commander program.
*/
export declare function createProgram(version?: string): Command;
//# sourceMappingURL=program.d.ts.map
{"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAmBvD"}
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Oleksii PELYKH
import { Command } from "commander";
import { authCommand } from "./commands/auth/index.js";
import { completionCommand } from "./commands/completion.js";
import { postCommand } from "./commands/post/index.js";
import { profileCommand } from "./commands/profile/index.js";
import { whoamiCommand } from "./commands/whoami.js";
/**
* Build and return the top-level Commander program.
*/
export function createProgram(version) {
const program = new Command("linkedctl");
program.description("CLI for the LinkedIn API");
if (version !== undefined) {
program.version(version);
}
program.enablePositionalOptions();
program.option("--profile <name>", "profile to use from config file");
program.option("--no-color", "disable color output");
program.addCommand(authCommand());
program.addCommand(completionCommand(program));
program.addCommand(postCommand());
program.addCommand(profileCommand());
program.addCommand(whoamiCommand());
program.addHelpText("after", "\nGet started: linkedctl auth setup");
return program;
}
//# sourceMappingURL=program.js.map
{"version":3,"file":"program.js","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,OAAgB;IAC5C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,WAAW,CAAC,CAAC;IACzC,OAAO,CAAC,WAAW,CAAC,0BAA0B,CAAC,CAAC;IAChD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,CAAC,uBAAuB,EAAE,CAAC;IAClC,OAAO,CAAC,MAAM,CAAC,kBAAkB,EAAE,iCAAiC,CAAC,CAAC;IACtE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,sBAAsB,CAAC,CAAC;IAErD,OAAO,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;IAClC,OAAO,CAAC,UAAU,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/C,OAAO,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;IAClC,OAAO,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC,CAAC;IACrC,OAAO,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;IAEpC,OAAO,CAAC,WAAW,CAAC,OAAO,EAAE,qCAAqC,CAAC,CAAC;IAEpE,OAAO,OAAO,CAAC;AACjB,CAAC"}
# @linkedctl/cli
CLI commands for LinkedIn API integration -- the command-line interface used by [`linkedctl`](https://github.com/alexey-pelykh/linkedctl).
## Installation
```sh
npm install @linkedctl/cli
```
Requires Node.js >= 24.
## Overview
This package provides the CLI command definitions and program setup for LinkedCtl. It includes commands for authentication (`auth`), posting (`post`), profile management (`profile`), and user info (`whoami`).
For full CLI documentation and usage examples, see the [main project](https://github.com/alexey-pelykh/linkedctl).
## License
[AGPL-3.0-only](https://www.gnu.org/licenses/agpl-3.0.txt)
+3
-1

@@ -1,2 +0,4 @@

export {};
export type { OutputFormat } from "./output/index.js";
export { detectFormat, resolveFormat, formatJson, formatTable, formatOutput, isColorEnabled } from "./output/index.js";
export { createProgram } from "./program.js";
//# sourceMappingURL=index.d.ts.map

@@ -1,1 +0,1 @@

{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC"}
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACvH,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Oleksii PELYKH
export {};
export { detectFormat, resolveFormat, formatJson, formatTable, formatOutput, isColorEnabled } from "./output/index.js";
export { createProgram } from "./program.js";
//# sourceMappingURL=index.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,EAAE,CAAC"}
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAGpC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACvH,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
{
"name": "@linkedctl/cli",
"version": "0.0.0",
"version": "0.1.0",
"description": "CLI for LinkedIn API integration",

@@ -29,3 +29,4 @@ "type": "module",

"files": [
"dist"
"dist",
"assets"
],

@@ -42,5 +43,14 @@ "keywords": [

},
"dependencies": {
"commander": "^14.0.3",
"@linkedctl/core": "^0.1.0"
},
"devDependencies": {
"@types/node": "^24",
"eslint": "^9.39.2",
"typescript": "^5.9.3",
"vitest": "^4.0.18"
},
"scripts": {
"clean": "rm -rf dist tsconfig.tsbuildinfo",
"prepack": "cp ../../LICENSE .",
"build": "tsc",

@@ -51,13 +61,3 @@ "typecheck": "tsc --noEmit",

"dev": "tsc --watch"
},
"dependencies": {
"@linkedctl/core": "workspace:^",
"commander": "catalog:"
},
"devDependencies": {
"@types/node": "catalog:",
"eslint": "catalog:",
"typescript": "catalog:",
"vitest": "catalog:"
}
}
}