zinkee 0.1.30 → 0.1.32

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
@@ -248,6 +248,30 @@ date_format(44b72f55-3fc3-40f4-88bb-343bb4a6270c, "AAAA-MM")
248
248
  - Functions: `concat`, `if`, `date_format`, `datetime_diff`, arithmetic (`+`,`-`,`*`,`/`)
249
249
  - Invalid formulas are created with status `DRAFT` and evaluate to `null`
250
250
 
251
+ ### Set unique fields
252
+
253
+ Define a composite unique constraint: the listed fields must be unique **together**
254
+ across the schema's records. `--field` accepts a field UUID or slug and is repeatable;
255
+ the order you pass them is the order of the constraint.
256
+
257
+ ```bash
258
+ # Single field must be unique
259
+ zinkee schemas set-unique-fields contacts --field email
260
+
261
+ # Composite: the (contact-name, notes) combination must be unique
262
+ zinkee schemas set-unique-fields contacts --field contact-name --field notes
263
+
264
+ # Remove the unique constraint
265
+ zinkee schemas set-unique-fields contacts --clear
266
+ ```
267
+
268
+ Notes:
269
+
270
+ - Pass either one or more `--field`, or `--clear` — not both, and not neither.
271
+ - Every `--field` must already exist in the schema, otherwise the command fails.
272
+ - If existing records already violate the requested constraint, the backend rejects
273
+ it with `409 Conflict`.
274
+
251
275
  ---
252
276
 
253
277
  ## Records
package/dist/index.js CHANGED
@@ -667,6 +667,13 @@ var commandRegistry = {
667
667
  supportsRaw: false,
668
668
  output: writeOutput
669
669
  },
670
+ "schemas set-unique-fields": {
671
+ command: "schemas set-unique-fields",
672
+ accessLevel: "write",
673
+ supportsExample: true,
674
+ supportsRaw: false,
675
+ output: writeOutput
676
+ },
670
677
  "schemas delete": {
671
678
  command: "schemas delete",
672
679
  accessLevel: "destructive",
@@ -2417,7 +2424,8 @@ var specificExamples = {
2417
2424
  "conditionalFormatting": []
2418
2425
  }
2419
2426
  }
2420
- ]
2427
+ ],
2428
+ "uniqueFields": []
2421
2429
  }`
2422
2430
  },
2423
2431
  {
@@ -2436,10 +2444,83 @@ var specificExamples = {
2436
2444
  }`
2437
2445
  },
