@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 CHANGED
@@ -54,11 +54,23 @@ Nested scout sources:
54
54
 
55
55
  ```bash
56
56
  pilfer sources list --scout-id <id>
57
- pilfer sources create --scout-id <id> --url <url> --title "Vendor" --price 49
57
+ pilfer sources create --scout-id <id> --url <url> --name "Vendor" --price 49
58
58
  pilfer sources update --scout-id <id> <source-id> --starred true
59
59
  pilfer sources delete --scout-id <id> <source-id>
60
60
  ```
61
61
 
62
+ Agent workflow helpers:
63
+
64
+ ```bash
65
+ pilfer scouts shortlist
66
+ pilfer scouts pipeline
67
+ pilfer scouts purchase <scout-id> --cost 120
68
+ pilfer reports scouting
69
+ pilfer reports assets
70
+ pilfer reports balance --project-id <id>
71
+ pilfer reports balance --space-id <id>
72
+ ```
73
+
62
74
  Top-level helpers:
63
75
 
64
76
  ```bash
package/SKILL.md CHANGED
@@ -19,11 +19,27 @@ Scout sources are nested and use custom commands:
19
19
  ```bash
20
20
  pilfer sources list --scout-id <id>
21
21
  pilfer sources get --scout-id <id> <source-id>
22
- pilfer sources create --scout-id <id> --url <url> --title <title> --price <n>
22
+ pilfer sources create --scout-id <id> --url <url> --name <name> --price <n>
23
23
  pilfer sources update --scout-id <id> <source-id> --price <n>
24
24
  pilfer sources delete --scout-id <id> <source-id>
