zinkee 0.1.27 → 0.1.28
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/.claude/settings.local.json +3 -1
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/records.test.ts +104 -0
- package/src/commands/records.ts +10 -4
package/package.json
CHANGED
|
@@ -236,6 +236,110 @@ describe("records commands", () => {
|
|
|
236
236
|
});
|
|
237
237
|
});
|
|
238
238
|
|
|
239
|
+
it("accumulates repeated --select flags into a single field selection", async () => {
|
|
240
|
+
const configPath = createApiConfig();
|
|
241
|
+
const output = createStdoutBuffer();
|
|
242
|
+
const fetchMock = createFetchMock();
|
|
243
|
+
mockSchemaLookup(fetchMock);
|
|
244
|
+
fetchMock.mockResolvedValueOnce(
|
|
245
|
+
jsonResponse({
|
|
246
|
+
records: [{ recordId: "record-1", values: { name: "Ana" } }],
|
|
247
|
+
page: { offset: 0, limit: 25, total: 1, count: 1, hasMore: false },
|
|
248
|
+
}),
|
|
249
|
+
);
|
|
250
|
+
const program = buildProgram({ configPath, stdout: output.stdout });
|
|
251
|
+
|
|
252
|
+
await program.parseAsync([
|
|
253
|
+
"node",
|
|
254
|
+
"zinkee",
|
|
255
|
+
"--json",
|
|
256
|
+
"records",
|
|
257
|
+
"query",
|
|
258
|
+
"contacts",
|
|
259
|
+
"--select",
|
|
260
|
+
"campo-1",
|
|
261
|
+
"--select",
|
|
262
|
+
"campo-2",
|
|
263
|
+
]);
|
|
264
|
+
|
|
265
|
+
const init = fetchMock.mock.calls[1]?.[1];
|
|
266
|
+
|
|
267
|
+
expect(JSON.parse(String(init?.body))).toEqual({
|
|
268
|
+
select: ["campo-1", "campo-2"],
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it("mixes comma-separated and repeated --select flags preserving order", async () => {
|
|
273
|
+
const configPath = createApiConfig();
|
|
274
|
+
const output = createStdoutBuffer();
|
|
275
|
+
const fetchMock = createFetchMock();
|
|
276
|
+
mockSchemaLookup(fetchMock);
|
|
277
|
+
fetchMock.mockResolvedValueOnce(
|
|
278
|
+
jsonResponse({
|
|
279
|
+
records: [{ recordId: "record-1", values: { name: "Ana" } }],
|
|
280
|
+
page: { offset: 0, limit: 25, total: 1, count: 1, hasMore: false },
|
|
281
|
+
}),
|
|
282
|
+
);
|
|
283
|
+
const program = buildProgram({ configPath, stdout: output.stdout });
|
|
284
|
+
|
|
285
|
+
await program.parseAsync([
|
|
286
|
+
"node",
|
|
287
|
+
"zinkee",
|
|
288
|
+
"--json",
|
|
289
|
+
"records",
|
|
290
|
+
"query",
|
|
291
|
+
"contacts",
|
|
292
|
+
"--select",
|
|
293
|
+
"a,b",
|
|
294
|
+
"--select",
|
|
295
|
+
"c",
|
|
296
|
+
]);
|
|
297
|
+
|
|
298
|
+
const init = fetchMock.mock.calls[1]?.[1];
|
|
299
|
+
|
|
300
|
+
expect(JSON.parse(String(init?.body))).toEqual({
|
|
301
|
+
select: ["a", "b", "c"],
|
|
302
|
+
});
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it("deduplicates repeated fields across --select and --sort flags", async () => {
|
|
306
|
+
const configPath = createApiConfig();
|
|
307
|
+
const output = createStdoutBuffer();
|
|
308
|
+
const fetchMock = createFetchMock();
|
|
309
|
+
mockSchemaLookup(fetchMock);
|
|
310
|
+
fetchMock.mockResolvedValueOnce(
|
|
311
|
+
jsonResponse({
|
|
312
|
+
records: [{ recordId: "record-1", values: { name: "Ana" } }],
|
|
313
|
+
page: { offset: 0, limit: 25, total: 1, count: 1, hasMore: false },
|
|
314
|
+
}),
|
|
315
|
+
);
|
|
316
|
+
const program = buildProgram({ configPath, stdout: output.stdout });
|
|
317
|
+
|
|
318
|
+
await program.parseAsync([
|
|
319
|
+
"node",
|
|
320
|
+
"zinkee",
|
|
321
|
+
"--json",
|
|
322
|
+
"records",
|
|
323
|
+
"query",
|
|
324
|
+
"contacts",
|
|
325
|
+
"--select",
|
|
326
|
+
"id",
|
|
327
|
+
"--select",
|
|
328
|
+
"id",
|
|
329
|
+
"--sort",
|
|
330
|
+
"name:asc",
|
|
331
|
+
"--sort",
|
|
332
|
+
"name:asc",
|
|
333
|
+
]);
|
|
334
|
+
|
|
335
|
+
const init = fetchMock.mock.calls[1]?.[1];
|
|
336
|
+
|
|
337
|
+
expect(JSON.parse(String(init?.body))).toEqual({
|
|
338
|
+
select: ["id"],
|
|
339
|
+
sort: [{ field: "name", direction: "ASC" }],
|
|
340
|
+
});
|
|
341
|
+
});
|
|
342
|
+
|
|
239
343
|
it("normalizes UUID selectors for records get", async () => {
|
|
240
344
|
const configPath = createApiConfig();
|
|
241
345
|
const output = createStdoutBuffer();
|
package/src/commands/records.ts
CHANGED
|
@@ -233,12 +233,20 @@ function parseJsonKeyValueAssignment(input: string): JsonKeyValueAssignment {
|
|
|
233
233
|
}
|
|
234
234
|
}
|
|
235
235
|
|
|
236
|
+
function dedupeStrings(values: string[]): string[] {
|
|
237
|
+
return [...new Set(values)];
|
|
238
|
+
}
|
|
239
|
+
|
|
236
240
|
function collectStringValues(value: string, previous: string[] = []): string[] {
|
|
237
241
|
return [...previous, value];
|
|
238
242
|
}
|
|
239
243
|
|
|
244
|
+
function collectSelectValues(value: string, previous: string[] = []): string[] {
|
|
245
|
+
return dedupeStrings([...previous, ...parseCommaSeparatedValues(value, "--select")]);
|
|
246
|
+
}
|
|
247
|
+
|
|
240
248
|
function collectSortValues(value: string, previous: string[] = []): string[] {
|
|
241
|
-
return [...previous, ...parseCommaSeparatedValues(value, "--sort")];
|
|
249
|
+
return dedupeStrings([...previous, ...parseCommaSeparatedValues(value, "--sort")]);
|
|
242
250
|
}
|
|
243
251
|
|
|
244
252
|
function collectWhereExpressions(
|
|
@@ -578,9 +586,7 @@ export function registerRecordsCommands(
|
|
|
578
586
|
.command("query")
|
|
579
587
|
.description("Query records for a schema")
|
|
580
588
|
.argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector)
|
|
581
|
-
.option("--select <fields>", "comma-separated
|
|
582
|
-
parseCommaSeparatedValues(value, "--select")
|
|
583
|
-
))
|
|
589
|
+
.option("--select <fields>", "field selection (comma-separated, repeatable)", collectSelectValues, [])
|
|
584
590
|
.option("--where <expression>", "where expression", collectWhereExpressions, [])
|
|
585
591
|
.option(
|
|
586
592
|
"--search <term>",
|