@getpilfer/cli 0.1.0 → 0.1.2
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 +14 -2
- package/SKILL.md +18 -2
- package/dist/build-program.js +2 -2
- package/dist/{chunk-HJFKOMTC.js → chunk-AQXEFAD4.js} +174 -73
- package/dist/chunk-AQXEFAD4.js.map +1 -0
- package/dist/chunk-W2HZLBPI.js +1038 -0
- package/dist/chunk-W2HZLBPI.js.map +1 -0
- package/dist/{generated-D7S53VGE.js → generated-UG3O6FVC.js} +628 -62
- package/dist/generated-UG3O6FVC.js.map +1 -0
- package/dist/index.js +2 -2
- package/package.json +2 -2
- package/dist/chunk-GWWE2AMO.js +0 -407
- package/dist/chunk-GWWE2AMO.js.map +0 -1
- package/dist/chunk-HJFKOMTC.js.map +0 -1
- package/dist/generated-D7S53VGE.js.map +0 -1
|
@@ -3,12 +3,55 @@ import {
|
|
|
3
3
|
apiRequest,
|
|
4
4
|
coerceBodyFlag,
|
|
5
5
|
coerceQueryFlag,
|
|
6
|
+
fetchList,
|
|
6
7
|
mergeBody,
|
|
8
|
+
printList,
|
|
7
9
|
printOutput
|
|
8
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-AQXEFAD4.js";
|
|
9
11
|
import "./chunk-GZ4DXDQM.js";
|
|
10
12
|
|
|
13
|
+
// src/lib/idempotent-create.ts
|
|
14
|
+
async function findExistingResource(options) {
|
|
15
|
+
const identity = options.identityFields.filter(
|
|
16
|
+
(field) => isComparable(options.body[field])
|
|
17
|
+
);
|
|
18
|
+
if (identity.length === 0) return null;
|
|
19
|
+
const query = {};
|
|
20
|
+
for (const field of identity) {
|
|
21
|
+
if (!options.queryFields.includes(field)) continue;
|
|
22
|
+
const value = options.body[field];
|
|
23
|
+
if (typeof value === "string" || typeof value === "number") {
|
|
24
|
+
query[field] = value;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const res = await options.request({
|
|
28
|
+
method: "GET",
|
|
29
|
+
path: options.resource,
|
|
30
|
+
token: options.token,
|
|
31
|
+
baseUrl: options.baseUrl,
|
|
32
|
+
query
|
|
33
|
+
});
|
|
34
|
+
if (!res.ok) return null;
|
|
35
|
+
const rows = (res.data?.data ?? []).filter(
|
|
36
|
+
isRecord
|
|
37
|
+
);
|
|
38
|
+
return rows.find((row) => identity.every((field) => equalValue(row[field], options.body[field]))) ?? null;
|
|
39
|
+
}
|
|
40
|
+
function isComparable(value) {
|
|
41
|
+
return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
42
|
+
}
|
|
43
|
+
function equalValue(a, b) {
|
|
44
|
+
if (typeof a === "string" && typeof b === "string") {
|
|
45
|
+
return a.trim().toLowerCase() === b.trim().toLowerCase();
|
|
46
|
+
}
|
|
47
|
+
return a === b;
|
|
48
|
+
}
|
|
49
|
+
function isRecord(value) {
|
|
50
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
51
|
+
}
|
|
52
|
+
|
|
11
53
|
// src/lib/bulk.ts
|
|
54
|
+
import { readFile } from "fs/promises";
|
|
12
55
|
var MAX_IDS = 25;
|
|
13
56
|
var CONCURRENCY = 5;
|
|
14
57
|
var MAX_RETRIES = 3;
|
|
@@ -16,6 +59,33 @@ function parseIds(idsFlag) {
|
|
|
16
59
|
if (!idsFlag?.trim()) return [];
|
|
17
60
|
return idsFlag.split(",").map((s) => s.trim()).filter(Boolean);
|
|
18
61
|
}
|
|
62
|
+
async function parseIdsInput(idsFlag, idsFile) {
|
|
63
|
+
const inline = idsFlag?.trim() === "-" ? await readStdin() : idsFlag;
|
|
64
|
+
const fromFile = idsFile ? await readTextSource(idsFile) : "";
|
|
65
|
+
return [...parseIds(inline), ...parseIdsText(fromFile)];
|
|
66
|
+
}
|
|
67
|
+
async function parseBulkInput(input) {
|
|
68
|
+
if (!input?.trim()) return [];
|
|
69
|
+
const text = await readTextSource(input);
|
|
70
|
+
if (!text.trim()) return [];
|
|
71
|
+
if (text.trim().startsWith("[") || text.trim().startsWith("{")) {
|
|
72
|
+
try {
|
|
73
|
+
const parsed = JSON.parse(text);
|
|
74
|
+
if (Array.isArray(parsed)) return parsed.filter(isRecord2);
|
|
75
|
+
if (isRecord2(parsed) && Array.isArray(parsed.data)) {
|
|
76
|
+
return parsed.data.filter(isRecord2);
|
|
77
|
+
}
|
|
78
|
+
if (isRecord2(parsed)) return [parsed];
|
|
79
|
+
} catch {
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return text.split(/\r?\n/).map((line) => line.trim()).filter(Boolean).map((line) => JSON.parse(line)).filter(isRecord2);
|
|
83
|
+
}
|
|
84
|
+
function getBulkRecordId(record) {
|
|
85
|
+
if (typeof record._id === "string" && record._id.trim()) return record._id.trim();
|
|
86
|
+
if (typeof record.id === "string" && record.id.trim()) return record.id.trim();
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
19
89
|
function validateBulkIds(ids, resourceLabel) {
|
|
20
90
|
if (ids.length > MAX_IDS) {
|
|
21
91
|
throw new Error(
|
|
@@ -29,17 +99,17 @@ async function runBulk(options) {
|
|
|
29
99
|
const results = [];
|
|
30
100
|
let succeeded = 0;
|
|
31
101
|
let failed = 0;
|
|
32
|
-
async function runWithRetry(
|
|
102
|
+
async function runWithRetry(item) {
|
|
33
103
|
let lastRes = null;
|
|
34
104
|
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
35
|
-
const res = await runOne(
|
|
105
|
+
const res = await runOne(item);
|
|
36
106
|
lastRes = res;
|
|
37
107
|
if (res.status !== 429) break;
|
|
38
108
|
const retryAfter = 2 ** attempt;
|
|
39
109
|
await new Promise((r2) => setTimeout(r2, retryAfter * 1e3));
|
|
40
110
|
}
|
|
41
111
|
const r = lastRes;
|
|
42
|
-
const result = toResult(
|
|
112
|
+
const result = toResult(item, r.ok, r.status, r.data, r.error);
|
|
43
113
|
if (r.ok) succeeded++;
|
|
44
114
|
else failed++;
|
|
45
115
|
return result;
|
|
@@ -47,8 +117,8 @@ async function runBulk(options) {
|
|
|
47
117
|
const queue = [...items];
|
|
48
118
|
const workers = Array.from({ length: concurrency }, async () => {
|
|
49
119
|
while (queue.length > 0) {
|
|
50
|
-
const
|
|
51
|
-
const result = await runWithRetry(
|
|
120
|
+
const item = queue.shift();
|
|
121
|
+
const result = await runWithRetry(item);
|
|
52
122
|
results.push(result);
|
|
53
123
|
}
|
|
54
124
|
});
|
|
@@ -58,12 +128,30 @@ async function runBulk(options) {
|
|
|
58
128
|
summary: { total: items.length, succeeded, failed }
|
|
59
129
|
};
|
|
60
130
|
}
|
|
131
|
+
function parseIdsText(text) {
|
|
132
|
+
if (!text?.trim()) return [];
|
|
133
|
+
return text.split(/[\s,]+/).map((s) => s.trim()).filter(Boolean);
|
|
134
|
+
}
|
|
135
|
+
async function readTextSource(source) {
|
|
136
|
+
if (source === "-") return readStdin();
|
|
137
|
+
return readFile(source, "utf-8");
|
|
138
|
+
}
|
|
139
|
+
async function readStdin() {
|
|
140
|
+
const chunks = [];
|
|
141
|
+
for await (const chunk of process.stdin) {
|
|
142
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));
|
|
143
|
+
}
|
|
144
|
+
return Buffer.concat(chunks).toString("utf-8");
|
|
145
|
+
}
|
|
146
|
+
function isRecord2(value) {
|
|
147
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
148
|
+
}
|
|
61
149
|
|
|
62
150
|
// src/commands/generated/index.ts
|
|
63
151
|
function register(program, helpers) {
|
|
64
152
|
const { getOutputFormat, requireToken, exitWithError, getBaseUrl, syncRootOptsFromCommand } = helpers;
|
|
65
153
|
const organizationsCmd = program.command("organizations").description("organizations resource");
|
|
66
|
-
organizationsCmd.command("list").description("List organizations").option("--limit <n>", "Max results").option("--offset <n>", "Skip n results").hook("preAction", (thisCommand) => {
|
|
154
|
+
organizationsCmd.command("list").description("List organizations").option("--limit <n>", "Max results").option("--offset <n>", "Skip n results").option("--all", "Fetch all pages").option("--fields <fields>", "Comma-separated fields to print").option("--where <field=value>", "Client-side exact filters, comma-separated").option("--jsonl", "Print one compact JSON object per row").hook("preAction", (thisCommand) => {
|
|
67
155
|
syncRootOptsFromCommand(thisCommand);
|
|
68
156
|
}).action(async (opts) => {
|
|
69
157
|
const token = requireToken();
|
|
@@ -71,10 +159,10 @@ function register(program, helpers) {
|
|
|
71
159
|
const query = {};
|
|
72
160
|
if (opts.limit != null) query.limit = opts.limit;
|
|
73
161
|
if (opts.offset != null) query.offset = opts.offset;
|
|
74
|
-
const res = await
|
|
162
|
+
const res = await fetchList({ path: "organizations", token, baseUrl: getBaseUrl(), query, all: Boolean(opts.all), request: apiRequest });
|
|
75
163
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
76
164
|
const data = res.data?.data ?? [];
|
|
77
|
-
|
|
165
|
+
printList({ format: getOutputFormat(), data, fields: opts.fields, where: opts.where, jsonl: Boolean(opts.jsonl) });
|
|
78
166
|
});
|
|
79
167
|
organizationsCmd.command("get <id>").description("Get one organizations by id").hook("preAction", (thisCommand) => {
|
|
80
168
|
syncRootOptsFromCommand(thisCommand);
|
|
@@ -88,7 +176,7 @@ function register(program, helpers) {
|
|
|
88
176
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
89
177
|
});
|
|
90
178
|
const projectsCmd = program.command("projects").description("projects resource");
|
|
91
|
-
projectsCmd.command("list").description("List projects").option("--limit <n>", "Max results").option("--offset <n>", "Skip n results").option("--organization-id <value>", "Filter by organizationId").hook("preAction", (thisCommand) => {
|
|
179
|
+
projectsCmd.command("list").description("List projects").option("--limit <n>", "Max results").option("--offset <n>", "Skip n results").option("--all", "Fetch all pages").option("--fields <fields>", "Comma-separated fields to print").option("--where <field=value>", "Client-side exact filters, comma-separated").option("--jsonl", "Print one compact JSON object per row").option("--organization-id <value>", "Filter by organizationId").hook("preAction", (thisCommand) => {
|
|
92
180
|
syncRootOptsFromCommand(thisCommand);
|
|
93
181
|
}).action(async (opts) => {
|
|
94
182
|
const token = requireToken();
|
|
@@ -99,10 +187,10 @@ function register(program, helpers) {
|
|
|
99
187
|
if (opts.organizationId != null) {
|
|
100
188
|
query.organizationId = coerceQueryFlag(opts.organizationId, { field: "organizationId", flag: "--organization-id", kind: "string" }, exitWithError);
|
|
101
189
|
}
|
|
102
|
-
const res = await
|
|
190
|
+
const res = await fetchList({ path: "projects", token, baseUrl: getBaseUrl(), query, all: Boolean(opts.all), request: apiRequest });
|
|
103
191
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
104
192
|
const data = res.data?.data ?? [];
|
|
105
|
-
|
|
193
|
+
printList({ format: getOutputFormat(), data, fields: opts.fields, where: opts.where, jsonl: Boolean(opts.jsonl) });
|
|
106
194
|
});
|
|
107
195
|
projectsCmd.command("get <id>").description("Get one projects by id").hook("preAction", (thisCommand) => {
|
|
108
196
|
syncRootOptsFromCommand(thisCommand);
|
|
@@ -131,20 +219,69 @@ function register(program, helpers) {
|
|
|
131
219
|
if (parsedPriority !== void 0) bodyFromFlags.priority = parsedPriority;
|
|
132
220
|
const body = mergeBody(bodyFromFlags, opts.body);
|
|
133
221
|
if (opts.ifNotExists) {
|
|
222
|
+
const existing = await findExistingResource({
|
|
223
|
+
resource: "projects",
|
|
224
|
+
token,
|
|
225
|
+
baseUrl: getBaseUrl(),
|
|
226
|
+
body,
|
|
227
|
+
identityFields: ["name", "organizationId"],
|
|
228
|
+
queryFields: ["organizationId"],
|
|
229
|
+
request: apiRequest
|
|
230
|
+
});
|
|
231
|
+
if (existing) {
|
|
232
|
+
printOutput(getOutputFormat(), existing, false);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
134
235
|
}
|
|
135
236
|
const res = await apiRequest({ method: "POST", path: "projects", token, baseUrl: getBaseUrl(), body });
|
|
136
237
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
137
238
|
const data = res.data?.data ?? res.data;
|
|
138
239
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
139
240
|
});
|
|
140
|
-
projectsCmd.command("update
|
|
241
|
+
projectsCmd.command("update [id]").description("Update projects").option("--body <json>", "Request body JSON (merged with flags)").option("--ids <ids>", "Comma-separated IDs for bulk update (max 25)").option("--ids-file <path>", "File containing IDs for bulk update").option("--input <path>", "JSON/JSONL records for bulk update; use - for stdin").option("--dry-run", "Preview bulk update without sending requests").option("--name <value>", "name").option("--description <value>", "description").option("--priority <value>", "priority").hook("preAction", (thisCommand) => {
|
|
141
242
|
syncRootOptsFromCommand(thisCommand);
|
|
142
243
|
}).action(async (id, opts) => {
|
|
143
244
|
const token = requireToken();
|
|
144
245
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
145
|
-
const
|
|
246
|
+
const inputRecords = await parseBulkInput(opts.input);
|
|
247
|
+
if (inputRecords.length > 0) {
|
|
248
|
+
const ids2 = inputRecords.map(getBulkRecordId).filter((value) => value !== null);
|
|
249
|
+
if (ids2.length !== inputRecords.length) exitWithError(400, "Each --input record must include id or _id");
|
|
250
|
+
validateBulkIds(ids2, "projects");
|
|
251
|
+
if (opts.dryRun) {
|
|
252
|
+
printOutput(getOutputFormat(), { data: ids2.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids2.length, succeeded: ids2.length, failed: 0 } }, false);
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
const { data: data2, summary } = await runBulk({
|
|
256
|
+
items: inputRecords,
|
|
257
|
+
runOne: async (record) => {
|
|
258
|
+
const itemId = getBulkRecordId(record);
|
|
259
|
+
const recordBody = { ...record };
|
|
260
|
+
delete recordBody.id;
|
|
261
|
+
delete recordBody._id;
|
|
262
|
+
const bodyFromFlags2 = {};
|
|
263
|
+
const parsedName2 = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
264
|
+
if (parsedName2 !== void 0) bodyFromFlags2.name = parsedName2;
|
|
265
|
+
const parsedDescription2 = coerceBodyFlag(opts.description, { field: "description", flag: "--description", kind: "string" }, exitWithError);
|
|
266
|
+
if (parsedDescription2 !== void 0) bodyFromFlags2.description = parsedDescription2;
|
|
267
|
+
const parsedPriority2 = coerceBodyFlag(opts.priority, { field: "priority", flag: "--priority", kind: "string" }, exitWithError);
|
|
268
|
+
if (parsedPriority2 !== void 0) bodyFromFlags2.priority = parsedPriority2;
|
|
269
|
+
const body2 = { ...recordBody, ...mergeBody(bodyFromFlags2, opts.body) };
|
|
270
|
+
const res2 = await apiRequest({ method: "PATCH", path: "projects/" + encodeURIComponent(itemId), token, baseUrl: getBaseUrl(), body: body2 });
|
|
271
|
+
return { ok: res2.ok, status: res2.status || 0, data: res2.data, error: res2.error };
|
|
272
|
+
},
|
|
273
|
+
toResult: (record, ok, status, _data, err) => ok ? { _id: getBulkRecordId(record), status: "updated" } : { _id: getBulkRecordId(record) ?? void 0, error: true, statusCode: status, message: err ?? "Failed" }
|
|
274
|
+
});
|
|
275
|
+
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
146
279
|
if (ids.length > 0) {
|
|
147
280
|
validateBulkIds(ids, "projects");
|
|
281
|
+
if (opts.dryRun) {
|
|
282
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
148
285
|
const { data: data2, summary } = await runBulk({
|
|
149
286
|
items: ids,
|
|
150
287
|
runOne: async (itemId) => {
|
|
@@ -164,6 +301,7 @@ function register(program, helpers) {
|
|
|
164
301
|
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
165
302
|
return;
|
|
166
303
|
}
|
|
304
|
+
if (!id) exitWithError(400, "Provide id, --ids, --ids-file, or --input");
|
|
167
305
|
const bodyFromFlags = {};
|
|
168
306
|
const parsedName = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
169
307
|
if (parsedName !== void 0) bodyFromFlags.name = parsedName;
|
|
@@ -177,14 +315,18 @@ function register(program, helpers) {
|
|
|
177
315
|
const data = res.data?.data ?? res.data;
|
|
178
316
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
179
317
|
});
|
|
180
|
-
projectsCmd.command("delete
|
|
318
|
+
projectsCmd.command("delete [id]").description("Delete projects").option("--ids <ids>", "Comma-separated IDs for bulk delete (max 25)").option("--ids-file <path>", "File containing IDs for bulk delete").option("--dry-run", "Preview delete without sending requests").option("--yes", "Confirm destructive bulk delete").hook("preAction", (thisCommand) => {
|
|
181
319
|
syncRootOptsFromCommand(thisCommand);
|
|
182
320
|
}).action(async (id, opts) => {
|
|
183
321
|
const token = requireToken();
|
|
184
322
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
185
|
-
const ids =
|
|
323
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
186
324
|
if (ids.length > 0) {
|
|
187
325
|
validateBulkIds(ids, "projects");
|
|
326
|
+
if (opts.dryRun) {
|
|
327
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_delete" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
188
330
|
const { data, summary } = await runBulk({
|
|
189
331
|
items: ids,
|
|
190
332
|
runOne: async (itemId) => {
|
|
@@ -196,12 +338,17 @@ function register(program, helpers) {
|
|
|
196
338
|
printOutput(getOutputFormat(), { data, summary }, false);
|
|
197
339
|
return;
|
|
198
340
|
}
|
|
341
|
+
if (!id) exitWithError(400, "Provide id, --ids, or --ids-file");
|
|
342
|
+
if (opts.dryRun) {
|
|
343
|
+
printOutput(getOutputFormat(), { _id: id, status: "would_delete" }, false);
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
199
346
|
const res = await apiRequest({ method: "DELETE", path: "projects/" + encodeURIComponent(id), token, baseUrl: getBaseUrl() });
|
|
200
347
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
201
348
|
if (getOutputFormat() === "json") console.log(JSON.stringify({ data: null, deleted: true }));
|
|
202
349
|
});
|
|
203
350
|
const spacesCmd = program.command("spaces").description("spaces resource");
|
|
204
|
-
spacesCmd.command("list").description("List spaces").option("--limit <n>", "Max results").option("--offset <n>", "Skip n results").option("--organization-id <value>", "Filter by organizationId").option("--project-id <value>", "Filter by projectId").hook("preAction", (thisCommand) => {
|
|
351
|
+
spacesCmd.command("list").description("List spaces").option("--limit <n>", "Max results").option("--offset <n>", "Skip n results").option("--all", "Fetch all pages").option("--fields <fields>", "Comma-separated fields to print").option("--where <field=value>", "Client-side exact filters, comma-separated").option("--jsonl", "Print one compact JSON object per row").option("--organization-id <value>", "Filter by organizationId").option("--project-id <value>", "Filter by projectId").hook("preAction", (thisCommand) => {
|
|
205
352
|
syncRootOptsFromCommand(thisCommand);
|
|
206
353
|
}).action(async (opts) => {
|
|
207
354
|
const token = requireToken();
|
|
@@ -215,10 +362,10 @@ function register(program, helpers) {
|
|
|
215
362
|
if (opts.projectId != null) {
|
|
216
363
|
query.projectId = coerceQueryFlag(opts.projectId, { field: "projectId", flag: "--project-id", kind: "string" }, exitWithError);
|
|
217
364
|
}
|
|
218
|
-
const res = await
|
|
365
|
+
const res = await fetchList({ path: "spaces", token, baseUrl: getBaseUrl(), query, all: Boolean(opts.all), request: apiRequest });
|
|
219
366
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
220
367
|
const data = res.data?.data ?? [];
|
|
221
|
-
|
|
368
|
+
printList({ format: getOutputFormat(), data, fields: opts.fields, where: opts.where, jsonl: Boolean(opts.jsonl) });
|
|
222
369
|
});
|
|
223
370
|
spacesCmd.command("get <id>").description("Get one spaces by id").hook("preAction", (thisCommand) => {
|
|
224
371
|
syncRootOptsFromCommand(thisCommand);
|
|
@@ -253,20 +400,75 @@ function register(program, helpers) {
|
|
|
253
400
|
if (parsedCurrentStrength !== void 0) bodyFromFlags.currentStrength = parsedCurrentStrength;
|
|
254
401
|
const body = mergeBody(bodyFromFlags, opts.body);
|
|
255
402
|
if (opts.ifNotExists) {
|
|
403
|
+
const existing = await findExistingResource({
|
|
404
|
+
resource: "spaces",
|
|
405
|
+
token,
|
|
406
|
+
baseUrl: getBaseUrl(),
|
|
407
|
+
body,
|
|
408
|
+
identityFields: ["name", "organizationId", "projectId"],
|
|
409
|
+
queryFields: ["organizationId", "projectId"],
|
|
410
|
+
request: apiRequest
|
|
411
|
+
});
|
|
412
|
+
if (existing) {
|
|
413
|
+
printOutput(getOutputFormat(), existing, false);
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
256
416
|
}
|
|
257
417
|
const res = await apiRequest({ method: "POST", path: "spaces", token, baseUrl: getBaseUrl(), body });
|
|
258
418
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
259
419
|
const data = res.data?.data ?? res.data;
|
|
260
420
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
261
421
|
});
|
|
262
|
-
spacesCmd.command("update
|
|
422
|
+
spacesCmd.command("update [id]").description("Update spaces").option("--body <json>", "Request body JSON (merged with flags)").option("--ids <ids>", "Comma-separated IDs for bulk update (max 25)").option("--ids-file <path>", "File containing IDs for bulk update").option("--input <path>", "JSON/JSONL records for bulk update; use - for stdin").option("--dry-run", "Preview bulk update without sending requests").option("--name <value>", "name").option("--description <value>", "description").option("--project-id <value>", "projectId").option("--status <value>", "status").option("--priority <value>", "priority").option("--current-strength <value>", "currentStrength").hook("preAction", (thisCommand) => {
|
|
263
423
|
syncRootOptsFromCommand(thisCommand);
|
|
264
424
|
}).action(async (id, opts) => {
|
|
265
425
|
const token = requireToken();
|
|
266
426
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
267
|
-
const
|
|
427
|
+
const inputRecords = await parseBulkInput(opts.input);
|
|
428
|
+
if (inputRecords.length > 0) {
|
|
429
|
+
const ids2 = inputRecords.map(getBulkRecordId).filter((value) => value !== null);
|
|
430
|
+
if (ids2.length !== inputRecords.length) exitWithError(400, "Each --input record must include id or _id");
|
|
431
|
+
validateBulkIds(ids2, "spaces");
|
|
432
|
+
if (opts.dryRun) {
|
|
433
|
+
printOutput(getOutputFormat(), { data: ids2.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids2.length, succeeded: ids2.length, failed: 0 } }, false);
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
const { data: data2, summary } = await runBulk({
|
|
437
|
+
items: inputRecords,
|
|
438
|
+
runOne: async (record) => {
|
|
439
|
+
const itemId = getBulkRecordId(record);
|
|
440
|
+
const recordBody = { ...record };
|
|
441
|
+
delete recordBody.id;
|
|
442
|
+
delete recordBody._id;
|
|
443
|
+
const bodyFromFlags2 = {};
|
|
444
|
+
const parsedName2 = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
445
|
+
if (parsedName2 !== void 0) bodyFromFlags2.name = parsedName2;
|
|
446
|
+
const parsedDescription2 = coerceBodyFlag(opts.description, { field: "description", flag: "--description", kind: "string" }, exitWithError);
|
|
447
|
+
if (parsedDescription2 !== void 0) bodyFromFlags2.description = parsedDescription2;
|
|
448
|
+
const parsedProjectId2 = coerceBodyFlag(opts.projectId, { field: "projectId", flag: "--project-id", kind: "string", allowNull: true }, exitWithError);
|
|
449
|
+
if (parsedProjectId2 !== void 0) bodyFromFlags2.projectId = parsedProjectId2;
|
|
450
|
+
const parsedStatus2 = coerceBodyFlag(opts.status, { field: "status", flag: "--status", kind: "string" }, exitWithError);
|
|
451
|
+
if (parsedStatus2 !== void 0) bodyFromFlags2.status = parsedStatus2;
|
|
452
|
+
const parsedPriority2 = coerceBodyFlag(opts.priority, { field: "priority", flag: "--priority", kind: "string" }, exitWithError);
|
|
453
|
+
if (parsedPriority2 !== void 0) bodyFromFlags2.priority = parsedPriority2;
|
|
454
|
+
const parsedCurrentStrength2 = coerceBodyFlag(opts.currentStrength, { field: "currentStrength", flag: "--current-strength", kind: "number" }, exitWithError);
|
|
455
|
+
if (parsedCurrentStrength2 !== void 0) bodyFromFlags2.currentStrength = parsedCurrentStrength2;
|
|
456
|
+
const body2 = { ...recordBody, ...mergeBody(bodyFromFlags2, opts.body) };
|
|
457
|
+
const res2 = await apiRequest({ method: "PATCH", path: "spaces/" + encodeURIComponent(itemId), token, baseUrl: getBaseUrl(), body: body2 });
|
|
458
|
+
return { ok: res2.ok, status: res2.status || 0, data: res2.data, error: res2.error };
|
|
459
|
+
},
|
|
460
|
+
toResult: (record, ok, status, _data, err) => ok ? { _id: getBulkRecordId(record), status: "updated" } : { _id: getBulkRecordId(record) ?? void 0, error: true, statusCode: status, message: err ?? "Failed" }
|
|
461
|
+
});
|
|
462
|
+
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
268
466
|
if (ids.length > 0) {
|
|
269
467
|
validateBulkIds(ids, "spaces");
|
|
468
|
+
if (opts.dryRun) {
|
|
469
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
270
472
|
const { data: data2, summary } = await runBulk({
|
|
271
473
|
items: ids,
|
|
272
474
|
runOne: async (itemId) => {
|
|
@@ -292,6 +494,7 @@ function register(program, helpers) {
|
|
|
292
494
|
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
293
495
|
return;
|
|
294
496
|
}
|
|
497
|
+
if (!id) exitWithError(400, "Provide id, --ids, --ids-file, or --input");
|
|
295
498
|
const bodyFromFlags = {};
|
|
296
499
|
const parsedName = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
297
500
|
if (parsedName !== void 0) bodyFromFlags.name = parsedName;
|
|
@@ -311,14 +514,18 @@ function register(program, helpers) {
|
|
|
311
514
|
const data = res.data?.data ?? res.data;
|
|
312
515
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
313
516
|
});
|
|
314
|
-
spacesCmd.command("delete
|
|
517
|
+
spacesCmd.command("delete [id]").description("Delete spaces").option("--ids <ids>", "Comma-separated IDs for bulk delete (max 25)").option("--ids-file <path>", "File containing IDs for bulk delete").option("--dry-run", "Preview delete without sending requests").option("--yes", "Confirm destructive bulk delete").hook("preAction", (thisCommand) => {
|
|
315
518
|
syncRootOptsFromCommand(thisCommand);
|
|
316
519
|
}).action(async (id, opts) => {
|
|
317
520
|
const token = requireToken();
|
|
318
521
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
319
|
-
const ids =
|
|
522
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
320
523
|
if (ids.length > 0) {
|
|
321
524
|
validateBulkIds(ids, "spaces");
|
|
525
|
+
if (opts.dryRun) {
|
|
526
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_delete" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
322
529
|
const { data, summary } = await runBulk({
|
|
323
530
|
items: ids,
|
|
324
531
|
runOne: async (itemId) => {
|
|
@@ -330,12 +537,17 @@ function register(program, helpers) {
|
|
|
330
537
|
printOutput(getOutputFormat(), { data, summary }, false);
|
|
331
538
|
return;
|
|
332
539
|
}
|
|
540
|
+
if (!id) exitWithError(400, "Provide id, --ids, or --ids-file");
|
|
541
|
+
if (opts.dryRun) {
|
|
542
|
+
printOutput(getOutputFormat(), { _id: id, status: "would_delete" }, false);
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
333
545
|
const res = await apiRequest({ method: "DELETE", path: "spaces/" + encodeURIComponent(id), token, baseUrl: getBaseUrl() });
|
|
334
546
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
335
547
|
if (getOutputFormat() === "json") console.log(JSON.stringify({ data: null, deleted: true }));
|
|
336
548
|
});
|
|
337
549
|
const scoutsCmd = program.command("scouts").description("scouts resource");
|
|
338
|
-
scoutsCmd.command("list").description("List scouts").option("--limit <n>", "Max results").option("--offset <n>", "Skip n results").option("--organization-id <value>", "Filter by organizationId").option("--category-id <value>", "Filter by categoryId").hook("preAction", (thisCommand) => {
|
|
550
|
+
scoutsCmd.command("list").description("List scouts").option("--limit <n>", "Max results").option("--offset <n>", "Skip n results").option("--all", "Fetch all pages").option("--fields <fields>", "Comma-separated fields to print").option("--where <field=value>", "Client-side exact filters, comma-separated").option("--jsonl", "Print one compact JSON object per row").option("--organization-id <value>", "Filter by organizationId").option("--category-id <value>", "Filter by categoryId").hook("preAction", (thisCommand) => {
|
|
339
551
|
syncRootOptsFromCommand(thisCommand);
|
|
340
552
|
}).action(async (opts) => {
|
|
341
553
|
const token = requireToken();
|
|
@@ -349,10 +561,10 @@ function register(program, helpers) {
|
|
|
349
561
|
if (opts.categoryId != null) {
|
|
350
562
|
query.categoryId = coerceQueryFlag(opts.categoryId, { field: "categoryId", flag: "--category-id", kind: "string" }, exitWithError);
|
|
351
563
|
}
|
|
352
|
-
const res = await
|
|
564
|
+
const res = await fetchList({ path: "scouts", token, baseUrl: getBaseUrl(), query, all: Boolean(opts.all), request: apiRequest });
|
|
353
565
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
354
566
|
const data = res.data?.data ?? [];
|
|
355
|
-
|
|
567
|
+
printList({ format: getOutputFormat(), data, fields: opts.fields, where: opts.where, jsonl: Boolean(opts.jsonl) });
|
|
356
568
|
});
|
|
357
569
|
scoutsCmd.command("get <id>").description("Get one scouts by id").hook("preAction", (thisCommand) => {
|
|
358
570
|
syncRootOptsFromCommand(thisCommand);
|
|
@@ -413,20 +625,99 @@ function register(program, helpers) {
|
|
|
413
625
|
if (parsedActivationPotential !== void 0) bodyFromFlags.activationPotential = parsedActivationPotential;
|
|
414
626
|
const body = mergeBody(bodyFromFlags, opts.body);
|
|
415
627
|
if (opts.ifNotExists) {
|
|
628
|
+
const existing = await findExistingResource({
|
|
629
|
+
resource: "scouts",
|
|
630
|
+
token,
|
|
631
|
+
baseUrl: getBaseUrl(),
|
|
632
|
+
body,
|
|
633
|
+
identityFields: ["name", "organizationId"],
|
|
634
|
+
queryFields: ["organizationId", "categoryId"],
|
|
635
|
+
request: apiRequest
|
|
636
|
+
});
|
|
637
|
+
if (existing) {
|
|
638
|
+
printOutput(getOutputFormat(), existing, false);
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
416
641
|
}
|
|
417
642
|
const res = await apiRequest({ method: "POST", path: "scouts", token, baseUrl: getBaseUrl(), body });
|
|
418
643
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
419
644
|
const data = res.data?.data ?? res.data;
|
|
420
645
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
421
646
|
});
|
|
422
|
-
scoutsCmd.command("update
|
|
647
|
+
scoutsCmd.command("update [id]").description("Update scouts").option("--body <json>", "Request body JSON (merged with flags)").option("--ids <ids>", "Comma-separated IDs for bulk update (max 25)").option("--ids-file <path>", "File containing IDs for bulk update").option("--input <path>", "JSON/JSONL records for bulk update; use - for stdin").option("--dry-run", "Preview bulk update without sending requests").option("--name <value>", "name").option("--description <value>", "description").option("--category-id <value>", "categoryId").option("--url <value>", "url").option("--hero-image <value>", "heroImage").option("--priority <value>", "priority").option("--status <value>", "status").option("--estimated-cost <value>", "estimatedCost").option("--potential-cost <value>", "potentialCost").option("--need <value>", "need").option("--urgency <value>", "urgency").option("--use <value>", "use").option("--longevity <value>", "longevity").option("--roi <value>", "roi").option("--system-fit <value>", "systemFit").option("--emotional-pull <value>", "emotionalPull").option("--infrastructure-fit <value>", "infrastructureFit").option("--activation-potential <value>", "activationPotential").hook("preAction", (thisCommand) => {
|
|
423
648
|
syncRootOptsFromCommand(thisCommand);
|
|
424
649
|
}).action(async (id, opts) => {
|
|
425
650
|
const token = requireToken();
|
|
426
651
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
427
|
-
const
|
|
652
|
+
const inputRecords = await parseBulkInput(opts.input);
|
|
653
|
+
if (inputRecords.length > 0) {
|
|
654
|
+
const ids2 = inputRecords.map(getBulkRecordId).filter((value) => value !== null);
|
|
655
|
+
if (ids2.length !== inputRecords.length) exitWithError(400, "Each --input record must include id or _id");
|
|
656
|
+
validateBulkIds(ids2, "scouts");
|
|
657
|
+
if (opts.dryRun) {
|
|
658
|
+
printOutput(getOutputFormat(), { data: ids2.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids2.length, succeeded: ids2.length, failed: 0 } }, false);
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
const { data: data2, summary } = await runBulk({
|
|
662
|
+
items: inputRecords,
|
|
663
|
+
runOne: async (record) => {
|
|
664
|
+
const itemId = getBulkRecordId(record);
|
|
665
|
+
const recordBody = { ...record };
|
|
666
|
+
delete recordBody.id;
|
|
667
|
+
delete recordBody._id;
|
|
668
|
+
const bodyFromFlags2 = {};
|
|
669
|
+
const parsedName2 = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
670
|
+
if (parsedName2 !== void 0) bodyFromFlags2.name = parsedName2;
|
|
671
|
+
const parsedDescription2 = coerceBodyFlag(opts.description, { field: "description", flag: "--description", kind: "string" }, exitWithError);
|
|
672
|
+
if (parsedDescription2 !== void 0) bodyFromFlags2.description = parsedDescription2;
|
|
673
|
+
const parsedCategoryId2 = coerceBodyFlag(opts.categoryId, { field: "categoryId", flag: "--category-id", kind: "string", allowNull: true }, exitWithError);
|
|
674
|
+
if (parsedCategoryId2 !== void 0) bodyFromFlags2.categoryId = parsedCategoryId2;
|
|
675
|
+
const parsedUrl2 = coerceBodyFlag(opts.url, { field: "url", flag: "--url", kind: "string" }, exitWithError);
|
|
676
|
+
if (parsedUrl2 !== void 0) bodyFromFlags2.url = parsedUrl2;
|
|
677
|
+
const parsedHeroImage2 = coerceBodyFlag(opts.heroImage, { field: "heroImage", flag: "--hero-image", kind: "string" }, exitWithError);
|
|
678
|
+
if (parsedHeroImage2 !== void 0) bodyFromFlags2.heroImage = parsedHeroImage2;
|
|
679
|
+
const parsedPriority2 = coerceBodyFlag(opts.priority, { field: "priority", flag: "--priority", kind: "string" }, exitWithError);
|
|
680
|
+
if (parsedPriority2 !== void 0) bodyFromFlags2.priority = parsedPriority2;
|
|
681
|
+
const parsedStatus2 = coerceBodyFlag(opts.status, { field: "status", flag: "--status", kind: "string" }, exitWithError);
|
|
682
|
+
if (parsedStatus2 !== void 0) bodyFromFlags2.status = parsedStatus2;
|
|
683
|
+
const parsedEstimatedCost2 = coerceBodyFlag(opts.estimatedCost, { field: "estimatedCost", flag: "--estimated-cost", kind: "number" }, exitWithError);
|
|
684
|
+
if (parsedEstimatedCost2 !== void 0) bodyFromFlags2.estimatedCost = parsedEstimatedCost2;
|
|
685
|
+
const parsedPotentialCost2 = coerceBodyFlag(opts.potentialCost, { field: "potentialCost", flag: "--potential-cost", kind: "number" }, exitWithError);
|
|
686
|
+
if (parsedPotentialCost2 !== void 0) bodyFromFlags2.potentialCost = parsedPotentialCost2;
|
|
687
|
+
const parsedNeed2 = coerceBodyFlag(opts.need, { field: "need", flag: "--need", kind: "number" }, exitWithError);
|
|
688
|
+
if (parsedNeed2 !== void 0) bodyFromFlags2.need = parsedNeed2;
|
|
689
|
+
const parsedUrgency2 = coerceBodyFlag(opts.urgency, { field: "urgency", flag: "--urgency", kind: "number" }, exitWithError);
|
|
690
|
+
if (parsedUrgency2 !== void 0) bodyFromFlags2.urgency = parsedUrgency2;
|
|
691
|
+
const parsedUse2 = coerceBodyFlag(opts.use, { field: "use", flag: "--use", kind: "number" }, exitWithError);
|
|
692
|
+
if (parsedUse2 !== void 0) bodyFromFlags2.use = parsedUse2;
|
|
693
|
+
const parsedLongevity2 = coerceBodyFlag(opts.longevity, { field: "longevity", flag: "--longevity", kind: "number" }, exitWithError);
|
|
694
|
+
if (parsedLongevity2 !== void 0) bodyFromFlags2.longevity = parsedLongevity2;
|
|
695
|
+
const parsedRoi2 = coerceBodyFlag(opts.roi, { field: "roi", flag: "--roi", kind: "number" }, exitWithError);
|
|
696
|
+
if (parsedRoi2 !== void 0) bodyFromFlags2.roi = parsedRoi2;
|
|
697
|
+
const parsedSystemFit2 = coerceBodyFlag(opts.systemFit, { field: "systemFit", flag: "--system-fit", kind: "number" }, exitWithError);
|
|
698
|
+
if (parsedSystemFit2 !== void 0) bodyFromFlags2.systemFit = parsedSystemFit2;
|
|
699
|
+
const parsedEmotionalPull2 = coerceBodyFlag(opts.emotionalPull, { field: "emotionalPull", flag: "--emotional-pull", kind: "number" }, exitWithError);
|
|
700
|
+
if (parsedEmotionalPull2 !== void 0) bodyFromFlags2.emotionalPull = parsedEmotionalPull2;
|
|
701
|
+
const parsedInfrastructureFit2 = coerceBodyFlag(opts.infrastructureFit, { field: "infrastructureFit", flag: "--infrastructure-fit", kind: "number" }, exitWithError);
|
|
702
|
+
if (parsedInfrastructureFit2 !== void 0) bodyFromFlags2.infrastructureFit = parsedInfrastructureFit2;
|
|
703
|
+
const parsedActivationPotential2 = coerceBodyFlag(opts.activationPotential, { field: "activationPotential", flag: "--activation-potential", kind: "number" }, exitWithError);
|
|
704
|
+
if (parsedActivationPotential2 !== void 0) bodyFromFlags2.activationPotential = parsedActivationPotential2;
|
|
705
|
+
const body2 = { ...recordBody, ...mergeBody(bodyFromFlags2, opts.body) };
|
|
706
|
+
const res2 = await apiRequest({ method: "PATCH", path: "scouts/" + encodeURIComponent(itemId), token, baseUrl: getBaseUrl(), body: body2 });
|
|
707
|
+
return { ok: res2.ok, status: res2.status || 0, data: res2.data, error: res2.error };
|
|
708
|
+
},
|
|
709
|
+
toResult: (record, ok, status, _data, err) => ok ? { _id: getBulkRecordId(record), status: "updated" } : { _id: getBulkRecordId(record) ?? void 0, error: true, statusCode: status, message: err ?? "Failed" }
|
|
710
|
+
});
|
|
711
|
+
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
712
|
+
return;
|
|
713
|
+
}
|
|
714
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
428
715
|
if (ids.length > 0) {
|
|
429
716
|
validateBulkIds(ids, "scouts");
|
|
717
|
+
if (opts.dryRun) {
|
|
718
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
719
|
+
return;
|
|
720
|
+
}
|
|
430
721
|
const { data: data2, summary } = await runBulk({
|
|
431
722
|
items: ids,
|
|
432
723
|
runOne: async (itemId) => {
|
|
@@ -476,6 +767,7 @@ function register(program, helpers) {
|
|
|
476
767
|
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
477
768
|
return;
|
|
478
769
|
}
|
|
770
|
+
if (!id) exitWithError(400, "Provide id, --ids, --ids-file, or --input");
|
|
479
771
|
const bodyFromFlags = {};
|
|
480
772
|
const parsedName = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
481
773
|
if (parsedName !== void 0) bodyFromFlags.name = parsedName;
|
|
@@ -519,14 +811,18 @@ function register(program, helpers) {
|
|
|
519
811
|
const data = res.data?.data ?? res.data;
|
|
520
812
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
521
813
|
});
|
|
522
|
-
scoutsCmd.command("delete
|
|
814
|
+
scoutsCmd.command("delete [id]").description("Delete scouts").option("--ids <ids>", "Comma-separated IDs for bulk delete (max 25)").option("--ids-file <path>", "File containing IDs for bulk delete").option("--dry-run", "Preview delete without sending requests").option("--yes", "Confirm destructive bulk delete").hook("preAction", (thisCommand) => {
|
|
523
815
|
syncRootOptsFromCommand(thisCommand);
|
|
524
816
|
}).action(async (id, opts) => {
|
|
525
817
|
const token = requireToken();
|
|
526
818
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
527
|
-
const ids =
|
|
819
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
528
820
|
if (ids.length > 0) {
|
|
529
821
|
validateBulkIds(ids, "scouts");
|
|
822
|
+
if (opts.dryRun) {
|
|
823
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_delete" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
824
|
+
return;
|
|
825
|
+
}
|
|
530
826
|
const { data, summary } = await runBulk({
|
|
531
827
|
items: ids,
|
|
532
828
|
runOne: async (itemId) => {
|
|
@@ -538,12 +834,17 @@ function register(program, helpers) {
|
|
|
538
834
|
printOutput(getOutputFormat(), { data, summary }, false);
|
|
539
835
|
return;
|
|
540
836
|
}
|
|
837
|
+
if (!id) exitWithError(400, "Provide id, --ids, or --ids-file");
|
|
838
|
+
if (opts.dryRun) {
|
|
839
|
+
printOutput(getOutputFormat(), { _id: id, status: "would_delete" }, false);
|
|
840
|
+
return;
|
|
841
|
+
}
|
|
541
842
|
const res = await apiRequest({ method: "DELETE", path: "scouts/" + encodeURIComponent(id), token, baseUrl: getBaseUrl() });
|
|
542
843
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
543
844
|
if (getOutputFormat() === "json") console.log(JSON.stringify({ data: null, deleted: true }));
|
|
544
845
|
});
|
|
545
846
|
const assetsCmd = program.command("assets").description("assets resource");
|
|
546
|
-
assetsCmd.command("list").description("List assets").option("--limit <n>", "Max results").option("--offset <n>", "Skip n results").option("--organization-id <value>", "Filter by organizationId").option("--scout-id <value>", "Filter by scoutId").hook("preAction", (thisCommand) => {
|
|
847
|
+
assetsCmd.command("list").description("List assets").option("--limit <n>", "Max results").option("--offset <n>", "Skip n results").option("--all", "Fetch all pages").option("--fields <fields>", "Comma-separated fields to print").option("--where <field=value>", "Client-side exact filters, comma-separated").option("--jsonl", "Print one compact JSON object per row").option("--organization-id <value>", "Filter by organizationId").option("--scout-id <value>", "Filter by scoutId").hook("preAction", (thisCommand) => {
|
|
547
848
|
syncRootOptsFromCommand(thisCommand);
|
|
548
849
|
}).action(async (opts) => {
|
|
549
850
|
const token = requireToken();
|
|
@@ -557,10 +858,10 @@ function register(program, helpers) {
|
|
|
557
858
|
if (opts.scoutId != null) {
|
|
558
859
|
query.scoutId = coerceQueryFlag(opts.scoutId, { field: "scoutId", flag: "--scout-id", kind: "string" }, exitWithError);
|
|
559
860
|
}
|
|
560
|
-
const res = await
|
|
861
|
+
const res = await fetchList({ path: "assets", token, baseUrl: getBaseUrl(), query, all: Boolean(opts.all), request: apiRequest });
|
|
561
862
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
562
863
|
const data = res.data?.data ?? [];
|
|
563
|
-
|
|
864
|
+
printList({ format: getOutputFormat(), data, fields: opts.fields, where: opts.where, jsonl: Boolean(opts.jsonl) });
|
|
564
865
|
});
|
|
565
866
|
assetsCmd.command("get <id>").description("Get one assets by id").hook("preAction", (thisCommand) => {
|
|
566
867
|
syncRootOptsFromCommand(thisCommand);
|
|
@@ -607,20 +908,87 @@ function register(program, helpers) {
|
|
|
607
908
|
if (parsedCost !== void 0) bodyFromFlags.cost = parsedCost;
|
|
608
909
|
const body = mergeBody(bodyFromFlags, opts.body);
|
|
609
910
|
if (opts.ifNotExists) {
|
|
911
|
+
const existing = await findExistingResource({
|
|
912
|
+
resource: "assets",
|
|
913
|
+
token,
|
|
914
|
+
baseUrl: getBaseUrl(),
|
|
915
|
+
body,
|
|
916
|
+
identityFields: ["name", "organizationId"],
|
|
917
|
+
queryFields: ["organizationId", "scoutId"],
|
|
918
|
+
request: apiRequest
|
|
919
|
+
});
|
|
920
|
+
if (existing) {
|
|
921
|
+
printOutput(getOutputFormat(), existing, false);
|
|
922
|
+
return;
|
|
923
|
+
}
|
|
610
924
|
}
|
|
611
925
|
const res = await apiRequest({ method: "POST", path: "assets", token, baseUrl: getBaseUrl(), body });
|
|
612
926
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
613
927
|
const data = res.data?.data ?? res.data;
|
|
614
928
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
615
929
|
});
|
|
616
|
-
assetsCmd.command("update
|
|
930
|
+
assetsCmd.command("update [id]").description("Update assets").option("--body <json>", "Request body JSON (merged with flags)").option("--ids <ids>", "Comma-separated IDs for bulk update (max 25)").option("--ids-file <path>", "File containing IDs for bulk update").option("--input <path>", "JSON/JSONL records for bulk update; use - for stdin").option("--dry-run", "Preview bulk update without sending requests").option("--name <value>", "name").option("--description <value>", "description").option("--scout-id <value>", "scoutId").option("--category-id <value>", "categoryId").option("--hero-image <value>", "heroImage").option("--condition <value>", "condition").option("--satisfaction <value>", "satisfaction").option("--usage <value>", "usage").option("--friction <value>", "friction").option("--lifetime-value <value>", "lifetimeValue").option("--acquisition-date <value>", "acquisitionDate").option("--cost <value>", "cost").hook("preAction", (thisCommand) => {
|
|
617
931
|
syncRootOptsFromCommand(thisCommand);
|
|
618
932
|
}).action(async (id, opts) => {
|
|
619
933
|
const token = requireToken();
|
|
620
934
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
621
|
-
const
|
|
935
|
+
const inputRecords = await parseBulkInput(opts.input);
|
|
936
|
+
if (inputRecords.length > 0) {
|
|
937
|
+
const ids2 = inputRecords.map(getBulkRecordId).filter((value) => value !== null);
|
|
938
|
+
if (ids2.length !== inputRecords.length) exitWithError(400, "Each --input record must include id or _id");
|
|
939
|
+
validateBulkIds(ids2, "assets");
|
|
940
|
+
if (opts.dryRun) {
|
|
941
|
+
printOutput(getOutputFormat(), { data: ids2.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids2.length, succeeded: ids2.length, failed: 0 } }, false);
|
|
942
|
+
return;
|
|
943
|
+
}
|
|
944
|
+
const { data: data2, summary } = await runBulk({
|
|
945
|
+
items: inputRecords,
|
|
946
|
+
runOne: async (record) => {
|
|
947
|
+
const itemId = getBulkRecordId(record);
|
|
948
|
+
const recordBody = { ...record };
|
|
949
|
+
delete recordBody.id;
|
|
950
|
+
delete recordBody._id;
|
|
951
|
+
const bodyFromFlags2 = {};
|
|
952
|
+
const parsedName2 = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
953
|
+
if (parsedName2 !== void 0) bodyFromFlags2.name = parsedName2;
|
|
954
|
+
const parsedDescription2 = coerceBodyFlag(opts.description, { field: "description", flag: "--description", kind: "string" }, exitWithError);
|
|
955
|
+
if (parsedDescription2 !== void 0) bodyFromFlags2.description = parsedDescription2;
|
|
956
|
+
const parsedScoutId2 = coerceBodyFlag(opts.scoutId, { field: "scoutId", flag: "--scout-id", kind: "string", allowNull: true }, exitWithError);
|
|
957
|
+
if (parsedScoutId2 !== void 0) bodyFromFlags2.scoutId = parsedScoutId2;
|
|
958
|
+
const parsedCategoryId2 = coerceBodyFlag(opts.categoryId, { field: "categoryId", flag: "--category-id", kind: "string", allowNull: true }, exitWithError);
|
|
959
|
+
if (parsedCategoryId2 !== void 0) bodyFromFlags2.categoryId = parsedCategoryId2;
|
|
960
|
+
const parsedHeroImage2 = coerceBodyFlag(opts.heroImage, { field: "heroImage", flag: "--hero-image", kind: "string" }, exitWithError);
|
|
961
|
+
if (parsedHeroImage2 !== void 0) bodyFromFlags2.heroImage = parsedHeroImage2;
|
|
962
|
+
const parsedCondition2 = coerceBodyFlag(opts.condition, { field: "condition", flag: "--condition", kind: "number" }, exitWithError);
|
|
963
|
+
if (parsedCondition2 !== void 0) bodyFromFlags2.condition = parsedCondition2;
|
|
964
|
+
const parsedSatisfaction2 = coerceBodyFlag(opts.satisfaction, { field: "satisfaction", flag: "--satisfaction", kind: "number" }, exitWithError);
|
|
965
|
+
if (parsedSatisfaction2 !== void 0) bodyFromFlags2.satisfaction = parsedSatisfaction2;
|
|
966
|
+
const parsedUsage2 = coerceBodyFlag(opts.usage, { field: "usage", flag: "--usage", kind: "number" }, exitWithError);
|
|
967
|
+
if (parsedUsage2 !== void 0) bodyFromFlags2.usage = parsedUsage2;
|
|
968
|
+
const parsedFriction2 = coerceBodyFlag(opts.friction, { field: "friction", flag: "--friction", kind: "number" }, exitWithError);
|
|
969
|
+
if (parsedFriction2 !== void 0) bodyFromFlags2.friction = parsedFriction2;
|
|
970
|
+
const parsedLifetimeValue2 = coerceBodyFlag(opts.lifetimeValue, { field: "lifetimeValue", flag: "--lifetime-value", kind: "number" }, exitWithError);
|
|
971
|
+
if (parsedLifetimeValue2 !== void 0) bodyFromFlags2.lifetimeValue = parsedLifetimeValue2;
|
|
972
|
+
const parsedAcquisitionDate2 = coerceBodyFlag(opts.acquisitionDate, { field: "acquisitionDate", flag: "--acquisition-date", kind: "number" }, exitWithError);
|
|
973
|
+
if (parsedAcquisitionDate2 !== void 0) bodyFromFlags2.acquisitionDate = parsedAcquisitionDate2;
|
|
974
|
+
const parsedCost2 = coerceBodyFlag(opts.cost, { field: "cost", flag: "--cost", kind: "number" }, exitWithError);
|
|
975
|
+
if (parsedCost2 !== void 0) bodyFromFlags2.cost = parsedCost2;
|
|
976
|
+
const body2 = { ...recordBody, ...mergeBody(bodyFromFlags2, opts.body) };
|
|
977
|
+
const res2 = await apiRequest({ method: "PATCH", path: "assets/" + encodeURIComponent(itemId), token, baseUrl: getBaseUrl(), body: body2 });
|
|
978
|
+
return { ok: res2.ok, status: res2.status || 0, data: res2.data, error: res2.error };
|
|
979
|
+
},
|
|
980
|
+
toResult: (record, ok, status, _data, err) => ok ? { _id: getBulkRecordId(record), status: "updated" } : { _id: getBulkRecordId(record) ?? void 0, error: true, statusCode: status, message: err ?? "Failed" }
|
|
981
|
+
});
|
|
982
|
+
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
983
|
+
return;
|
|
984
|
+
}
|
|
985
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
622
986
|
if (ids.length > 0) {
|
|
623
987
|
validateBulkIds(ids, "assets");
|
|
988
|
+
if (opts.dryRun) {
|
|
989
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
990
|
+
return;
|
|
991
|
+
}
|
|
624
992
|
const { data: data2, summary } = await runBulk({
|
|
625
993
|
items: ids,
|
|
626
994
|
runOne: async (itemId) => {
|
|
@@ -658,6 +1026,7 @@ function register(program, helpers) {
|
|
|
658
1026
|
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
659
1027
|
return;
|
|
660
1028
|
}
|
|
1029
|
+
if (!id) exitWithError(400, "Provide id, --ids, --ids-file, or --input");
|
|
661
1030
|
const bodyFromFlags = {};
|
|
662
1031
|
const parsedName = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
663
1032
|
if (parsedName !== void 0) bodyFromFlags.name = parsedName;
|
|
@@ -689,14 +1058,18 @@ function register(program, helpers) {
|
|
|
689
1058
|
const data = res.data?.data ?? res.data;
|
|
690
1059
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
691
1060
|
});
|
|
692
|
-
assetsCmd.command("delete
|
|
1061
|
+
assetsCmd.command("delete [id]").description("Delete assets").option("--ids <ids>", "Comma-separated IDs for bulk delete (max 25)").option("--ids-file <path>", "File containing IDs for bulk delete").option("--dry-run", "Preview delete without sending requests").option("--yes", "Confirm destructive bulk delete").hook("preAction", (thisCommand) => {
|
|
693
1062
|
syncRootOptsFromCommand(thisCommand);
|
|
694
1063
|
}).action(async (id, opts) => {
|
|
695
1064
|
const token = requireToken();
|
|
696
1065
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
697
|
-
const ids =
|
|
1066
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
698
1067
|
if (ids.length > 0) {
|
|
699
1068
|
validateBulkIds(ids, "assets");
|
|
1069
|
+
if (opts.dryRun) {
|
|
1070
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_delete" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
1071
|
+
return;
|
|
1072
|
+
}
|
|
700
1073
|
const { data, summary } = await runBulk({
|
|
701
1074
|
items: ids,
|
|
702
1075
|
runOne: async (itemId) => {
|
|
@@ -708,12 +1081,17 @@ function register(program, helpers) {
|
|
|
708
1081
|
printOutput(getOutputFormat(), { data, summary }, false);
|
|
709
1082
|
return;
|
|
710
1083
|
}
|
|
1084
|
+
if (!id) exitWithError(400, "Provide id, --ids, or --ids-file");
|
|
1085
|
+
if (opts.dryRun) {
|
|
1086
|
+
printOutput(getOutputFormat(), { _id: id, status: "would_delete" }, false);
|
|
1087
|
+
return;
|
|
1088
|
+
}
|
|
711
1089
|
const res = await apiRequest({ method: "DELETE", path: "assets/" + encodeURIComponent(id), token, baseUrl: getBaseUrl() });
|
|
712
1090
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
713
1091
|
if (getOutputFormat() === "json") console.log(JSON.stringify({ data: null, deleted: true }));
|
|
714
1092
|
});
|
|
715
1093
|
const categoriesCmd = program.command("categories").description("categories resource");
|
|
716
|
-
categoriesCmd.command("list").description("List categories").option("--limit <n>", "Max results").option("--offset <n>", "Skip n results").option("--organization-id <value>", "Filter by organizationId").hook("preAction", (thisCommand) => {
|
|
1094
|
+
categoriesCmd.command("list").description("List categories").option("--limit <n>", "Max results").option("--offset <n>", "Skip n results").option("--all", "Fetch all pages").option("--fields <fields>", "Comma-separated fields to print").option("--where <field=value>", "Client-side exact filters, comma-separated").option("--jsonl", "Print one compact JSON object per row").option("--organization-id <value>", "Filter by organizationId").hook("preAction", (thisCommand) => {
|
|
717
1095
|
syncRootOptsFromCommand(thisCommand);
|
|
718
1096
|
}).action(async (opts) => {
|
|
719
1097
|
const token = requireToken();
|
|
@@ -724,10 +1102,10 @@ function register(program, helpers) {
|
|
|
724
1102
|
if (opts.organizationId != null) {
|
|
725
1103
|
query.organizationId = coerceQueryFlag(opts.organizationId, { field: "organizationId", flag: "--organization-id", kind: "string" }, exitWithError);
|
|
726
1104
|
}
|
|
727
|
-
const res = await
|
|
1105
|
+
const res = await fetchList({ path: "categories", token, baseUrl: getBaseUrl(), query, all: Boolean(opts.all), request: apiRequest });
|
|
728
1106
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
729
1107
|
const data = res.data?.data ?? [];
|
|
730
|
-
|
|
1108
|
+
printList({ format: getOutputFormat(), data, fields: opts.fields, where: opts.where, jsonl: Boolean(opts.jsonl) });
|
|
731
1109
|
});
|
|
732
1110
|
categoriesCmd.command("get <id>").description("Get one categories by id").hook("preAction", (thisCommand) => {
|
|
733
1111
|
syncRootOptsFromCommand(thisCommand);
|
|
@@ -754,20 +1132,67 @@ function register(program, helpers) {
|
|
|
754
1132
|
if (parsedDefaultBucket !== void 0) bodyFromFlags.defaultBucket = parsedDefaultBucket;
|
|
755
1133
|
const body = mergeBody(bodyFromFlags, opts.body);
|
|
756
1134
|
if (opts.ifNotExists) {
|
|
1135
|
+
const existing = await findExistingResource({
|
|
1136
|
+
resource: "categories",
|
|
1137
|
+
token,
|
|
1138
|
+
baseUrl: getBaseUrl(),
|
|
1139
|
+
body,
|
|
1140
|
+
identityFields: ["name", "organizationId"],
|
|
1141
|
+
queryFields: ["organizationId"],
|
|
1142
|
+
request: apiRequest
|
|
1143
|
+
});
|
|
1144
|
+
if (existing) {
|
|
1145
|
+
printOutput(getOutputFormat(), existing, false);
|
|
1146
|
+
return;
|
|
1147
|
+
}
|
|
757
1148
|
}
|
|
758
1149
|
const res = await apiRequest({ method: "POST", path: "categories", token, baseUrl: getBaseUrl(), body });
|
|
759
1150
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
760
1151
|
const data = res.data?.data ?? res.data;
|
|
761
1152
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
762
1153
|
});
|
|
763
|
-
categoriesCmd.command("update
|
|
1154
|
+
categoriesCmd.command("update [id]").description("Update categories").option("--body <json>", "Request body JSON (merged with flags)").option("--ids <ids>", "Comma-separated IDs for bulk update (max 25)").option("--ids-file <path>", "File containing IDs for bulk update").option("--input <path>", "JSON/JSONL records for bulk update; use - for stdin").option("--dry-run", "Preview bulk update without sending requests").option("--name <value>", "name").option("--default-bucket <value>", "defaultBucket").hook("preAction", (thisCommand) => {
|
|
764
1155
|
syncRootOptsFromCommand(thisCommand);
|
|
765
1156
|
}).action(async (id, opts) => {
|
|
766
1157
|
const token = requireToken();
|
|
767
1158
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
768
|
-
const
|
|
1159
|
+
const inputRecords = await parseBulkInput(opts.input);
|
|
1160
|
+
if (inputRecords.length > 0) {
|
|
1161
|
+
const ids2 = inputRecords.map(getBulkRecordId).filter((value) => value !== null);
|
|
1162
|
+
if (ids2.length !== inputRecords.length) exitWithError(400, "Each --input record must include id or _id");
|
|
1163
|
+
validateBulkIds(ids2, "categories");
|
|
1164
|
+
if (opts.dryRun) {
|
|
1165
|
+
printOutput(getOutputFormat(), { data: ids2.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids2.length, succeeded: ids2.length, failed: 0 } }, false);
|
|
1166
|
+
return;
|
|
1167
|
+
}
|
|
1168
|
+
const { data: data2, summary } = await runBulk({
|
|
1169
|
+
items: inputRecords,
|
|
1170
|
+
runOne: async (record) => {
|
|
1171
|
+
const itemId = getBulkRecordId(record);
|
|
1172
|
+
const recordBody = { ...record };
|
|
1173
|
+
delete recordBody.id;
|
|
1174
|
+
delete recordBody._id;
|
|
1175
|
+
const bodyFromFlags2 = {};
|
|
1176
|
+
const parsedName2 = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
1177
|
+
if (parsedName2 !== void 0) bodyFromFlags2.name = parsedName2;
|
|
1178
|
+
const parsedDefaultBucket2 = coerceBodyFlag(opts.defaultBucket, { field: "defaultBucket", flag: "--default-bucket", kind: "string" }, exitWithError);
|
|
1179
|
+
if (parsedDefaultBucket2 !== void 0) bodyFromFlags2.defaultBucket = parsedDefaultBucket2;
|
|
1180
|
+
const body2 = { ...recordBody, ...mergeBody(bodyFromFlags2, opts.body) };
|
|
1181
|
+
const res2 = await apiRequest({ method: "PATCH", path: "categories/" + encodeURIComponent(itemId), token, baseUrl: getBaseUrl(), body: body2 });
|
|
1182
|
+
return { ok: res2.ok, status: res2.status || 0, data: res2.data, error: res2.error };
|
|
1183
|
+
},
|
|
1184
|
+
toResult: (record, ok, status, _data, err) => ok ? { _id: getBulkRecordId(record), status: "updated" } : { _id: getBulkRecordId(record) ?? void 0, error: true, statusCode: status, message: err ?? "Failed" }
|
|
1185
|
+
});
|
|
1186
|
+
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
1187
|
+
return;
|
|
1188
|
+
}
|
|
1189
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
769
1190
|
if (ids.length > 0) {
|
|
770
1191
|
validateBulkIds(ids, "categories");
|
|
1192
|
+
if (opts.dryRun) {
|
|
1193
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
1194
|
+
return;
|
|
1195
|
+
}
|
|
771
1196
|
const { data: data2, summary } = await runBulk({
|
|
772
1197
|
items: ids,
|
|
773
1198
|
runOne: async (itemId) => {
|
|
@@ -785,6 +1210,7 @@ function register(program, helpers) {
|
|
|
785
1210
|
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
786
1211
|
return;
|
|
787
1212
|
}
|
|
1213
|
+
if (!id) exitWithError(400, "Provide id, --ids, --ids-file, or --input");
|
|
788
1214
|
const bodyFromFlags = {};
|
|
789
1215
|
const parsedName = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
790
1216
|
if (parsedName !== void 0) bodyFromFlags.name = parsedName;
|
|
@@ -796,14 +1222,18 @@ function register(program, helpers) {
|
|
|
796
1222
|
const data = res.data?.data ?? res.data;
|
|
797
1223
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
798
1224
|
});
|
|
799
|
-
categoriesCmd.command("delete
|
|
1225
|
+
categoriesCmd.command("delete [id]").description("Delete categories").option("--ids <ids>", "Comma-separated IDs for bulk delete (max 25)").option("--ids-file <path>", "File containing IDs for bulk delete").option("--dry-run", "Preview delete without sending requests").option("--yes", "Confirm destructive bulk delete").hook("preAction", (thisCommand) => {
|
|
800
1226
|
syncRootOptsFromCommand(thisCommand);
|
|
801
1227
|
}).action(async (id, opts) => {
|
|
802
1228
|
const token = requireToken();
|
|
803
1229
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
804
|
-
const ids =
|
|
1230
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
805
1231
|
if (ids.length > 0) {
|
|
806
1232
|
validateBulkIds(ids, "categories");
|
|
1233
|
+
if (opts.dryRun) {
|
|
1234
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_delete" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
1235
|
+
return;
|
|
1236
|
+
}
|
|
807
1237
|
const { data, summary } = await runBulk({
|
|
808
1238
|
items: ids,
|
|
809
1239
|
runOne: async (itemId) => {
|
|
@@ -815,12 +1245,17 @@ function register(program, helpers) {
|
|
|
815
1245
|
printOutput(getOutputFormat(), { data, summary }, false);
|
|
816
1246
|
return;
|
|
817
1247
|
}
|
|
1248
|
+
if (!id) exitWithError(400, "Provide id, --ids, or --ids-file");
|
|
1249
|
+
if (opts.dryRun) {
|
|
1250
|
+
printOutput(getOutputFormat(), { _id: id, status: "would_delete" }, false);
|
|
1251
|
+
return;
|
|
1252
|
+
}
|
|
818
1253
|
const res = await apiRequest({ method: "DELETE", path: "categories/" + encodeURIComponent(id), token, baseUrl: getBaseUrl() });
|
|
819
1254
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
820
1255
|
if (getOutputFormat() === "json") console.log(JSON.stringify({ data: null, deleted: true }));
|
|
821
1256
|
});
|
|
822
1257
|
const labelsCmd = program.command("labels").description("labels resource");
|
|
823
|
-
labelsCmd.command("list").description("List labels").option("--limit <n>", "Max results").option("--offset <n>", "Skip n results").option("--organization-id <value>", "Filter by organizationId").hook("preAction", (thisCommand) => {
|
|
1258
|
+
labelsCmd.command("list").description("List labels").option("--limit <n>", "Max results").option("--offset <n>", "Skip n results").option("--all", "Fetch all pages").option("--fields <fields>", "Comma-separated fields to print").option("--where <field=value>", "Client-side exact filters, comma-separated").option("--jsonl", "Print one compact JSON object per row").option("--organization-id <value>", "Filter by organizationId").hook("preAction", (thisCommand) => {
|
|
824
1259
|
syncRootOptsFromCommand(thisCommand);
|
|
825
1260
|
}).action(async (opts) => {
|
|
826
1261
|
const token = requireToken();
|
|
@@ -831,10 +1266,10 @@ function register(program, helpers) {
|
|
|
831
1266
|
if (opts.organizationId != null) {
|
|
832
1267
|
query.organizationId = coerceQueryFlag(opts.organizationId, { field: "organizationId", flag: "--organization-id", kind: "string" }, exitWithError);
|
|
833
1268
|
}
|
|
834
|
-
const res = await
|
|
1269
|
+
const res = await fetchList({ path: "labels", token, baseUrl: getBaseUrl(), query, all: Boolean(opts.all), request: apiRequest });
|
|
835
1270
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
836
1271
|
const data = res.data?.data ?? [];
|
|
837
|
-
|
|
1272
|
+
printList({ format: getOutputFormat(), data, fields: opts.fields, where: opts.where, jsonl: Boolean(opts.jsonl) });
|
|
838
1273
|
});
|
|
839
1274
|
labelsCmd.command("get <id>").description("Get one labels by id").hook("preAction", (thisCommand) => {
|
|
840
1275
|
syncRootOptsFromCommand(thisCommand);
|
|
@@ -861,20 +1296,67 @@ function register(program, helpers) {
|
|
|
861
1296
|
if (parsedColour !== void 0) bodyFromFlags.colour = parsedColour;
|
|
862
1297
|
const body = mergeBody(bodyFromFlags, opts.body);
|
|
863
1298
|
if (opts.ifNotExists) {
|
|
1299
|
+
const existing = await findExistingResource({
|
|
1300
|
+
resource: "labels",
|
|
1301
|
+
token,
|
|
1302
|
+
baseUrl: getBaseUrl(),
|
|
1303
|
+
body,
|
|
1304
|
+
identityFields: ["name", "organizationId"],
|
|
1305
|
+
queryFields: ["organizationId"],
|
|
1306
|
+
request: apiRequest
|
|
1307
|
+
});
|
|
1308
|
+
if (existing) {
|
|
1309
|
+
printOutput(getOutputFormat(), existing, false);
|
|
1310
|
+
return;
|
|
1311
|
+
}
|
|
864
1312
|
}
|
|
865
1313
|
const res = await apiRequest({ method: "POST", path: "labels", token, baseUrl: getBaseUrl(), body });
|
|
866
1314
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
867
1315
|
const data = res.data?.data ?? res.data;
|
|
868
1316
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
869
1317
|
});
|
|
870
|
-
labelsCmd.command("update
|
|
1318
|
+
labelsCmd.command("update [id]").description("Update labels").option("--body <json>", "Request body JSON (merged with flags)").option("--ids <ids>", "Comma-separated IDs for bulk update (max 25)").option("--ids-file <path>", "File containing IDs for bulk update").option("--input <path>", "JSON/JSONL records for bulk update; use - for stdin").option("--dry-run", "Preview bulk update without sending requests").option("--name <value>", "name").option("--colour <value>", "colour").hook("preAction", (thisCommand) => {
|
|
871
1319
|
syncRootOptsFromCommand(thisCommand);
|
|
872
1320
|
}).action(async (id, opts) => {
|
|
873
1321
|
const token = requireToken();
|
|
874
1322
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
875
|
-
const
|
|
1323
|
+
const inputRecords = await parseBulkInput(opts.input);
|
|
1324
|
+
if (inputRecords.length > 0) {
|
|
1325
|
+
const ids2 = inputRecords.map(getBulkRecordId).filter((value) => value !== null);
|
|
1326
|
+
if (ids2.length !== inputRecords.length) exitWithError(400, "Each --input record must include id or _id");
|
|
1327
|
+
validateBulkIds(ids2, "labels");
|
|
1328
|
+
if (opts.dryRun) {
|
|
1329
|
+
printOutput(getOutputFormat(), { data: ids2.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids2.length, succeeded: ids2.length, failed: 0 } }, false);
|
|
1330
|
+
return;
|
|
1331
|
+
}
|
|
1332
|
+
const { data: data2, summary } = await runBulk({
|
|
1333
|
+
items: inputRecords,
|
|
1334
|
+
runOne: async (record) => {
|
|
1335
|
+
const itemId = getBulkRecordId(record);
|
|
1336
|
+
const recordBody = { ...record };
|
|
1337
|
+
delete recordBody.id;
|
|
1338
|
+
delete recordBody._id;
|
|
1339
|
+
const bodyFromFlags2 = {};
|
|
1340
|
+
const parsedName2 = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
1341
|
+
if (parsedName2 !== void 0) bodyFromFlags2.name = parsedName2;
|
|
1342
|
+
const parsedColour2 = coerceBodyFlag(opts.colour, { field: "colour", flag: "--colour", kind: "string" }, exitWithError);
|
|
1343
|
+
if (parsedColour2 !== void 0) bodyFromFlags2.colour = parsedColour2;
|
|
1344
|
+
const body2 = { ...recordBody, ...mergeBody(bodyFromFlags2, opts.body) };
|
|
1345
|
+
const res2 = await apiRequest({ method: "PATCH", path: "labels/" + encodeURIComponent(itemId), token, baseUrl: getBaseUrl(), body: body2 });
|
|
1346
|
+
return { ok: res2.ok, status: res2.status || 0, data: res2.data, error: res2.error };
|
|
1347
|
+
},
|
|
1348
|
+
toResult: (record, ok, status, _data, err) => ok ? { _id: getBulkRecordId(record), status: "updated" } : { _id: getBulkRecordId(record) ?? void 0, error: true, statusCode: status, message: err ?? "Failed" }
|
|
1349
|
+
});
|
|
1350
|
+
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
1351
|
+
return;
|
|
1352
|
+
}
|
|
1353
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
876
1354
|
if (ids.length > 0) {
|
|
877
1355
|
validateBulkIds(ids, "labels");
|
|
1356
|
+
if (opts.dryRun) {
|
|
1357
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
878
1360
|
const { data: data2, summary } = await runBulk({
|
|
879
1361
|
items: ids,
|
|
880
1362
|
runOne: async (itemId) => {
|
|
@@ -892,6 +1374,7 @@ function register(program, helpers) {
|
|
|
892
1374
|
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
893
1375
|
return;
|
|
894
1376
|
}
|
|
1377
|
+
if (!id) exitWithError(400, "Provide id, --ids, --ids-file, or --input");
|
|
895
1378
|
const bodyFromFlags = {};
|
|
896
1379
|
const parsedName = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
897
1380
|
if (parsedName !== void 0) bodyFromFlags.name = parsedName;
|
|
@@ -903,14 +1386,18 @@ function register(program, helpers) {
|
|
|
903
1386
|
const data = res.data?.data ?? res.data;
|
|
904
1387
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
905
1388
|
});
|
|
906
|
-
labelsCmd.command("delete
|
|
1389
|
+
labelsCmd.command("delete [id]").description("Delete labels").option("--ids <ids>", "Comma-separated IDs for bulk delete (max 25)").option("--ids-file <path>", "File containing IDs for bulk delete").option("--dry-run", "Preview delete without sending requests").option("--yes", "Confirm destructive bulk delete").hook("preAction", (thisCommand) => {
|
|
907
1390
|
syncRootOptsFromCommand(thisCommand);
|
|
908
1391
|
}).action(async (id, opts) => {
|
|
909
1392
|
const token = requireToken();
|
|
910
1393
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
911
|
-
const ids =
|
|
1394
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
912
1395
|
if (ids.length > 0) {
|
|
913
1396
|
validateBulkIds(ids, "labels");
|
|
1397
|
+
if (opts.dryRun) {
|
|
1398
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_delete" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
1399
|
+
return;
|
|
1400
|
+
}
|
|
914
1401
|
const { data, summary } = await runBulk({
|
|
915
1402
|
items: ids,
|
|
916
1403
|
runOne: async (itemId) => {
|
|
@@ -922,12 +1409,17 @@ function register(program, helpers) {
|
|
|
922
1409
|
printOutput(getOutputFormat(), { data, summary }, false);
|
|
923
1410
|
return;
|
|
924
1411
|
}
|
|
1412
|
+
if (!id) exitWithError(400, "Provide id, --ids, or --ids-file");
|
|
1413
|
+
if (opts.dryRun) {
|
|
1414
|
+
printOutput(getOutputFormat(), { _id: id, status: "would_delete" }, false);
|
|
1415
|
+
return;
|
|
1416
|
+
}
|
|
925
1417
|
const res = await apiRequest({ method: "DELETE", path: "labels/" + encodeURIComponent(id), token, baseUrl: getBaseUrl() });
|
|
926
1418
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
927
1419
|
if (getOutputFormat() === "json") console.log(JSON.stringify({ data: null, deleted: true }));
|
|
928
1420
|
});
|
|
929
1421
|
const viewsCmd = program.command("views").description("views resource");
|
|
930
|
-
viewsCmd.command("list").description("List views").option("--limit <n>", "Max results").option("--offset <n>", "Skip n results").option("--organization-id <value>", "Filter by organizationId").option("--project-id <value>", "Filter by projectId").option("--entity-type <value>", "Filter by entityType").hook("preAction", (thisCommand) => {
|
|
1422
|
+
viewsCmd.command("list").description("List views").option("--limit <n>", "Max results").option("--offset <n>", "Skip n results").option("--all", "Fetch all pages").option("--fields <fields>", "Comma-separated fields to print").option("--where <field=value>", "Client-side exact filters, comma-separated").option("--jsonl", "Print one compact JSON object per row").option("--organization-id <value>", "Filter by organizationId").option("--project-id <value>", "Filter by projectId").option("--entity-type <value>", "Filter by entityType").hook("preAction", (thisCommand) => {
|
|
931
1423
|
syncRootOptsFromCommand(thisCommand);
|
|
932
1424
|
}).action(async (opts) => {
|
|
933
1425
|
const token = requireToken();
|
|
@@ -944,10 +1436,10 @@ function register(program, helpers) {
|
|
|
944
1436
|
if (opts.entityType != null) {
|
|
945
1437
|
query.entityType = coerceQueryFlag(opts.entityType, { field: "entityType", flag: "--entity-type", kind: "string" }, exitWithError);
|
|
946
1438
|
}
|
|
947
|
-
const res = await
|
|
1439
|
+
const res = await fetchList({ path: "views", token, baseUrl: getBaseUrl(), query, all: Boolean(opts.all), request: apiRequest });
|
|
948
1440
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
949
1441
|
const data = res.data?.data ?? [];
|
|
950
|
-
|
|
1442
|
+
printList({ format: getOutputFormat(), data, fields: opts.fields, where: opts.where, jsonl: Boolean(opts.jsonl) });
|
|
951
1443
|
});
|
|
952
1444
|
viewsCmd.command("get <id>").description("Get one views by id").hook("preAction", (thisCommand) => {
|
|
953
1445
|
syncRootOptsFromCommand(thisCommand);
|
|
@@ -980,20 +1472,71 @@ function register(program, helpers) {
|
|
|
980
1472
|
if (parsedIsDefault !== void 0) bodyFromFlags.isDefault = parsedIsDefault;
|
|
981
1473
|
const body = mergeBody(bodyFromFlags, opts.body);
|
|
982
1474
|
if (opts.ifNotExists) {
|
|
1475
|
+
const existing = await findExistingResource({
|
|
1476
|
+
resource: "views",
|
|
1477
|
+
token,
|
|
1478
|
+
baseUrl: getBaseUrl(),
|
|
1479
|
+
body,
|
|
1480
|
+
identityFields: ["name", "entityType", "organizationId", "projectId"],
|
|
1481
|
+
queryFields: ["organizationId", "projectId", "entityType"],
|
|
1482
|
+
request: apiRequest
|
|
1483
|
+
});
|
|
1484
|
+
if (existing) {
|
|
1485
|
+
printOutput(getOutputFormat(), existing, false);
|
|
1486
|
+
return;
|
|
1487
|
+
}
|
|
983
1488
|
}
|
|
984
1489
|
const res = await apiRequest({ method: "POST", path: "views", token, baseUrl: getBaseUrl(), body });
|
|
985
1490
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
986
1491
|
const data = res.data?.data ?? res.data;
|
|
987
1492
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
988
1493
|
});
|
|
989
|
-
viewsCmd.command("update
|
|
1494
|
+
viewsCmd.command("update [id]").description("Update views").option("--body <json>", "Request body JSON (merged with flags)").option("--ids <ids>", "Comma-separated IDs for bulk update (max 25)").option("--ids-file <path>", "File containing IDs for bulk update").option("--input <path>", "JSON/JSONL records for bulk update; use - for stdin").option("--dry-run", "Preview bulk update without sending requests").option("--name <value>", "name").option("--project-id <value>", "projectId").option("--config <value>", "config").option("--is-default <value>", "isDefault").hook("preAction", (thisCommand) => {
|
|
990
1495
|
syncRootOptsFromCommand(thisCommand);
|
|
991
1496
|
}).action(async (id, opts) => {
|
|
992
1497
|
const token = requireToken();
|
|
993
1498
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
994
|
-
const
|
|
1499
|
+
const inputRecords = await parseBulkInput(opts.input);
|
|
1500
|
+
if (inputRecords.length > 0) {
|
|
1501
|
+
const ids2 = inputRecords.map(getBulkRecordId).filter((value) => value !== null);
|
|
1502
|
+
if (ids2.length !== inputRecords.length) exitWithError(400, "Each --input record must include id or _id");
|
|
1503
|
+
validateBulkIds(ids2, "views");
|
|
1504
|
+
if (opts.dryRun) {
|
|
1505
|
+
printOutput(getOutputFormat(), { data: ids2.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids2.length, succeeded: ids2.length, failed: 0 } }, false);
|
|
1506
|
+
return;
|
|
1507
|
+
}
|
|
1508
|
+
const { data: data2, summary } = await runBulk({
|
|
1509
|
+
items: inputRecords,
|
|
1510
|
+
runOne: async (record) => {
|
|
1511
|
+
const itemId = getBulkRecordId(record);
|
|
1512
|
+
const recordBody = { ...record };
|
|
1513
|
+
delete recordBody.id;
|
|
1514
|
+
delete recordBody._id;
|
|
1515
|
+
const bodyFromFlags2 = {};
|
|
1516
|
+
const parsedName2 = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
1517
|
+
if (parsedName2 !== void 0) bodyFromFlags2.name = parsedName2;
|
|
1518
|
+
const parsedProjectId2 = coerceBodyFlag(opts.projectId, { field: "projectId", flag: "--project-id", kind: "string" }, exitWithError);
|
|
1519
|
+
if (parsedProjectId2 !== void 0) bodyFromFlags2.projectId = parsedProjectId2;
|
|
1520
|
+
const parsedConfig2 = coerceBodyFlag(opts.config, { field: "config", flag: "--config", kind: "string" }, exitWithError);
|
|
1521
|
+
if (parsedConfig2 !== void 0) bodyFromFlags2.config = parsedConfig2;
|
|
1522
|
+
const parsedIsDefault2 = coerceBodyFlag(opts.isDefault, { field: "isDefault", flag: "--is-default", kind: "boolean" }, exitWithError);
|
|
1523
|
+
if (parsedIsDefault2 !== void 0) bodyFromFlags2.isDefault = parsedIsDefault2;
|
|
1524
|
+
const body2 = { ...recordBody, ...mergeBody(bodyFromFlags2, opts.body) };
|
|
1525
|
+
const res2 = await apiRequest({ method: "PATCH", path: "views/" + encodeURIComponent(itemId), token, baseUrl: getBaseUrl(), body: body2 });
|
|
1526
|
+
return { ok: res2.ok, status: res2.status || 0, data: res2.data, error: res2.error };
|
|
1527
|
+
},
|
|
1528
|
+
toResult: (record, ok, status, _data, err) => ok ? { _id: getBulkRecordId(record), status: "updated" } : { _id: getBulkRecordId(record) ?? void 0, error: true, statusCode: status, message: err ?? "Failed" }
|
|
1529
|
+
});
|
|
1530
|
+
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
1531
|
+
return;
|
|
1532
|
+
}
|
|
1533
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
995
1534
|
if (ids.length > 0) {
|
|
996
1535
|
validateBulkIds(ids, "views");
|
|
1536
|
+
if (opts.dryRun) {
|
|
1537
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
1538
|
+
return;
|
|
1539
|
+
}
|
|
997
1540
|
const { data: data2, summary } = await runBulk({
|
|
998
1541
|
items: ids,
|
|
999
1542
|
runOne: async (itemId) => {
|
|
@@ -1015,6 +1558,7 @@ function register(program, helpers) {
|
|
|
1015
1558
|
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
1016
1559
|
return;
|
|
1017
1560
|
}
|
|
1561
|
+
if (!id) exitWithError(400, "Provide id, --ids, --ids-file, or --input");
|
|
1018
1562
|
const bodyFromFlags = {};
|
|
1019
1563
|
const parsedName = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
1020
1564
|
if (parsedName !== void 0) bodyFromFlags.name = parsedName;
|
|
@@ -1030,14 +1574,18 @@ function register(program, helpers) {
|
|
|
1030
1574
|
const data = res.data?.data ?? res.data;
|
|
1031
1575
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
1032
1576
|
});
|
|
1033
|
-
viewsCmd.command("delete
|
|
1577
|
+
viewsCmd.command("delete [id]").description("Delete views").option("--ids <ids>", "Comma-separated IDs for bulk delete (max 25)").option("--ids-file <path>", "File containing IDs for bulk delete").option("--dry-run", "Preview delete without sending requests").option("--yes", "Confirm destructive bulk delete").hook("preAction", (thisCommand) => {
|
|
1034
1578
|
syncRootOptsFromCommand(thisCommand);
|
|
1035
1579
|
}).action(async (id, opts) => {
|
|
1036
1580
|
const token = requireToken();
|
|
1037
1581
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
1038
|
-
const ids =
|
|
1582
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
1039
1583
|
if (ids.length > 0) {
|
|
1040
1584
|
validateBulkIds(ids, "views");
|
|
1585
|
+
if (opts.dryRun) {
|
|
1586
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_delete" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
1587
|
+
return;
|
|
1588
|
+
}
|
|
1041
1589
|
const { data, summary } = await runBulk({
|
|
1042
1590
|
items: ids,
|
|
1043
1591
|
runOne: async (itemId) => {
|
|
@@ -1049,12 +1597,17 @@ function register(program, helpers) {
|
|
|
1049
1597
|
printOutput(getOutputFormat(), { data, summary }, false);
|
|
1050
1598
|
return;
|
|
1051
1599
|
}
|
|
1600
|
+
if (!id) exitWithError(400, "Provide id, --ids, or --ids-file");
|
|
1601
|
+
if (opts.dryRun) {
|
|
1602
|
+
printOutput(getOutputFormat(), { _id: id, status: "would_delete" }, false);
|
|
1603
|
+
return;
|
|
1604
|
+
}
|
|
1052
1605
|
const res = await apiRequest({ method: "DELETE", path: "views/" + encodeURIComponent(id), token, baseUrl: getBaseUrl() });
|
|
1053
1606
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
1054
1607
|
if (getOutputFormat() === "json") console.log(JSON.stringify({ data: null, deleted: true }));
|
|
1055
1608
|
});
|
|
1056
1609
|
const commentsCmd = program.command("comments").description("comments resource");
|
|
1057
|
-
commentsCmd.command("list").description("List comments").option("--limit <n>", "Max results").option("--offset <n>", "Skip n results").option("--entity-type <value>", "Filter by entityType").option("--entity-id <value>", "Filter by entityId").hook("preAction", (thisCommand) => {
|
|
1610
|
+
commentsCmd.command("list").description("List comments").option("--limit <n>", "Max results").option("--offset <n>", "Skip n results").option("--all", "Fetch all pages").option("--fields <fields>", "Comma-separated fields to print").option("--where <field=value>", "Client-side exact filters, comma-separated").option("--jsonl", "Print one compact JSON object per row").option("--entity-type <value>", "Filter by entityType").option("--entity-id <value>", "Filter by entityId").hook("preAction", (thisCommand) => {
|
|
1058
1611
|
syncRootOptsFromCommand(thisCommand);
|
|
1059
1612
|
}).action(async (opts) => {
|
|
1060
1613
|
const token = requireToken();
|
|
@@ -1068,10 +1621,10 @@ function register(program, helpers) {
|
|
|
1068
1621
|
if (opts.entityId != null) {
|
|
1069
1622
|
query.entityId = coerceQueryFlag(opts.entityId, { field: "entityId", flag: "--entity-id", kind: "string" }, exitWithError);
|
|
1070
1623
|
}
|
|
1071
|
-
const res = await
|
|
1624
|
+
const res = await fetchList({ path: "comments", token, baseUrl: getBaseUrl(), query, all: Boolean(opts.all), request: apiRequest });
|
|
1072
1625
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
1073
1626
|
const data = res.data?.data ?? [];
|
|
1074
|
-
|
|
1627
|
+
printList({ format: getOutputFormat(), data, fields: opts.fields, where: opts.where, jsonl: Boolean(opts.jsonl) });
|
|
1075
1628
|
});
|
|
1076
1629
|
commentsCmd.command("create").description("Create comments").option("--body <json>", "Request body JSON (merged with flags)").option("--entity-type <value>", "entityType").option("--entity-id <value>", "entityId").option("--text <value>", "body").option("--parent-comment-id <value>", "parentCommentId").option("--if-not-exists", "Return existing if match found").hook("preAction", (thisCommand) => {
|
|
1077
1630
|
syncRootOptsFromCommand(thisCommand);
|
|
@@ -1089,6 +1642,19 @@ function register(program, helpers) {
|
|
|
1089
1642
|
if (parsedParentCommentId !== void 0) bodyFromFlags.parentCommentId = parsedParentCommentId;
|
|
1090
1643
|
const body = mergeBody(bodyFromFlags, opts.body);
|
|
1091
1644
|
if (opts.ifNotExists) {
|
|
1645
|
+
const existing = await findExistingResource({
|
|
1646
|
+
resource: "comments",
|
|
1647
|
+
token,
|
|
1648
|
+
baseUrl: getBaseUrl(),
|
|
1649
|
+
body,
|
|
1650
|
+
identityFields: ["entityType", "entityId"],
|
|
1651
|
+
queryFields: ["entityType", "entityId"],
|
|
1652
|
+
request: apiRequest
|
|
1653
|
+
});
|
|
1654
|
+
if (existing) {
|
|
1655
|
+
printOutput(getOutputFormat(), existing, false);
|
|
1656
|
+
return;
|
|
1657
|
+
}
|
|
1092
1658
|
}
|
|
1093
1659
|
const res = await apiRequest({ method: "POST", path: "comments", token, baseUrl: getBaseUrl(), body });
|
|
1094
1660
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
@@ -1099,4 +1665,4 @@ function register(program, helpers) {
|
|
|
1099
1665
|
export {
|
|
1100
1666
|
register
|
|
1101
1667
|
};
|
|
1102
|
-
//# sourceMappingURL=generated-
|
|
1668
|
+
//# sourceMappingURL=generated-UG3O6FVC.js.map
|