2438
2446
  {
2439
- description: "Set the highlighted (main) field of a schema.",
2447
+ description: "Set the schema's highlighted (main) field \u2014 the field whose value names each record in the UI (activity-panel title and detail-view record list).",
2440
2448
  command: "zinkee --json schemas update contacts --highlighted-field contact-name",
2441
2449
  raw: `{
2442
2450
  "highlightedField": "c60b8526-5835-4c9f-aecd-9a16c7704a34"
2451
+ }`
2452
+ }
2453
+ ]),
2454
+ "schemas set-unique-fields": buildCommandExamples([
2455
+ {
2456
+ description: "Set a composite unique constraint: the listed fields must be unique together across records.",
2457
+ command: "zinkee --json schemas set-unique-fields contacts --field contact-name --field notes",
2458
+ raw: `{
2459
+ "fieldIds": [
2460
+ "c60b8526-5835-4c9f-aecd-9a16c7704a34",
2461
+ "1d2e3f4a-5b6c-7d8e-9f01-23456789abcd"
2462
+ ]
2463
+ }`,
2464
+ response: `{
2465
+ "id": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
2466
+ "name": "Contacts",
2467
+ "slug": "contacts",
2468
+ "folder": {
2469
+ "id": "7f4e7c25-d8b2-4c1a-9f3e-6a7b5c8d9e1f",
2470
+ "name": "Customers",
2471
+ "isRoot": false
2472
+ },
2473
+ "auditable": true,
2474
+ "commentable": true,
2475
+ "highlightedField": "c60b8526-5835-4c9f-aecd-9a16c7704a34",
2476
+ "fields": [
2477
+ {
2478
+ "id": "c60b8526-5835-4c9f-aecd-9a16c7704a34",
2479
+ "type": "TextField",
2480
+ "slug": "contact-name",
2481
+ "label": "Customer Name",
2482
+ "required": true,
2483
+ "system": false,
2484
+ "config": {
2485
+ "textType": "NORMAL",
2486
+ "defaultValue": "Unknown",
2487
+ "conditionalFormatting": []
2488
+ }
2489
+ },
2490
+ {
2491
+ "id": "1d2e3f4a-5b6c-7d8e-9f01-23456789abcd",
2492
+ "type": "TextField",
2493
+ "slug": "notes",
2494
+ "label": "Notes",
2495
+ "required": false,
2496
+ "system": false,
2497
+ "config": {
2498
+ "textType": "LONG",
2499
+ "defaultValue": null,
2500
+ "conditionalFormatting": []
2501
+ }
2502
+ }
2503
+ ],
2504
+ "uniqueFields": [
2505
+ "c60b8526-5835-4c9f-aecd-9a16c7704a34",
2506
+ "1d2e3f4a-5b6c-7d8e-9f01-23456789abcd"
2507
+ ]
2508
+ }`
2509
+ },
2510
+ {
2511
+ description: "Set a single-field unique constraint.",
2512
+ command: "zinkee --json schemas set-unique-fields contacts --field contact-name",
2513
+ raw: `{
2514
+ "fieldIds": [
2515
+ "c60b8526-5835-4c9f-aecd-9a16c7704a34"
2516
+ ]
2517
+ }`
2518
+ },
2519
+ {
2520
+ description: "Clear the unique constraint (no field must be unique anymore).",
2521
+ command: "zinkee --json schemas set-unique-fields contacts --clear",
2522
+ raw: `{
2523
+ "fieldIds": []
2443
2524
  }`
2444
2525
  }
2445
2526
  ]),
@@ -4290,6 +4371,10 @@ var specificExamples = {
4290
4371
  "conditionalFormatting": []
4291
4372
  }
4292
4373
  }
4374
+ ],
4375
+ "uniqueFields": [
4376
+ "c60b8526-5835-4c9f-aecd-9a16c7704a34",
4377
+ "1d2e3f4a-5b6c-7d8e-9f01-23456789abcd"
4293
4378
  ]
