@getpilfer/cli 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/SKILL.md +1 -1
- package/dist/build-program.js +2 -2
- package/dist/{chunk-GWWE2AMO.js → chunk-2QYZ5OEW.js} +6 -6
- package/dist/{chunk-GWWE2AMO.js.map → chunk-2QYZ5OEW.js.map} +1 -1
- package/dist/{chunk-HJFKOMTC.js → chunk-QH2MMA3M.js} +2 -2
- package/dist/{chunk-HJFKOMTC.js.map → chunk-QH2MMA3M.js.map} +1 -1
- package/dist/{generated-D7S53VGE.js → generated-IFLUY7PB.js} +2 -2
- package/dist/index.js +2 -2
- package/package.json +1 -1
- /package/dist/{generated-D7S53VGE.js.map → generated-IFLUY7PB.js.map} +0 -0
package/README.md
CHANGED
package/SKILL.md
CHANGED
package/dist/build-program.js
CHANGED
|
@@ -4,8 +4,8 @@ import {
|
|
|
4
4
|
createProgramForCLI,
|
|
5
5
|
getProgramForDocs,
|
|
6
6
|
syncRootOptsFromCommand
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-2QYZ5OEW.js";
|
|
8
|
+
import "./chunk-QH2MMA3M.js";
|
|
9
9
|
import "./chunk-GZ4DXDQM.js";
|
|
10
10
|
export {
|
|
11
11
|
createProgram,
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
mergeBody,
|
|
9
9
|
printOutput,
|
|
10
10
|
printStructuredError
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-QH2MMA3M.js";
|
|
12
12
|
import {
|
|
13
13
|
resolveToken
|
|
14
14
|
} from "./chunk-GZ4DXDQM.js";
|
|
@@ -34,7 +34,7 @@ var DUMMY_HELPERS = {
|
|
|
34
34
|
exitWithError: () => {
|
|
35
35
|
throw new Error("Docs generator: action should not run");
|
|
36
36
|
},
|
|
37
|
-
getBaseUrl: () => "https://api.
|
|
37
|
+
getBaseUrl: () => "https://api.getpilfer.com",
|
|
38
38
|
syncRootOptsFromCommand: () => {
|
|
39
39
|
}
|
|
40
40
|
};
|
|
@@ -174,7 +174,7 @@ To use the Pilfer CLI from an AI agent or script:
|
|
|
174
174
|
export PILFER_API_TOKEN="plf_..."
|
|
175
175
|
|
|
176
176
|
2. Optional: override API base URL for local or early deployments:
|
|
177
|
-
export PILFER_API_BASE_URL="https://api.
|
|
177
|
+
export PILFER_API_BASE_URL="https://api.getpilfer.com"
|
|
178
178
|
|
|
179
179
|
3. Verify auth:
|
|
180
180
|
pilfer whoami
|
|
@@ -246,7 +246,7 @@ To use the Pilfer CLI from an AI agent or script:
|
|
|
246
246
|
});
|
|
247
247
|
}
|
|
248
248
|
async function registerGeneratedCommands(program, helpers) {
|
|
249
|
-
const mod = await import("./generated-
|
|
249
|
+
const mod = await import("./generated-IFLUY7PB.js").catch(() => null);
|
|
250
250
|
if (mod?.register) mod.register(program, helpers);
|
|
251
251
|
}
|
|
252
252
|
function registerSourceCommands(program, helpers) {
|
|
@@ -361,7 +361,7 @@ function registerSourceCommands(program, helpers) {
|
|
|
361
361
|
}
|
|
362
362
|
async function createProgram(helpers) {
|
|
363
363
|
const program = new Command();
|
|
364
|
-
program.name("pilfer").description("Pilfer REST API CLI").version(CLI_VERSION).option("-t, --token <token>", "API token (overrides env and config file)").option("-o, --output <format>", "Output format: json | table | csv").option("--base-url <url>", "API base URL (default: https://api.
|
|
364
|
+
program.name("pilfer").description("Pilfer REST API CLI").version(CLI_VERSION).option("-t, --token <token>", "API token (overrides env and config file)").option("-o, --output <format>", "Output format: json | table | csv").option("--base-url <url>", "API base URL (default: https://api.getpilfer.com)").option("--api <url>", "Alias for --base-url").hook("preAction", (thisCommand) => {
|
|
365
365
|
syncRootOptsFromCommand(thisCommand);
|
|
366
366
|
const opts = thisCommand.opts();
|
|
367
367
|
if (opts.output == null || opts.output === "") {
|
|
@@ -404,4 +404,4 @@ export {
|
|
|
404
404
|
createProgramForCLI,
|
|
405
405
|
getProgramForDocs
|
|
406
406
|
};
|
|
407
|
-
//# sourceMappingURL=chunk-
|
|
407
|
+
//# sourceMappingURL=chunk-2QYZ5OEW.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/build-program.ts"],"sourcesContent":["/**\n * Builds the Commander program for the Pilfer CLI.\n * Used by the main entry (index.ts) and by docs/tools that inspect the program.\n */\nimport { createRequire } from \"module\";\nimport { Command } from \"commander\";\n\nimport type { CommandHelpers } from \"./commands/generated/index.js\";\nimport { resolveToken } from \"./lib/auth.js\";\nimport { apiRequest, getBaseUrl } from \"./lib/client.js\";\nimport { coerceBodyFlag } from \"./lib/flag-coercion.js\";\nimport { mergeBody } from \"./lib/merge-body.js\";\nimport {\n formatErrorPayload,\n getDefaultOutputFormat,\n printOutput,\n printStructuredError,\n type OutputFormat,\n} from \"./lib/output.js\";\n\nconst _require = createRequire(import.meta.url);\nconst { version: CLI_VERSION } = _require(\"../package.json\") as {\n version: string;\n};\n\nlet rootOpts: { token?: string; output?: string; baseUrl?: string; api?: string } =\n {};\n\ntype MaybeCommand = Partial<Command> & {\n parent?: MaybeCommand;\n opts?: () => Record<string, unknown>;\n};\n\n/** Call from a subcommand's preAction so rootOpts is set from the root program. */\nexport function syncRootOptsFromCommand(cmd: Command | unknown): void {\n const maybeCommand = cmd as MaybeCommand | null | undefined;\n if (!maybeCommand || typeof maybeCommand !== \"object\") return;\n if (typeof maybeCommand.opts !== \"function\") return;\n\n let root: MaybeCommand = maybeCommand;\n while (root.parent) root = root.parent;\n\n if (typeof root.opts !== \"function\") return;\n rootOpts = root.opts() as typeof rootOpts;\n}\n\nconst DUMMY_HELPERS: CommandHelpers = {\n getOutputFormat: () => \"json\",\n requireToken: () => null,\n exitWithError: () => {\n throw new Error(\"Docs generator: action should not run\");\n },\n getBaseUrl: () => \"https://api.usepilfer.com\",\n syncRootOptsFromCommand: () => {},\n};\n\nfunction addTopLevelCommands(program: Command, helpers: CommandHelpers): void {\n const { getOutputFormat, requireToken, exitWithError } = helpers;\n\n function getRequiredToken(): string {\n const token = requireToken();\n if (!token) exitWithError(401, \"Missing or invalid token. Run: pilfer login\");\n return token as string;\n }\n\n function getOutputFormatFromProgram(_p: Command): OutputFormat {\n const raw = rootOpts.output as string | undefined;\n if (raw === \"json\" || raw === \"table\" || raw === \"csv\") return raw;\n return getDefaultOutputFormat();\n }\n\n function exitWithErrorHandler(\n program: Command,\n status: number,\n message: string,\n ): never {\n const format = getOutputFormatFromProgram(program);\n const payload = formatErrorPayload(status, message);\n printStructuredError(format, payload);\n process.exit(status === 401 || status === 403 ? 1 : 2);\n }\n\n program.action(() => {\n console.log(`\n Welcome to the Pilfer CLI - manage your Pilfer data from the terminal.\n\n Get started\n ----------\n Log in: pilfer login\n Verify: pilfer whoami\n Overview: pilfer status\n\n Resources (list | get | create | update | delete)\n ------------------------------------------------\n organizations projects spaces scouts\n sources assets categories labels views\n\n Examples\n --------\n pilfer organizations list\n pilfer projects create --name \"Studio upgrade\"\n pilfer scouts list --status Shortlist\n pilfer sources list --scout-id scout_123\n\n Help\n ----\n pilfer --help\n pilfer <resource> --help\n`);\n });\n\n program\n .command(\"whoami\")\n .description(\"Verify auth and show current user and token scopes\")\n .action(async () => {\n const token = getRequiredToken();\n const res = await apiRequest<{\n data?: { userId?: string; organizationId?: string | null; scopes?: string[] };\n }>({\n method: \"GET\",\n path: \"me\",\n token,\n baseUrl: rootOpts.baseUrl,\n });\n if (!res.ok) exitWithError(res.status || 401, res.error ?? \"Unauthorized\");\n const data = res.data?.data ?? res.data;\n printOutput(getOutputFormat(), data ?? {}, false);\n });\n\n program\n .command(\"login [token]\")\n .description(\"Store API token (prompt or pass token as argument)\")\n .action(async (tokenArg: string | undefined) => {\n const { saveToken } = await import(\"./lib/auth.js\");\n let token = tokenArg?.trim();\n if (!token) {\n const readline = await import(\"readline\");\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stderr,\n });\n token = await new Promise<string>((resolve) => {\n rl.question(\"API token: \", (answer) => {\n rl.close();\n resolve(answer?.trim() ?? \"\");\n });\n });\n }\n if (!token) {\n console.error(\"No token provided.\");\n process.exit(1);\n }\n const res = await apiRequest({\n method: \"GET\",\n path: \"me\",\n token,\n baseUrl: rootOpts.baseUrl,\n });\n if (!res.ok) {\n console.error(\"Invalid token or API error:\", res.error ?? res.status);\n process.exit(1);\n }\n saveToken(token);\n console.log(\"Logged in successfully.\");\n });\n\n const config = program.command(\"config\").description(\"Persist and inspect CLI config\");\n\n config\n .command(\"show\")\n .description(\"Show stored CLI config\")\n .action(async () => {\n const { getCredentialsPath, resolveStoredBaseUrl } = await import(\n \"./lib/auth.js\"\n );\n const token = resolveToken(rootOpts.token ?? undefined);\n const baseUrl = getBaseUrl(rootOpts.baseUrl ?? rootOpts.api);\n const storedBaseUrl = resolveStoredBaseUrl();\n printOutput(\n getOutputFormat(),\n {\n configPath: getCredentialsPath(),\n tokenConfigured: Boolean(token),\n baseUrl,\n baseUrlSource: rootOpts.baseUrl ?? rootOpts.api\n ? \"flag\"\n : process.env.PILFER_API_BASE_URL\n ? \"env\"\n : storedBaseUrl\n ? \"config\"\n : \"default\",\n },\n false,\n );\n });\n\n config\n .command(\"set-base-url <url>\")\n .alias(\"set-api\")\n .description(\"Persist default API base URL\")\n .action(async (url: string) => {\n const { saveBaseUrl } = await import(\"./lib/auth.js\");\n const normalized = url.trim().replace(/\\/$/, \"\");\n if (!normalized) {\n console.error(\"No base URL provided.\");\n process.exit(1);\n }\n saveBaseUrl(normalized);\n console.log(`Saved API base URL: ${normalized}`);\n });\n\n config\n .command(\"unset-base-url\")\n .alias(\"unset-api\")\n .description(\"Remove persisted API base URL\")\n .action(async () => {\n const { clearBaseUrl } = await import(\"./lib/auth.js\");\n clearBaseUrl();\n console.log(\"Cleared stored API base URL.\");\n });\n\n program\n .command(\"logout\")\n .description(\"Remove stored API token\")\n .action(async () => {\n const { clearCredentials } = await import(\"./lib/auth.js\");\n clearCredentials();\n console.log(\"Logged out.\");\n });\n\n program\n .command(\"setup-agent\")\n .description(\"Print instructions for configuring Pilfer CLI for AI agents\")\n .action(() => {\n console.log(`\nTo use the Pilfer CLI from an AI agent or script:\n\n1. Set your API token:\n export PILFER_API_TOKEN=\"plf_...\"\n\n2. Optional: override API base URL for local or early deployments:\n export PILFER_API_BASE_URL=\"https://api.usepilfer.com\"\n\n3. Verify auth:\n pilfer whoami\n\n4. Commands use the pattern: pilfer <resource> list|get|create|update|delete\n When stdout is not a TTY, output defaults to JSON.\n`);\n });\n\n program\n .command(\"status\")\n .description(\"Situational summary: organizations, projects, spaces, scouts, assets\")\n .action(async () => {\n const token = getRequiredToken();\n const baseUrl = rootOpts.baseUrl;\n const [orgsRes, projectsRes, spacesRes, scoutsRes, assetsRes] =\n await Promise.all([\n apiRequest<{ data?: unknown[] }>({\n method: \"GET\",\n path: \"organizations\",\n token,\n baseUrl,\n }),\n apiRequest<{ data?: unknown[] }>({\n method: \"GET\",\n path: \"projects\",\n token,\n baseUrl,\n }),\n apiRequest<{ data?: unknown[] }>({\n method: \"GET\",\n path: \"spaces\",\n token,\n baseUrl,\n }),\n apiRequest<{ data?: unknown[] }>({\n method: \"GET\",\n path: \"scouts\",\n token,\n baseUrl,\n }),\n apiRequest<{ data?: unknown[] }>({\n method: \"GET\",\n path: \"assets\",\n token,\n baseUrl,\n }),\n ]);\n const unwrap = (res: { ok: boolean; data?: { data?: unknown[] } }) =>\n res.ok && res.data ? (res.data.data ?? []) : [];\n const scouts = unwrap(scoutsRes);\n const scoutStatuses = (scouts as { status?: string }[]).reduce<\n Record<string, number>\n >((acc, scout) => {\n const status = scout.status ?? \"unknown\";\n acc[status] = (acc[status] ?? 0) + 1;\n return acc;\n }, {});\n printOutput(\n getOutputFormat(),\n {\n organizations: unwrap(orgsRes).length,\n projects: unwrap(projectsRes).length,\n spaces: unwrap(spacesRes).length,\n scouts: scouts.length,\n assets: unwrap(assetsRes).length,\n scoutsByStatus: scoutStatuses,\n },\n false,\n );\n });\n\n program.exitOverride((err) => {\n if (\n err.code === \"commander.helpDisplayed\" ||\n err.code === \"commander.version\"\n ) {\n throw err;\n }\n exitWithErrorHandler(program, 2, err.message);\n });\n}\n\nasync function registerGeneratedCommands(\n program: Command,\n helpers: CommandHelpers,\n): Promise<void> {\n const mod = await import(\"./commands/generated/index.js\").catch(() => null);\n if (mod?.register) mod.register(program, helpers);\n}\n\nfunction registerSourceCommands(program: Command, helpers: CommandHelpers): void {\n const { getOutputFormat, requireToken, exitWithError, getBaseUrl } = helpers;\n\n function getRequiredToken(): string {\n const token = requireToken();\n if (!token) exitWithError(401, \"Missing or invalid token. Run: pilfer login\");\n return token as string;\n }\n\n function bodyFromFlags(opts: Record<string, unknown>, isUpdate: boolean) {\n const bodyFromFlags: Record<string, unknown> = {};\n for (const field of [\"url\", \"title\", \"price\", \"imageUrl\", \"notes\", \"starred\"]) {\n const value = opts[field];\n const kind =\n field === \"price\" ? \"number\" : field === \"starred\" ? \"boolean\" : \"string\";\n const parsed = coerceBodyFlag(\n value,\n {\n field,\n flag: `--${field.replace(/([a-z])([A-Z])/g, \"$1-$2\").toLowerCase()}`,\n kind,\n },\n exitWithError,\n );\n if (parsed !== undefined) bodyFromFlags[field] = parsed;\n }\n if (!isUpdate && Object.keys(bodyFromFlags).length === 0 && !opts.body) {\n exitWithError(400, \"Provide source fields or --body JSON\");\n }\n return mergeBody(bodyFromFlags, opts.body as string | undefined);\n }\n\n const sources = program.command(\"sources\").description(\"Manage scout sources\");\n\n sources\n .command(\"list\")\n .description(\"List sources for a scout\")\n .requiredOption(\"--scout-id <id>\", \"Scout id\")\n .option(\"--limit <n>\", \"Max results\")\n .option(\"--offset <n>\", \"Skip n results\")\n .hook(\"preAction\", (thisCommand: Command) => {\n helpers.syncRootOptsFromCommand(thisCommand);\n })\n .action(async (opts: { scoutId: string; limit?: string; offset?: string }) => {\n const token = getRequiredToken();\n const res = await apiRequest({\n method: \"GET\",\n path: `scouts/${encodeURIComponent(opts.scoutId)}/sources`,\n token,\n baseUrl: getBaseUrl(),\n query: { limit: opts.limit, offset: opts.offset },\n });\n if (!res.ok) exitWithError(res.status || 500, res.error ?? \"Request failed\");\n const data = (res.data as { data?: unknown[] })?.data ?? [];\n printOutput(getOutputFormat(), data, false);\n });\n\n sources\n .command(\"get <sourceId>\")\n .description(\"Get one source by id\")\n .requiredOption(\"--scout-id <id>\", \"Scout id\")\n .hook(\"preAction\", (thisCommand: Command) => {\n helpers.syncRootOptsFromCommand(thisCommand);\n })\n .action(async (sourceId: string, opts: { scoutId: string }) => {\n const token = getRequiredToken();\n const res = await apiRequest({\n method: \"GET\",\n path: `scouts/${encodeURIComponent(opts.scoutId)}/sources/${encodeURIComponent(\n sourceId,\n )}`,\n token,\n baseUrl: getBaseUrl(),\n });\n if (!res.ok) exitWithError(res.status || 500, res.error ?? \"Request failed\");\n const data = (res.data as { data?: unknown })?.data ?? res.data;\n printOutput(getOutputFormat(), data ?? {}, false);\n });\n\n sources\n .command(\"create\")\n .description(\"Create a source for a scout\")\n .requiredOption(\"--scout-id <id>\", \"Scout id\")\n .option(\"--url <value>\", \"url\")\n .option(\"--title <value>\", \"title\")\n .option(\"--price <value>\", \"price\")\n .option(\"--image-url <value>\", \"imageUrl\")\n .option(\"--notes <value>\", \"notes\")\n .option(\"--starred <value>\", \"starred\")\n .option(\"--body <json>\", \"Request body JSON (merged with flags)\")\n .hook(\"preAction\", (thisCommand: Command) => {\n helpers.syncRootOptsFromCommand(thisCommand);\n })\n .action(async (opts) => {\n const token = getRequiredToken();\n const res = await apiRequest({\n method: \"POST\",\n path: `scouts/${encodeURIComponent(opts.scoutId)}/sources`,\n token,\n baseUrl: getBaseUrl(),\n body: bodyFromFlags(opts, false),\n });\n if (!res.ok) exitWithError(res.status || 500, res.error ?? \"Request failed\");\n const data = (res.data as { data?: unknown })?.data ?? res.data;\n printOutput(getOutputFormat(), data ?? {}, false);\n });\n\n sources\n .command(\"update <sourceId>\")\n .description(\"Update a source\")\n .requiredOption(\"--scout-id <id>\", \"Scout id\")\n .option(\"--url <value>\", \"url\")\n .option(\"--title <value>\", \"title\")\n .option(\"--price <value>\", \"price\")\n .option(\"--image-url <value>\", \"imageUrl\")\n .option(\"--notes <value>\", \"notes\")\n .option(\"--starred <value>\", \"starred\")\n .option(\"--body <json>\", \"Request body JSON (merged with flags)\")\n .hook(\"preAction\", (thisCommand: Command) => {\n helpers.syncRootOptsFromCommand(thisCommand);\n })\n .action(async (sourceId: string, opts) => {\n const token = getRequiredToken();\n const res = await apiRequest({\n method: \"PATCH\",\n path: `scouts/${encodeURIComponent(opts.scoutId)}/sources/${encodeURIComponent(\n sourceId,\n )}`,\n token,\n baseUrl: getBaseUrl(),\n body: bodyFromFlags(opts, true),\n });\n if (!res.ok) exitWithError(res.status || 500, res.error ?? \"Request failed\");\n const data = (res.data as { data?: unknown })?.data ?? res.data;\n printOutput(getOutputFormat(), data ?? {}, false);\n });\n\n sources\n .command(\"delete <sourceId>\")\n .description(\"Delete a source\")\n .requiredOption(\"--scout-id <id>\", \"Scout id\")\n .hook(\"preAction\", (thisCommand: Command) => {\n helpers.syncRootOptsFromCommand(thisCommand);\n })\n .action(async (sourceId: string, opts: { scoutId: string }) => {\n const token = getRequiredToken();\n const res = await apiRequest({\n method: \"DELETE\",\n path: `scouts/${encodeURIComponent(opts.scoutId)}/sources/${encodeURIComponent(\n sourceId,\n )}`,\n token,\n baseUrl: getBaseUrl(),\n });\n if (!res.ok) exitWithError(res.status || 500, res.error ?? \"Request failed\");\n if (getOutputFormat() === \"json\") {\n console.log(JSON.stringify({ data: null, deleted: true }));\n }\n });\n}\n\nexport async function createProgram(helpers?: CommandHelpers): Promise<Command> {\n const program = new Command();\n\n program\n .name(\"pilfer\")\n .description(\"Pilfer REST API CLI\")\n .version(CLI_VERSION)\n .option(\"-t, --token <token>\", \"API token (overrides env and config file)\")\n .option(\"-o, --output <format>\", \"Output format: json | table | csv\")\n .option(\"--base-url <url>\", \"API base URL (default: https://api.usepilfer.com)\")\n .option(\"--api <url>\", \"Alias for --base-url\")\n .hook(\"preAction\", (thisCommand) => {\n syncRootOptsFromCommand(thisCommand);\n const opts = thisCommand.opts();\n if (opts.output == null || opts.output === \"\") {\n thisCommand.setOptionValue(\"output\", getDefaultOutputFormat());\n }\n });\n\n const resolvedHelpers = helpers ?? DUMMY_HELPERS;\n addTopLevelCommands(program, resolvedHelpers);\n await registerGeneratedCommands(program, resolvedHelpers);\n registerSourceCommands(program, resolvedHelpers);\n\n return program;\n}\n\nexport async function createProgramForCLI(): Promise<Command> {\n const realHelpers: CommandHelpers = {\n getOutputFormat: () => {\n const raw = rootOpts.output as string | undefined;\n if (raw === \"json\" || raw === \"table\" || raw === \"csv\") return raw;\n return getDefaultOutputFormat();\n },\n requireToken: () => resolveToken(rootOpts.token ?? undefined),\n exitWithError: (status: number, message: string): never => {\n const raw = rootOpts.output as string | undefined;\n const format: OutputFormat =\n raw === \"json\" || raw === \"table\" || raw === \"csv\"\n ? raw\n : getDefaultOutputFormat();\n const payload = formatErrorPayload(status, message);\n printStructuredError(format, payload);\n process.exit(status === 401 || status === 403 ? 1 : 2);\n },\n getBaseUrl: () => getBaseUrl(rootOpts.baseUrl ?? rootOpts.api),\n syncRootOptsFromCommand,\n };\n return createProgram(realHelpers);\n}\n\nexport async function getProgramForDocs(): Promise<Command> {\n return createProgram();\n}\n"],"mappings":"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","names":["program","getBaseUrl","bodyFromFlags"]}
|
|
1
|
+
{"version":3,"sources":["../src/build-program.ts"],"sourcesContent":["/**\n * Builds the Commander program for the Pilfer CLI.\n * Used by the main entry (index.ts) and by docs/tools that inspect the program.\n */\nimport { createRequire } from \"module\";\nimport { Command } from \"commander\";\n\nimport type { CommandHelpers } from \"./commands/generated/index.js\";\nimport { resolveToken } from \"./lib/auth.js\";\nimport { apiRequest, getBaseUrl } from \"./lib/client.js\";\nimport { coerceBodyFlag } from \"./lib/flag-coercion.js\";\nimport { mergeBody } from \"./lib/merge-body.js\";\nimport {\n formatErrorPayload,\n getDefaultOutputFormat,\n printOutput,\n printStructuredError,\n type OutputFormat,\n} from \"./lib/output.js\";\n\nconst _require = createRequire(import.meta.url);\nconst { version: CLI_VERSION } = _require(\"../package.json\") as {\n version: string;\n};\n\nlet rootOpts: { token?: string; output?: string; baseUrl?: string; api?: string } =\n {};\n\ntype MaybeCommand = Partial<Command> & {\n parent?: MaybeCommand;\n opts?: () => Record<string, unknown>;\n};\n\n/** Call from a subcommand's preAction so rootOpts is set from the root program. */\nexport function syncRootOptsFromCommand(cmd: Command | unknown): void {\n const maybeCommand = cmd as MaybeCommand | null | undefined;\n if (!maybeCommand || typeof maybeCommand !== \"object\") return;\n if (typeof maybeCommand.opts !== \"function\") return;\n\n let root: MaybeCommand = maybeCommand;\n while (root.parent) root = root.parent;\n\n if (typeof root.opts !== \"function\") return;\n rootOpts = root.opts() as typeof rootOpts;\n}\n\nconst DUMMY_HELPERS: CommandHelpers = {\n getOutputFormat: () => \"json\",\n requireToken: () => null,\n exitWithError: () => {\n throw new Error(\"Docs generator: action should not run\");\n },\n getBaseUrl: () => \"https://api.getpilfer.com\",\n syncRootOptsFromCommand: () => {},\n};\n\nfunction addTopLevelCommands(program: Command, helpers: CommandHelpers): void {\n const { getOutputFormat, requireToken, exitWithError } = helpers;\n\n function getRequiredToken(): string {\n const token = requireToken();\n if (!token) exitWithError(401, \"Missing or invalid token. Run: pilfer login\");\n return token as string;\n }\n\n function getOutputFormatFromProgram(_p: Command): OutputFormat {\n const raw = rootOpts.output as string | undefined;\n if (raw === \"json\" || raw === \"table\" || raw === \"csv\") return raw;\n return getDefaultOutputFormat();\n }\n\n function exitWithErrorHandler(\n program: Command,\n status: number,\n message: string,\n ): never {\n const format = getOutputFormatFromProgram(program);\n const payload = formatErrorPayload(status, message);\n printStructuredError(format, payload);\n process.exit(status === 401 || status === 403 ? 1 : 2);\n }\n\n program.action(() => {\n console.log(`\n Welcome to the Pilfer CLI - manage your Pilfer data from the terminal.\n\n Get started\n ----------\n Log in: pilfer login\n Verify: pilfer whoami\n Overview: pilfer status\n\n Resources (list | get | create | update | delete)\n ------------------------------------------------\n organizations projects spaces scouts\n sources assets categories labels views\n\n Examples\n --------\n pilfer organizations list\n pilfer projects create --name \"Studio upgrade\"\n pilfer scouts list --status Shortlist\n pilfer sources list --scout-id scout_123\n\n Help\n ----\n pilfer --help\n pilfer <resource> --help\n`);\n });\n\n program\n .command(\"whoami\")\n .description(\"Verify auth and show current user and token scopes\")\n .action(async () => {\n const token = getRequiredToken();\n const res = await apiRequest<{\n data?: { userId?: string; organizationId?: string | null; scopes?: string[] };\n }>({\n method: \"GET\",\n path: \"me\",\n token,\n baseUrl: rootOpts.baseUrl,\n });\n if (!res.ok) exitWithError(res.status || 401, res.error ?? \"Unauthorized\");\n const data = res.data?.data ?? res.data;\n printOutput(getOutputFormat(), data ?? {}, false);\n });\n\n program\n .command(\"login [token]\")\n .description(\"Store API token (prompt or pass token as argument)\")\n .action(async (tokenArg: string | undefined) => {\n const { saveToken } = await import(\"./lib/auth.js\");\n let token = tokenArg?.trim();\n if (!token) {\n const readline = await import(\"readline\");\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stderr,\n });\n token = await new Promise<string>((resolve) => {\n rl.question(\"API token: \", (answer) => {\n rl.close();\n resolve(answer?.trim() ?? \"\");\n });\n });\n }\n if (!token) {\n console.error(\"No token provided.\");\n process.exit(1);\n }\n const res = await apiRequest({\n method: \"GET\",\n path: \"me\",\n token,\n baseUrl: rootOpts.baseUrl,\n });\n if (!res.ok) {\n console.error(\"Invalid token or API error:\", res.error ?? res.status);\n process.exit(1);\n }\n saveToken(token);\n console.log(\"Logged in successfully.\");\n });\n\n const config = program.command(\"config\").description(\"Persist and inspect CLI config\");\n\n config\n .command(\"show\")\n .description(\"Show stored CLI config\")\n .action(async () => {\n const { getCredentialsPath, resolveStoredBaseUrl } = await import(\n \"./lib/auth.js\"\n );\n const token = resolveToken(rootOpts.token ?? undefined);\n const baseUrl = getBaseUrl(rootOpts.baseUrl ?? rootOpts.api);\n const storedBaseUrl = resolveStoredBaseUrl();\n printOutput(\n getOutputFormat(),\n {\n configPath: getCredentialsPath(),\n tokenConfigured: Boolean(token),\n baseUrl,\n baseUrlSource: rootOpts.baseUrl ?? rootOpts.api\n ? \"flag\"\n : process.env.PILFER_API_BASE_URL\n ? \"env\"\n : storedBaseUrl\n ? \"config\"\n : \"default\",\n },\n false,\n );\n });\n\n config\n .command(\"set-base-url <url>\")\n .alias(\"set-api\")\n .description(\"Persist default API base URL\")\n .action(async (url: string) => {\n const { saveBaseUrl } = await import(\"./lib/auth.js\");\n const normalized = url.trim().replace(/\\/$/, \"\");\n if (!normalized) {\n console.error(\"No base URL provided.\");\n process.exit(1);\n }\n saveBaseUrl(normalized);\n console.log(`Saved API base URL: ${normalized}`);\n });\n\n config\n .command(\"unset-base-url\")\n .alias(\"unset-api\")\n .description(\"Remove persisted API base URL\")\n .action(async () => {\n const { clearBaseUrl } = await import(\"./lib/auth.js\");\n clearBaseUrl();\n console.log(\"Cleared stored API base URL.\");\n });\n\n program\n .command(\"logout\")\n .description(\"Remove stored API token\")\n .action(async () => {\n const { clearCredentials } = await import(\"./lib/auth.js\");\n clearCredentials();\n console.log(\"Logged out.\");\n });\n\n program\n .command(\"setup-agent\")\n .description(\"Print instructions for configuring Pilfer CLI for AI agents\")\n .action(() => {\n console.log(`\nTo use the Pilfer CLI from an AI agent or script:\n\n1. Set your API token:\n export PILFER_API_TOKEN=\"plf_...\"\n\n2. Optional: override API base URL for local or early deployments:\n export PILFER_API_BASE_URL=\"https://api.getpilfer.com\"\n\n3. Verify auth:\n pilfer whoami\n\n4. Commands use the pattern: pilfer <resource> list|get|create|update|delete\n When stdout is not a TTY, output defaults to JSON.\n`);\n });\n\n program\n .command(\"status\")\n .description(\"Situational summary: organizations, projects, spaces, scouts, assets\")\n .action(async () => {\n const token = getRequiredToken();\n const baseUrl = rootOpts.baseUrl;\n const [orgsRes, projectsRes, spacesRes, scoutsRes, assetsRes] =\n await Promise.all([\n apiRequest<{ data?: unknown[] }>({\n method: \"GET\",\n path: \"organizations\",\n token,\n baseUrl,\n }),\n apiRequest<{ data?: unknown[] }>({\n method: \"GET\",\n path: \"projects\",\n token,\n baseUrl,\n }),\n apiRequest<{ data?: unknown[] }>({\n method: \"GET\",\n path: \"spaces\",\n token,\n baseUrl,\n }),\n apiRequest<{ data?: unknown[] }>({\n method: \"GET\",\n path: \"scouts\",\n token,\n baseUrl,\n }),\n apiRequest<{ data?: unknown[] }>({\n method: \"GET\",\n path: \"assets\",\n token,\n baseUrl,\n }),\n ]);\n const unwrap = (res: { ok: boolean; data?: { data?: unknown[] } }) =>\n res.ok && res.data ? (res.data.data ?? []) : [];\n const scouts = unwrap(scoutsRes);\n const scoutStatuses = (scouts as { status?: string }[]).reduce<\n Record<string, number>\n >((acc, scout) => {\n const status = scout.status ?? \"unknown\";\n acc[status] = (acc[status] ?? 0) + 1;\n return acc;\n }, {});\n printOutput(\n getOutputFormat(),\n {\n organizations: unwrap(orgsRes).length,\n projects: unwrap(projectsRes).length,\n spaces: unwrap(spacesRes).length,\n scouts: scouts.length,\n assets: unwrap(assetsRes).length,\n scoutsByStatus: scoutStatuses,\n },\n false,\n );\n });\n\n program.exitOverride((err) => {\n if (\n err.code === \"commander.helpDisplayed\" ||\n err.code === \"commander.version\"\n ) {\n throw err;\n }\n exitWithErrorHandler(program, 2, err.message);\n });\n}\n\nasync function registerGeneratedCommands(\n program: Command,\n helpers: CommandHelpers,\n): Promise<void> {\n const mod = await import(\"./commands/generated/index.js\").catch(() => null);\n if (mod?.register) mod.register(program, helpers);\n}\n\nfunction registerSourceCommands(program: Command, helpers: CommandHelpers): void {\n const { getOutputFormat, requireToken, exitWithError, getBaseUrl } = helpers;\n\n function getRequiredToken(): string {\n const token = requireToken();\n if (!token) exitWithError(401, \"Missing or invalid token. Run: pilfer login\");\n return token as string;\n }\n\n function bodyFromFlags(opts: Record<string, unknown>, isUpdate: boolean) {\n const bodyFromFlags: Record<string, unknown> = {};\n for (const field of [\"url\", \"title\", \"price\", \"imageUrl\", \"notes\", \"starred\"]) {\n const value = opts[field];\n const kind =\n field === \"price\" ? \"number\" : field === \"starred\" ? \"boolean\" : \"string\";\n const parsed = coerceBodyFlag(\n value,\n {\n field,\n flag: `--${field.replace(/([a-z])([A-Z])/g, \"$1-$2\").toLowerCase()}`,\n kind,\n },\n exitWithError,\n );\n if (parsed !== undefined) bodyFromFlags[field] = parsed;\n }\n if (!isUpdate && Object.keys(bodyFromFlags).length === 0 && !opts.body) {\n exitWithError(400, \"Provide source fields or --body JSON\");\n }\n return mergeBody(bodyFromFlags, opts.body as string | undefined);\n }\n\n const sources = program.command(\"sources\").description(\"Manage scout sources\");\n\n sources\n .command(\"list\")\n .description(\"List sources for a scout\")\n .requiredOption(\"--scout-id <id>\", \"Scout id\")\n .option(\"--limit <n>\", \"Max results\")\n .option(\"--offset <n>\", \"Skip n results\")\n .hook(\"preAction\", (thisCommand: Command) => {\n helpers.syncRootOptsFromCommand(thisCommand);\n })\n .action(async (opts: { scoutId: string; limit?: string; offset?: string }) => {\n const token = getRequiredToken();\n const res = await apiRequest({\n method: \"GET\",\n path: `scouts/${encodeURIComponent(opts.scoutId)}/sources`,\n token,\n baseUrl: getBaseUrl(),\n query: { limit: opts.limit, offset: opts.offset },\n });\n if (!res.ok) exitWithError(res.status || 500, res.error ?? \"Request failed\");\n const data = (res.data as { data?: unknown[] })?.data ?? [];\n printOutput(getOutputFormat(), data, false);\n });\n\n sources\n .command(\"get <sourceId>\")\n .description(\"Get one source by id\")\n .requiredOption(\"--scout-id <id>\", \"Scout id\")\n .hook(\"preAction\", (thisCommand: Command) => {\n helpers.syncRootOptsFromCommand(thisCommand);\n })\n .action(async (sourceId: string, opts: { scoutId: string }) => {\n const token = getRequiredToken();\n const res = await apiRequest({\n method: \"GET\",\n path: `scouts/${encodeURIComponent(opts.scoutId)}/sources/${encodeURIComponent(\n sourceId,\n )}`,\n token,\n baseUrl: getBaseUrl(),\n });\n if (!res.ok) exitWithError(res.status || 500, res.error ?? \"Request failed\");\n const data = (res.data as { data?: unknown })?.data ?? res.data;\n printOutput(getOutputFormat(), data ?? {}, false);\n });\n\n sources\n .command(\"create\")\n .description(\"Create a source for a scout\")\n .requiredOption(\"--scout-id <id>\", \"Scout id\")\n .option(\"--url <value>\", \"url\")\n .option(\"--title <value>\", \"title\")\n .option(\"--price <value>\", \"price\")\n .option(\"--image-url <value>\", \"imageUrl\")\n .option(\"--notes <value>\", \"notes\")\n .option(\"--starred <value>\", \"starred\")\n .option(\"--body <json>\", \"Request body JSON (merged with flags)\")\n .hook(\"preAction\", (thisCommand: Command) => {\n helpers.syncRootOptsFromCommand(thisCommand);\n })\n .action(async (opts) => {\n const token = getRequiredToken();\n const res = await apiRequest({\n method: \"POST\",\n path: `scouts/${encodeURIComponent(opts.scoutId)}/sources`,\n token,\n baseUrl: getBaseUrl(),\n body: bodyFromFlags(opts, false),\n });\n if (!res.ok) exitWithError(res.status || 500, res.error ?? \"Request failed\");\n const data = (res.data as { data?: unknown })?.data ?? res.data;\n printOutput(getOutputFormat(), data ?? {}, false);\n });\n\n sources\n .command(\"update <sourceId>\")\n .description(\"Update a source\")\n .requiredOption(\"--scout-id <id>\", \"Scout id\")\n .option(\"--url <value>\", \"url\")\n .option(\"--title <value>\", \"title\")\n .option(\"--price <value>\", \"price\")\n .option(\"--image-url <value>\", \"imageUrl\")\n .option(\"--notes <value>\", \"notes\")\n .option(\"--starred <value>\", \"starred\")\n .option(\"--body <json>\", \"Request body JSON (merged with flags)\")\n .hook(\"preAction\", (thisCommand: Command) => {\n helpers.syncRootOptsFromCommand(thisCommand);\n })\n .action(async (sourceId: string, opts) => {\n const token = getRequiredToken();\n const res = await apiRequest({\n method: \"PATCH\",\n path: `scouts/${encodeURIComponent(opts.scoutId)}/sources/${encodeURIComponent(\n sourceId,\n )}`,\n token,\n baseUrl: getBaseUrl(),\n body: bodyFromFlags(opts, true),\n });\n if (!res.ok) exitWithError(res.status || 500, res.error ?? \"Request failed\");\n const data = (res.data as { data?: unknown })?.data ?? res.data;\n printOutput(getOutputFormat(), data ?? {}, false);\n });\n\n sources\n .command(\"delete <sourceId>\")\n .description(\"Delete a source\")\n .requiredOption(\"--scout-id <id>\", \"Scout id\")\n .hook(\"preAction\", (thisCommand: Command) => {\n helpers.syncRootOptsFromCommand(thisCommand);\n })\n .action(async (sourceId: string, opts: { scoutId: string }) => {\n const token = getRequiredToken();\n const res = await apiRequest({\n method: \"DELETE\",\n path: `scouts/${encodeURIComponent(opts.scoutId)}/sources/${encodeURIComponent(\n sourceId,\n )}`,\n token,\n baseUrl: getBaseUrl(),\n });\n if (!res.ok) exitWithError(res.status || 500, res.error ?? \"Request failed\");\n if (getOutputFormat() === \"json\") {\n console.log(JSON.stringify({ data: null, deleted: true }));\n }\n });\n}\n\nexport async function createProgram(helpers?: CommandHelpers): Promise<Command> {\n const program = new Command();\n\n program\n .name(\"pilfer\")\n .description(\"Pilfer REST API CLI\")\n .version(CLI_VERSION)\n .option(\"-t, --token <token>\", \"API token (overrides env and config file)\")\n .option(\"-o, --output <format>\", \"Output format: json | table | csv\")\n .option(\"--base-url <url>\", \"API base URL (default: https://api.getpilfer.com)\")\n .option(\"--api <url>\", \"Alias for --base-url\")\n .hook(\"preAction\", (thisCommand) => {\n syncRootOptsFromCommand(thisCommand);\n const opts = thisCommand.opts();\n if (opts.output == null || opts.output === \"\") {\n thisCommand.setOptionValue(\"output\", getDefaultOutputFormat());\n }\n });\n\n const resolvedHelpers = helpers ?? DUMMY_HELPERS;\n addTopLevelCommands(program, resolvedHelpers);\n await registerGeneratedCommands(program, resolvedHelpers);\n registerSourceCommands(program, resolvedHelpers);\n\n return program;\n}\n\nexport async function createProgramForCLI(): Promise<Command> {\n const realHelpers: CommandHelpers = {\n getOutputFormat: () => {\n const raw = rootOpts.output as string | undefined;\n if (raw === \"json\" || raw === \"table\" || raw === \"csv\") return raw;\n return getDefaultOutputFormat();\n },\n requireToken: () => resolveToken(rootOpts.token ?? undefined),\n exitWithError: (status: number, message: string): never => {\n const raw = rootOpts.output as string | undefined;\n const format: OutputFormat =\n raw === \"json\" || raw === \"table\" || raw === \"csv\"\n ? raw\n : getDefaultOutputFormat();\n const payload = formatErrorPayload(status, message);\n printStructuredError(format, payload);\n process.exit(status === 401 || status === 403 ? 1 : 2);\n },\n getBaseUrl: () => getBaseUrl(rootOpts.baseUrl ?? rootOpts.api),\n syncRootOptsFromCommand,\n };\n return createProgram(realHelpers);\n}\n\nexport async function getProgramForDocs(): Promise<Command> {\n return createProgram();\n}\n"],"mappings":"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","names":["program","getBaseUrl","bodyFromFlags"]}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-GZ4DXDQM.js";
|
|
5
5
|
|
|
6
6
|
// src/lib/client.ts
|
|
7
|
-
var DEFAULT_BASE_URL = "https://api.
|
|
7
|
+
var DEFAULT_BASE_URL = "https://api.getpilfer.com";
|
|
8
8
|
function getBaseUrl(override) {
|
|
9
9
|
const env = process.env.PILFER_API_BASE_URL;
|
|
10
10
|
const stored = resolveStoredBaseUrl();
|
|
@@ -278,4 +278,4 @@ export {
|
|
|
278
278
|
printOutput,
|
|
279
279
|
printStructuredError
|
|
280
280
|
};
|
|
281
|
-
//# sourceMappingURL=chunk-
|
|
281
|
+
//# sourceMappingURL=chunk-QH2MMA3M.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/client.ts","../src/lib/flag-coercion.ts","../src/lib/merge-body.ts","../src/lib/output.ts"],"sourcesContent":["import { resolveStoredBaseUrl } from \"./auth.js\";\n\nconst DEFAULT_BASE_URL = \"https://api.usepilfer.com\";\n\nexport function getBaseUrl(override?: string): string {\n const env = process.env.PILFER_API_BASE_URL;\n const stored = resolveStoredBaseUrl();\n const base = override ?? env ?? stored ?? DEFAULT_BASE_URL;\n return base.replace(/\\/$/, \"\");\n}\n\nexport interface RequestOptions {\n method: \"GET\" | \"POST\" | \"PATCH\" | \"DELETE\";\n path: string;\n token: string | null;\n baseUrl?: string;\n query?: Record<string, string | number | undefined>;\n body?: unknown;\n}\n\nexport interface ApiResponse<T = unknown> {\n ok: boolean;\n status: number;\n data?: T;\n error?: string;\n headers?: Headers;\n}\n\nconst RETRYABLE_STATUSES = new Set([502, 503, 504]);\nconst GET_MAX_ATTEMPTS = 3;\nconst GET_RETRY_BASE_DELAY_MS = 150;\n\nfunction shouldRetryRequest(method: RequestOptions[\"method\"], response: ApiResponse<unknown>, attempt: number): boolean {\n if (method !== \"GET\") return false;\n if (attempt >= GET_MAX_ATTEMPTS) return false;\n if (response.status === 0) return true;\n return RETRYABLE_STATUSES.has(response.status);\n}\n\nfunction getRetryDelayMs(attempt: number): number {\n const exp = GET_RETRY_BASE_DELAY_MS * Math.pow(2, Math.max(0, attempt - 1));\n const jitter = Math.floor(Math.random() * 50);\n return exp + jitter;\n}\n\nasync function sleep(ms: number): Promise<void> {\n await new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Call the Pilfer REST API. Path should be relative to /api/v1 (e.g. \"me\", \"projects\", \"projects/123\").\n */\nexport async function apiRequest<T = unknown>(\n options: RequestOptions,\n): Promise<ApiResponse<T>> {\n const base = getBaseUrl(options.baseUrl);\n const url = new URL(`/api/v1/${options.path.replace(/^\\//, \"\")}`, base);\n if (options.query) {\n for (const [k, v] of Object.entries(options.query)) {\n if (v !== undefined && v !== \"\") url.searchParams.set(k, String(v));\n }\n }\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${options.token ?? \"\"}`,\n \"Content-Type\": \"application/json\",\n };\n\n const init: RequestInit = {\n method: options.method,\n headers,\n };\n if (\n options.body !== undefined &&\n options.method !== \"GET\"\n ) {\n init.body = JSON.stringify(options.body);\n }\n\n for (let attempt = 1; ; attempt++) {\n const response = await doRequest<T>(url.toString(), init);\n if (!shouldRetryRequest(options.method, response, attempt)) {\n return response;\n }\n await sleep(getRetryDelayMs(attempt));\n }\n}\n\nasync function doRequest<T>(url: string, init: RequestInit): Promise<ApiResponse<T>> {\n let res: Response;\n try {\n res = await fetch(url, init);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { ok: false, status: 0, error: message };\n }\n\n let data: T | undefined;\n const text = await res.text();\n if (text) {\n try {\n data = JSON.parse(text) as T;\n } catch {\n data = undefined;\n }\n }\n\n return {\n ok: res.ok,\n status: res.status,\n data,\n error: !res.ok\n ? extractErrorMessage(data)\n : undefined,\n headers: res.headers,\n };\n}\n\nfunction extractErrorMessage(data: unknown): string | undefined {\n if (data == null || typeof data !== \"object\") return undefined;\n\n const body = data as {\n error?: unknown;\n message?: unknown;\n requestId?: unknown;\n };\n\n const baseMessage =\n typeof body.error === \"string\"\n ? body.error\n : typeof body.message === \"string\"\n ? body.message\n : undefined;\n if (baseMessage == null) return undefined;\n\n if (typeof body.requestId === \"string\" && body.requestId.trim() !== \"\") {\n return `${baseMessage} (requestId: ${body.requestId})`;\n }\n return baseMessage;\n}\n","type ExitWithError = (status: number, message: string) => never;\n\ntype PrimitiveKind = \"string\" | \"number\" | \"boolean\";\n\ninterface CoerceConfig {\n field: string;\n flag: string;\n kind: PrimitiveKind;\n allowNull?: boolean;\n allowDateTime?: boolean;\n}\n\nfunction fail(exitWithError: ExitWithError, message: string): never {\n return exitWithError(400, message);\n}\n\nfunction parseBoolean(\n raw: string,\n config: CoerceConfig,\n exitWithError: ExitWithError,\n): boolean {\n const value = raw.trim().toLowerCase();\n if ([\"true\", \"1\", \"yes\", \"y\", \"on\"].includes(value)) return true;\n if ([\"false\", \"0\", \"no\", \"n\", \"off\"].includes(value)) return false;\n return fail(\n exitWithError,\n `Invalid value for ${config.flag} (${config.field}): expected boolean but got \"${raw}\"`,\n );\n}\n\nfunction parseNumber(\n raw: string,\n config: CoerceConfig,\n exitWithError: ExitWithError,\n): number {\n const trimmed = raw.trim();\n const asNumber = Number(trimmed);\n if (Number.isFinite(asNumber)) return asNumber;\n\n if (config.allowDateTime) {\n const asDate = Date.parse(trimmed);\n if (Number.isFinite(asDate)) return asDate;\n }\n\n return fail(\n exitWithError,\n `Invalid value for ${config.flag} (${config.field}): expected number${config.allowDateTime ? \" or ISO datetime\" : \"\"} but got \"${raw}\"`,\n );\n}\n\nexport function coerceBodyFlag(\n raw: unknown,\n config: CoerceConfig,\n exitWithError: ExitWithError,\n): unknown {\n if (raw == null) return undefined;\n const value = String(raw);\n const trimmed = value.trim();\n\n if (config.allowNull && trimmed.toLowerCase() === \"null\") {\n return null;\n }\n\n if (config.kind === \"string\") return value;\n if (config.kind === \"boolean\") return parseBoolean(value, config, exitWithError);\n return parseNumber(value, config, exitWithError);\n}\n\nexport function coerceQueryFlag(\n raw: unknown,\n config: CoerceConfig,\n exitWithError: ExitWithError,\n): string | number {\n if (raw == null) {\n return fail(\n exitWithError,\n `Missing value for ${config.flag} (${config.field})`,\n );\n }\n\n const value = String(raw);\n if (config.kind === \"string\") return value;\n if (config.kind === \"boolean\") {\n return parseBoolean(value, config, exitWithError) ? \"true\" : \"false\";\n }\n return parseNumber(value, config, exitWithError);\n}\n","/**\n * Merge optional JSON body (from --body) with object built from flags.\n * Flags override keys in body when both are provided.\n */\nexport function mergeBody(\n bodyFromFlags: Record<string, unknown>,\n bodyOption: string | undefined,\n): Record<string, unknown> {\n let base: Record<string, unknown> = {};\n if (bodyOption?.trim()) {\n try {\n base = JSON.parse(bodyOption) as Record<string, unknown>;\n } catch {\n // ignore invalid JSON\n }\n }\n return { ...base, ...bodyFromFlags };\n}\n","export type OutputFormat = \"json\" | \"table\" | \"csv\";\n\nexport function getDefaultOutputFormat(): OutputFormat {\n return process.stdout.isTTY ? \"table\" : \"json\";\n}\n\nexport interface ErrorPayload {\n error: true;\n status: number;\n code: string;\n message: string;\n}\n\nexport function formatErrorPayload(status: number, message: string): ErrorPayload {\n const code = statusToCode(status);\n return { error: true, status, code, message };\n}\n\nfunction statusToCode(status: number): string {\n if (status === 401) return \"UNAUTHORIZED\";\n if (status === 403) return \"FORBIDDEN\";\n if (status === 404) return \"NOT_FOUND\";\n if (status === 400) return \"BAD_REQUEST\";\n if (status === 429) return \"TOO_MANY_REQUESTS\";\n if (status >= 500) return \"SERVER_ERROR\";\n return \"ERROR\";\n}\n\n/**\n * Print result to stdout according to format. For list responses, pass the data array.\n * For single resource, pass the data object.\n */\nexport function printOutput(\n format: OutputFormat,\n data: unknown,\n isError = false,\n): void {\n if (format === \"json\") {\n const out = Array.isArray(data)\n ? { data }\n : typeof data === \"object\" && data !== null && \"data\" in data\n ? data\n : { data };\n console.log(JSON.stringify(out, null, 0));\n return;\n }\n if (format === \"table\") {\n printTable(data);\n return;\n }\n if (format === \"csv\") {\n printCsv(data);\n return;\n }\n console.log(JSON.stringify(data));\n}\n\nfunction getRows(data: unknown): Record<string, unknown>[] {\n if (Array.isArray(data)) return data as Record<string, unknown>[];\n if (typeof data === \"object\" && data !== null && \"data\" in data) {\n const d = (data as { data: unknown }).data;\n if (Array.isArray(d)) return d as Record<string, unknown>[];\n if (typeof d === \"object\" && d !== null) return [d as Record<string, unknown>];\n }\n if (typeof data === \"object\" && data !== null && !Array.isArray(data)) {\n return [data as Record<string, unknown>];\n }\n return [];\n}\n\nfunction getColumns(rows: Record<string, unknown>[]): string[] {\n const set = new Set<string>();\n for (const row of rows) {\n for (const k of Object.keys(row)) set.add(k);\n }\n return [...set].sort((a, b) => {\n const aIsId = a === \"_id\" || a === \"id\" || a.endsWith(\"Id\");\n const bIsId = b === \"_id\" || b === \"id\" || b.endsWith(\"Id\");\n if (aIsId !== bIsId) return aIsId ? 1 : -1;\n return a.localeCompare(b);\n });\n}\n\nfunction printTable(data: unknown): void {\n const rows = getRows(data);\n if (rows.length === 0) {\n console.log(\"(no data)\");\n return;\n }\n const cols = getColumns(rows);\n const widths = cols.map((c) => Math.max(c.length, 8));\n for (const row of rows) {\n for (let i = 0; i < cols.length; i++) {\n const col = cols[i]!;\n const val = row[col];\n const s = val === null || val === undefined ? \"\" : String(val);\n if (s.length > widths[i]!) widths[i] = Math.min(s.length, 40);\n }\n }\n const header = cols.map((c, i) => c.padEnd(widths[i]!)).join(\" \");\n console.log(header);\n console.log(cols.map((_, i) => \"-\".repeat(widths[i]!)).join(\" \"));\n for (const row of rows) {\n const line = cols\n .map((c, i) => {\n const val = row[c];\n const s = val === null || val === undefined ? \"\" : String(val);\n return s.slice(0, widths[i]!).padEnd(widths[i]!);\n })\n .join(\" \");\n console.log(line);\n }\n}\n\nfunction printCsv(data: unknown): void {\n const rows = getRows(data);\n if (rows.length === 0) {\n console.log(\"\");\n return;\n }\n const cols = getColumns(rows);\n const escape = (v: unknown): string => {\n const s = v === null || v === undefined ? \"\" : String(v);\n if (s.includes(\",\") || s.includes('\"') || s.includes(\"\\n\")) {\n return `\"${s.replace(/\"/g, '\"\"')}\"`;\n }\n return s;\n };\n console.log(cols.join(\",\"));\n for (const row of rows) {\n console.log(cols.map((c) => escape(row[c])).join(\",\"));\n }\n}\n\nexport function printStructuredError(format: OutputFormat, payload: ErrorPayload): void {\n if (format === \"json\") {\n console.log(JSON.stringify(payload));\n return;\n }\n console.error(`Error ${payload.status} (${payload.code}): ${payload.message}`);\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/lib/client.ts","../src/lib/flag-coercion.ts","../src/lib/merge-body.ts","../src/lib/output.ts"],"sourcesContent":["import { resolveStoredBaseUrl } from \"./auth.js\";\n\nconst DEFAULT_BASE_URL = \"https://api.getpilfer.com\";\n\nexport function getBaseUrl(override?: string): string {\n const env = process.env.PILFER_API_BASE_URL;\n const stored = resolveStoredBaseUrl();\n const base = override ?? env ?? stored ?? DEFAULT_BASE_URL;\n return base.replace(/\\/$/, \"\");\n}\n\nexport interface RequestOptions {\n method: \"GET\" | \"POST\" | \"PATCH\" | \"DELETE\";\n path: string;\n token: string | null;\n baseUrl?: string;\n query?: Record<string, string | number | undefined>;\n body?: unknown;\n}\n\nexport interface ApiResponse<T = unknown> {\n ok: boolean;\n status: number;\n data?: T;\n error?: string;\n headers?: Headers;\n}\n\nconst RETRYABLE_STATUSES = new Set([502, 503, 504]);\nconst GET_MAX_ATTEMPTS = 3;\nconst GET_RETRY_BASE_DELAY_MS = 150;\n\nfunction shouldRetryRequest(method: RequestOptions[\"method\"], response: ApiResponse<unknown>, attempt: number): boolean {\n if (method !== \"GET\") return false;\n if (attempt >= GET_MAX_ATTEMPTS) return false;\n if (response.status === 0) return true;\n return RETRYABLE_STATUSES.has(response.status);\n}\n\nfunction getRetryDelayMs(attempt: number): number {\n const exp = GET_RETRY_BASE_DELAY_MS * Math.pow(2, Math.max(0, attempt - 1));\n const jitter = Math.floor(Math.random() * 50);\n return exp + jitter;\n}\n\nasync function sleep(ms: number): Promise<void> {\n await new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Call the Pilfer REST API. Path should be relative to /api/v1 (e.g. \"me\", \"projects\", \"projects/123\").\n */\nexport async function apiRequest<T = unknown>(\n options: RequestOptions,\n): Promise<ApiResponse<T>> {\n const base = getBaseUrl(options.baseUrl);\n const url = new URL(`/api/v1/${options.path.replace(/^\\//, \"\")}`, base);\n if (options.query) {\n for (const [k, v] of Object.entries(options.query)) {\n if (v !== undefined && v !== \"\") url.searchParams.set(k, String(v));\n }\n }\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${options.token ?? \"\"}`,\n \"Content-Type\": \"application/json\",\n };\n\n const init: RequestInit = {\n method: options.method,\n headers,\n };\n if (\n options.body !== undefined &&\n options.method !== \"GET\"\n ) {\n init.body = JSON.stringify(options.body);\n }\n\n for (let attempt = 1; ; attempt++) {\n const response = await doRequest<T>(url.toString(), init);\n if (!shouldRetryRequest(options.method, response, attempt)) {\n return response;\n }\n await sleep(getRetryDelayMs(attempt));\n }\n}\n\nasync function doRequest<T>(url: string, init: RequestInit): Promise<ApiResponse<T>> {\n let res: Response;\n try {\n res = await fetch(url, init);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { ok: false, status: 0, error: message };\n }\n\n let data: T | undefined;\n const text = await res.text();\n if (text) {\n try {\n data = JSON.parse(text) as T;\n } catch {\n data = undefined;\n }\n }\n\n return {\n ok: res.ok,\n status: res.status,\n data,\n error: !res.ok\n ? extractErrorMessage(data)\n : undefined,\n headers: res.headers,\n };\n}\n\nfunction extractErrorMessage(data: unknown): string | undefined {\n if (data == null || typeof data !== \"object\") return undefined;\n\n const body = data as {\n error?: unknown;\n message?: unknown;\n requestId?: unknown;\n };\n\n const baseMessage =\n typeof body.error === \"string\"\n ? body.error\n : typeof body.message === \"string\"\n ? body.message\n : undefined;\n if (baseMessage == null) return undefined;\n\n if (typeof body.requestId === \"string\" && body.requestId.trim() !== \"\") {\n return `${baseMessage} (requestId: ${body.requestId})`;\n }\n return baseMessage;\n}\n","type ExitWithError = (status: number, message: string) => never;\n\ntype PrimitiveKind = \"string\" | \"number\" | \"boolean\";\n\ninterface CoerceConfig {\n field: string;\n flag: string;\n kind: PrimitiveKind;\n allowNull?: boolean;\n allowDateTime?: boolean;\n}\n\nfunction fail(exitWithError: ExitWithError, message: string): never {\n return exitWithError(400, message);\n}\n\nfunction parseBoolean(\n raw: string,\n config: CoerceConfig,\n exitWithError: ExitWithError,\n): boolean {\n const value = raw.trim().toLowerCase();\n if ([\"true\", \"1\", \"yes\", \"y\", \"on\"].includes(value)) return true;\n if ([\"false\", \"0\", \"no\", \"n\", \"off\"].includes(value)) return false;\n return fail(\n exitWithError,\n `Invalid value for ${config.flag} (${config.field}): expected boolean but got \"${raw}\"`,\n );\n}\n\nfunction parseNumber(\n raw: string,\n config: CoerceConfig,\n exitWithError: ExitWithError,\n): number {\n const trimmed = raw.trim();\n const asNumber = Number(trimmed);\n if (Number.isFinite(asNumber)) return asNumber;\n\n if (config.allowDateTime) {\n const asDate = Date.parse(trimmed);\n if (Number.isFinite(asDate)) return asDate;\n }\n\n return fail(\n exitWithError,\n `Invalid value for ${config.flag} (${config.field}): expected number${config.allowDateTime ? \" or ISO datetime\" : \"\"} but got \"${raw}\"`,\n );\n}\n\nexport function coerceBodyFlag(\n raw: unknown,\n config: CoerceConfig,\n exitWithError: ExitWithError,\n): unknown {\n if (raw == null) return undefined;\n const value = String(raw);\n const trimmed = value.trim();\n\n if (config.allowNull && trimmed.toLowerCase() === \"null\") {\n return null;\n }\n\n if (config.kind === \"string\") return value;\n if (config.kind === \"boolean\") return parseBoolean(value, config, exitWithError);\n return parseNumber(value, config, exitWithError);\n}\n\nexport function coerceQueryFlag(\n raw: unknown,\n config: CoerceConfig,\n exitWithError: ExitWithError,\n): string | number {\n if (raw == null) {\n return fail(\n exitWithError,\n `Missing value for ${config.flag} (${config.field})`,\n );\n }\n\n const value = String(raw);\n if (config.kind === \"string\") return value;\n if (config.kind === \"boolean\") {\n return parseBoolean(value, config, exitWithError) ? \"true\" : \"false\";\n }\n return parseNumber(value, config, exitWithError);\n}\n","/**\n * Merge optional JSON body (from --body) with object built from flags.\n * Flags override keys in body when both are provided.\n */\nexport function mergeBody(\n bodyFromFlags: Record<string, unknown>,\n bodyOption: string | undefined,\n): Record<string, unknown> {\n let base: Record<string, unknown> = {};\n if (bodyOption?.trim()) {\n try {\n base = JSON.parse(bodyOption) as Record<string, unknown>;\n } catch {\n // ignore invalid JSON\n }\n }\n return { ...base, ...bodyFromFlags };\n}\n","export type OutputFormat = \"json\" | \"table\" | \"csv\";\n\nexport function getDefaultOutputFormat(): OutputFormat {\n return process.stdout.isTTY ? \"table\" : \"json\";\n}\n\nexport interface ErrorPayload {\n error: true;\n status: number;\n code: string;\n message: string;\n}\n\nexport function formatErrorPayload(status: number, message: string): ErrorPayload {\n const code = statusToCode(status);\n return { error: true, status, code, message };\n}\n\nfunction statusToCode(status: number): string {\n if (status === 401) return \"UNAUTHORIZED\";\n if (status === 403) return \"FORBIDDEN\";\n if (status === 404) return \"NOT_FOUND\";\n if (status === 400) return \"BAD_REQUEST\";\n if (status === 429) return \"TOO_MANY_REQUESTS\";\n if (status >= 500) return \"SERVER_ERROR\";\n return \"ERROR\";\n}\n\n/**\n * Print result to stdout according to format. For list responses, pass the data array.\n * For single resource, pass the data object.\n */\nexport function printOutput(\n format: OutputFormat,\n data: unknown,\n isError = false,\n): void {\n if (format === \"json\") {\n const out = Array.isArray(data)\n ? { data }\n : typeof data === \"object\" && data !== null && \"data\" in data\n ? data\n : { data };\n console.log(JSON.stringify(out, null, 0));\n return;\n }\n if (format === \"table\") {\n printTable(data);\n return;\n }\n if (format === \"csv\") {\n printCsv(data);\n return;\n }\n console.log(JSON.stringify(data));\n}\n\nfunction getRows(data: unknown): Record<string, unknown>[] {\n if (Array.isArray(data)) return data as Record<string, unknown>[];\n if (typeof data === \"object\" && data !== null && \"data\" in data) {\n const d = (data as { data: unknown }).data;\n if (Array.isArray(d)) return d as Record<string, unknown>[];\n if (typeof d === \"object\" && d !== null) return [d as Record<string, unknown>];\n }\n if (typeof data === \"object\" && data !== null && !Array.isArray(data)) {\n return [data as Record<string, unknown>];\n }\n return [];\n}\n\nfunction getColumns(rows: Record<string, unknown>[]): string[] {\n const set = new Set<string>();\n for (const row of rows) {\n for (const k of Object.keys(row)) set.add(k);\n }\n return [...set].sort((a, b) => {\n const aIsId = a === \"_id\" || a === \"id\" || a.endsWith(\"Id\");\n const bIsId = b === \"_id\" || b === \"id\" || b.endsWith(\"Id\");\n if (aIsId !== bIsId) return aIsId ? 1 : -1;\n return a.localeCompare(b);\n });\n}\n\nfunction printTable(data: unknown): void {\n const rows = getRows(data);\n if (rows.length === 0) {\n console.log(\"(no data)\");\n return;\n }\n const cols = getColumns(rows);\n const widths = cols.map((c) => Math.max(c.length, 8));\n for (const row of rows) {\n for (let i = 0; i < cols.length; i++) {\n const col = cols[i]!;\n const val = row[col];\n const s = val === null || val === undefined ? \"\" : String(val);\n if (s.length > widths[i]!) widths[i] = Math.min(s.length, 40);\n }\n }\n const header = cols.map((c, i) => c.padEnd(widths[i]!)).join(\" \");\n console.log(header);\n console.log(cols.map((_, i) => \"-\".repeat(widths[i]!)).join(\" \"));\n for (const row of rows) {\n const line = cols\n .map((c, i) => {\n const val = row[c];\n const s = val === null || val === undefined ? \"\" : String(val);\n return s.slice(0, widths[i]!).padEnd(widths[i]!);\n })\n .join(\" \");\n console.log(line);\n }\n}\n\nfunction printCsv(data: unknown): void {\n const rows = getRows(data);\n if (rows.length === 0) {\n console.log(\"\");\n return;\n }\n const cols = getColumns(rows);\n const escape = (v: unknown): string => {\n const s = v === null || v === undefined ? \"\" : String(v);\n if (s.includes(\",\") || s.includes('\"') || s.includes(\"\\n\")) {\n return `\"${s.replace(/\"/g, '\"\"')}\"`;\n }\n return s;\n };\n console.log(cols.join(\",\"));\n for (const row of rows) {\n console.log(cols.map((c) => escape(row[c])).join(\",\"));\n }\n}\n\nexport function printStructuredError(format: OutputFormat, payload: ErrorPayload): void {\n if (format === \"json\") {\n console.log(JSON.stringify(payload));\n return;\n }\n console.error(`Error ${payload.status} (${payload.code}): ${payload.message}`);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
coerceQueryFlag,
|
|
6
6
|
mergeBody,
|
|
7
7
|
printOutput
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-QH2MMA3M.js";
|
|
9
9
|
import "./chunk-GZ4DXDQM.js";
|
|
10
10
|
|
|
11
11
|
// src/lib/bulk.ts
|
|
@@ -1099,4 +1099,4 @@ function register(program, helpers) {
|
|
|
1099
1099
|
export {
|
|
1100
1100
|
register
|
|
1101
1101
|
};
|
|
1102
|
-
//# sourceMappingURL=generated-
|
|
1102
|
+
//# sourceMappingURL=generated-IFLUY7PB.js.map
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
File without changes
|