25
25
  ```
26
26
 
27
+ ## Agent Workflows
28
+
29
+ Use workflow helpers before composing raw CRUD:
30
+
31
+ ```bash
32
+ pilfer scouts shortlist
33
+ pilfer scouts pipeline
34
+ pilfer scouts purchase <scout-id> --cost <n>
35
+ pilfer reports scouting
36
+ pilfer reports assets
37
+ pilfer reports balance [--project-id <id> | --space-id <id>]
38
+ ```
39
+
40
+ `scouts purchase` creates an asset linked to the scout, then marks the scout `Purchased`.
41
+ `reports balance` compares owned asset value with active scouting value; if scoped relation data is unavailable from REST payloads it returns a `scopeWarning`.
42
+
27
43
  ## Auth
28
44
 
29
45
  Resolution order:
@@ -4,8 +4,8 @@ import {
4
4
  createProgramForCLI,
5
5
  getProgramForDocs,
6
6
  syncRootOptsFromCommand
7
- } from "./chunk-2QYZ5OEW.js";
8
- import "./chunk-QH2MMA3M.js";
7
+ } from "./chunk-NFFHTNJE.js";
8
+ import "./chunk-CXNVJZ4C.js";
9
9
  import "./chunk-GZ4DXDQM.js";
10
10
  export {
11
11
  createProgram,
@@ -91,77 +91,22 @@ function extractErrorMessage(data) {
91
91
  return baseMessage;
92
92
  }
93
93
 
94
- // src/lib/flag-coercion.ts
95
- function fail(exitWithError, message) {
96
- return exitWithError(400, message);
97
- }
98
- function parseBoolean(raw, config, exitWithError) {
99
- const value = raw.trim().toLowerCase();
100
- if (["true", "1", "yes", "y", "on"].includes(value)) return true;
101
- if (["false", "0", "no", "n", "off"].includes(value)) return false;
102
- return fail(
103
- exitWithError,
104
- `Invalid value for ${config.flag} (${config.field}): expected boolean but got "${raw}"`
105
- );
106
- }
107
- function parseNumber(raw, config, exitWithError) {
108
- const trimmed = raw.trim();
109
- const asNumber = Number(trimmed);
110
- if (Number.isFinite(asNumber)) return asNumber;
111
- if (config.allowDateTime) {
112
- const asDate = Date.parse(trimmed);
113
- if (Number.isFinite(asDate)) return asDate;
114
- }
115
- return fail(
116
- exitWithError,
117
- `Invalid value for ${config.flag} (${config.field}): expected number${config.allowDateTime ? " or ISO datetime" : ""} but got "${raw}"`
118
- );
119
- }
120
- function coerceBodyFlag(raw, config, exitWithError) {
121
- if (raw == null) return void 0;
122
- const value = String(raw);
123
- const trimmed = value.trim();
124
- if (config.allowNull && trimmed.toLowerCase() === "null") {
125
- return null;
126
- }
127
- if (config.kind === "string") return value;
128
- if (config.kind === "boolean") return parseBoolean(value, config, exitWithError);
129
- return parseNumber(value, config, exitWithError);
130
- }
131
- function coerceQueryFlag(raw, config, exitWithError) {
132
- if (raw == null) {
133
- return fail(
134
- exitWithError,
135
- `Missing value for ${config.flag} (${config.field})`
136
- );
137
- }
138
- const value = String(raw);
139
- if (config.kind === "string") return value;
140
- if (config.kind === "boolean") {
141
- return parseBoolean(value, config, exitWithError) ? "true" : "false";
142
- }
143
- return parseNumber(value, config, exitWithError);
144
- }
145
-
146
- // src/lib/merge-body.ts
147
- function mergeBody(bodyFromFlags, bodyOption) {
148
- let base = {};
149
- if (bodyOption?.trim()) {
150
- try {
151
- base = JSON.parse(bodyOption);
152
- } catch {
153
- }
154
- }
155
- return { ...base, ...bodyFromFlags };
156
- }
157
-
158
94
  // src/lib/output.ts
159
95
  function getDefaultOutputFormat() {
160
96
  return process.stdout.isTTY ? "table" : "json";
161
97
  }
162
- function formatErrorPayload(status, message) {
98
+ function formatErrorPayload(status, message, meta = {}) {
163
99
  const code = statusToCode(status);
164
- return { error: true, status, code, message };
100
+ const requestId = meta.requestId ?? extractRequestId(message);
101
+ return {
102
+ error: true,
103
+ status,
104
+ code,
105
+ message,
106
+ ...requestId ? { requestId } : {},
107
+ ...meta.method ? { method: meta.method } : {},
108
+ ...meta.path ? { path: meta.path } : {}
109
+ };
165
110
  }
166
111
  function statusToCode(status) {
167
112
  if (status === 401) return "UNAUTHORIZED";
@@ -261,21 +206,177 @@ function printCsv(data) {
261
206
  }
262
207
  function printStructuredError(format, payload) {
263
208
  if (format === "json") {
264
- console.log(JSON.stringify(payload));
209
+ console.error(JSON.stringify(payload));
265
210
  return;
266
211
  }
267
212
  console.error(`Error ${payload.status} (${payload.code}): ${payload.message}`);
268
213
  }
214
+ function extractRequestId(message) {
215
+ const match = message.match(/\(requestId: ([^)]+)\)/);
216
+ return match?.[1];
217
+ }
218
+
219
+ // src/lib/list-controls.ts
220
+ var DEFAULT_PAGE_LIMIT = 100;
221
+ async function fetchList(options) {
222
+ if (!options.all) {
223
+ return options.request({
224
+ method: "GET",
225
+ path: options.path,
226
+ token: options.token,
227
+ baseUrl: options.baseUrl,
228
+ query: options.query
229
+ });
230
+ }
231
+ const limit = parsePositiveInt(options.query.limit, DEFAULT_PAGE_LIMIT);
232
+ let offset = parsePositiveInt(options.query.offset, 0);
233
+ const data = [];
234
+ for (; ; ) {
235
+ const res = await options.request({
236
+ method: "GET",
237
+ path: options.path,
238
+ token: options.token,
239
+ baseUrl: options.baseUrl,
240
+ query: { ...options.query, limit, offset }
241
+ });
242
+ if (!res.ok) return res;
243
+ const batch = Array.isArray(res.data?.data) ? res.data.data : [];
244
+ data.push(...batch);
245
+ if (batch.length < limit || batch.length === 0) break;
246
+ offset += limit;
247
+ }
248
+ return { ok: true, status: 200, data: { data } };
249
+ }
250
+ function printList(options) {
251
+ const rows = projectRows(filterRows(options.data, options.where), options.fields);
252
+ if (options.jsonl) {
253
+ for (const row of rows) console.log(JSON.stringify(row));
254
+ return;
255
+ }
256
+ printOutput(options.format, rows, false);
257
+ }
258
+ function filterRows(data, where) {
259
+ const rows = data.filter(isRecord);
260
+ const filters = parseWhere(where);
261
+ if (filters.length === 0) return rows;
262
+ return rows.filter(
263
+ (row) => filters.every(({ field, value }) => equalValue(row[field], value))
264
+ );
265
+ }
266
+ function projectRows(rows, fields) {
267
+ const selected = parseFields(fields);
268
+ if (selected.length === 0) return rows;
269
+ return rows.map((row) => {
270
+ const projected = {};
271
+ for (const field of selected) projected[field] = row[field];
272
+ return projected;
273
+ });
274
+ }
275
+ function parseWhere(where) {
276
+ if (!where?.trim()) return [];
277
+ return where.split(",").map((part) => part.trim()).filter(Boolean).map((part) => {
278
+ const eq = part.indexOf("=");
279
+ if (eq === -1) return null;
280
+ const field = part.slice(0, eq).trim();
281
+ const value = part.slice(eq + 1).trim();
282
+ return field ? { field, value } : null;
283
+ }).filter((entry) => entry !== null);
284
+ }
285
+ function parseFields(fields) {
286
+ if (!fields?.trim()) return [];
287
+ return fields.split(",").map((field) => field.trim()).filter(Boolean);
288
+ }
289
+ function equalValue(actual, expected) {
290
+ if (actual == null) return expected === "";
291
+ if (typeof actual === "string") {
292
+ return actual.trim().toLowerCase() === expected.trim().toLowerCase();
293
+ }
294
+ return String(actual) === expected;
295
+ }
296
+ function parsePositiveInt(value, fallback) {
297
+ const parsed = Number(value);
298
+ if (!Number.isInteger(parsed) || parsed < 1) return fallback;
299
+ return parsed;
300
+ }
301
+ function isRecord(value) {
302
+ return typeof value === "object" && value !== null && !Array.isArray(value);
303
+ }
304
+
305
+ // src/lib/flag-coercion.ts
306
+ function fail(exitWithError, message) {
307
+ return exitWithError(400, message);
308
+ }
309
+ function parseBoolean(raw, config, exitWithError) {
310
+ const value = raw.trim().toLowerCase();
311
+ if (["true", "1", "yes", "y", "on"].includes(value)) return true;
312
+ if (["false", "0", "no", "n", "off"].includes(value)) return false;
313
+ return fail(
314
+ exitWithError,
315
+ `Invalid value for ${config.flag} (${config.field}): expected boolean but got "${raw}"`
316
+ );
317
+ }
318
+ function parseNumber(raw, config, exitWithError) {
319
+ const trimmed = raw.trim();
320
+ const asNumber = Number(trimmed);
321
+ if (Number.isFinite(asNumber)) return asNumber;
322
+ if (config.allowDateTime) {
323
+ const asDate = Date.parse(trimmed);
324
+ if (Number.isFinite(asDate)) return asDate;
325
+ }
326
+ return fail(
327
+ exitWithError,
328
+ `Invalid value for ${config.flag} (${config.field}): expected number${config.allowDateTime ? " or ISO datetime" : ""} but got "${raw}"`
329
+ );
330
+ }
331
+ function coerceBodyFlag(raw, config, exitWithError) {
332
+ if (raw == null) return void 0;
333
+ const value = String(raw);
334
+ const trimmed = value.trim();
335
+ if (config.allowNull && trimmed.toLowerCase() === "null") {
336
+ return null;
337
+ }
338
+ if (config.kind === "string") return value;
339
+ if (config.kind === "boolean") return parseBoolean(value, config, exitWithError);
340
+ return parseNumber(value, config, exitWithError);
341
+ }
342
+ function coerceQueryFlag(raw, config, exitWithError) {
343
+ if (raw == null) {
344
+ return fail(
345
+ exitWithError,
346
+ `Missing value for ${config.flag} (${config.field})`
347
+ );
348
+ }
349
+ const value = String(raw);
350
+ if (config.kind === "string") return value;
351
+ if (config.kind === "boolean") {
352
+ return parseBoolean(value, config, exitWithError) ? "true" : "false";
353
+ }
354
+ return parseNumber(value, config, exitWithError);
355
+ }
356
+
357
+ // src/lib/merge-body.ts
358
+ function mergeBody(bodyFromFlags, bodyOption) {
359
+ let base = {};
360
+ if (bodyOption?.trim()) {
361
+ try {
362
+ base = JSON.parse(bodyOption);
363
+ } catch {
364
+ }
365
+ }
366
+ return { ...base, ...bodyFromFlags };
367
+ }
269
368
 
270
369
  export {
271
370
  getBaseUrl,
272
371
  apiRequest,
273
- coerceBodyFlag,
274
- coerceQueryFlag,
275
- mergeBody,
276
372
  getDefaultOutputFormat,
277
373
  formatErrorPayload,
278
374
  printOutput,
279
- printStructuredError
375
+ printStructuredError,
376
+ fetchList,
377
+ printList,
378
+ coerceBodyFlag,
379
+ coerceQueryFlag,
380
+ mergeBody
280
381
  };
281
- //# sourceMappingURL=chunk-QH2MMA3M.js.map
382
+ //# sourceMappingURL=chunk-CXNVJZ4C.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/client.ts","../src/lib/output.ts","../src/lib/list-controls.ts","../src/lib/flag-coercion.ts","../src/lib/merge-body.ts"],"sourcesContent":["import { resolveStoredBaseUrl } from \"./auth.js\";\n\nconst DEFAULT_BASE_URL = \"https://api.getpilfer.com\";\n\nexport function getBaseUrl(override?: string): string {\n const env = process.env.PILFER_API_BASE_URL;\n const stored = resolveStoredBaseUrl();\n const base = override ?? env ?? stored ?? DEFAULT_BASE_URL;\n return base.replace(/\\/$/, \"\");\n}\n\nexport interface RequestOptions {\n method: \"GET\" | \"POST\" | \"PATCH\" | \"PUT\" | \"DELETE\";\n path: string;\n token: string | null;\n baseUrl?: string;\n query?: Record<string, string | number | undefined>;\n body?: unknown;\n}\n\nexport interface ApiResponse<T = unknown> {\n ok: boolean;\n status: number;\n data?: T;\n error?: string;\n headers?: Headers;\n}\n\nconst RETRYABLE_STATUSES = new Set([502, 503, 504]);\nconst GET_MAX_ATTEMPTS = 3;\nconst GET_RETRY_BASE_DELAY_MS = 150;\n\nfunction shouldRetryRequest(method: RequestOptions[\"method\"], response: ApiResponse<unknown>, attempt: number): boolean {\n if (method !== \"GET\") return false;\n if (attempt >= GET_MAX_ATTEMPTS) return false;\n if (response.status === 0) return true;\n return RETRYABLE_STATUSES.has(response.status);\n}\n\nfunction getRetryDelayMs(attempt: number): number {\n const exp = GET_RETRY_BASE_DELAY_MS * Math.pow(2, Math.max(0, attempt - 1));\n const jitter = Math.floor(Math.random() * 50);\n return exp + jitter;\n}\n\nasync function sleep(ms: number): Promise<void> {\n await new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Call the Pilfer REST API. Path should be relative to /api/v1 (e.g. \"me\", \"projects\", \"projects/123\").\n */\nexport async function apiRequest<T = unknown>(\n options: RequestOptions,\n): Promise<ApiResponse<T>> {\n const base = getBaseUrl(options.baseUrl);\n const url = new URL(`/api/v1/${options.path.replace(/^\\//, \"\")}`, base);\n if (options.query) {\n for (const [k, v] of Object.entries(options.query)) {\n if (v !== undefined && v !== \"\") url.searchParams.set(k, String(v));\n }\n }\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${options.token ?? \"\"}`,\n \"Content-Type\": \"application/json\",\n };\n\n const init: RequestInit = {\n method: options.method,\n headers,\n };\n if (\n options.body !== undefined &&\n options.method !== \"GET\"\n ) {\n init.body = JSON.stringify(options.body);\n }\n\n for (let attempt = 1; ; attempt++) {\n const response = await doRequest<T>(url.toString(), init);\n if (!shouldRetryRequest(options.method, response, attempt)) {\n return response;\n }\n await sleep(getRetryDelayMs(attempt));\n }\n}\n\nasync function doRequest<T>(url: string, init: RequestInit): Promise<ApiResponse<T>> {\n let res: Response;\n try {\n res = await fetch(url, init);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { ok: false, status: 0, error: message };\n }\n\n let data: T | undefined;\n const text = await res.text();\n if (text) {\n try {\n data = JSON.parse(text) as T;\n } catch {\n data = undefined;\n }\n }\n\n return {\n ok: res.ok,\n status: res.status,\n data,\n error: !res.ok\n ? extractErrorMessage(data)\n : undefined,\n headers: res.headers,\n };\n}\n\nfunction extractErrorMessage(data: unknown): string | undefined {\n if (data == null || typeof data !== \"object\") return undefined;\n\n const body = data as {\n error?: unknown;\n message?: unknown;\n requestId?: unknown;\n };\n\n const baseMessage =\n typeof body.error === \"string\"\n ? body.error\n : typeof body.message === \"string\"\n ? body.message\n : undefined;\n if (baseMessage == null) return undefined;\n\n if (typeof body.requestId === \"string\" && body.requestId.trim() !== \"\") {\n return `${baseMessage} (requestId: ${body.requestId})`;\n }\n return baseMessage;\n}\n","export type OutputFormat = \"json\" | \"table\" | \"csv\";\n\nexport function getDefaultOutputFormat(): OutputFormat {\n return process.stdout.isTTY ? \"table\" : \"json\";\n}\n\nexport interface ErrorPayload {\n error: true;\n status: number;\n code: string;\n message: string;\n requestId?: string;\n method?: string;\n path?: string;\n}\n\nexport function formatErrorPayload(\n status: number,\n message: string,\n meta: { requestId?: string; method?: string; path?: string } = {},\n): ErrorPayload {\n const code = statusToCode(status);\n const requestId = meta.requestId ?? extractRequestId(message);\n return {\n error: true,\n status,\n code,\n message,\n ...(requestId ? { requestId } : {}),\n ...(meta.method ? { method: meta.method } : {}),\n ...(meta.path ? { path: meta.path } : {}),\n };\n}\n\nfunction statusToCode(status: number): string {\n if (status === 401) return \"UNAUTHORIZED\";\n if (status === 403) return \"FORBIDDEN\";\n if (status === 404) return \"NOT_FOUND\";\n if (status === 400) return \"BAD_REQUEST\";\n if (status === 429) return \"TOO_MANY_REQUESTS\";\n if (status >= 500) return \"SERVER_ERROR\";\n return \"ERROR\";\n}\n\n/**\n * Print result to stdout according to format. For list responses, pass the data array.\n * For single resource, pass the data object.\n */\nexport function printOutput(\n format: OutputFormat,\n data: unknown,\n isError = false,\n): void {\n if (format === \"json\") {\n const out = Array.isArray(data)\n ? { data }\n : typeof data === \"object\" && data !== null && \"data\" in data\n ? data\n : { data };\n console.log(JSON.stringify(out, null, 0));\n return;\n }\n if (format === \"table\") {\n printTable(data);\n return;\n }\n if (format === \"csv\") {\n printCsv(data);\n return;\n }\n console.log(JSON.stringify(data));\n}\n\nfunction getRows(data: unknown): Record<string, unknown>[] {\n if (Array.isArray(data)) return data as Record<string, unknown>[];\n if (typeof data === \"object\" && data !== null && \"data\" in data) {\n const d = (data as { data: unknown }).data;\n if (Array.isArray(d)) return d as Record<string, unknown>[];\n if (typeof d === \"object\" && d !== null) return [d as Record<string, unknown>];\n }\n if (typeof data === \"object\" && data !== null && !Array.isArray(data)) {\n return [data as Record<string, unknown>];\n }\n return [];\n}\n\nfunction getColumns(rows: Record<string, unknown>[]): string[] {\n const set = new Set<string>();\n for (const row of rows) {\n for (const k of Object.keys(row)) set.add(k);\n }\n return [...set].sort((a, b) => {\n const aIsId = a === \"_id\" || a === \"id\" || a.endsWith(\"Id\");\n const bIsId = b === \"_id\" || b === \"id\" || b.endsWith(\"Id\");\n if (aIsId !== bIsId) return aIsId ? 1 : -1;\n return a.localeCompare(b);\n });\n}\n\nfunction printTable(data: unknown): void {\n const rows = getRows(data);\n if (rows.length === 0) {\n console.log(\"(no data)\");\n return;\n }\n const cols = getColumns(rows);\n const widths = cols.map((c) => Math.max(c.length, 8));\n for (const row of rows) {\n for (let i = 0; i < cols.length; i++) {\n const col = cols[i]!;\n const val = row[col];\n const s = val === null || val === undefined ? \"\" : String(val);\n if (s.length > widths[i]!) widths[i] = Math.min(s.length, 40);\n }\n }\n const header = cols.map((c, i) => c.padEnd(widths[i]!)).join(\" \");\n console.log(header);\n console.log(cols.map((_, i) => \"-\".repeat(widths[i]!)).join(\" \"));\n for (const row of rows) {\n const line = cols\n .map((c, i) => {\n const val = row[c];\n const s = val === null || val === undefined ? \"\" : String(val);\n return s.slice(0, widths[i]!).padEnd(widths[i]!);\n })\n .join(\" \");\n console.log(line);\n }\n}\n\nfunction printCsv(data: unknown): void {\n const rows = getRows(data);\n if (rows.length === 0) {\n console.log(\"\");\n return;\n }\n const cols = getColumns(rows);\n const escape = (v: unknown): string => {\n const s = v === null || v === undefined ? \"\" : String(v);\n if (s.includes(\",\") || s.includes('\"') || s.includes(\"\\n\")) {\n return `\"${s.replace(/\"/g, '\"\"')}\"`;\n }\n return s;\n };\n console.log(cols.join(\",\"));\n for (const row of rows) {\n console.log(cols.map((c) => escape(row[c])).join(\",\"));\n }\n}\n\nexport function printStructuredError(format: OutputFormat, payload: ErrorPayload): void {\n if (format === \"json\") {\n console.error(JSON.stringify(payload));\n return;\n }\n console.error(`Error ${payload.status} (${payload.code}): ${payload.message}`);\n}\n\nfunction extractRequestId(message: string): string | undefined {\n const match = message.match(/\\(requestId: ([^)]+)\\)/);\n return match?.[1];\n}\n","import type { ApiResponse, RequestOptions } from \"./client.js\";\nimport { printOutput, type OutputFormat } from \"./output.js\";\n\nconst DEFAULT_PAGE_LIMIT = 100;\n\nexport interface FetchListOptions {\n path: string;\n token: string | null;\n baseUrl: string;\n query: Record<string, string | number | undefined>;\n all: boolean;\n request: <T = unknown>(options: RequestOptions) => Promise<ApiResponse<T>>;\n}\n\nexport interface PrintListOptions {\n format: OutputFormat;\n data: unknown[];\n fields?: string;\n where?: string;\n jsonl?: boolean;\n}\n\nexport async function fetchList(options: FetchListOptions): Promise<ApiResponse<{ data?: unknown[] }>> {\n if (!options.all) {\n return options.request<{ data?: unknown[] }>({\n method: \"GET\",\n path: options.path,\n token: options.token,\n baseUrl: options.baseUrl,\n query: options.query,\n });\n }\n\n const limit = parsePositiveInt(options.query.limit, DEFAULT_PAGE_LIMIT);\n let offset = parsePositiveInt(options.query.offset, 0);\n const data: unknown[] = [];\n\n for (;;) {\n const res = await options.request<{ data?: unknown[] }>({\n method: \"GET\",\n path: options.path,\n token: options.token,\n baseUrl: options.baseUrl,\n query: { ...options.query, limit, offset },\n });\n if (!res.ok) return res;\n\n const batch = Array.isArray(res.data?.data) ? res.data.data : [];\n data.push(...batch);\n if (batch.length < limit || batch.length === 0) break;\n offset += limit;\n }\n\n return { ok: true, status: 200, data: { data } };\n}\n\nexport function printList(options: PrintListOptions): void {\n const rows = projectRows(filterRows(options.data, options.where), options.fields);\n if (options.jsonl) {\n for (const row of rows) console.log(JSON.stringify(row));\n return;\n }\n printOutput(options.format, rows, false);\n}\n\nexport function filterRows(data: unknown[], where?: string): Record<string, unknown>[] {\n const rows = data.filter(isRecord);\n const filters = parseWhere(where);\n if (filters.length === 0) return rows;\n return rows.filter((row) =>\n filters.every(({ field, value }) => equalValue(row[field], value)),\n );\n}\n\nexport function projectRows(\n rows: Record<string, unknown>[],\n fields?: string,\n): Record<string, unknown>[] {\n const selected = parseFields(fields);\n if (selected.length === 0) return rows;\n return rows.map((row) => {\n const projected: Record<string, unknown> = {};\n for (const field of selected) projected[field] = row[field];\n return projected;\n });\n}\n\nfunction parseWhere(where?: string): Array<{ field: string; value: string }> {\n if (!where?.trim()) return [];\n return where\n .split(\",\")\n .map((part) => part.trim())\n .filter(Boolean)\n .map((part) => {\n const eq = part.indexOf(\"=\");\n if (eq === -1) return null;\n const field = part.slice(0, eq).trim();\n const value = part.slice(eq + 1).trim();\n return field ? { field, value } : null;\n })\n .filter((entry): entry is { field: string; value: string } => entry !== null);\n}\n\nfunction parseFields(fields?: string): string[] {\n if (!fields?.trim()) return [];\n return fields.split(\",\").map((field) => field.trim()).filter(Boolean);\n}\n\nfunction equalValue(actual: unknown, expected: string): boolean {\n if (actual == null) return expected === \"\";\n if (typeof actual === \"string\") {\n return actual.trim().toLowerCase() === expected.trim().toLowerCase();\n }\n return String(actual) === expected;\n}\n\nfunction parsePositiveInt(value: unknown, fallback: number): number {\n const parsed = Number(value);\n if (!Number.isInteger(parsed) || parsed < 1) return fallback;\n return parsed;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","type ExitWithError = (status: number, message: string) => never;\n\ntype PrimitiveKind = \"string\" | \"number\" | \"boolean\";\n\ninterface CoerceConfig {\n field: string;\n flag: string;\n kind: PrimitiveKind;\n allowNull?: boolean;\n allowDateTime?: boolean;\n}\n\nfunction fail(exitWithError: ExitWithError, message: string): never {\n return exitWithError(400, message);\n}\n\nfunction parseBoolean(\n raw: string,\n config: CoerceConfig,\n exitWithError: ExitWithError,\n): boolean {\n const value = raw.trim().toLowerCase();\n if ([\"true\", \"1\", \"yes\", \"y\", \"on\"].includes(value)) return true;\n if ([\"false\", \"0\", \"no\", \"n\", \"off\"].includes(value)) return false;\n return fail(\n exitWithError,\n `Invalid value for ${config.flag} (${config.field}): expected boolean but got \"${raw}\"`,\n );\n}\n\nfunction parseNumber(\n raw: string,\n config: CoerceConfig,\n exitWithError: ExitWithError,\n): number {\n const trimmed = raw.trim();\n const asNumber = Number(trimmed);\n if (Number.isFinite(asNumber)) return asNumber;\n\n if (config.allowDateTime) {\n const asDate = Date.parse(trimmed);\n if (Number.isFinite(asDate)) return asDate;\n }\n\n return fail(\n exitWithError,\n `Invalid value for ${config.flag} (${config.field}): expected number${config.allowDateTime ? \" or ISO datetime\" : \"\"} but got \"${raw}\"`,\n );\n}\n\nexport function coerceBodyFlag(\n raw: unknown,\n config: CoerceConfig,\n exitWithError: ExitWithError,\n): unknown {\n if (raw == null) return undefined;\n const value = String(raw);\n const trimmed = value.trim();\n\n if (config.allowNull && trimmed.toLowerCase() === \"null\") {\n return null;\n }\n\n if (config.kind === \"string\") return value;\n if (config.kind === \"boolean\") return parseBoolean(value, config, exitWithError);\n return parseNumber(value, config, exitWithError);\n}\n\nexport function coerceQueryFlag(\n raw: unknown,\n config: CoerceConfig,\n exitWithError: ExitWithError,\n): string | number {\n if (raw == null) {\n return fail(\n exitWithError,\n `Missing value for ${config.flag} (${config.field})`,\n );\n }\n\n const value = String(raw);\n if (config.kind === \"string\") return value;\n if (config.kind === \"boolean\") {\n return parseBoolean(value, config, exitWithError) ? \"true\" : \"false\";\n }\n return parseNumber(value, config, exitWithError);\n}\n","/**\n * Merge optional JSON body (from --body) with object built from flags.\n * Flags override keys in body when both are provided.\n */\nexport function mergeBody(\n bodyFromFlags: Record<string, unknown>,\n bodyOption: string | undefined,\n): Record<string, unknown> {\n let base: Record<string, unknown> = {};\n if (bodyOption?.trim()) {\n try {\n base = JSON.parse(bodyOption) as Record<string, unknown>;\n } catch {\n // ignore invalid JSON\n }\n }\n return { ...base, ...bodyFromFlags };\n}\n"],"mappings":"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","names":[]}