4294
4379
  }`
4295
4380
  }
@@ -10720,6 +10805,12 @@ var SchemasApi = class {
10720
10805
  jsonOptions7(input, "PATCH")
10721
10806
  );
10722
10807
  }
10808
+ setUniqueFields(schema, input) {
10809
+ return this.client.requestJson(
10810
+ `/api/v2/schemas/${selectorValue9(schema)}/unique-fields`,
10811
+ jsonOptions7(input, "PUT")
10812
+ );
10813
+ }
10723
10814
  deleteSchema(schema) {
10724
10815
  return this.client.requestJson(
10725
10816
  `/api/v2/schemas/${selectorValue9(schema)}`,
@@ -11175,6 +11266,15 @@ function registerRecordsCommands(program, options = {}) {
11175
11266
  // src/commands/schemas.ts
11176
11267
  import { readFileSync as readFileSync9 } from "fs";
11177
11268
  import { InvalidArgumentError as InvalidArgumentError9 } from "commander";
11269
+ var HIGHLIGHTED_FIELD_HELP = `
11270
+ Highlighted field:
11271
+ The schema's "main" field. The frontend uses its value as each record's
11272
+ display name, in two places:
11273
+ - Activity panel: the record's title in the activity side panel
11274
+ (the panel with the record's logs and comments).
11275
+ - Detail view: the record's name in the left-hand record list you
11276
+ browse to open each record's form.
11277
+ `;
11178
11278
  function getCommandIo11(stdout) {
11179
11279
  return stdout ?? process.stdout;
11180
11280
  }
@@ -11248,6 +11348,9 @@ function parseUuidOrSlugSelector9(input) {
11248
11348
  throw new InvalidArgumentError9(message);
11249
11349
  }
11250
11350
  }
11351
+ function collectFieldSelectors(value, previous = []) {
11352
+ return [...previous, parseUuidOrSlugSelector9(value)];
11353
+ }
11251
11354
  function parseBooleanFlag(input) {
11252
11355
  const normalized = input.trim().toLowerCase();
11253
11356
  if (["true", "1", "yes", "y", "on"].includes(normalized)) {
@@ -11509,7 +11612,7 @@ function registerSchemasCommands(program, options = {}) {
11509
11612
  });
11510
11613
  schemas.command("update").description("Update a schema").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector9).option("--name <name>", "schema name").option("--slug <slug>", "schema slug").option("--auditable <bool>", "auditable flag", parseBooleanFlag).option("--commentable <bool>", "commentable flag", parseBooleanFlag).option(
11511
11614
  "--highlighted-field <field>",
11512
- "highlighted (main) field uuid or slug",
11615
+ "its value is used as each record's display name in the UI (field uuid or slug)",
11513
11616
  parseUuidOrSlugSelector9
11514
11617
  ).action(async function action(schema, commandOptions) {
11515
11618
  const { api, json, readOnly } = createSchemasApi(this, filePath);
@@ -11536,6 +11639,49 @@ function registerSchemasCommands(program, options = {}) {
11536
11639
  return;
11537
11640
  }
11538
11641
  writeLine11(stdout, `Updated schema "${data.slug ?? schema.value}".`);
11642
+ }).addHelpText("after", HIGHLIGHTED_FIELD_HELP);
11643
+ schemas.command("set-unique-fields").description("Set or clear the composite unique-field constraint on a schema").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector9).option(
11644
+ "--field <field>",
11645
+ "field uuid or slug to include in the unique constraint (repeatable)",
11646
+ collectFieldSelectors,
11647
+ []
11648
+ ).option("--clear", "clear the unique constraint (sends an empty field list)").action(async function action(schema, commandOptions) {
11649
+ const { api, json, readOnly } = createSchemasApi(this, filePath);
11650
+ ensureWritable8("schemas set-unique-fields", readOnly, "write");
11651
+ const selectors = commandOptions.field ?? [];
11652
+ if (commandOptions.clear && selectors.length > 0) {
11653
+ throw new CliError(
11654
+ "invalid_cli_usage",
11655
+ 'Use either "--field" or "--clear", not both.'
11656
+ );
11657
+ }
11658
+ if (!commandOptions.clear && selectors.length === 0) {
11659
+ throw new CliError(
11660
+ "invalid_cli_usage",
11661
+ 'Provide at least one field via "--field", or pass "--clear" to remove the unique constraint.'
11662
+ );
11663
+ }
11664
+ const resolvedSchema = await resolveSchemaSelector2(api, schema);
11665
+ const resolvedFields = await Promise.all(
11666
+ selectors.map((selector) => resolveFieldSelector(api, resolvedSchema, selector))
11667
+ );
11668
+ const input = {
11669
+ fieldIds: resolvedFields.map((field) => field.value)
11670
+ };
11671
+ const data = await api.setUniqueFields(resolvedSchema, input);
11672
+ if (json) {
11673
+ emitJson11(stdout, "schemas set-unique-fields", data, filePath);
11674
+ return;
11675
+ }
11676
+ if (input.fieldIds.length === 0) {
11677
+ writeLine11(stdout, `Cleared unique fields on schema "${schema.value}".`);
11678
+ return;
11679
+ }
11680
+ const count = input.fieldIds.length;
11681
+ writeLine11(
11682
+ stdout,
11683
+ `Set unique fields on schema "${schema.value}" (${count} field${count === 1 ? "" : "s"}).`
11684
+ );
11539
11685
  });
11540
11686
  schemas.command("delete").description("Delete a schema").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector9).action(async function action(schema) {
11541
11687
  const { api, json, readOnly } = createSchemasApi(this, filePath);