zinkee 0.1.28 → 0.1.30

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.28",
3
+ "version": "0.1.30",
4
4
  "description": "CLI for Zinkee API v2",
5
5
  "type": "module",
6
6
  "bin": {
@@ -38,7 +38,6 @@ export interface CreateRecordInput {
38
38
  }
39
39
 
40
40
  export interface UpdateRecordInput {
41
- [key: string]: unknown;
42
41
  set?: Record<string, unknown>;
43
42
  unset?: string[];
44
43
  }
@@ -17,6 +17,7 @@ export interface ApiSchema {
17
17
  slug?: string;
18
18
  auditable?: boolean;
19
19
  commentable?: boolean;
20
+ highlightedField?: string;
20
21
  fields?: ApiSchemaField[];
21
22
  }
22
23
 
@@ -32,6 +33,7 @@ export interface UpdateSchemaInput {
32
33
  slug?: string;
33
34
  auditable?: boolean;
34
35
  commentable?: boolean;
36
+ highlightedField?: string;
35
37
  }
36
38
 
37
39
  export interface CreateSchemaFieldInput {
@@ -412,7 +412,7 @@ describe("records commands", () => {
412
412
  });
413
413
  });
414
414
 
415
- it("updates records with the patch-style set and unset contract", async () => {
415
+ it("wraps raw-file fields into the set payload", async () => {
416
416
  const configPath = createApiConfig();
417
417
  const output = createStdoutBuffer();
418
418
  const fetchMock = createFetchMock();
@@ -423,15 +423,9 @@ describe("records commands", () => {
423
423
  writeFileSync(
424
424
  rawFile,
425
425
  JSON.stringify({
426
- set: {
427
- status: "inactive",
428
- metadata: {
429
- imported: true,
430
- },
431
- },
432
- unset: ["legacyCode"],
433
- audit: {
434
- reason: "sync",
426
+ status: "inactive",
427
+ metadata: {
428
+ imported: true,
435
429
  },
436
430
  }),
437
431
  "utf8",
@@ -472,9 +466,6 @@ describe("records commands", () => {
472
466
  );
473
467
  expect(init?.method).toBe("PATCH");
474
468
  expect(JSON.parse(String(init?.body))).toEqual({
475
- audit: {
476
- reason: "sync",
477
- },
478
469
  set: {
479
470
  status: "active",
480
471
  metadata: {
@@ -484,7 +475,81 @@ describe("records commands", () => {
484
475
  tier: "gold",
485
476
  },
486
477
  },
487
- unset: ["legacyCode", "tempField"],
478
+ unset: ["tempField"],
479
+ });
480
+ });
481
+
482
+ it("wraps bare raw fields into the set payload", async () => {
483
+ const configPath = createApiConfig();
484
+ const output = createStdoutBuffer();
485
+ const fetchMock = createFetchMock();
486
+ mockSchemaLookup(fetchMock);
487
+ fetchMock.mockResolvedValueOnce(
488
+ jsonResponse({
489
+ id: "550e8400-e29b-41d4-a716-446655440001",
490
+ uno: "prueba mod",
491
+ }),
492
+ );
493
+ const program = buildProgram({ configPath, stdout: output.stdout });
494
+
495
+ await program.parseAsync([
496
+ "node",
497
+ "zinkee",
498
+ "--json",
499
+ "records",
500
+ "update",
501
+ "contacts",
502
+ "550E8400-E29B-41D4-A716-446655440001",
503
+ "--raw",
504
+ '{"uno":"prueba mod"}',
505
+ ]);
506
+
507
+ const init = fetchMock.mock.calls[1]?.[1];
508
+
509
+ expect(fetchMock.mock.calls[1]?.[0]).toBe(
510
+ "https://api.zinkee.test/api/v2/schemas/schema-1/records/550e8400-e29b-41d4-a716-446655440001",
511
+ );
512
+ expect(init?.method).toBe("PATCH");
513
+ expect(JSON.parse(String(init?.body))).toEqual({
514
+ set: {
515
+ uno: "prueba mod",
516
+ },
517
+ });
518
+ });
519
+
520
+ it("lets --set override raw fields with the same key", async () => {
521
+ const configPath = createApiConfig();
522
+ const output = createStdoutBuffer();
523
+ const fetchMock = createFetchMock();
524
+ mockSchemaLookup(fetchMock);
525
+ fetchMock.mockResolvedValueOnce(
526
+ jsonResponse({
527
+ id: "550e8400-e29b-41d4-a716-446655440001",
528
+ }),
529
+ );
530
+ const program = buildProgram({ configPath, stdout: output.stdout });
531
+
532
+ await program.parseAsync([
533
+ "node",
534
+ "zinkee",
535
+ "--json",
536
+ "records",
537
+ "update",
538
+ "contacts",
539
+ "550E8400-E29B-41D4-A716-446655440001",
540
+ "--raw",
541
+ '{"uno":"raw value"}',
542
+ "--set",
543
+ "uno=set value",
544
+ ]);
545
+
546
+ const init = fetchMock.mock.calls[1]?.[1];
547
+
548
+ expect(init?.method).toBe("PATCH");
549
+ expect(JSON.parse(String(init?.body))).toEqual({
550
+ set: {
551
+ uno: "set value",
552
+ },
488
553
  });
489
554
  });
490
555
 
@@ -421,50 +421,16 @@ function buildRecordCreateInput(
421
421
  return { values };
422
422
  }
423
423
 
424
- function readRawSetPayload(raw: JsonObject): Record<string, unknown> {
425
- const setValue = raw.set;
426
-
427
- if (setValue === undefined) {
428
- return {};
429
- }
430
-
431
- if (!isJsonObject(setValue)) {
432
- throw new CliError(
433
- "invalid_cli_usage",
434
- 'Expected raw update payload field "set" to be a JSON object.',
435
- );
436
- }
437
-
438
- return { ...setValue };
439
- }
440
-
441
- function readRawUnsetPayload(raw: JsonObject): string[] {
442
- const unsetValue = raw.unset;
443
-
444
- if (unsetValue === undefined) {
445
- return [];
446
- }
447
-
448
- if (!Array.isArray(unsetValue) || !unsetValue.every((value) => typeof value === "string")) {
449
- throw new CliError(
450
- "invalid_cli_usage",
451
- 'Expected raw update payload field "unset" to be an array of strings.',
452
- );
453
- }
454
-
455
- return [...unsetValue];
456
- }
457
-
458
424
  function buildRecordUpdateInput(
459
425
  options: RecordsUpdateCommandOptions,
460
426
  ): UpdateRecordInput {
461
427
  const raw = readRawObject(options.raw, options.rawFile);
462
- const input: UpdateRecordInput = { ...raw };
428
+ const input: UpdateRecordInput = {};
463
429
  const setPayload = {
464
- ...readRawSetPayload(raw),
430
+ ...raw,
465
431
  ...buildAssignmentObject(options.set, options.setJson),
466
432
  };
467
- const unsetPayload = [...readRawUnsetPayload(raw), ...(options.unset ?? [])];
433
+ const unsetPayload = [...(options.unset ?? [])];
468
434
 
469
435
  for (const key of Object.keys(setPayload)) {
470
436
  const unsetIndex = unsetPayload.indexOf(key);
@@ -684,8 +650,8 @@ export function registerRecordsCommands(
684
650
  .option("--set <field=value>", "set a string field", collectKeyValueAssignments, [])
685
651
  .option("--set-json <field=json>", "set a structured field", collectJsonAssignments, [])
686
652
  .option("--unset <field>", "unset a field", collectStringValues, [])
687
- .option("--raw <json>", "raw JSON object payload")
688
- .option("--raw-file <path>", "path to a raw JSON object payload")
653
+ .option("--raw <json>", "raw JSON object of fields to set")
654
+ .option("--raw-file <path>", "path to a JSON object of fields to set")
689
655
  .action(async function action(
690
656
  this: Command,
691
657
  schema: NormalizedUuidOrSlug,
@@ -968,4 +968,84 @@ describe("schemas commands", () => {
968
968
  },
969
969
  });
970
970
  });
971
+
972
+ it("updates a schema highlighted field by slug after resolving the field id", async () => {
973
+ const configPath = createApiConfig();
974
+ const output = createStdoutBuffer();
975
+ const fetchMock = createFetchMock();
976
+ mockSchemaLookup(fetchMock);
977
+ fetchMock.mockResolvedValueOnce(
978
+ jsonResponse({
979
+ id: "schema-1",
980
+ slug: "contacts",
981
+ fields: [
982
+ {
983
+ id: "550e8400-e29b-41d4-a716-446655440001",
984
+ slug: "email",
985
+ type: "TextField",
986
+ label: "Email",
987
+ },
988
+ ],
989
+ }),
990
+ );
991
+ fetchMock.mockResolvedValueOnce(
992
+ jsonResponse({
993
+ id: "schema-1",
994
+ slug: "contacts",
995
+ highlightedField: "550e8400-e29b-41d4-a716-446655440001",
996
+ }),
997
+ );
998
+ const program = buildProgram({ configPath, stdout: output.stdout });
999
+
1000
+ await program.parseAsync([
1001
+ "node",
1002
+ "zinkee",
1003
+ "--json",
1004
+ "schemas",
1005
+ "update",
1006
+ "contacts",
1007
+ "--highlighted-field",
1008
+ "email",
1009
+ ]);
1010
+
1011
+ expect(fetchMock.mock.calls[2]?.[0]).toBe("https://api.zinkee.test/api/v2/schemas/schema-1");
1012
+ expect(fetchMock.mock.calls[2]?.[1]?.method).toBe("PATCH");
1013
+ expect(JSON.parse(String(fetchMock.mock.calls[2]?.[1]?.body))).toEqual({
1014
+ highlightedField: "550e8400-e29b-41d4-a716-446655440001",
1015
+ });
1016
+ });
1017
+
1018
+ it("updates a schema highlighted field by uuid without extra lookups", async () => {
1019
+ const configPath = createApiConfig();
1020
+ const output = createStdoutBuffer();
1021
+ const fetchMock = createFetchMock();
1022
+ fetchMock.mockResolvedValueOnce(
1023
+ jsonResponse({
1024
+ id: "550e8400-e29b-41d4-a716-446655440000",
1025
+ slug: "contacts",
1026
+ highlightedField: "550e8400-e29b-41d4-a716-446655440001",
1027
+ }),
1028
+ );
1029
+ const program = buildProgram({ configPath, stdout: output.stdout });
1030
+
1031
+ await program.parseAsync([
1032
+ "node",
1033
+ "zinkee",
1034
+ "--json",
1035
+ "schemas",
1036
+ "update",
1037
+ "550e8400-e29b-41d4-a716-446655440000",
1038
+ "--highlighted-field",
1039
+ "550e8400-e29b-41d4-a716-446655440001",
1040
+ ]);
1041
+
1042
+ expect(fetchMock).toHaveBeenCalledTimes(1);
1043
+ expect(fetchMock.mock.calls[0]?.[0]).toBe(
1044
+ "https://api.zinkee.test/api/v2/schemas/550e8400-e29b-41d4-a716-446655440000",
1045
+ );
1046
+ expect(fetchMock.mock.calls[0]?.[1]?.method).toBe("PATCH");
1047
+ expect(JSON.parse(String(fetchMock.mock.calls[0]?.[1]?.body))).toEqual({
1048
+ highlightedField: "550e8400-e29b-41d4-a716-446655440001",
1049
+ });
1050
+ });
971
1051
  });
@@ -56,6 +56,7 @@ interface SchemaUpdateCommandOptions {
56
56
  slug?: string;
57
57
  auditable?: boolean;
58
58
  commentable?: boolean;
59
+ highlightedField?: NormalizedUuidOrSlug;
59
60
  }
60
61
 
61
62
  interface FieldCreateCommandOptions {
@@ -568,6 +569,11 @@ export function registerSchemasCommands(
568
569
  .option("--slug <slug>", "schema slug")
569
570
  .option("--auditable <bool>", "auditable flag", parseBooleanFlag)
570
571
  .option("--commentable <bool>", "commentable flag", parseBooleanFlag)
572
+ .option(
573
+ "--highlighted-field <field>",
574
+ "highlighted (main) field uuid or slug",
575
+ parseUuidOrSlugSelector,
576
+ )
571
577
  .action(async function action(
572
578
  this: Command,
573
579
  schema: NormalizedUuidOrSlug,
@@ -579,10 +585,19 @@ export function registerSchemasCommands(
579
585
 
580
586
  const input = buildSchemaUpdateInput(commandOptions);
581
587
 
588
+ if (commandOptions.highlightedField !== undefined) {
589
+ const resolvedField = await resolveFieldSelector(
590
+ api,
591
+ resolvedSchema,
592
+ commandOptions.highlightedField,
593
+ );
594
+ input.highlightedField = resolvedField.value;
595
+ }
596
+
582
597
  if (isEmptyObject(input)) {
583
598
  throw new CliError(
584
599
  "invalid_cli_usage",
585
- 'Provide at least one schema field to update via "--name", "--slug", "--auditable", or "--commentable".',
600
+ 'Provide at least one schema field to update via "--name", "--slug", "--auditable", "--commentable", or "--highlighted-field".',
586
601
  );
587
602
  }
588
603
 
@@ -228,6 +228,7 @@ const specificExamples: Record<string, readonly CommandExample[]> = {
228
228
  },
229
229
  "auditable": true,
230
230
  "commentable": true,
231
+ "highlightedField": "c60b8526-5835-4c9f-aecd-9a16c7704a34",
231
232
  "fields": [
232
233
  {
233
234
  "id": "c60b8526-5835-4c9f-aecd-9a16c7704a34",
@@ -259,6 +260,14 @@ const specificExamples: Record<string, readonly CommandExample[]> = {
259
260
  command: 'zinkee --json schemas update contacts --auditable true',
260
261
  raw: `{
261
262
  "auditable": true
263
+ }`,
264
+ },
265
+ {
266
+ description: "Set the highlighted (main) field of a schema.",
267
+ command:
268
+ 'zinkee --json schemas update contacts --highlighted-field contact-name',
269
+ raw: `{
270
+ "highlightedField": "c60b8526-5835-4c9f-aecd-9a16c7704a34"
262
271
  }`,
263
272
  },
264
273
  ]),
@@ -1904,6 +1913,7 @@ const specificExamples: Record<string, readonly CommandExample[]> = {
1904
1913
  },
1905
1914
  "auditable": true,
1906
1915
  "commentable": true,
1916
+ "highlightedField": "c60b8526-5835-4c9f-aecd-9a16c7704a34",
1907
1917
  "fields": [
1908
1918
  {
1909
1919
  "id": "c60b8526-5835-4c9f-aecd-9a16c7704a34",