@getpilfer/cli 0.1.0
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 +81 -0
- package/SKILL.md +47 -0
- package/dist/auth-VFGSMTC6.js +20 -0
- package/dist/auth-VFGSMTC6.js.map +1 -0
- package/dist/build-program.js +16 -0
- package/dist/build-program.js.map +1 -0
- package/dist/chunk-GWWE2AMO.js +407 -0
- package/dist/chunk-GWWE2AMO.js.map +1 -0
- package/dist/chunk-GZ4DXDQM.js +76 -0
- package/dist/chunk-GZ4DXDQM.js.map +1 -0
- package/dist/chunk-HJFKOMTC.js +281 -0
- package/dist/chunk-HJFKOMTC.js.map +1 -0
- package/dist/generated-D7S53VGE.js +1102 -0
- package/dist/generated-D7S53VGE.js.map +1 -0
- package/dist/index.js +117 -0
- package/dist/index.js.map +1 -0
- package/package.json +45 -0
package/README.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# @getpilfer/cli
|
|
2
|
+
|
|
3
|
+
Pilfer REST API CLI for terminal and script use.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @getpilfer/cli
|
|
9
|
+
pilfer whoami
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Or run without installing:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npx @getpilfer/cli whoami
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Auth
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pilfer login
|
|
22
|
+
# or
|
|
23
|
+
export PILFER_API_TOKEN="plf_..."
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Tokens are stored in `~/.config/pilfer/credentials.json`. API keys use the `plf_` prefix.
|
|
27
|
+
|
|
28
|
+
## Base URL
|
|
29
|
+
|
|
30
|
+
Default: `https://api.usepilfer.com`.
|
|
31
|
+
|
|
32
|
+
Override for local or early deployments:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
export PILFER_API_BASE_URL="https://api.example.com"
|
|
36
|
+
pilfer --base-url https://api.example.com projects list
|
|
37
|
+
pilfer config set-base-url https://api.example.com
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Commands
|
|
41
|
+
|
|
42
|
+
Generated resources:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pilfer organizations list
|
|
46
|
+
pilfer projects list
|
|
47
|
+
pilfer spaces list --project-id <id>
|
|
48
|
+
pilfer scouts create --name "New candidate"
|
|
49
|
+
pilfer assets update <id> --cost 120
|
|
50
|
+
pilfer comments list --entity-type scout --entity-id <id>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Nested scout sources:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pilfer sources list --scout-id <id>
|
|
57
|
+
pilfer sources create --scout-id <id> --url <url> --title "Vendor" --price 49
|
|
58
|
+
pilfer sources update --scout-id <id> <source-id> --starred true
|
|
59
|
+
pilfer sources delete --scout-id <id> <source-id>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Top-level helpers:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pilfer whoami
|
|
66
|
+
pilfer status
|
|
67
|
+
pilfer login [token]
|
|
68
|
+
pilfer logout
|
|
69
|
+
pilfer config show
|
|
70
|
+
pilfer setup-agent
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Development
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
pnpm --filter @getpilfer/cli generate
|
|
77
|
+
pnpm --filter @getpilfer/cli check-types
|
|
78
|
+
pnpm --filter @getpilfer/cli build
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Resource commands are generated from `apps/api/spec/openapi.yaml`.
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Pilfer CLI - Agent Skill
|
|
2
|
+
|
|
3
|
+
The Pilfer CLI lets agents and scripts interact with the Pilfer REST API from the terminal.
|
|
4
|
+
|
|
5
|
+
## Command Pattern
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pilfer <resource> list [--filters...]
|
|
9
|
+
pilfer <resource> get <id>
|
|
10
|
+
pilfer <resource> create [--fields...] [--body JSON]
|
|
11
|
+
pilfer <resource> update <id> [--fields...] [--body JSON]
|
|
12
|
+
pilfer <resource> delete <id>
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Core resources: `organizations`, `projects`, `spaces`, `scouts`, `assets`, `categories`, `labels`, `views`, `comments`.
|
|
16
|
+
|
|
17
|
+
Scout sources are nested and use custom commands:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pilfer sources list --scout-id <id>
|
|
21
|
+
pilfer sources get --scout-id <id> <source-id>
|
|
22
|
+
pilfer sources create --scout-id <id> --url <url> --title <title> --price <n>
|
|
23
|
+
pilfer sources update --scout-id <id> <source-id> --price <n>
|
|
24
|
+
pilfer sources delete --scout-id <id> <source-id>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Auth
|
|
28
|
+
|
|
29
|
+
Resolution order:
|
|
30
|
+
|
|
31
|
+
1. `--token <token>`
|
|
32
|
+
2. `PILFER_API_TOKEN`
|
|
33
|
+
3. `~/.config/pilfer/credentials.json` from `pilfer login`
|
|
34
|
+
|
|
35
|
+
Use `plf_` API keys. Verify first with `pilfer whoami`.
|
|
36
|
+
|
|
37
|
+
## Output
|
|
38
|
+
|
|
39
|
+
Use `--output json | table | csv`. Non-TTY output defaults to JSON.
|
|
40
|
+
|
|
41
|
+
## Setup
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
export PILFER_API_TOKEN="plf_..."
|
|
45
|
+
export PILFER_API_BASE_URL="https://api.usepilfer.com"
|
|
46
|
+
pilfer whoami
|
|
47
|
+
```
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
clearBaseUrl,
|
|
4
|
+
clearCredentials,
|
|
5
|
+
getCredentialsPath,
|
|
6
|
+
resolveStoredBaseUrl,
|
|
7
|
+
resolveToken,
|
|
8
|
+
saveBaseUrl,
|
|
9
|
+
saveToken
|
|
10
|
+
} from "./chunk-GZ4DXDQM.js";
|
|
11
|
+
export {
|
|
12
|
+
clearBaseUrl,
|
|
13
|
+
clearCredentials,
|
|
14
|
+
getCredentialsPath,
|
|
15
|
+
resolveStoredBaseUrl,
|
|
16
|
+
resolveToken,
|
|
17
|
+
saveBaseUrl,
|
|
18
|
+
saveToken
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=auth-VFGSMTC6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
createProgram,
|
|
4
|
+
createProgramForCLI,
|
|
5
|
+
getProgramForDocs,
|
|
6
|
+
syncRootOptsFromCommand
|
|
7
|
+
} from "./chunk-GWWE2AMO.js";
|
|
8
|
+
import "./chunk-HJFKOMTC.js";
|
|
9
|
+
import "./chunk-GZ4DXDQM.js";
|
|
10
|
+
export {
|
|
11
|
+
createProgram,
|
|
12
|
+
createProgramForCLI,
|
|
13
|
+
getProgramForDocs,
|
|
14
|
+
syncRootOptsFromCommand
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=build-program.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
apiRequest,
|
|
4
|
+
coerceBodyFlag,
|
|
5
|
+
formatErrorPayload,
|
|
6
|
+
getBaseUrl,
|
|
7
|
+
getDefaultOutputFormat,
|
|
8
|
+
mergeBody,
|
|
9
|
+
printOutput,
|
|
10
|
+
printStructuredError
|
|
11
|
+
} from "./chunk-HJFKOMTC.js";
|
|
12
|
+
import {
|
|
13
|
+
resolveToken
|
|
14
|
+
} from "./chunk-GZ4DXDQM.js";
|
|
15
|
+
|
|
16
|
+
// src/build-program.ts
|
|
17
|
+
import { createRequire } from "module";
|
|
18
|
+
import { Command } from "commander";
|
|
19
|
+
var _require = createRequire(import.meta.url);
|
|
20
|
+
var { version: CLI_VERSION } = _require("../package.json");
|
|
21
|
+
var rootOpts = {};
|
|
22
|
+
function syncRootOptsFromCommand(cmd) {
|
|
23
|
+
const maybeCommand = cmd;
|
|
24
|
+
if (!maybeCommand || typeof maybeCommand !== "object") return;
|
|
25
|
+
if (typeof maybeCommand.opts !== "function") return;
|
|
26
|
+
let root = maybeCommand;
|
|
27
|
+
while (root.parent) root = root.parent;
|
|
28
|
+
if (typeof root.opts !== "function") return;
|
|
29
|
+
rootOpts = root.opts();
|
|
30
|
+
}
|
|
31
|
+
var DUMMY_HELPERS = {
|
|
32
|
+
getOutputFormat: () => "json",
|
|
33
|
+
requireToken: () => null,
|
|
34
|
+
exitWithError: () => {
|
|
35
|
+
throw new Error("Docs generator: action should not run");
|
|
36
|
+
},
|
|
37
|
+
getBaseUrl: () => "https://api.usepilfer.com",
|
|
38
|
+
syncRootOptsFromCommand: () => {
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
function addTopLevelCommands(program, helpers) {
|
|
42
|
+
const { getOutputFormat, requireToken, exitWithError } = helpers;
|
|
43
|
+
function getRequiredToken() {
|
|
44
|
+
const token = requireToken();
|
|
45
|
+
if (!token) exitWithError(401, "Missing or invalid token. Run: pilfer login");
|
|
46
|
+
return token;
|
|
47
|
+
}
|
|
48
|
+
function getOutputFormatFromProgram(_p) {
|
|
49
|
+
const raw = rootOpts.output;
|
|
50
|
+
if (raw === "json" || raw === "table" || raw === "csv") return raw;
|
|
51
|
+
return getDefaultOutputFormat();
|
|
52
|
+
}
|
|
53
|
+
function exitWithErrorHandler(program2, status, message) {
|
|
54
|
+
const format = getOutputFormatFromProgram(program2);
|
|
55
|
+
const payload = formatErrorPayload(status, message);
|
|
56
|
+
printStructuredError(format, payload);
|
|
57
|
+
process.exit(status === 401 || status === 403 ? 1 : 2);
|
|
58
|
+
}
|
|
59
|
+
program.action(() => {
|
|
60
|
+
console.log(`
|
|
61
|
+
Welcome to the Pilfer CLI - manage your Pilfer data from the terminal.
|
|
62
|
+
|
|
63
|
+
Get started
|
|
64
|
+
----------
|
|
65
|
+
Log in: pilfer login
|
|
66
|
+
Verify: pilfer whoami
|
|
67
|
+
Overview: pilfer status
|
|
68
|
+
|
|
69
|
+
Resources (list | get | create | update | delete)
|
|
70
|
+
------------------------------------------------
|
|
71
|
+
organizations projects spaces scouts
|
|
72
|
+
sources assets categories labels views
|
|
73
|
+
|
|
74
|
+
Examples
|
|
75
|
+
--------
|
|
76
|
+
pilfer organizations list
|
|
77
|
+
pilfer projects create --name "Studio upgrade"
|
|
78
|
+
pilfer scouts list --status Shortlist
|
|
79
|
+
pilfer sources list --scout-id scout_123
|
|
80
|
+
|
|
81
|
+
Help
|
|
82
|
+
----
|
|
83
|
+
pilfer --help
|
|
84
|
+
pilfer <resource> --help
|
|
85
|
+
`);
|
|
86
|
+
});
|
|
87
|
+
program.command("whoami").description("Verify auth and show current user and token scopes").action(async () => {
|
|
88
|
+
const token = getRequiredToken();
|
|
89
|
+
const res = await apiRequest({
|
|
90
|
+
method: "GET",
|
|
91
|
+
path: "me",
|
|
92
|
+
token,
|
|
93
|
+
baseUrl: rootOpts.baseUrl
|
|
94
|
+
});
|
|
95
|
+
if (!res.ok) exitWithError(res.status || 401, res.error ?? "Unauthorized");
|
|
96
|
+
const data = res.data?.data ?? res.data;
|
|
97
|
+
printOutput(getOutputFormat(), data ?? {}, false);
|
|
98
|
+
});
|
|
99
|
+
program.command("login [token]").description("Store API token (prompt or pass token as argument)").action(async (tokenArg) => {
|
|
100
|
+
const { saveToken } = await import("./auth-VFGSMTC6.js");
|
|
101
|
+
let token = tokenArg?.trim();
|
|
102
|
+
if (!token) {
|
|
103
|
+
const readline = await import("readline");
|
|
104
|
+
const rl = readline.createInterface({
|
|
105
|
+
input: process.stdin,
|
|
106
|
+
output: process.stderr
|
|
107
|
+
});
|
|
108
|
+
token = await new Promise((resolve) => {
|
|
109
|
+
rl.question("API token: ", (answer) => {
|
|
110
|
+
rl.close();
|
|
111
|
+
resolve(answer?.trim() ?? "");
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
if (!token) {
|
|
116
|
+
console.error("No token provided.");
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
const res = await apiRequest({
|
|
120
|
+
method: "GET",
|
|
121
|
+
path: "me",
|
|
122
|
+
token,
|
|
123
|
+
baseUrl: rootOpts.baseUrl
|
|
124
|
+
});
|
|
125
|
+
if (!res.ok) {
|
|
126
|
+
console.error("Invalid token or API error:", res.error ?? res.status);
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
129
|
+
saveToken(token);
|
|
130
|
+
console.log("Logged in successfully.");
|
|
131
|
+
});
|
|
132
|
+
const config = program.command("config").description("Persist and inspect CLI config");
|
|
133
|
+
config.command("show").description("Show stored CLI config").action(async () => {
|
|
134
|
+
const { getCredentialsPath, resolveStoredBaseUrl } = await import("./auth-VFGSMTC6.js");
|
|
135
|
+
const token = resolveToken(rootOpts.token ?? void 0);
|
|
136
|
+
const baseUrl = getBaseUrl(rootOpts.baseUrl ?? rootOpts.api);
|
|
137
|
+
const storedBaseUrl = resolveStoredBaseUrl();
|
|
138
|
+
printOutput(
|
|
139
|
+
getOutputFormat(),
|
|
140
|
+
{
|
|
141
|
+
configPath: getCredentialsPath(),
|
|
142
|
+
tokenConfigured: Boolean(token),
|
|
143
|
+
baseUrl,
|
|
144
|
+
baseUrlSource: rootOpts.baseUrl ?? rootOpts.api ? "flag" : process.env.PILFER_API_BASE_URL ? "env" : storedBaseUrl ? "config" : "default"
|
|
145
|
+
},
|
|
146
|
+
false
|
|
147
|
+
);
|
|
148
|
+
});
|
|
149
|
+
config.command("set-base-url <url>").alias("set-api").description("Persist default API base URL").action(async (url) => {
|
|
150
|
+
const { saveBaseUrl } = await import("./auth-VFGSMTC6.js");
|
|
151
|
+
const normalized = url.trim().replace(/\/$/, "");
|
|
152
|
+
if (!normalized) {
|
|
153
|
+
console.error("No base URL provided.");
|
|
154
|
+
process.exit(1);
|
|
155
|
+
}
|
|
156
|
+
saveBaseUrl(normalized);
|
|
157
|
+
console.log(`Saved API base URL: ${normalized}`);
|
|
158
|
+
});
|
|
159
|
+
config.command("unset-base-url").alias("unset-api").description("Remove persisted API base URL").action(async () => {
|
|
160
|
+
const { clearBaseUrl } = await import("./auth-VFGSMTC6.js");
|
|
161
|
+
clearBaseUrl();
|
|
162
|
+
console.log("Cleared stored API base URL.");
|
|
163
|
+
});
|
|
164
|
+
program.command("logout").description("Remove stored API token").action(async () => {
|
|
165
|
+
const { clearCredentials } = await import("./auth-VFGSMTC6.js");
|
|
166
|
+
clearCredentials();
|
|
167
|
+
console.log("Logged out.");
|
|
168
|
+
});
|
|
169
|
+
program.command("setup-agent").description("Print instructions for configuring Pilfer CLI for AI agents").action(() => {
|
|
170
|
+
console.log(`
|
|
171
|
+
To use the Pilfer CLI from an AI agent or script:
|
|
172
|
+
|
|
173
|
+
1. Set your API token:
|
|
174
|
+
export PILFER_API_TOKEN="plf_..."
|
|
175
|
+
|
|
176
|
+
2. Optional: override API base URL for local or early deployments:
|
|
177
|
+
export PILFER_API_BASE_URL="https://api.usepilfer.com"
|
|
178
|
+
|
|
179
|
+
3. Verify auth:
|
|
180
|
+
pilfer whoami
|
|
181
|
+
|
|
182
|
+
4. Commands use the pattern: pilfer <resource> list|get|create|update|delete
|
|
183
|
+
When stdout is not a TTY, output defaults to JSON.
|
|
184
|
+
`);
|
|
185
|
+
});
|
|
186
|
+
program.command("status").description("Situational summary: organizations, projects, spaces, scouts, assets").action(async () => {
|
|
187
|
+
const token = getRequiredToken();
|
|
188
|
+
const baseUrl = rootOpts.baseUrl;
|
|
189
|
+
const [orgsRes, projectsRes, spacesRes, scoutsRes, assetsRes] = await Promise.all([
|
|
190
|
+
apiRequest({
|
|
191
|
+
method: "GET",
|
|
192
|
+
path: "organizations",
|
|
193
|
+
token,
|
|
194
|
+
baseUrl
|
|
195
|
+
}),
|
|
196
|
+
apiRequest({
|
|
197
|
+
method: "GET",
|
|
198
|
+
path: "projects",
|
|
199
|
+
token,
|
|
200
|
+
baseUrl
|
|
201
|
+
}),
|
|
202
|
+
apiRequest({
|
|
203
|
+
method: "GET",
|
|
204
|
+
path: "spaces",
|
|
205
|
+
token,
|
|
206
|
+
baseUrl
|
|
207
|
+
}),
|
|
208
|
+
apiRequest({
|
|
209
|
+
method: "GET",
|
|
210
|
+
path: "scouts",
|
|
211
|
+
token,
|
|
212
|
+
baseUrl
|
|
213
|
+
}),
|
|
214
|
+
apiRequest({
|
|
215
|
+
method: "GET",
|
|
216
|
+
path: "assets",
|
|
217
|
+
token,
|
|
218
|
+
baseUrl
|
|
219
|
+
})
|
|
220
|
+
]);
|
|
221
|
+
const unwrap = (res) => res.ok && res.data ? res.data.data ?? [] : [];
|
|
222
|
+
const scouts = unwrap(scoutsRes);
|
|
223
|
+
const scoutStatuses = scouts.reduce((acc, scout) => {
|
|
224
|
+
const status = scout.status ?? "unknown";
|
|
225
|
+
acc[status] = (acc[status] ?? 0) + 1;
|
|
226
|
+
return acc;
|
|
227
|
+
}, {});
|
|
228
|
+
printOutput(
|
|
229
|
+
getOutputFormat(),
|
|
230
|
+
{
|
|
231
|
+
organizations: unwrap(orgsRes).length,
|
|
232
|
+
projects: unwrap(projectsRes).length,
|
|
233
|
+
spaces: unwrap(spacesRes).length,
|
|
234
|
+
scouts: scouts.length,
|
|
235
|
+
assets: unwrap(assetsRes).length,
|
|
236
|
+
scoutsByStatus: scoutStatuses
|
|
237
|
+
},
|
|
238
|
+
false
|
|
239
|
+
);
|
|
240
|
+
});
|
|
241
|
+
program.exitOverride((err) => {
|
|
242
|
+
if (err.code === "commander.helpDisplayed" || err.code === "commander.version") {
|
|
243
|
+
throw err;
|
|
244
|
+
}
|
|
245
|
+
exitWithErrorHandler(program, 2, err.message);
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
async function registerGeneratedCommands(program, helpers) {
|
|
249
|
+
const mod = await import("./generated-D7S53VGE.js").catch(() => null);
|
|
250
|
+
if (mod?.register) mod.register(program, helpers);
|
|
251
|
+
}
|
|
252
|
+
function registerSourceCommands(program, helpers) {
|
|
253
|
+
const { getOutputFormat, requireToken, exitWithError, getBaseUrl: getBaseUrl2 } = helpers;
|
|
254
|
+
function getRequiredToken() {
|
|
255
|
+
const token = requireToken();
|
|
256
|
+
if (!token) exitWithError(401, "Missing or invalid token. Run: pilfer login");
|
|
257
|
+
return token;
|
|
258
|
+
}
|
|
259
|
+
function bodyFromFlags(opts, isUpdate) {
|
|
260
|
+
const bodyFromFlags2 = {};
|
|
261
|
+
for (const field of ["url", "title", "price", "imageUrl", "notes", "starred"]) {
|
|
262
|
+
const value = opts[field];
|
|
263
|
+
const kind = field === "price" ? "number" : field === "starred" ? "boolean" : "string";
|
|
264
|
+
const parsed = coerceBodyFlag(
|
|
265
|
+
value,
|
|
266
|
+
{
|
|
267
|
+
field,
|
|
268
|
+
flag: `--${field.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase()}`,
|
|
269
|
+
kind
|
|
270
|
+
},
|
|
271
|
+
exitWithError
|
|
272
|
+
);
|
|
273
|
+
if (parsed !== void 0) bodyFromFlags2[field] = parsed;
|
|
274
|
+
}
|
|
275
|
+
if (!isUpdate && Object.keys(bodyFromFlags2).length === 0 && !opts.body) {
|
|
276
|
+
exitWithError(400, "Provide source fields or --body JSON");
|
|
277
|
+
}
|
|
278
|
+
return mergeBody(bodyFromFlags2, opts.body);
|
|
279
|
+
}
|
|
280
|
+
const sources = program.command("sources").description("Manage scout sources");
|
|
281
|
+
sources.command("list").description("List sources for a scout").requiredOption("--scout-id <id>", "Scout id").option("--limit <n>", "Max results").option("--offset <n>", "Skip n results").hook("preAction", (thisCommand) => {
|
|
282
|
+
helpers.syncRootOptsFromCommand(thisCommand);
|
|
283
|
+
}).action(async (opts) => {
|
|
284
|
+
const token = getRequiredToken();
|
|
285
|
+
const res = await apiRequest({
|
|
286
|
+
method: "GET",
|
|
287
|
+
path: `scouts/${encodeURIComponent(opts.scoutId)}/sources`,
|
|
288
|
+
token,
|
|
289
|
+
baseUrl: getBaseUrl2(),
|
|
290
|
+
query: { limit: opts.limit, offset: opts.offset }
|
|
291
|
+
});
|
|
292
|
+
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
293
|
+
const data = res.data?.data ?? [];
|
|
294
|
+
printOutput(getOutputFormat(), data, false);
|
|
295
|
+
});
|
|
296
|
+
sources.command("get <sourceId>").description("Get one source by id").requiredOption("--scout-id <id>", "Scout id").hook("preAction", (thisCommand) => {
|
|
297
|
+
helpers.syncRootOptsFromCommand(thisCommand);
|
|
298
|
+
}).action(async (sourceId, opts) => {
|
|
299
|
+
const token = getRequiredToken();
|
|
300
|
+
const res = await apiRequest({
|
|
301
|
+
method: "GET",
|
|
302
|
+
path: `scouts/${encodeURIComponent(opts.scoutId)}/sources/${encodeURIComponent(
|
|
303
|
+
sourceId
|
|
304
|
+
)}`,
|
|
305
|
+
token,
|
|
306
|
+
baseUrl: getBaseUrl2()
|
|
307
|
+
});
|
|
308
|
+
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
309
|
+
const data = res.data?.data ?? res.data;
|
|
310
|
+
printOutput(getOutputFormat(), data ?? {}, false);
|
|
311
|
+
});
|
|
312
|
+
sources.command("create").description("Create a source for a scout").requiredOption("--scout-id <id>", "Scout id").option("--url <value>", "url").option("--title <value>", "title").option("--price <value>", "price").option("--image-url <value>", "imageUrl").option("--notes <value>", "notes").option("--starred <value>", "starred").option("--body <json>", "Request body JSON (merged with flags)").hook("preAction", (thisCommand) => {
|
|
313
|
+
helpers.syncRootOptsFromCommand(thisCommand);
|
|
314
|
+
}).action(async (opts) => {
|
|
315
|
+
const token = getRequiredToken();
|
|
316
|
+
const res = await apiRequest({
|
|
317
|
+
method: "POST",
|
|
318
|
+
path: `scouts/${encodeURIComponent(opts.scoutId)}/sources`,
|
|
319
|
+
token,
|
|
320
|
+
baseUrl: getBaseUrl2(),
|
|
321
|
+
body: bodyFromFlags(opts, false)
|
|
322
|
+
});
|
|
323
|
+
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
324
|
+
const data = res.data?.data ?? res.data;
|
|
325
|
+
printOutput(getOutputFormat(), data ?? {}, false);
|
|
326
|
+
});
|
|
327
|
+
sources.command("update <sourceId>").description("Update a source").requiredOption("--scout-id <id>", "Scout id").option("--url <value>", "url").option("--title <value>", "title").option("--price <value>", "price").option("--image-url <value>", "imageUrl").option("--notes <value>", "notes").option("--starred <value>", "starred").option("--body <json>", "Request body JSON (merged with flags)").hook("preAction", (thisCommand) => {
|
|
328
|
+
helpers.syncRootOptsFromCommand(thisCommand);
|
|
329
|
+
}).action(async (sourceId, opts) => {
|
|
330
|
+
const token = getRequiredToken();
|
|
331
|
+
const res = await apiRequest({
|
|
332
|
+
method: "PATCH",
|
|
333
|
+
path: `scouts/${encodeURIComponent(opts.scoutId)}/sources/${encodeURIComponent(
|
|
334
|
+
sourceId
|
|
335
|
+
)}`,
|
|
336
|
+
token,
|
|
337
|
+
baseUrl: getBaseUrl2(),
|
|
338
|
+
body: bodyFromFlags(opts, true)
|
|
339
|
+
});
|
|
340
|
+
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
341
|
+
const data = res.data?.data ?? res.data;
|
|
342
|
+
printOutput(getOutputFormat(), data ?? {}, false);
|
|
343
|
+
});
|
|
344
|
+
sources.command("delete <sourceId>").description("Delete a source").requiredOption("--scout-id <id>", "Scout id").hook("preAction", (thisCommand) => {
|
|
345
|
+
helpers.syncRootOptsFromCommand(thisCommand);
|
|
346
|
+
}).action(async (sourceId, opts) => {
|
|
347
|
+
const token = getRequiredToken();
|
|
348
|
+
const res = await apiRequest({
|
|
349
|
+
method: "DELETE",
|
|
350
|
+
path: `scouts/${encodeURIComponent(opts.scoutId)}/sources/${encodeURIComponent(
|
|
351
|
+
sourceId
|
|
352
|
+
)}`,
|
|
353
|
+
token,
|
|
354
|
+
baseUrl: getBaseUrl2()
|
|
355
|
+
});
|
|
356
|
+
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
357
|
+
if (getOutputFormat() === "json") {
|
|
358
|
+
console.log(JSON.stringify({ data: null, deleted: true }));
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
async function createProgram(helpers) {
|
|
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.usepilfer.com)").option("--api <url>", "Alias for --base-url").hook("preAction", (thisCommand) => {
|
|
365
|
+
syncRootOptsFromCommand(thisCommand);
|
|
366
|
+
const opts = thisCommand.opts();
|
|
367
|
+
if (opts.output == null || opts.output === "") {
|
|
368
|
+
thisCommand.setOptionValue("output", getDefaultOutputFormat());
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
const resolvedHelpers = helpers ?? DUMMY_HELPERS;
|
|
372
|
+
addTopLevelCommands(program, resolvedHelpers);
|
|
373
|
+
await registerGeneratedCommands(program, resolvedHelpers);
|
|
374
|
+
registerSourceCommands(program, resolvedHelpers);
|
|
375
|
+
return program;
|
|
376
|
+
}
|
|
377
|
+
async function createProgramForCLI() {
|
|
378
|
+
const realHelpers = {
|
|
379
|
+
getOutputFormat: () => {
|
|
380
|
+
const raw = rootOpts.output;
|
|
381
|
+
if (raw === "json" || raw === "table" || raw === "csv") return raw;
|
|
382
|
+
return getDefaultOutputFormat();
|
|
383
|
+
},
|
|
384
|
+
requireToken: () => resolveToken(rootOpts.token ?? void 0),
|
|
385
|
+
exitWithError: (status, message) => {
|
|
386
|
+
const raw = rootOpts.output;
|
|
387
|
+
const format = raw === "json" || raw === "table" || raw === "csv" ? raw : getDefaultOutputFormat();
|
|
388
|
+
const payload = formatErrorPayload(status, message);
|
|
389
|
+
printStructuredError(format, payload);
|
|
390
|
+
process.exit(status === 401 || status === 403 ? 1 : 2);
|
|
391
|
+
},
|
|
392
|
+
getBaseUrl: () => getBaseUrl(rootOpts.baseUrl ?? rootOpts.api),
|
|
393
|
+
syncRootOptsFromCommand
|
|
394
|
+
};
|
|
395
|
+
return createProgram(realHelpers);
|
|
396
|
+
}
|
|
397
|
+
async function getProgramForDocs() {
|
|
398
|
+
return createProgram();
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
export {
|
|
402
|
+
syncRootOptsFromCommand,
|
|
403
|
+
createProgram,
|
|
404
|
+
createProgramForCLI,
|
|
405
|
+
getProgramForDocs
|
|
406
|
+
};
|
|
407
|
+
//# sourceMappingURL=chunk-GWWE2AMO.js.map
|
|
@@ -0,0 +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"]}
|