@getpilfer/cli 0.1.1 → 0.1.3
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 +13 -1
- package/SKILL.md +17 -1
- package/dist/build-program.js +2 -2
- package/dist/{chunk-QH2MMA3M.js → chunk-CXNVJZ4C.js} +173 -72
- package/dist/chunk-CXNVJZ4C.js.map +1 -0
- package/dist/chunk-NFFHTNJE.js +1161 -0
- package/dist/chunk-NFFHTNJE.js.map +1 -0
- package/dist/{generated-IFLUY7PB.js → generated-7QDIZ5V5.js} +656 -66
- package/dist/generated-7QDIZ5V5.js.map +1 -0
- package/dist/index.js +2 -2
- package/package.json +2 -2
- package/dist/chunk-2QYZ5OEW.js +0 -407
- package/dist/chunk-2QYZ5OEW.js.map +0 -1
- package/dist/chunk-QH2MMA3M.js.map +0 -1
- package/dist/generated-IFLUY7PB.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-CXNVJZ4C.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").option("--include <value>", "Filter by include").hook("preAction", (thisCommand) => {
|
|
92
180
|
syncRootOptsFromCommand(thisCommand);
|
|
93
181
|
}).action(async (opts) => {
|
|
94
182
|
const token = requireToken();
|
|
@@ -99,17 +187,23 @@ 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
|
-
|
|
190
|
+
if (opts.include != null) {
|
|
191
|
+
query.include = coerceQueryFlag(opts.include, { field: "include", flag: "--include", kind: "string" }, exitWithError);
|
|
192
|
+
}
|
|
193
|
+
const res = await fetchList({ path: "projects", token, baseUrl: getBaseUrl(), query, all: Boolean(opts.all), request: apiRequest });
|
|
103
194
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
104
195
|
const data = res.data?.data ?? [];
|
|
105
|
-
|
|
196
|
+
printList({ format: getOutputFormat(), data, fields: opts.fields, where: opts.where, jsonl: Boolean(opts.jsonl) });
|
|
106
197
|
});
|
|
107
|
-
projectsCmd.command("get <id>").description("Get one projects by id").hook("preAction", (thisCommand) => {
|
|
198
|
+
projectsCmd.command("get <id>").description("Get one projects by id").option("--include <value>", "Include/filter by include").hook("preAction", (thisCommand) => {
|
|
108
199
|
syncRootOptsFromCommand(thisCommand);
|
|
109
200
|
}).action(async (id, opts) => {
|
|
110
201
|
const token = requireToken();
|
|
111
202
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
112
203
|
const query = {};
|
|
204
|
+
if (opts.include != null) {
|
|
205
|
+
query.include = coerceQueryFlag(opts.include, { field: "include", flag: "--include", kind: "string" }, exitWithError);
|
|
206
|
+
}
|
|
113
207
|
const res = await apiRequest({ method: "GET", path: "projects/" + encodeURIComponent(id), token, baseUrl: getBaseUrl(), query });
|
|
114
208
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
115
209
|
const data = res.data?.data ?? res.data;
|
|
@@ -131,20 +225,69 @@ function register(program, helpers) {
|
|
|
131
225
|
if (parsedPriority !== void 0) bodyFromFlags.priority = parsedPriority;
|
|
132
226
|
const body = mergeBody(bodyFromFlags, opts.body);
|
|
133
227
|
if (opts.ifNotExists) {
|
|
228
|
+
const existing = await findExistingResource({
|
|
229
|
+
resource: "projects",
|
|
230
|
+
token,
|
|
231
|
+
baseUrl: getBaseUrl(),
|
|
232
|
+
body,
|
|
233
|
+
identityFields: ["name", "organizationId"],
|
|
234
|
+
queryFields: ["organizationId", "include"],
|
|
235
|
+
request: apiRequest
|
|
236
|
+
});
|
|
237
|
+
if (existing) {
|
|
238
|
+
printOutput(getOutputFormat(), existing, false);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
134
241
|
}
|
|
135
242
|
const res = await apiRequest({ method: "POST", path: "projects", token, baseUrl: getBaseUrl(), body });
|
|
136
243
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
137
244
|
const data = res.data?.data ?? res.data;
|
|
138
245
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
139
246
|
});
|
|
140
|
-
projectsCmd.command("update
|
|
247
|
+
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
248
|
syncRootOptsFromCommand(thisCommand);
|
|
142
249
|
}).action(async (id, opts) => {
|
|
143
250
|
const token = requireToken();
|
|
144
251
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
145
|
-
const
|
|
252
|
+
const inputRecords = await parseBulkInput(opts.input);
|
|
253
|
+
if (inputRecords.length > 0) {
|
|
254
|
+
const ids2 = inputRecords.map(getBulkRecordId).filter((value) => value !== null);
|
|
255
|
+
if (ids2.length !== inputRecords.length) exitWithError(400, "Each --input record must include id or _id");
|
|
256
|
+
validateBulkIds(ids2, "projects");
|
|
257
|
+
if (opts.dryRun) {
|
|
258
|
+
printOutput(getOutputFormat(), { data: ids2.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids2.length, succeeded: ids2.length, failed: 0 } }, false);
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
const { data: data2, summary } = await runBulk({
|
|
262
|
+
items: inputRecords,
|
|
263
|
+
runOne: async (record) => {
|
|
264
|
+
const itemId = getBulkRecordId(record);
|
|
265
|
+
const recordBody = { ...record };
|
|
266
|
+
delete recordBody.id;
|
|
267
|
+
delete recordBody._id;
|
|
268
|
+
const bodyFromFlags2 = {};
|
|
269
|
+
const parsedName2 = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
270
|
+
if (parsedName2 !== void 0) bodyFromFlags2.name = parsedName2;
|
|
271
|
+
const parsedDescription2 = coerceBodyFlag(opts.description, { field: "description", flag: "--description", kind: "string" }, exitWithError);
|
|
272
|
+
if (parsedDescription2 !== void 0) bodyFromFlags2.description = parsedDescription2;
|
|
273
|
+
const parsedPriority2 = coerceBodyFlag(opts.priority, { field: "priority", flag: "--priority", kind: "string" }, exitWithError);
|
|
274
|
+
if (parsedPriority2 !== void 0) bodyFromFlags2.priority = parsedPriority2;
|
|
275
|
+
const body2 = { ...recordBody, ...mergeBody(bodyFromFlags2, opts.body) };
|
|
276
|
+
const res2 = await apiRequest({ method: "PATCH", path: "projects/" + encodeURIComponent(itemId), token, baseUrl: getBaseUrl(), body: body2 });
|
|
277
|
+
return { ok: res2.ok, status: res2.status || 0, data: res2.data, error: res2.error };
|
|
278
|
+
},
|
|
279
|
+
toResult: (record, ok, status, _data, err) => ok ? { _id: getBulkRecordId(record), status: "updated" } : { _id: getBulkRecordId(record) ?? void 0, error: true, statusCode: status, message: err ?? "Failed" }
|
|
280
|
+
});
|
|
281
|
+
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
146
285
|
if (ids.length > 0) {
|
|
147
286
|
validateBulkIds(ids, "projects");
|
|
287
|
+
if (opts.dryRun) {
|
|
288
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
148
291
|
const { data: data2, summary } = await runBulk({
|
|
149
292
|
items: ids,
|
|
150
293
|
runOne: async (itemId) => {
|
|
@@ -164,6 +307,7 @@ function register(program, helpers) {
|
|
|
164
307
|
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
165
308
|
return;
|
|
166
309
|
}
|
|
310
|
+
if (!id) exitWithError(400, "Provide id, --ids, --ids-file, or --input");
|
|
167
311
|
const bodyFromFlags = {};
|
|
168
312
|
const parsedName = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
169
313
|
if (parsedName !== void 0) bodyFromFlags.name = parsedName;
|
|
@@ -177,14 +321,18 @@ function register(program, helpers) {
|
|
|
177
321
|
const data = res.data?.data ?? res.data;
|
|
178
322
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
179
323
|
});
|
|
180
|
-
projectsCmd.command("delete
|
|
324
|
+
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
325
|
syncRootOptsFromCommand(thisCommand);
|
|
182
326
|
}).action(async (id, opts) => {
|
|
183
327
|
const token = requireToken();
|
|
184
328
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
185
|
-
const ids =
|
|
329
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
186
330
|
if (ids.length > 0) {
|
|
187
331
|
validateBulkIds(ids, "projects");
|
|
332
|
+
if (opts.dryRun) {
|
|
333
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_delete" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
188
336
|
const { data, summary } = await runBulk({
|
|
189
337
|
items: ids,
|
|
190
338
|
runOne: async (itemId) => {
|
|
@@ -196,12 +344,17 @@ function register(program, helpers) {
|
|
|
196
344
|
printOutput(getOutputFormat(), { data, summary }, false);
|
|
197
345
|
return;
|
|
198
346
|
}
|
|
347
|
+
if (!id) exitWithError(400, "Provide id, --ids, or --ids-file");
|
|
348
|
+
if (opts.dryRun) {
|
|
349
|
+
printOutput(getOutputFormat(), { _id: id, status: "would_delete" }, false);
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
199
352
|
const res = await apiRequest({ method: "DELETE", path: "projects/" + encodeURIComponent(id), token, baseUrl: getBaseUrl() });
|
|
200
353
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
201
354
|
if (getOutputFormat() === "json") console.log(JSON.stringify({ data: null, deleted: true }));
|
|
202
355
|
});
|
|
203
356
|
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) => {
|
|
357
|
+
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").option("--include <value>", "Filter by include").hook("preAction", (thisCommand) => {
|
|
205
358
|
syncRootOptsFromCommand(thisCommand);
|
|
206
359
|
}).action(async (opts) => {
|
|
207
360
|
const token = requireToken();
|
|
@@ -215,17 +368,23 @@ function register(program, helpers) {
|
|
|
215
368
|
if (opts.projectId != null) {
|
|
216
369
|
query.projectId = coerceQueryFlag(opts.projectId, { field: "projectId", flag: "--project-id", kind: "string" }, exitWithError);
|
|
217
370
|
}
|
|
218
|
-
|
|
371
|
+
if (opts.include != null) {
|
|
372
|
+
query.include = coerceQueryFlag(opts.include, { field: "include", flag: "--include", kind: "string" }, exitWithError);
|
|
373
|
+
}
|
|
374
|
+
const res = await fetchList({ path: "spaces", token, baseUrl: getBaseUrl(), query, all: Boolean(opts.all), request: apiRequest });
|
|
219
375
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
220
376
|
const data = res.data?.data ?? [];
|
|
221
|
-
|
|
377
|
+
printList({ format: getOutputFormat(), data, fields: opts.fields, where: opts.where, jsonl: Boolean(opts.jsonl) });
|
|
222
378
|
});
|
|
223
|
-
spacesCmd.command("get <id>").description("Get one spaces by id").hook("preAction", (thisCommand) => {
|
|
379
|
+
spacesCmd.command("get <id>").description("Get one spaces by id").option("--include <value>", "Include/filter by include").hook("preAction", (thisCommand) => {
|
|
224
380
|
syncRootOptsFromCommand(thisCommand);
|
|
225
381
|
}).action(async (id, opts) => {
|
|
226
382
|
const token = requireToken();
|
|
227
383
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
228
384
|
const query = {};
|
|
385
|
+
if (opts.include != null) {
|
|
386
|
+
query.include = coerceQueryFlag(opts.include, { field: "include", flag: "--include", kind: "string" }, exitWithError);
|
|
387
|
+
}
|
|
229
388
|
const res = await apiRequest({ method: "GET", path: "spaces/" + encodeURIComponent(id), token, baseUrl: getBaseUrl(), query });
|
|
230
389
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
231
390
|
const data = res.data?.data ?? res.data;
|
|
@@ -253,20 +412,75 @@ function register(program, helpers) {
|
|
|
253
412
|
if (parsedCurrentStrength !== void 0) bodyFromFlags.currentStrength = parsedCurrentStrength;
|
|
254
413
|
const body = mergeBody(bodyFromFlags, opts.body);
|
|
255
414
|
if (opts.ifNotExists) {
|
|
415
|
+
const existing = await findExistingResource({
|
|
416
|
+
resource: "spaces",
|
|
417
|
+
token,
|
|
418
|
+
baseUrl: getBaseUrl(),
|
|
419
|
+
body,
|
|
420
|
+
identityFields: ["name", "organizationId", "projectId"],
|
|
421
|
+
queryFields: ["organizationId", "projectId", "include"],
|
|
422
|
+
request: apiRequest
|
|
423
|
+
});
|
|
424
|
+
if (existing) {
|
|
425
|
+
printOutput(getOutputFormat(), existing, false);
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
256
428
|
}
|
|
257
429
|
const res = await apiRequest({ method: "POST", path: "spaces", token, baseUrl: getBaseUrl(), body });
|
|
258
430
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
259
431
|
const data = res.data?.data ?? res.data;
|
|
260
432
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
261
433
|
});
|
|
262
|
-
spacesCmd.command("update
|
|
434
|
+
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
435
|
syncRootOptsFromCommand(thisCommand);
|
|
264
436
|
}).action(async (id, opts) => {
|
|
265
437
|
const token = requireToken();
|
|
266
438
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
267
|
-
const
|
|
439
|
+
const inputRecords = await parseBulkInput(opts.input);
|
|
440
|
+
if (inputRecords.length > 0) {
|
|
441
|
+
const ids2 = inputRecords.map(getBulkRecordId).filter((value) => value !== null);
|
|
442
|
+
if (ids2.length !== inputRecords.length) exitWithError(400, "Each --input record must include id or _id");
|
|
443
|
+
validateBulkIds(ids2, "spaces");
|
|
444
|
+
if (opts.dryRun) {
|
|
445
|
+
printOutput(getOutputFormat(), { data: ids2.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids2.length, succeeded: ids2.length, failed: 0 } }, false);
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
const { data: data2, summary } = await runBulk({
|
|
449
|
+
items: inputRecords,
|
|
450
|
+
runOne: async (record) => {
|
|
451
|
+
const itemId = getBulkRecordId(record);
|
|
452
|
+
const recordBody = { ...record };
|
|
453
|
+
delete recordBody.id;
|
|
454
|
+
delete recordBody._id;
|
|
455
|
+
const bodyFromFlags2 = {};
|
|
456
|
+
const parsedName2 = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
457
|
+
if (parsedName2 !== void 0) bodyFromFlags2.name = parsedName2;
|
|
458
|
+
const parsedDescription2 = coerceBodyFlag(opts.description, { field: "description", flag: "--description", kind: "string" }, exitWithError);
|
|
459
|
+
if (parsedDescription2 !== void 0) bodyFromFlags2.description = parsedDescription2;
|
|
460
|
+
const parsedProjectId2 = coerceBodyFlag(opts.projectId, { field: "projectId", flag: "--project-id", kind: "string", allowNull: true }, exitWithError);
|
|
461
|
+
if (parsedProjectId2 !== void 0) bodyFromFlags2.projectId = parsedProjectId2;
|
|
462
|
+
const parsedStatus2 = coerceBodyFlag(opts.status, { field: "status", flag: "--status", kind: "string" }, exitWithError);
|
|
463
|
+
if (parsedStatus2 !== void 0) bodyFromFlags2.status = parsedStatus2;
|
|
464
|
+
const parsedPriority2 = coerceBodyFlag(opts.priority, { field: "priority", flag: "--priority", kind: "string" }, exitWithError);
|
|
465
|
+
if (parsedPriority2 !== void 0) bodyFromFlags2.priority = parsedPriority2;
|
|
466
|
+
const parsedCurrentStrength2 = coerceBodyFlag(opts.currentStrength, { field: "currentStrength", flag: "--current-strength", kind: "number" }, exitWithError);
|
|
467
|
+
if (parsedCurrentStrength2 !== void 0) bodyFromFlags2.currentStrength = parsedCurrentStrength2;
|
|
468
|
+
const body2 = { ...recordBody, ...mergeBody(bodyFromFlags2, opts.body) };
|
|
469
|
+
const res2 = await apiRequest({ method: "PATCH", path: "spaces/" + encodeURIComponent(itemId), token, baseUrl: getBaseUrl(), body: body2 });
|
|
470
|
+
return { ok: res2.ok, status: res2.status || 0, data: res2.data, error: res2.error };
|
|
471
|
+
},
|
|
472
|
+
toResult: (record, ok, status, _data, err) => ok ? { _id: getBulkRecordId(record), status: "updated" } : { _id: getBulkRecordId(record) ?? void 0, error: true, statusCode: status, message: err ?? "Failed" }
|
|
473
|
+
});
|
|
474
|
+
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
268
478
|
if (ids.length > 0) {
|
|
269
479
|
validateBulkIds(ids, "spaces");
|
|
480
|
+
if (opts.dryRun) {
|
|
481
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
270
484
|
const { data: data2, summary } = await runBulk({
|
|
271
485
|
items: ids,
|
|
272
486
|
runOne: async (itemId) => {
|
|
@@ -292,6 +506,7 @@ function register(program, helpers) {
|
|
|
292
506
|
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
293
507
|
return;
|
|
294
508
|
}
|
|
509
|
+
if (!id) exitWithError(400, "Provide id, --ids, --ids-file, or --input");
|
|
295
510
|
const bodyFromFlags = {};
|
|
296
511
|
const parsedName = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
297
512
|
if (parsedName !== void 0) bodyFromFlags.name = parsedName;
|
|
@@ -311,14 +526,18 @@ function register(program, helpers) {
|
|
|
311
526
|
const data = res.data?.data ?? res.data;
|
|
312
527
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
313
528
|
});
|
|
314
|
-
spacesCmd.command("delete
|
|
529
|
+
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
530
|
syncRootOptsFromCommand(thisCommand);
|
|
316
531
|
}).action(async (id, opts) => {
|
|
317
532
|
const token = requireToken();
|
|
318
533
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
319
|
-
const ids =
|
|
534
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
320
535
|
if (ids.length > 0) {
|
|
321
536
|
validateBulkIds(ids, "spaces");
|
|
537
|
+
if (opts.dryRun) {
|
|
538
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_delete" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
322
541
|
const { data, summary } = await runBulk({
|
|
323
542
|
items: ids,
|
|
324
543
|
runOne: async (itemId) => {
|
|
@@ -330,12 +549,17 @@ function register(program, helpers) {
|
|
|
330
549
|
printOutput(getOutputFormat(), { data, summary }, false);
|
|
331
550
|
return;
|
|
332
551
|
}
|
|
552
|
+
if (!id) exitWithError(400, "Provide id, --ids, or --ids-file");
|
|
553
|
+
if (opts.dryRun) {
|
|
554
|
+
printOutput(getOutputFormat(), { _id: id, status: "would_delete" }, false);
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
333
557
|
const res = await apiRequest({ method: "DELETE", path: "spaces/" + encodeURIComponent(id), token, baseUrl: getBaseUrl() });
|
|
334
558
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
335
559
|
if (getOutputFormat() === "json") console.log(JSON.stringify({ data: null, deleted: true }));
|
|
336
560
|
});
|
|
337
561
|
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) => {
|
|
562
|
+
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").option("--include <value>", "Filter by include").hook("preAction", (thisCommand) => {
|
|
339
563
|
syncRootOptsFromCommand(thisCommand);
|
|
340
564
|
}).action(async (opts) => {
|
|
341
565
|
const token = requireToken();
|
|
@@ -349,17 +573,23 @@ function register(program, helpers) {
|
|
|
349
573
|
if (opts.categoryId != null) {
|
|
350
574
|
query.categoryId = coerceQueryFlag(opts.categoryId, { field: "categoryId", flag: "--category-id", kind: "string" }, exitWithError);
|
|
351
575
|
}
|
|
352
|
-
|
|
576
|
+
if (opts.include != null) {
|
|
577
|
+
query.include = coerceQueryFlag(opts.include, { field: "include", flag: "--include", kind: "string" }, exitWithError);
|
|
578
|
+
}
|
|
579
|
+
const res = await fetchList({ path: "scouts", token, baseUrl: getBaseUrl(), query, all: Boolean(opts.all), request: apiRequest });
|
|
353
580
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
354
581
|
const data = res.data?.data ?? [];
|
|
355
|
-
|
|
582
|
+
printList({ format: getOutputFormat(), data, fields: opts.fields, where: opts.where, jsonl: Boolean(opts.jsonl) });
|
|
356
583
|
});
|
|
357
|
-
scoutsCmd.command("get <id>").description("Get one scouts by id").hook("preAction", (thisCommand) => {
|
|
584
|
+
scoutsCmd.command("get <id>").description("Get one scouts by id").option("--include <value>", "Include/filter by include").hook("preAction", (thisCommand) => {
|
|
358
585
|
syncRootOptsFromCommand(thisCommand);
|
|
359
586
|
}).action(async (id, opts) => {
|
|
360
587
|
const token = requireToken();
|
|
361
588
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
362
589
|
const query = {};
|
|
590
|
+
if (opts.include != null) {
|
|
591
|
+
query.include = coerceQueryFlag(opts.include, { field: "include", flag: "--include", kind: "string" }, exitWithError);
|
|
592
|
+
}
|
|
363
593
|
const res = await apiRequest({ method: "GET", path: "scouts/" + encodeURIComponent(id), token, baseUrl: getBaseUrl(), query });
|
|
364
594
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
365
595
|
const data = res.data?.data ?? res.data;
|
|
@@ -413,20 +643,99 @@ function register(program, helpers) {
|
|
|
413
643
|
if (parsedActivationPotential !== void 0) bodyFromFlags.activationPotential = parsedActivationPotential;
|
|
414
644
|
const body = mergeBody(bodyFromFlags, opts.body);
|
|
415
645
|
if (opts.ifNotExists) {
|
|
646
|
+
const existing = await findExistingResource({
|
|
647
|
+
resource: "scouts",
|
|
648
|
+
token,
|
|
649
|
+
baseUrl: getBaseUrl(),
|
|
650
|
+
body,
|
|
651
|
+
identityFields: ["name", "organizationId"],
|
|
652
|
+
queryFields: ["organizationId", "categoryId", "include"],
|
|
653
|
+
request: apiRequest
|
|
654
|
+
});
|
|
655
|
+
if (existing) {
|
|
656
|
+
printOutput(getOutputFormat(), existing, false);
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
416
659
|
}
|
|
417
660
|
const res = await apiRequest({ method: "POST", path: "scouts", token, baseUrl: getBaseUrl(), body });
|
|
418
661
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
419
662
|
const data = res.data?.data ?? res.data;
|
|
420
663
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
421
664
|
});
|
|
422
|
-
scoutsCmd.command("update
|
|
665
|
+
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
666
|
syncRootOptsFromCommand(thisCommand);
|
|
424
667
|
}).action(async (id, opts) => {
|
|
425
668
|
const token = requireToken();
|
|
426
669
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
427
|
-
const
|
|
670
|
+
const inputRecords = await parseBulkInput(opts.input);
|
|
671
|
+
if (inputRecords.length > 0) {
|
|
672
|
+
const ids2 = inputRecords.map(getBulkRecordId).filter((value) => value !== null);
|
|
673
|
+
if (ids2.length !== inputRecords.length) exitWithError(400, "Each --input record must include id or _id");
|
|
674
|
+
validateBulkIds(ids2, "scouts");
|
|
675
|
+
if (opts.dryRun) {
|
|
676
|
+
printOutput(getOutputFormat(), { data: ids2.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids2.length, succeeded: ids2.length, failed: 0 } }, false);
|
|
677
|
+
return;
|
|
678
|
+
}
|
|
679
|
+
const { data: data2, summary } = await runBulk({
|
|
680
|
+
items: inputRecords,
|
|
681
|
+
runOne: async (record) => {
|
|
682
|
+
const itemId = getBulkRecordId(record);
|
|
683
|
+
const recordBody = { ...record };
|
|
684
|
+
delete recordBody.id;
|
|
685
|
+
delete recordBody._id;
|
|
686
|
+
const bodyFromFlags2 = {};
|
|
687
|
+
const parsedName2 = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
688
|
+
if (parsedName2 !== void 0) bodyFromFlags2.name = parsedName2;
|
|
689
|
+
const parsedDescription2 = coerceBodyFlag(opts.description, { field: "description", flag: "--description", kind: "string" }, exitWithError);
|
|
690
|
+
if (parsedDescription2 !== void 0) bodyFromFlags2.description = parsedDescription2;
|
|
691
|
+
const parsedCategoryId2 = coerceBodyFlag(opts.categoryId, { field: "categoryId", flag: "--category-id", kind: "string", allowNull: true }, exitWithError);
|
|
692
|
+
if (parsedCategoryId2 !== void 0) bodyFromFlags2.categoryId = parsedCategoryId2;
|
|
693
|
+
const parsedUrl2 = coerceBodyFlag(opts.url, { field: "url", flag: "--url", kind: "string" }, exitWithError);
|
|
694
|
+
if (parsedUrl2 !== void 0) bodyFromFlags2.url = parsedUrl2;
|
|
695
|
+
const parsedHeroImage2 = coerceBodyFlag(opts.heroImage, { field: "heroImage", flag: "--hero-image", kind: "string" }, exitWithError);
|
|
696
|
+
if (parsedHeroImage2 !== void 0) bodyFromFlags2.heroImage = parsedHeroImage2;
|
|
697
|
+
const parsedPriority2 = coerceBodyFlag(opts.priority, { field: "priority", flag: "--priority", kind: "string" }, exitWithError);
|
|
698
|
+
if (parsedPriority2 !== void 0) bodyFromFlags2.priority = parsedPriority2;
|
|
699
|
+
const parsedStatus2 = coerceBodyFlag(opts.status, { field: "status", flag: "--status", kind: "string" }, exitWithError);
|
|
700
|
+
if (parsedStatus2 !== void 0) bodyFromFlags2.status = parsedStatus2;
|
|
701
|
+
const parsedEstimatedCost2 = coerceBodyFlag(opts.estimatedCost, { field: "estimatedCost", flag: "--estimated-cost", kind: "number" }, exitWithError);
|
|
702
|
+
if (parsedEstimatedCost2 !== void 0) bodyFromFlags2.estimatedCost = parsedEstimatedCost2;
|
|
703
|
+
const parsedPotentialCost2 = coerceBodyFlag(opts.potentialCost, { field: "potentialCost", flag: "--potential-cost", kind: "number" }, exitWithError);
|
|
704
|
+
if (parsedPotentialCost2 !== void 0) bodyFromFlags2.potentialCost = parsedPotentialCost2;
|
|
705
|
+
const parsedNeed2 = coerceBodyFlag(opts.need, { field: "need", flag: "--need", kind: "number" }, exitWithError);
|
|
706
|
+
if (parsedNeed2 !== void 0) bodyFromFlags2.need = parsedNeed2;
|
|
707
|
+
const parsedUrgency2 = coerceBodyFlag(opts.urgency, { field: "urgency", flag: "--urgency", kind: "number" }, exitWithError);
|
|
708
|
+
if (parsedUrgency2 !== void 0) bodyFromFlags2.urgency = parsedUrgency2;
|
|
709
|
+
const parsedUse2 = coerceBodyFlag(opts.use, { field: "use", flag: "--use", kind: "number" }, exitWithError);
|
|
710
|
+
if (parsedUse2 !== void 0) bodyFromFlags2.use = parsedUse2;
|
|
711
|
+
const parsedLongevity2 = coerceBodyFlag(opts.longevity, { field: "longevity", flag: "--longevity", kind: "number" }, exitWithError);
|
|
712
|
+
if (parsedLongevity2 !== void 0) bodyFromFlags2.longevity = parsedLongevity2;
|
|
713
|
+
const parsedRoi2 = coerceBodyFlag(opts.roi, { field: "roi", flag: "--roi", kind: "number" }, exitWithError);
|
|
714
|
+
if (parsedRoi2 !== void 0) bodyFromFlags2.roi = parsedRoi2;
|
|
715
|
+
const parsedSystemFit2 = coerceBodyFlag(opts.systemFit, { field: "systemFit", flag: "--system-fit", kind: "number" }, exitWithError);
|
|
716
|
+
if (parsedSystemFit2 !== void 0) bodyFromFlags2.systemFit = parsedSystemFit2;
|
|
717
|
+
const parsedEmotionalPull2 = coerceBodyFlag(opts.emotionalPull, { field: "emotionalPull", flag: "--emotional-pull", kind: "number" }, exitWithError);
|
|
718
|
+
if (parsedEmotionalPull2 !== void 0) bodyFromFlags2.emotionalPull = parsedEmotionalPull2;
|
|
719
|
+
const parsedInfrastructureFit2 = coerceBodyFlag(opts.infrastructureFit, { field: "infrastructureFit", flag: "--infrastructure-fit", kind: "number" }, exitWithError);
|
|
720
|
+
if (parsedInfrastructureFit2 !== void 0) bodyFromFlags2.infrastructureFit = parsedInfrastructureFit2;
|
|
721
|
+
const parsedActivationPotential2 = coerceBodyFlag(opts.activationPotential, { field: "activationPotential", flag: "--activation-potential", kind: "number" }, exitWithError);
|
|
722
|
+
if (parsedActivationPotential2 !== void 0) bodyFromFlags2.activationPotential = parsedActivationPotential2;
|
|
723
|
+
const body2 = { ...recordBody, ...mergeBody(bodyFromFlags2, opts.body) };
|
|
724
|
+
const res2 = await apiRequest({ method: "PATCH", path: "scouts/" + encodeURIComponent(itemId), token, baseUrl: getBaseUrl(), body: body2 });
|
|
725
|
+
return { ok: res2.ok, status: res2.status || 0, data: res2.data, error: res2.error };
|
|
726
|
+
},
|
|
727
|
+
toResult: (record, ok, status, _data, err) => ok ? { _id: getBulkRecordId(record), status: "updated" } : { _id: getBulkRecordId(record) ?? void 0, error: true, statusCode: status, message: err ?? "Failed" }
|
|
728
|
+
});
|
|
729
|
+
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
730
|
+
return;
|
|
731
|
+
}
|
|
732
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
428
733
|
if (ids.length > 0) {
|
|
429
734
|
validateBulkIds(ids, "scouts");
|
|
735
|
+
if (opts.dryRun) {
|
|
736
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
430
739
|
const { data: data2, summary } = await runBulk({
|
|
431
740
|
items: ids,
|
|
432
741
|
runOne: async (itemId) => {
|
|
@@ -476,6 +785,7 @@ function register(program, helpers) {
|
|
|
476
785
|
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
477
786
|
return;
|
|
478
787
|
}
|
|
788
|
+
if (!id) exitWithError(400, "Provide id, --ids, --ids-file, or --input");
|
|
479
789
|
const bodyFromFlags = {};
|
|
480
790
|
const parsedName = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
481
791
|
if (parsedName !== void 0) bodyFromFlags.name = parsedName;
|
|
@@ -519,14 +829,18 @@ function register(program, helpers) {
|
|
|
519
829
|
const data = res.data?.data ?? res.data;
|
|
520
830
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
521
831
|
});
|
|
522
|
-
scoutsCmd.command("delete
|
|
832
|
+
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
833
|
syncRootOptsFromCommand(thisCommand);
|
|
524
834
|
}).action(async (id, opts) => {
|
|
525
835
|
const token = requireToken();
|
|
526
836
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
527
|
-
const ids =
|
|
837
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
528
838
|
if (ids.length > 0) {
|
|
529
839
|
validateBulkIds(ids, "scouts");
|
|
840
|
+
if (opts.dryRun) {
|
|
841
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_delete" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
842
|
+
return;
|
|
843
|
+
}
|
|
530
844
|
const { data, summary } = await runBulk({
|
|
531
845
|
items: ids,
|
|
532
846
|
runOne: async (itemId) => {
|
|
@@ -538,12 +852,17 @@ function register(program, helpers) {
|
|
|
538
852
|
printOutput(getOutputFormat(), { data, summary }, false);
|
|
539
853
|
return;
|
|
540
854
|
}
|
|
855
|
+
if (!id) exitWithError(400, "Provide id, --ids, or --ids-file");
|
|
856
|
+
if (opts.dryRun) {
|
|
857
|
+
printOutput(getOutputFormat(), { _id: id, status: "would_delete" }, false);
|
|
858
|
+
return;
|
|
859
|
+
}
|
|
541
860
|
const res = await apiRequest({ method: "DELETE", path: "scouts/" + encodeURIComponent(id), token, baseUrl: getBaseUrl() });
|
|
542
861
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
543
862
|
if (getOutputFormat() === "json") console.log(JSON.stringify({ data: null, deleted: true }));
|
|
544
863
|
});
|
|
545
864
|
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) => {
|
|
865
|
+
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").option("--include <value>", "Filter by include").hook("preAction", (thisCommand) => {
|
|
547
866
|
syncRootOptsFromCommand(thisCommand);
|
|
548
867
|
}).action(async (opts) => {
|
|
549
868
|
const token = requireToken();
|
|
@@ -557,17 +876,23 @@ function register(program, helpers) {
|
|
|
557
876
|
if (opts.scoutId != null) {
|
|
558
877
|
query.scoutId = coerceQueryFlag(opts.scoutId, { field: "scoutId", flag: "--scout-id", kind: "string" }, exitWithError);
|
|
559
878
|
}
|
|
560
|
-
|
|
879
|
+
if (opts.include != null) {
|
|
880
|
+
query.include = coerceQueryFlag(opts.include, { field: "include", flag: "--include", kind: "string" }, exitWithError);
|
|
881
|
+
}
|
|
882
|
+
const res = await fetchList({ path: "assets", token, baseUrl: getBaseUrl(), query, all: Boolean(opts.all), request: apiRequest });
|
|
561
883
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
562
884
|
const data = res.data?.data ?? [];
|
|
563
|
-
|
|
885
|
+
printList({ format: getOutputFormat(), data, fields: opts.fields, where: opts.where, jsonl: Boolean(opts.jsonl) });
|
|
564
886
|
});
|
|
565
|
-
assetsCmd.command("get <id>").description("Get one assets by id").hook("preAction", (thisCommand) => {
|
|
887
|
+
assetsCmd.command("get <id>").description("Get one assets by id").option("--include <value>", "Include/filter by include").hook("preAction", (thisCommand) => {
|
|
566
888
|
syncRootOptsFromCommand(thisCommand);
|
|
567
889
|
}).action(async (id, opts) => {
|
|
568
890
|
const token = requireToken();
|
|
569
891
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
570
892
|
const query = {};
|
|
893
|
+
if (opts.include != null) {
|
|
894
|
+
query.include = coerceQueryFlag(opts.include, { field: "include", flag: "--include", kind: "string" }, exitWithError);
|
|
895
|
+
}
|
|
571
896
|
const res = await apiRequest({ method: "GET", path: "assets/" + encodeURIComponent(id), token, baseUrl: getBaseUrl(), query });
|
|
572
897
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
573
898
|
const data = res.data?.data ?? res.data;
|
|
@@ -607,20 +932,87 @@ function register(program, helpers) {
|
|
|
607
932
|
if (parsedCost !== void 0) bodyFromFlags.cost = parsedCost;
|
|
608
933
|
const body = mergeBody(bodyFromFlags, opts.body);
|
|
609
934
|
if (opts.ifNotExists) {
|
|
935
|
+
const existing = await findExistingResource({
|
|
936
|
+
resource: "assets",
|
|
937
|
+
token,
|
|
938
|
+
baseUrl: getBaseUrl(),
|
|
939
|
+
body,
|
|
940
|
+
identityFields: ["name", "organizationId"],
|
|
941
|
+
queryFields: ["organizationId", "scoutId", "include"],
|
|
942
|
+
request: apiRequest
|
|
943
|
+
});
|
|
944
|
+
if (existing) {
|
|
945
|
+
printOutput(getOutputFormat(), existing, false);
|
|
946
|
+
return;
|
|
947
|
+
}
|
|
610
948
|
}
|
|
611
949
|
const res = await apiRequest({ method: "POST", path: "assets", token, baseUrl: getBaseUrl(), body });
|
|
612
950
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
613
951
|
const data = res.data?.data ?? res.data;
|
|
614
952
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
615
953
|
});
|
|
616
|
-
assetsCmd.command("update
|
|
954
|
+
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
955
|
syncRootOptsFromCommand(thisCommand);
|
|
618
956
|
}).action(async (id, opts) => {
|
|
619
957
|
const token = requireToken();
|
|
620
958
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
621
|
-
const
|
|
959
|
+
const inputRecords = await parseBulkInput(opts.input);
|
|
960
|
+
if (inputRecords.length > 0) {
|
|
961
|
+
const ids2 = inputRecords.map(getBulkRecordId).filter((value) => value !== null);
|
|
962
|
+
if (ids2.length !== inputRecords.length) exitWithError(400, "Each --input record must include id or _id");
|
|
963
|
+
validateBulkIds(ids2, "assets");
|
|
964
|
+
if (opts.dryRun) {
|
|
965
|
+
printOutput(getOutputFormat(), { data: ids2.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids2.length, succeeded: ids2.length, failed: 0 } }, false);
|
|
966
|
+
return;
|
|
967
|
+
}
|
|
968
|
+
const { data: data2, summary } = await runBulk({
|
|
969
|
+
items: inputRecords,
|
|
970
|
+
runOne: async (record) => {
|
|
971
|
+
const itemId = getBulkRecordId(record);
|
|
972
|
+
const recordBody = { ...record };
|
|
973
|
+
delete recordBody.id;
|
|
974
|
+
delete recordBody._id;
|
|
975
|
+
const bodyFromFlags2 = {};
|
|
976
|
+
const parsedName2 = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
977
|
+
if (parsedName2 !== void 0) bodyFromFlags2.name = parsedName2;
|
|
978
|
+
const parsedDescription2 = coerceBodyFlag(opts.description, { field: "description", flag: "--description", kind: "string" }, exitWithError);
|
|
979
|
+
if (parsedDescription2 !== void 0) bodyFromFlags2.description = parsedDescription2;
|
|
980
|
+
const parsedScoutId2 = coerceBodyFlag(opts.scoutId, { field: "scoutId", flag: "--scout-id", kind: "string", allowNull: true }, exitWithError);
|
|
981
|
+
if (parsedScoutId2 !== void 0) bodyFromFlags2.scoutId = parsedScoutId2;
|
|
982
|
+
const parsedCategoryId2 = coerceBodyFlag(opts.categoryId, { field: "categoryId", flag: "--category-id", kind: "string", allowNull: true }, exitWithError);
|
|
983
|
+
if (parsedCategoryId2 !== void 0) bodyFromFlags2.categoryId = parsedCategoryId2;
|
|
984
|
+
const parsedHeroImage2 = coerceBodyFlag(opts.heroImage, { field: "heroImage", flag: "--hero-image", kind: "string" }, exitWithError);
|
|
985
|
+
if (parsedHeroImage2 !== void 0) bodyFromFlags2.heroImage = parsedHeroImage2;
|
|
986
|
+
const parsedCondition2 = coerceBodyFlag(opts.condition, { field: "condition", flag: "--condition", kind: "number" }, exitWithError);
|
|
987
|
+
if (parsedCondition2 !== void 0) bodyFromFlags2.condition = parsedCondition2;
|
|
988
|
+
const parsedSatisfaction2 = coerceBodyFlag(opts.satisfaction, { field: "satisfaction", flag: "--satisfaction", kind: "number" }, exitWithError);
|
|
989
|
+
if (parsedSatisfaction2 !== void 0) bodyFromFlags2.satisfaction = parsedSatisfaction2;
|
|
990
|
+
const parsedUsage2 = coerceBodyFlag(opts.usage, { field: "usage", flag: "--usage", kind: "number" }, exitWithError);
|
|
991
|
+
if (parsedUsage2 !== void 0) bodyFromFlags2.usage = parsedUsage2;
|
|
992
|
+
const parsedFriction2 = coerceBodyFlag(opts.friction, { field: "friction", flag: "--friction", kind: "number" }, exitWithError);
|
|
993
|
+
if (parsedFriction2 !== void 0) bodyFromFlags2.friction = parsedFriction2;
|
|
994
|
+
const parsedLifetimeValue2 = coerceBodyFlag(opts.lifetimeValue, { field: "lifetimeValue", flag: "--lifetime-value", kind: "number" }, exitWithError);
|
|
995
|
+
if (parsedLifetimeValue2 !== void 0) bodyFromFlags2.lifetimeValue = parsedLifetimeValue2;
|
|
996
|
+
const parsedAcquisitionDate2 = coerceBodyFlag(opts.acquisitionDate, { field: "acquisitionDate", flag: "--acquisition-date", kind: "number" }, exitWithError);
|
|
997
|
+
if (parsedAcquisitionDate2 !== void 0) bodyFromFlags2.acquisitionDate = parsedAcquisitionDate2;
|
|
998
|
+
const parsedCost2 = coerceBodyFlag(opts.cost, { field: "cost", flag: "--cost", kind: "number" }, exitWithError);
|
|
999
|
+
if (parsedCost2 !== void 0) bodyFromFlags2.cost = parsedCost2;
|
|
1000
|
+
const body2 = { ...recordBody, ...mergeBody(bodyFromFlags2, opts.body) };
|
|
1001
|
+
const res2 = await apiRequest({ method: "PATCH", path: "assets/" + encodeURIComponent(itemId), token, baseUrl: getBaseUrl(), body: body2 });
|
|
1002
|
+
return { ok: res2.ok, status: res2.status || 0, data: res2.data, error: res2.error };
|
|
1003
|
+
},
|
|
1004
|
+
toResult: (record, ok, status, _data, err) => ok ? { _id: getBulkRecordId(record), status: "updated" } : { _id: getBulkRecordId(record) ?? void 0, error: true, statusCode: status, message: err ?? "Failed" }
|
|
1005
|
+
});
|
|
1006
|
+
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
1007
|
+
return;
|
|
1008
|
+
}
|
|
1009
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
622
1010
|
if (ids.length > 0) {
|
|
623
1011
|
validateBulkIds(ids, "assets");
|
|
1012
|
+
if (opts.dryRun) {
|
|
1013
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
1014
|
+
return;
|
|
1015
|
+
}
|
|
624
1016
|
const { data: data2, summary } = await runBulk({
|
|
625
1017
|
items: ids,
|
|
626
1018
|
runOne: async (itemId) => {
|
|
@@ -658,6 +1050,7 @@ function register(program, helpers) {
|
|
|
658
1050
|
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
659
1051
|
return;
|
|
660
1052
|
}
|
|
1053
|
+
if (!id) exitWithError(400, "Provide id, --ids, --ids-file, or --input");
|
|
661
1054
|
const bodyFromFlags = {};
|
|
662
1055
|
const parsedName = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
663
1056
|
if (parsedName !== void 0) bodyFromFlags.name = parsedName;
|
|
@@ -689,14 +1082,18 @@ function register(program, helpers) {
|
|
|
689
1082
|
const data = res.data?.data ?? res.data;
|
|
690
1083
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
691
1084
|
});
|
|
692
|
-
assetsCmd.command("delete
|
|
1085
|
+
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
1086
|
syncRootOptsFromCommand(thisCommand);
|
|
694
1087
|
}).action(async (id, opts) => {
|
|
695
1088
|
const token = requireToken();
|
|
696
1089
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
697
|
-
const ids =
|
|
1090
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
698
1091
|
if (ids.length > 0) {
|
|
699
1092
|
validateBulkIds(ids, "assets");
|
|
1093
|
+
if (opts.dryRun) {
|
|
1094
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_delete" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
1095
|
+
return;
|
|
1096
|
+
}
|
|
700
1097
|
const { data, summary } = await runBulk({
|
|
701
1098
|
items: ids,
|
|
702
1099
|
runOne: async (itemId) => {
|
|
@@ -708,12 +1105,17 @@ function register(program, helpers) {
|
|
|
708
1105
|
printOutput(getOutputFormat(), { data, summary }, false);
|
|
709
1106
|
return;
|
|
710
1107
|
}
|
|
1108
|
+
if (!id) exitWithError(400, "Provide id, --ids, or --ids-file");
|
|
1109
|
+
if (opts.dryRun) {
|
|
1110
|
+
printOutput(getOutputFormat(), { _id: id, status: "would_delete" }, false);
|
|
1111
|
+
return;
|
|
1112
|
+
}
|
|
711
1113
|
const res = await apiRequest({ method: "DELETE", path: "assets/" + encodeURIComponent(id), token, baseUrl: getBaseUrl() });
|
|
712
1114
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
713
1115
|
if (getOutputFormat() === "json") console.log(JSON.stringify({ data: null, deleted: true }));
|
|
714
1116
|
});
|
|
715
1117
|
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) => {
|
|
1118
|
+
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
1119
|
syncRootOptsFromCommand(thisCommand);
|
|
718
1120
|
}).action(async (opts) => {
|
|
719
1121
|
const token = requireToken();
|
|
@@ -724,10 +1126,10 @@ function register(program, helpers) {
|
|
|
724
1126
|
if (opts.organizationId != null) {
|
|
725
1127
|
query.organizationId = coerceQueryFlag(opts.organizationId, { field: "organizationId", flag: "--organization-id", kind: "string" }, exitWithError);
|
|
726
1128
|
}
|
|
727
|
-
const res = await
|
|
1129
|
+
const res = await fetchList({ path: "categories", token, baseUrl: getBaseUrl(), query, all: Boolean(opts.all), request: apiRequest });
|
|
728
1130
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
729
1131
|
const data = res.data?.data ?? [];
|
|
730
|
-
|
|
1132
|
+
printList({ format: getOutputFormat(), data, fields: opts.fields, where: opts.where, jsonl: Boolean(opts.jsonl) });
|
|
731
1133
|
});
|
|
732
1134
|
categoriesCmd.command("get <id>").description("Get one categories by id").hook("preAction", (thisCommand) => {
|
|
733
1135
|
syncRootOptsFromCommand(thisCommand);
|
|
@@ -754,20 +1156,67 @@ function register(program, helpers) {
|
|
|
754
1156
|
if (parsedDefaultBucket !== void 0) bodyFromFlags.defaultBucket = parsedDefaultBucket;
|
|
755
1157
|
const body = mergeBody(bodyFromFlags, opts.body);
|
|
756
1158
|
if (opts.ifNotExists) {
|
|
1159
|
+
const existing = await findExistingResource({
|
|
1160
|
+
resource: "categories",
|
|
1161
|
+
token,
|
|
1162
|
+
baseUrl: getBaseUrl(),
|
|
1163
|
+
body,
|
|
1164
|
+
identityFields: ["name", "organizationId"],
|
|
1165
|
+
queryFields: ["organizationId"],
|
|
1166
|
+
request: apiRequest
|
|
1167
|
+
});
|
|
1168
|
+
if (existing) {
|
|
1169
|
+
printOutput(getOutputFormat(), existing, false);
|
|
1170
|
+
return;
|
|
1171
|
+
}
|
|
757
1172
|
}
|
|
758
1173
|
const res = await apiRequest({ method: "POST", path: "categories", token, baseUrl: getBaseUrl(), body });
|
|
759
1174
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
760
1175
|
const data = res.data?.data ?? res.data;
|
|
761
1176
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
762
1177
|
});
|
|
763
|
-
categoriesCmd.command("update
|
|
1178
|
+
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
1179
|
syncRootOptsFromCommand(thisCommand);
|
|
765
1180
|
}).action(async (id, opts) => {
|
|
766
1181
|
const token = requireToken();
|
|
767
1182
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
768
|
-
const
|
|
1183
|
+
const inputRecords = await parseBulkInput(opts.input);
|
|
1184
|
+
if (inputRecords.length > 0) {
|
|
1185
|
+
const ids2 = inputRecords.map(getBulkRecordId).filter((value) => value !== null);
|
|
1186
|
+
if (ids2.length !== inputRecords.length) exitWithError(400, "Each --input record must include id or _id");
|
|
1187
|
+
validateBulkIds(ids2, "categories");
|
|
1188
|
+
if (opts.dryRun) {
|
|
1189
|
+
printOutput(getOutputFormat(), { data: ids2.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids2.length, succeeded: ids2.length, failed: 0 } }, false);
|
|
1190
|
+
return;
|
|
1191
|
+
}
|
|
1192
|
+
const { data: data2, summary } = await runBulk({
|
|
1193
|
+
items: inputRecords,
|
|
1194
|
+
runOne: async (record) => {
|
|
1195
|
+
const itemId = getBulkRecordId(record);
|
|
1196
|
+
const recordBody = { ...record };
|
|
1197
|
+
delete recordBody.id;
|
|
1198
|
+
delete recordBody._id;
|
|
1199
|
+
const bodyFromFlags2 = {};
|
|
1200
|
+
const parsedName2 = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
1201
|
+
if (parsedName2 !== void 0) bodyFromFlags2.name = parsedName2;
|
|
1202
|
+
const parsedDefaultBucket2 = coerceBodyFlag(opts.defaultBucket, { field: "defaultBucket", flag: "--default-bucket", kind: "string" }, exitWithError);
|
|
1203
|
+
if (parsedDefaultBucket2 !== void 0) bodyFromFlags2.defaultBucket = parsedDefaultBucket2;
|
|
1204
|
+
const body2 = { ...recordBody, ...mergeBody(bodyFromFlags2, opts.body) };
|
|
1205
|
+
const res2 = await apiRequest({ method: "PATCH", path: "categories/" + encodeURIComponent(itemId), token, baseUrl: getBaseUrl(), body: body2 });
|
|
1206
|
+
return { ok: res2.ok, status: res2.status || 0, data: res2.data, error: res2.error };
|
|
1207
|
+
},
|
|
1208
|
+
toResult: (record, ok, status, _data, err) => ok ? { _id: getBulkRecordId(record), status: "updated" } : { _id: getBulkRecordId(record) ?? void 0, error: true, statusCode: status, message: err ?? "Failed" }
|
|
1209
|
+
});
|
|
1210
|
+
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
1211
|
+
return;
|
|
1212
|
+
}
|
|
1213
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
769
1214
|
if (ids.length > 0) {
|
|
770
1215
|
validateBulkIds(ids, "categories");
|
|
1216
|
+
if (opts.dryRun) {
|
|
1217
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
1218
|
+
return;
|
|
1219
|
+
}
|
|
771
1220
|
const { data: data2, summary } = await runBulk({
|
|
772
1221
|
items: ids,
|
|
773
1222
|
runOne: async (itemId) => {
|
|
@@ -785,6 +1234,7 @@ function register(program, helpers) {
|
|
|
785
1234
|
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
786
1235
|
return;
|
|
787
1236
|
}
|
|
1237
|
+
if (!id) exitWithError(400, "Provide id, --ids, --ids-file, or --input");
|
|
788
1238
|
const bodyFromFlags = {};
|
|
789
1239
|
const parsedName = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
790
1240
|
if (parsedName !== void 0) bodyFromFlags.name = parsedName;
|
|
@@ -796,14 +1246,18 @@ function register(program, helpers) {
|
|
|
796
1246
|
const data = res.data?.data ?? res.data;
|
|
797
1247
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
798
1248
|
});
|
|
799
|
-
categoriesCmd.command("delete
|
|
1249
|
+
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
1250
|
syncRootOptsFromCommand(thisCommand);
|
|
801
1251
|
}).action(async (id, opts) => {
|
|
802
1252
|
const token = requireToken();
|
|
803
1253
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
804
|
-
const ids =
|
|
1254
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
805
1255
|
if (ids.length > 0) {
|
|
806
1256
|
validateBulkIds(ids, "categories");
|
|
1257
|
+
if (opts.dryRun) {
|
|
1258
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_delete" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
1259
|
+
return;
|
|
1260
|
+
}
|
|
807
1261
|
const { data, summary } = await runBulk({
|
|
808
1262
|
items: ids,
|
|
809
1263
|
runOne: async (itemId) => {
|
|
@@ -815,12 +1269,17 @@ function register(program, helpers) {
|
|
|
815
1269
|
printOutput(getOutputFormat(), { data, summary }, false);
|
|
816
1270
|
return;
|
|
817
1271
|
}
|
|
1272
|
+
if (!id) exitWithError(400, "Provide id, --ids, or --ids-file");
|
|
1273
|
+
if (opts.dryRun) {
|
|
1274
|
+
printOutput(getOutputFormat(), { _id: id, status: "would_delete" }, false);
|
|
1275
|
+
return;
|
|
1276
|
+
}
|
|
818
1277
|
const res = await apiRequest({ method: "DELETE", path: "categories/" + encodeURIComponent(id), token, baseUrl: getBaseUrl() });
|
|
819
1278
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
820
1279
|
if (getOutputFormat() === "json") console.log(JSON.stringify({ data: null, deleted: true }));
|
|
821
1280
|
});
|
|
822
1281
|
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) => {
|
|
1282
|
+
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
1283
|
syncRootOptsFromCommand(thisCommand);
|
|
825
1284
|
}).action(async (opts) => {
|
|
826
1285
|
const token = requireToken();
|
|
@@ -831,10 +1290,10 @@ function register(program, helpers) {
|
|
|
831
1290
|
if (opts.organizationId != null) {
|
|
832
1291
|
query.organizationId = coerceQueryFlag(opts.organizationId, { field: "organizationId", flag: "--organization-id", kind: "string" }, exitWithError);
|
|
833
1292
|
}
|
|
834
|
-
const res = await
|
|
1293
|
+
const res = await fetchList({ path: "labels", token, baseUrl: getBaseUrl(), query, all: Boolean(opts.all), request: apiRequest });
|
|
835
1294
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
836
1295
|
const data = res.data?.data ?? [];
|
|
837
|
-
|
|
1296
|
+
printList({ format: getOutputFormat(), data, fields: opts.fields, where: opts.where, jsonl: Boolean(opts.jsonl) });
|
|
838
1297
|
});
|
|
839
1298
|
labelsCmd.command("get <id>").description("Get one labels by id").hook("preAction", (thisCommand) => {
|
|
840
1299
|
syncRootOptsFromCommand(thisCommand);
|
|
@@ -861,20 +1320,67 @@ function register(program, helpers) {
|
|
|
861
1320
|
if (parsedColour !== void 0) bodyFromFlags.colour = parsedColour;
|
|
862
1321
|
const body = mergeBody(bodyFromFlags, opts.body);
|
|
863
1322
|
if (opts.ifNotExists) {
|
|
1323
|
+
const existing = await findExistingResource({
|
|
1324
|
+
resource: "labels",
|
|
1325
|
+
token,
|
|
1326
|
+
baseUrl: getBaseUrl(),
|
|
1327
|
+
body,
|
|
1328
|
+
identityFields: ["name", "organizationId"],
|
|
1329
|
+
queryFields: ["organizationId"],
|
|
1330
|
+
request: apiRequest
|
|
1331
|
+
});
|
|
1332
|
+
if (existing) {
|
|
1333
|
+
printOutput(getOutputFormat(), existing, false);
|
|
1334
|
+
return;
|
|
1335
|
+
}
|
|
864
1336
|
}
|
|
865
1337
|
const res = await apiRequest({ method: "POST", path: "labels", token, baseUrl: getBaseUrl(), body });
|
|
866
1338
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
867
1339
|
const data = res.data?.data ?? res.data;
|
|
868
1340
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
869
1341
|
});
|
|
870
|
-
labelsCmd.command("update
|
|
1342
|
+
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
1343
|
syncRootOptsFromCommand(thisCommand);
|
|
872
1344
|
}).action(async (id, opts) => {
|
|
873
1345
|
const token = requireToken();
|
|
874
1346
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
875
|
-
const
|
|
1347
|
+
const inputRecords = await parseBulkInput(opts.input);
|
|
1348
|
+
if (inputRecords.length > 0) {
|
|
1349
|
+
const ids2 = inputRecords.map(getBulkRecordId).filter((value) => value !== null);
|
|
1350
|
+
if (ids2.length !== inputRecords.length) exitWithError(400, "Each --input record must include id or _id");
|
|
1351
|
+
validateBulkIds(ids2, "labels");
|
|
1352
|
+
if (opts.dryRun) {
|
|
1353
|
+
printOutput(getOutputFormat(), { data: ids2.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids2.length, succeeded: ids2.length, failed: 0 } }, false);
|
|
1354
|
+
return;
|
|
1355
|
+
}
|
|
1356
|
+
const { data: data2, summary } = await runBulk({
|
|
1357
|
+
items: inputRecords,
|
|
1358
|
+
runOne: async (record) => {
|
|
1359
|
+
const itemId = getBulkRecordId(record);
|
|
1360
|
+
const recordBody = { ...record };
|
|
1361
|
+
delete recordBody.id;
|
|
1362
|
+
delete recordBody._id;
|
|
1363
|
+
const bodyFromFlags2 = {};
|
|
1364
|
+
const parsedName2 = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
1365
|
+
if (parsedName2 !== void 0) bodyFromFlags2.name = parsedName2;
|
|
1366
|
+
const parsedColour2 = coerceBodyFlag(opts.colour, { field: "colour", flag: "--colour", kind: "string" }, exitWithError);
|
|
1367
|
+
if (parsedColour2 !== void 0) bodyFromFlags2.colour = parsedColour2;
|
|
1368
|
+
const body2 = { ...recordBody, ...mergeBody(bodyFromFlags2, opts.body) };
|
|
1369
|
+
const res2 = await apiRequest({ method: "PATCH", path: "labels/" + encodeURIComponent(itemId), token, baseUrl: getBaseUrl(), body: body2 });
|
|
1370
|
+
return { ok: res2.ok, status: res2.status || 0, data: res2.data, error: res2.error };
|
|
1371
|
+
},
|
|
1372
|
+
toResult: (record, ok, status, _data, err) => ok ? { _id: getBulkRecordId(record), status: "updated" } : { _id: getBulkRecordId(record) ?? void 0, error: true, statusCode: status, message: err ?? "Failed" }
|
|
1373
|
+
});
|
|
1374
|
+
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
1375
|
+
return;
|
|
1376
|
+
}
|
|
1377
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
876
1378
|
if (ids.length > 0) {
|
|
877
1379
|
validateBulkIds(ids, "labels");
|
|
1380
|
+
if (opts.dryRun) {
|
|
1381
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
1382
|
+
return;
|
|
1383
|
+
}
|
|
878
1384
|
const { data: data2, summary } = await runBulk({
|
|
879
1385
|
items: ids,
|
|
880
1386
|
runOne: async (itemId) => {
|
|
@@ -892,6 +1398,7 @@ function register(program, helpers) {
|
|
|
892
1398
|
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
893
1399
|
return;
|
|
894
1400
|
}
|
|
1401
|
+
if (!id) exitWithError(400, "Provide id, --ids, --ids-file, or --input");
|
|
895
1402
|
const bodyFromFlags = {};
|
|
896
1403
|
const parsedName = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
897
1404
|
if (parsedName !== void 0) bodyFromFlags.name = parsedName;
|
|
@@ -903,14 +1410,18 @@ function register(program, helpers) {
|
|
|
903
1410
|
const data = res.data?.data ?? res.data;
|
|
904
1411
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
905
1412
|
});
|
|
906
|
-
labelsCmd.command("delete
|
|
1413
|
+
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
1414
|
syncRootOptsFromCommand(thisCommand);
|
|
908
1415
|
}).action(async (id, opts) => {
|
|
909
1416
|
const token = requireToken();
|
|
910
1417
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
911
|
-
const ids =
|
|
1418
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
912
1419
|
if (ids.length > 0) {
|
|
913
1420
|
validateBulkIds(ids, "labels");
|
|
1421
|
+
if (opts.dryRun) {
|
|
1422
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_delete" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
1423
|
+
return;
|
|
1424
|
+
}
|
|
914
1425
|
const { data, summary } = await runBulk({
|
|
915
1426
|
items: ids,
|
|
916
1427
|
runOne: async (itemId) => {
|
|
@@ -922,12 +1433,17 @@ function register(program, helpers) {
|
|
|
922
1433
|
printOutput(getOutputFormat(), { data, summary }, false);
|
|
923
1434
|
return;
|
|
924
1435
|
}
|
|
1436
|
+
if (!id) exitWithError(400, "Provide id, --ids, or --ids-file");
|
|
1437
|
+
if (opts.dryRun) {
|
|
1438
|
+
printOutput(getOutputFormat(), { _id: id, status: "would_delete" }, false);
|
|
1439
|
+
return;
|
|
1440
|
+
}
|
|
925
1441
|
const res = await apiRequest({ method: "DELETE", path: "labels/" + encodeURIComponent(id), token, baseUrl: getBaseUrl() });
|
|
926
1442
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
927
1443
|
if (getOutputFormat() === "json") console.log(JSON.stringify({ data: null, deleted: true }));
|
|
928
1444
|
});
|
|
929
1445
|
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) => {
|
|
1446
|
+
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
1447
|
syncRootOptsFromCommand(thisCommand);
|
|
932
1448
|
}).action(async (opts) => {
|
|
933
1449
|
const token = requireToken();
|
|
@@ -944,10 +1460,10 @@ function register(program, helpers) {
|
|
|
944
1460
|
if (opts.entityType != null) {
|
|
945
1461
|
query.entityType = coerceQueryFlag(opts.entityType, { field: "entityType", flag: "--entity-type", kind: "string" }, exitWithError);
|
|
946
1462
|
}
|
|
947
|
-
const res = await
|
|
1463
|
+
const res = await fetchList({ path: "views", token, baseUrl: getBaseUrl(), query, all: Boolean(opts.all), request: apiRequest });
|
|
948
1464
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
949
1465
|
const data = res.data?.data ?? [];
|
|
950
|
-
|
|
1466
|
+
printList({ format: getOutputFormat(), data, fields: opts.fields, where: opts.where, jsonl: Boolean(opts.jsonl) });
|
|
951
1467
|
});
|
|
952
1468
|
viewsCmd.command("get <id>").description("Get one views by id").hook("preAction", (thisCommand) => {
|
|
953
1469
|
syncRootOptsFromCommand(thisCommand);
|
|
@@ -980,20 +1496,71 @@ function register(program, helpers) {
|
|
|
980
1496
|
if (parsedIsDefault !== void 0) bodyFromFlags.isDefault = parsedIsDefault;
|
|
981
1497
|
const body = mergeBody(bodyFromFlags, opts.body);
|
|
982
1498
|
if (opts.ifNotExists) {
|
|
1499
|
+
const existing = await findExistingResource({
|
|
1500
|
+
resource: "views",
|
|
1501
|
+
token,
|
|
1502
|
+
baseUrl: getBaseUrl(),
|
|
1503
|
+
body,
|
|
1504
|
+
identityFields: ["name", "entityType", "organizationId", "projectId"],
|
|
1505
|
+
queryFields: ["organizationId", "projectId", "entityType"],
|
|
1506
|
+
request: apiRequest
|
|
1507
|
+
});
|
|
1508
|
+
if (existing) {
|
|
1509
|
+
printOutput(getOutputFormat(), existing, false);
|
|
1510
|
+
return;
|
|
1511
|
+
}
|
|
983
1512
|
}
|
|
984
1513
|
const res = await apiRequest({ method: "POST", path: "views", token, baseUrl: getBaseUrl(), body });
|
|
985
1514
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
986
1515
|
const data = res.data?.data ?? res.data;
|
|
987
1516
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
988
1517
|
});
|
|
989
|
-
viewsCmd.command("update
|
|
1518
|
+
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
1519
|
syncRootOptsFromCommand(thisCommand);
|
|
991
1520
|
}).action(async (id, opts) => {
|
|
992
1521
|
const token = requireToken();
|
|
993
1522
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
994
|
-
const
|
|
1523
|
+
const inputRecords = await parseBulkInput(opts.input);
|
|
1524
|
+
if (inputRecords.length > 0) {
|
|
1525
|
+
const ids2 = inputRecords.map(getBulkRecordId).filter((value) => value !== null);
|
|
1526
|
+
if (ids2.length !== inputRecords.length) exitWithError(400, "Each --input record must include id or _id");
|
|
1527
|
+
validateBulkIds(ids2, "views");
|
|
1528
|
+
if (opts.dryRun) {
|
|
1529
|
+
printOutput(getOutputFormat(), { data: ids2.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids2.length, succeeded: ids2.length, failed: 0 } }, false);
|
|
1530
|
+
return;
|
|
1531
|
+
}
|
|
1532
|
+
const { data: data2, summary } = await runBulk({
|
|
1533
|
+
items: inputRecords,
|
|
1534
|
+
runOne: async (record) => {
|
|
1535
|
+
const itemId = getBulkRecordId(record);
|
|
1536
|
+
const recordBody = { ...record };
|
|
1537
|
+
delete recordBody.id;
|
|
1538
|
+
delete recordBody._id;
|
|
1539
|
+
const bodyFromFlags2 = {};
|
|
1540
|
+
const parsedName2 = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
1541
|
+
if (parsedName2 !== void 0) bodyFromFlags2.name = parsedName2;
|
|
1542
|
+
const parsedProjectId2 = coerceBodyFlag(opts.projectId, { field: "projectId", flag: "--project-id", kind: "string" }, exitWithError);
|
|
1543
|
+
if (parsedProjectId2 !== void 0) bodyFromFlags2.projectId = parsedProjectId2;
|
|
1544
|
+
const parsedConfig2 = coerceBodyFlag(opts.config, { field: "config", flag: "--config", kind: "string" }, exitWithError);
|
|
1545
|
+
if (parsedConfig2 !== void 0) bodyFromFlags2.config = parsedConfig2;
|
|
1546
|
+
const parsedIsDefault2 = coerceBodyFlag(opts.isDefault, { field: "isDefault", flag: "--is-default", kind: "boolean" }, exitWithError);
|
|
1547
|
+
if (parsedIsDefault2 !== void 0) bodyFromFlags2.isDefault = parsedIsDefault2;
|
|
1548
|
+
const body2 = { ...recordBody, ...mergeBody(bodyFromFlags2, opts.body) };
|
|
1549
|
+
const res2 = await apiRequest({ method: "PATCH", path: "views/" + encodeURIComponent(itemId), token, baseUrl: getBaseUrl(), body: body2 });
|
|
1550
|
+
return { ok: res2.ok, status: res2.status || 0, data: res2.data, error: res2.error };
|
|
1551
|
+
},
|
|
1552
|
+
toResult: (record, ok, status, _data, err) => ok ? { _id: getBulkRecordId(record), status: "updated" } : { _id: getBulkRecordId(record) ?? void 0, error: true, statusCode: status, message: err ?? "Failed" }
|
|
1553
|
+
});
|
|
1554
|
+
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
1555
|
+
return;
|
|
1556
|
+
}
|
|
1557
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
995
1558
|
if (ids.length > 0) {
|
|
996
1559
|
validateBulkIds(ids, "views");
|
|
1560
|
+
if (opts.dryRun) {
|
|
1561
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_update" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
1562
|
+
return;
|
|
1563
|
+
}
|
|
997
1564
|
const { data: data2, summary } = await runBulk({
|
|
998
1565
|
items: ids,
|
|
999
1566
|
runOne: async (itemId) => {
|
|
@@ -1015,6 +1582,7 @@ function register(program, helpers) {
|
|
|
1015
1582
|
printOutput(getOutputFormat(), { data: data2, summary }, false);
|
|
1016
1583
|
return;
|
|
1017
1584
|
}
|
|
1585
|
+
if (!id) exitWithError(400, "Provide id, --ids, --ids-file, or --input");
|
|
1018
1586
|
const bodyFromFlags = {};
|
|
1019
1587
|
const parsedName = coerceBodyFlag(opts.name, { field: "name", flag: "--name", kind: "string" }, exitWithError);
|
|
1020
1588
|
if (parsedName !== void 0) bodyFromFlags.name = parsedName;
|
|
@@ -1030,14 +1598,18 @@ function register(program, helpers) {
|
|
|
1030
1598
|
const data = res.data?.data ?? res.data;
|
|
1031
1599
|
printOutput(getOutputFormat(), data ?? {}, false);
|
|
1032
1600
|
});
|
|
1033
|
-
viewsCmd.command("delete
|
|
1601
|
+
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
1602
|
syncRootOptsFromCommand(thisCommand);
|
|
1035
1603
|
}).action(async (id, opts) => {
|
|
1036
1604
|
const token = requireToken();
|
|
1037
1605
|
if (!token) exitWithError(401, "Missing or invalid token");
|
|
1038
|
-
const ids =
|
|
1606
|
+
const ids = await parseIdsInput(opts.ids, opts.idsFile);
|
|
1039
1607
|
if (ids.length > 0) {
|
|
1040
1608
|
validateBulkIds(ids, "views");
|
|
1609
|
+
if (opts.dryRun) {
|
|
1610
|
+
printOutput(getOutputFormat(), { data: ids.map((_id) => ({ _id, status: "would_delete" })), summary: { total: ids.length, succeeded: ids.length, failed: 0 } }, false);
|
|
1611
|
+
return;
|
|
1612
|
+
}
|
|
1041
1613
|
const { data, summary } = await runBulk({
|
|
1042
1614
|
items: ids,
|
|
1043
1615
|
runOne: async (itemId) => {
|
|
@@ -1049,12 +1621,17 @@ function register(program, helpers) {
|
|
|
1049
1621
|
printOutput(getOutputFormat(), { data, summary }, false);
|
|
1050
1622
|
return;
|
|
1051
1623
|
}
|
|
1624
|
+
if (!id) exitWithError(400, "Provide id, --ids, or --ids-file");
|
|
1625
|
+
if (opts.dryRun) {
|
|
1626
|
+
printOutput(getOutputFormat(), { _id: id, status: "would_delete" }, false);
|
|
1627
|
+
return;
|
|
1628
|
+
}
|
|
1052
1629
|
const res = await apiRequest({ method: "DELETE", path: "views/" + encodeURIComponent(id), token, baseUrl: getBaseUrl() });
|
|
1053
1630
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
1054
1631
|
if (getOutputFormat() === "json") console.log(JSON.stringify({ data: null, deleted: true }));
|
|
1055
1632
|
});
|
|
1056
1633
|
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) => {
|
|
1634
|
+
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
1635
|
syncRootOptsFromCommand(thisCommand);
|
|
1059
1636
|
}).action(async (opts) => {
|
|
1060
1637
|
const token = requireToken();
|
|
@@ -1068,10 +1645,10 @@ function register(program, helpers) {
|
|
|
1068
1645
|
if (opts.entityId != null) {
|
|
1069
1646
|
query.entityId = coerceQueryFlag(opts.entityId, { field: "entityId", flag: "--entity-id", kind: "string" }, exitWithError);
|
|
1070
1647
|
}
|
|
1071
|
-
const res = await
|
|
1648
|
+
const res = await fetchList({ path: "comments", token, baseUrl: getBaseUrl(), query, all: Boolean(opts.all), request: apiRequest });
|
|
1072
1649
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
1073
1650
|
const data = res.data?.data ?? [];
|
|
1074
|
-
|
|
1651
|
+
printList({ format: getOutputFormat(), data, fields: opts.fields, where: opts.where, jsonl: Boolean(opts.jsonl) });
|
|
1075
1652
|
});
|
|
1076
1653
|
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
1654
|
syncRootOptsFromCommand(thisCommand);
|
|
@@ -1089,6 +1666,19 @@ function register(program, helpers) {
|
|
|
1089
1666
|
if (parsedParentCommentId !== void 0) bodyFromFlags.parentCommentId = parsedParentCommentId;
|
|
1090
1667
|
const body = mergeBody(bodyFromFlags, opts.body);
|
|
1091
1668
|
if (opts.ifNotExists) {
|
|
1669
|
+
const existing = await findExistingResource({
|
|
1670
|
+
resource: "comments",
|
|
1671
|
+
token,
|
|
1672
|
+
baseUrl: getBaseUrl(),
|
|
1673
|
+
body,
|
|
1674
|
+
identityFields: ["entityType", "entityId"],
|
|
1675
|
+
queryFields: ["entityType", "entityId"],
|
|
1676
|
+
request: apiRequest
|
|
1677
|
+
});
|
|
1678
|
+
if (existing) {
|
|
1679
|
+
printOutput(getOutputFormat(), existing, false);
|
|
1680
|
+
return;
|
|
1681
|
+
}
|
|
1092
1682
|
}
|
|
1093
1683
|
const res = await apiRequest({ method: "POST", path: "comments", token, baseUrl: getBaseUrl(), body });
|
|
1094
1684
|
if (!res.ok) exitWithError(res.status || 500, res.error ?? "Request failed");
|
|
@@ -1099,4 +1689,4 @@ function register(program, helpers) {
|
|
|
1099
1689
|
export {
|
|
1100
1690
|
register
|
|
1101
1691
|
};
|
|
1102
|
-
//# sourceMappingURL=generated-
|
|
1692
|
+
//# sourceMappingURL=generated-7QDIZ5V5.js.map
|