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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zinkee",
3
- "version": "0.1.27",
3
+ "version": "0.1.28",
4
4
  "description": "CLI for Zinkee API v2",
5
5
  "type": "module",
6
6
  "bin": {
@@ -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();
@@ -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 field selection", (value) => (
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>",