zinkee 0.1.24 → 0.1.25

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.
@@ -43,7 +43,11 @@
43
43
  "Bash(git -C /home/guillermo/dev/cli branch --show-current)",
44
44
  "Bash(git -C /home/guillermo/dev/cli diff --stat)",
45
45
  "Bash(git fetch *)",
46
- "Bash(pnpm exec *)"
46
+ "Bash(pnpm exec *)",
47
+ "Bash(echo \"=== exit $? \\(grep\\) ===\")",
48
+ "Bash(grep -rn \"resourceType\" src/)",
49
+ "Bash(grep -rn \"automation-folders/\\\\${\\\\|/automations:move\\\\|{folderId}/automations\" src/)",
50
+ "Bash(grep -rn \"navigation resources move.*--type\\\\|resourceType\" docs/ README.md)"
47
51
  ]
48
52
  }
49
53
  }
package/README.md CHANGED
@@ -338,7 +338,7 @@ zinkee --json logs list <schema-slug> <record-uuid>
338
338
 
339
339
  ## Navigation
340
340
 
341
- Organize schemas into database folders.
341
+ Organize schemas into database folders. The navigation menu holds databases, so only schemas can be moved here.
342
342
 
343
343
  ```bash
344
344
  # List folders with contents
@@ -348,13 +348,16 @@ zinkee --json navigation folders list
348
348
  zinkee navigation folders create --name "CRM" --order 1
349
349
 
350
350
  # Move a schema into a folder
351
- zinkee navigation resources move <schema-uuid> --type SCHEMA --to "CRM"
351
+ zinkee navigation resources move <schema-uuid> --to "CRM"
352
352
 
353
- # Delete folder (resources move back to root silently)
353
+ # Move a schema back to the workspace root
354
+ zinkee navigation resources move <schema-uuid> --to 00000000-0000-0000-0000-000000000000
355
+
356
+ # Delete folder (schemas move back to root silently)
354
357
  zinkee navigation folders delete "CRM"
355
358
  ```
356
359
 
357
- Root folder cannot be deleted.
360
+ Only schemas can be moved (schedules and sub-schemas follow their parent schema). Root folder cannot be deleted; its UUID is always `00000000-0000-0000-0000-000000000000`.
358
361
 
359
362
  ---
360
363
 
@@ -388,6 +391,27 @@ zinkee teamspace resources publish projects --to "Other Folder"
388
391
 
389
392
  Displays are dashboards composed of widgets that visualize data from schemas.
390
393
 
394
+ ### Display folders
395
+
396
+ Organize displays into folders in the displays menu. Folders are flat (name only) and only displays can be moved into them.
397
+
398
+ ```bash
399
+ # List display folders (non-root folders plus the root bucket)
400
+ zinkee --json displays folders list
401
+
402
+ # Create a folder
403
+ zinkee displays folders create --name "Executive Dashboards"
404
+
405
+ # Rename a folder
406
+ zinkee displays folders update "Executive Dashboards" --name "Executive Dashboards (2026)"
407
+
408
+ # Move a display into a folder
409
+ zinkee displays folders move <display-uuid> --to "Executive Dashboards"
410
+
411
+ # Delete a folder (its displays move back to the root folder)
412
+ zinkee displays folders delete "Executive Dashboards"
413
+ ```
414
+
391
415
  ### Creation flow
392
416
 
393
417
  1. Create the display
package/dist/index.js CHANGED
@@ -275,6 +275,41 @@ var commandRegistry = {
275
275
  supportsRaw: false,
276
276
  output: writeOutput
277
277
  },
278
+ "displays folders list": {
279
+ command: "displays folders list",
280
+ accessLevel: "read",
281
+ supportsExample: true,
282
+ supportsRaw: false,
283
+ output: readOutput
284
+ },
285
+ "displays folders create": {
286
+ command: "displays folders create",
287
+ accessLevel: "write",
288
+ supportsExample: true,
289
+ supportsRaw: false,
290
+ output: writeOutput
291
+ },
292
+ "displays folders update": {
293
+ command: "displays folders update",
294
+ accessLevel: "write",
295
+ supportsExample: true,
296
+ supportsRaw: false,
297
+ output: writeOutput
298
+ },
299
+ "displays folders delete": {
300
+ command: "displays folders delete",
301
+ accessLevel: "destructive",
302
+ supportsExample: true,
303
+ supportsRaw: false,
304
+ output: writeOutput
305
+ },
306
+ "displays folders move": {
307
+ command: "displays folders move",
308
+ accessLevel: "write",
309
+ supportsExample: true,
310
+ supportsRaw: false,
311
+ output: writeOutput
312
+ },
278
313
  "displays layout get": {
279
314
  command: "displays layout get",
280
315
  accessLevel: "read",
@@ -2919,11 +2954,10 @@ var specificExamples = {
2919
2954
  ]),
2920
2955
  "navigation resources move": buildCommandExamples([
2921
2956
  {
2922
- description: "Move a schema into a navigation folder.",
2923
- command: "zinkee --json navigation resources move 2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e --type SCHEMA --to Sales",
2957
+ description: "Move a schema into a navigation folder. Only schemas can be moved; the navigation menu holds databases.",
2958
+ command: "zinkee --json navigation resources move 2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e --to Sales",
2924
2959
  raw: `{
2925
2960
  "resourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
2926
- "resourceType": "SCHEMA",
2927
2961
  "targetFolderId": "84a0fca4-37ef-4c83-a8ed-9ef67ad9324a"
2928
2962
  }`,
2929
2963
  response: `{
@@ -2932,39 +2966,11 @@ var specificExamples = {
2932
2966
  }`
2933
2967
  },
2934
2968
  {
2935
- description: "Move a workflow.",
2936
- command: "zinkee --json navigation resources move 3f8a2c1b-9d4e-4a5b-8c6d-7e8f90123456 --type WORKFLOW --to Operations",
2937
- raw: `{
2938
- "resourceId": "3f8a2c1b-9d4e-4a5b-8c6d-7e8f90123456",
2939
- "resourceType": "WORKFLOW",
2940
- "targetFolderId": "b8c9d0e1-f2a3-4b5c-6d7e-8f9012345678"
2941
- }`
2942
- },
2943
- {
2944
- description: "Move a display.",
2945
- command: "zinkee --json navigation resources move 0f6f062f-1478-4df2-96a1-c495d037d260 --type DISPLAY --to Operations",
2946
- raw: `{
2947
- "resourceId": "0f6f062f-1478-4df2-96a1-c495d037d260",
2948
- "resourceType": "DISPLAY",
2949
- "targetFolderId": "b8c9d0e1-f2a3-4b5c-6d7e-8f9012345678"
2950
- }`
2951
- },
2952
- {
2953
- description: "Move a resource back to the root folder (root is always UUID 00000000-0000-0000-0000-000000000000).",
2954
- command: "zinkee --json navigation resources move 5223cbc8-8c6c-4694-93bc-dd176364df9b --type SCHEMA --to 00000000-0000-0000-0000-000000000000",
2969
+ description: "Move a schema back to the root folder (root is always UUID 00000000-0000-0000-0000-000000000000).",
2970
+ command: "zinkee --json navigation resources move 5223cbc8-8c6c-4694-93bc-dd176364df9b --to 00000000-0000-0000-0000-000000000000",
2955
2971
  raw: `{
2956
2972
  "resourceId": "5223cbc8-8c6c-4694-93bc-dd176364df9b",
2957
- "resourceType": "SCHEMA",
2958
2973
  "targetFolderId": "00000000-0000-0000-0000-000000000000"
2959
- }`
2960
- },
2961
- {
2962
- description: "Move a schedule resource.",
2963
- command: "zinkee --json navigation resources move a1b2c3d4-e5f6-7890-1234-567890abcdef --type SCHEDULE --to Operations",
2964
- raw: `{
2965
- "resourceId": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
2966
- "resourceType": "SCHEDULE",
2967
- "targetFolderId": "b8c9d0e1-f2a3-4b5c-6d7e-8f9012345678"
2968
2974
  }`
2969
2975
  }
2970
2976
  ]),
@@ -4453,7 +4459,7 @@ var specificExamples = {
4453
4459
  "resources": [
4454
4460
  {
4455
4461
  "id": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
4456
- "name": "Contacts",
4462
+ "name": "Customer records",
4457
4463
  "type": "SCHEMA",
4458
4464
  "isInSpace": false,
4459
4465
  "additionalProperties": {}
@@ -4477,19 +4483,10 @@ var specificExamples = {
4477
4483
  "resources": [
4478
4484
  {
4479
4485
  "id": "3f8a2c1b-9d4e-4a5b-8c6d-7e8f90123456",
4480
- "name": "Quote approval",
4481
- "type": "WORKFLOW",
4486
+ "name": "Shipments",
4487
+ "type": "SCHEMA",
4482
4488
  "isInSpace": false,
4483
4489
  "additionalProperties": {}
4484
- },
4485
- {
4486
- "id": "0f6f062f-1478-4df2-96a1-c495d037d260",
4487
- "name": "Executive Revenue",
4488
- "type": "DISPLAY",
4489
- "isInSpace": true,
4490
- "additionalProperties": {
4491
- "pinned": true
4492
- }
4493
4490
  }
4494
4491
  ],
4495
4492
  "additionalProperties": {
@@ -4536,8 +4533,13 @@ var specificExamples = {
4536
4533
  "name": "Shared Dashboards",
4537
4534
  "order": 1,
4538
4535
  "isRoot": false,
4539
- "resourceCount": 1,
4536
+ "resourceCount": 2,
4540
4537
  "resources": [
4538
+ {
4539
+ "id": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
4540
+ "name": "Customer records",
4541
+ "type": "SCHEMA"
4542
+ },
4541
4543
  {
4542
4544
  "id": "0f6f062f-1478-4df2-96a1-c495d037d260",
4543
4545
  "name": "Executive Revenue",
@@ -4756,6 +4758,83 @@ var specificExamples = {
4756
4758
  command: "zinkee --json displays delete 0f6f062f-1478-4df2-96a1-c495d037d260"
4757
4759
  }
4758
4760
  ]),
4761
+ "displays folders list": buildCommandExamples([
4762
+ {
4763
+ description: "List flat display folders (non-root folders plus the root bucket).",
4764
+ command: "zinkee --json displays folders list",
4765
+ response: `[
4766
+ {
4767
+ "id": "e7a1c3d2-5f4b-4a6c-9d8e-1f2a3b4c5d6e",
4768
+ "name": "Executive Dashboards",
4769
+ "isRoot": false,
4770
+ "displayCount": 2
4771
+ },
4772
+ {
4773
+ "id": "8b22282b-3db3-4dd7-87f7-b29365dcf3f6",
4774
+ "name": null,
4775
+ "isRoot": true,
4776
+ "displayCount": 4
4777
+ }
4778
+ ]`
4779
+ }
4780
+ ]),
4781
+ "displays folders create": buildCommandExamples([
4782
+ {
4783
+ description: "Create one flat display folder.",
4784
+ command: 'zinkee --json displays folders create --name "Executive Dashboards"',
4785
+ raw: `{
4786
+ "name": "Executive Dashboards"
4787
+ }`,
4788
+ response: `{
4789
+ "id": "e7a1c3d2-5f4b-4a6c-9d8e-1f2a3b4c5d6e",
4790
+ "name": "Executive Dashboards",
4791
+ "isRoot": false,
4792
+ "displayCount": 0
4793
+ }`
4794
+ }
4795
+ ]),
4796
+ "displays folders update": buildCommandExamples([
4797
+ {
4798
+ description: "Rename a display folder. The folder argument accepts a UUID or an exact name.",
4799
+ command: 'zinkee --json displays folders update "Executive Dashboards" --name "Executive Dashboards (2026)"',
4800
+ raw: `{
4801
+ "name": "Executive Dashboards (2026)"
4802
+ }`,
4803
+ response: `{
4804
+ "id": "e7a1c3d2-5f4b-4a6c-9d8e-1f2a3b4c5d6e",
4805
+ "name": "Executive Dashboards (2026)",
4806
+ "isRoot": false,
4807
+ "displayCount": 2
4808
+ }`
4809
+ }
4810
+ ]),
4811
+ "displays folders delete": buildCommandExamples([
4812
+ {
4813
+ description: "Delete a non-root display folder. Its displays move back to the root folder.",
4814
+ command: 'zinkee --json displays folders delete "Executive Dashboards"',
4815
+ response: `{
4816
+ "id": "e7a1c3d2-5f4b-4a6c-9d8e-1f2a3b4c5d6e",
4817
+ "name": "Executive Dashboards",
4818
+ "isRoot": false,
4819
+ "displayCount": 2
4820
+ }`
4821
+ }
4822
+ ]),
4823
+ "displays folders move": buildCommandExamples([
4824
+ {
4825
+ description: "Move one display into a target folder by exact folder name.",
4826
+ command: 'zinkee --json displays folders move 0f6f062f-1478-4df2-96a1-c495d037d260 --to "Executive Dashboards"',
4827
+ raw: `{
4828
+ "displayId": "0f6f062f-1478-4df2-96a1-c495d037d260",
4829
+ "targetFolderId": "e7a1c3d2-5f4b-4a6c-9d8e-1f2a3b4c5d6e"
4830
+ }`,
4831
+ response: `{
4832
+ "id": "e7a1c3d2-5f4b-4a6c-9d8e-1f2a3b4c5d6e",
4833
+ "name": "Executive Dashboards",
4834
+ "isRoot": false
4835
+ }`
4836
+ }
4837
+ ]),
4759
4838
  "displays layout get": buildCommandExamples([
4760
4839
  {
4761
4840
  description: "Get the layout block of a display (template + tabs/freeformLayouts/slots).",
@@ -5769,7 +5848,8 @@ var specificExamples = {
5769
5848
  description: "Move one automation into a target folder by exact folder name.",
5770
5849
  command: 'zinkee --json automations folders move automation-1 --to "Codex Frontend Demo"',
5771
5850
  raw: `{
5772
- "automationId": "automation-1"
5851
+ "automationId": "automation-1",
5852
+ "targetFolderId": "cdfc14e3-3169-4ffb-8d9b-b11858a9240f"
5773
5853
  }`,
5774
5854
  response: `{
5775
5855
  "id": "cdfc14e3-3169-4ffb-8d9b-b11858a9240f",
@@ -6415,7 +6495,7 @@ var AutomationsApi = class {
6415
6495
  }
6416
6496
  moveAutomation(input) {
6417
6497
  return this.client.requestJson(
6418
- `/api/v2/automation-folders/${segment(input.targetFolderId)}/automations:move`,
6498
+ "/api/v2/automation-folders/automations:move",
6419
6499
  jsonOptions(input, "POST")
6420
6500
  );
6421
6501
  }
@@ -7560,8 +7640,8 @@ function registerAutomationsCommands(program, options = {}) {
7560
7640
  const filePath = options.configPath ?? defaultConfigPath;
7561
7641
  const stdout = getCommandIo2(options.stdout);
7562
7642
  const automations = program.command("automations").description("Manage automations, triggers, actions, and connections");
7563
- const folders = automations.command("folders").description("Manage automation folders");
7564
- folders.command("list").description("List automation folders").action(async function action() {
7643
+ const folders = automations.command("folders").description("Manage automation folders (flat: a folder only has a name, no order or properties)");
7644
+ folders.command("list").description("List automation folders (non-root folders plus the root bucket, whose name is null)").action(async function action() {
7565
7645
  const { api, json } = createAutomationsApi(this, filePath);
7566
7646
  const data = await api.listFolders();
7567
7647
  if (json) {
@@ -7611,7 +7691,11 @@ function registerAutomationsCommands(program, options = {}) {
7611
7691
  }
7612
7692
  writeLine2(stdout, `Deleted automation folder "${folder.value}".`);
7613
7693
  });
7614
- folders.command("move").description("Move an automation into a folder").argument("<automation>", "automation UUID", parseUuidOrSlugSelector).requiredOption("--to <folder>", "target folder UUID or exact name", parseUuidOrSlugSelector).action(async function action(automation, commandOptions) {
7694
+ folders.command("move").description("Move an automation into a folder").argument("<automation>", "automation UUID", parseUuidOrSlugSelector).requiredOption(
7695
+ "--to <folder>",
7696
+ "target folder UUID or exact name (use the root folder to move it out of any folder)",
7697
+ parseUuidOrSlugSelector
7698
+ ).action(async function action(automation, commandOptions) {
7615
7699
  const { api, json, readOnly } = createAutomationsApi(this, filePath);
7616
7700
  ensureWritable("automations folders move", readOnly, "write");
7617
7701
  if (!commandOptions.to) {
@@ -8296,6 +8380,33 @@ var DisplaysApi = class {
8296
8380
  { method: "DELETE" }
8297
8381
  );
8298
8382
  }
8383
+ listFolders() {
8384
+ return this.client.getJson("/api/v2/display-folders");
8385
+ }
8386
+ createFolder(body) {
8387
+ return this.client.requestJson(
8388
+ "/api/v2/display-folders",
8389
+ jsonOptions3(body, "POST")
8390
+ );
8391
+ }
8392
+ updateFolder(folder, body) {
8393
+ return this.client.requestJson(
8394
+ `/api/v2/display-folders/${selectorValue3(folder)}`,
8395
+ jsonOptions3(body, "PATCH")
8396
+ );
8397
+ }
8398
+ deleteFolder(folder) {
8399
+ return this.client.requestJson(
8400
+ `/api/v2/display-folders/${selectorValue3(folder)}`,
8401
+ { method: "DELETE" }
8402
+ );
8403
+ }
8404
+ moveDisplay(input) {
8405
+ return this.client.requestJson(
8406
+ "/api/v2/display-folders/displays:move",
8407
+ jsonOptions3(input, "POST")
8408
+ );
8409
+ }
8299
8410
  };
8300
8411
 
8301
8412
  // src/parsers/expressions.ts
@@ -8523,6 +8634,31 @@ function getDisplaySubresource(value) {
8523
8634
  }
8524
8635
  return value.filter((entry) => Boolean(entry) && typeof entry === "object");
8525
8636
  }
8637
+ function displayFolderRows(folders) {
8638
+ return folders.map((folder) => ({
8639
+ id: folder.id ?? "",
8640
+ name: folder.name ?? "",
8641
+ isRoot: folder.isRoot ?? "",
8642
+ displayCount: folder.displayCount ?? ""
8643
+ }));
8644
+ }
8645
+ async function resolveDisplayFolderId(api, selector) {
8646
+ if (selector.kind === "uuid") {
8647
+ return selector.value;
8648
+ }
8649
+ const folders = await api.listFolders();
8650
+ const matches = folders.filter((folder) => folder.name === selector.value);
8651
+ if (matches.length === 1 && typeof matches[0]?.id === "string" && matches[0].id.length > 0) {
8652
+ return matches[0].id;
8653
+ }
8654
+ if (matches.length > 1) {
8655
+ throw new CliError(
8656
+ "invalid_cli_usage",
8657
+ `Folder "${selector.value}" is ambiguous. Found ${matches.length} matches.`
8658
+ );
8659
+ }
8660
+ throw new CliError("invalid_cli_usage", `Folder "${selector.value}" was not found.`);
8661
+ }
8526
8662
  function buildVariableBody(options) {
8527
8663
  const body = {
8528
8664
  ...readRawObject2(options.raw, options.rawFile)
@@ -8728,6 +8864,72 @@ function registerDisplaysCommands(program, options = {}) {
8728
8864
  }
8729
8865
  writeLine4(stdout, `Deleted display "${display.value}".`);
8730
8866
  });
8867
+ const folders = displays.command("folders").description("Manage display folders (flat: a folder only has a name, no order or properties)");
8868
+ folders.command("list").description("List display folders (non-root folders plus the root bucket, whose name is null)").action(async function action() {
8869
+ const { api, json } = createDisplaysApi(this, filePath);
8870
+ const data = await api.listFolders();
8871
+ if (json) {
8872
+ emitJson4(stdout, "displays folders list", data);
8873
+ return;
8874
+ }
8875
+ printTable(displayFolderRows(data), ["id", "name", "isRoot", "displayCount"], stdout);
8876
+ });
8877
+ folders.command("create").description("Create a display folder").requiredOption("--name <name>", "folder name").action(async function action(commandOptions) {
8878
+ const { api, json, readOnly } = createDisplaysApi(this, filePath);
8879
+ ensureWritable3("displays folders create", readOnly, "write");
8880
+ if (commandOptions.name === void 0) {
8881
+ throw new CliError("invalid_cli_usage", 'Provide folder name via "--name".');
8882
+ }
8883
+ const data = await api.createFolder({ name: commandOptions.name });
8884
+ if (json) {
8885
+ emitJson4(stdout, "displays folders create", data);
8886
+ return;
8887
+ }
8888
+ writeLine4(stdout, `Created display folder "${String(data.name ?? commandOptions.name)}".`);
8889
+ });
8890
+ folders.command("update").description("Rename a display folder").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector3).requiredOption("--name <name>", "folder name").action(async function action(folder, commandOptions) {
8891
+ const { api, json, readOnly } = createDisplaysApi(this, filePath);
8892
+ ensureWritable3("displays folders update", readOnly, "write");
8893
+ if (commandOptions.name === void 0) {
8894
+ throw new CliError("invalid_cli_usage", 'Provide folder name via "--name".');
8895
+ }
8896
+ const folderId = await resolveDisplayFolderId(api, folder);
8897
+ const data = await api.updateFolder({ kind: "uuid", value: folderId }, { name: commandOptions.name });
8898
+ if (json) {
8899
+ emitJson4(stdout, "displays folders update", data);
8900
+ return;
8901
+ }
8902
+ writeLine4(stdout, `Updated display folder "${String(data.name ?? folder.value)}".`);
8903
+ });
8904
+ folders.command("delete").description("Delete a display folder (its displays move back to the root folder)").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector3).action(async function action(folder) {
8905
+ const { api, json, readOnly } = createDisplaysApi(this, filePath);
8906
+ ensureWritable3("displays folders delete", readOnly, "destructive");
8907
+ const folderId = await resolveDisplayFolderId(api, folder);
8908
+ const data = await api.deleteFolder({ kind: "uuid", value: folderId });
8909
+ if (json) {
8910
+ emitJson4(stdout, "displays folders delete", data);
8911
+ return;
8912
+ }
8913
+ writeLine4(stdout, `Deleted display folder "${folder.value}".`);
8914
+ });
8915
+ folders.command("move").description("Move a display into a folder").argument("<display>", "display UUID", parseUuidOrSlugSelector3).requiredOption(
8916
+ "--to <folder>",
8917
+ "target folder UUID or exact name (use the root folder to move it out of any folder)",
8918
+ parseUuidOrSlugSelector3
8919
+ ).action(async function action(display, commandOptions) {
8920
+ const { api, json, readOnly } = createDisplaysApi(this, filePath);
8921
+ ensureWritable3("displays folders move", readOnly, "write");
8922
+ if (!commandOptions.to) {
8923
+ throw new CliError("invalid_cli_usage", 'Provide target folder via "--to".');
8924
+ }
8925
+ const targetFolderId = await resolveDisplayFolderId(api, commandOptions.to);
8926
+ const data = await api.moveDisplay({ displayId: display.value, targetFolderId });
8927
+ if (json) {
8928
+ emitJson4(stdout, "displays folders move", data);
8929
+ return;
8930
+ }
8931
+ writeLine4(stdout, `Moved display "${display.value}" to folder "${targetFolderId}".`);
8932
+ });
8731
8933
  const layout = displays.command("layout").description("Manage display layout");
8732
8934
  layout.command("get").description("Get display layout").argument("<display>", "display uuid or slug", parseUuidOrSlugSelector3).action(async function action(display) {
8733
8935
  const { api, json } = createDisplaysApi(this, filePath);
@@ -9901,7 +10103,7 @@ function registerNavigationCommands(program, options = {}) {
9901
10103
  }
9902
10104
  printTable(folderRows2([resolved]), ["id", "order", "name", "resourceCount"], stdout);
9903
10105
  });
9904
- folders.command("create").description("Create a navigation folder").requiredOption("--name <name>", "folder name").option("--order <n>", "folder order").option("--props <json>", "folder additionalProperties JSON").option("--props-file <path>", "folder additionalProperties JSON file").action(async function action(commandOptions) {
10106
+ folders.command("create").description("Create a navigation folder").requiredOption("--name <name>", "folder name").option("--order <n>", "display order (lower values appear first)").option("--props <json>", 'additionalProperties JSON: free-form client metadata, e.g. {"color":"blue","icon":"chart-line"}').option("--props-file <path>", "path to a file with the additionalProperties JSON").action(async function action(commandOptions) {
9905
10107
  const { api, json, readOnly } = createNavigationApi(this, filePath);
9906
10108
  ensureWritable6("navigation folders create", readOnly, "write");
9907
10109
  const data = await api.createFolder(buildFolderBody(commandOptions));
@@ -9911,7 +10113,7 @@ function registerNavigationCommands(program, options = {}) {
9911
10113
  }
9912
10114
  writeLine8(stdout, `Created navigation folder "${String(data.name ?? commandOptions.name)}".`);
9913
10115
  });
9914
- folders.command("update").description("Update a navigation folder").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector7).option("--name <name>", "folder name").option("--order <n>", "folder order").option("--props <json>", "folder additionalProperties JSON").option("--props-file <path>", "folder additionalProperties JSON file").action(async function action(folder, commandOptions) {
10116
+ folders.command("update").description("Update a navigation folder").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector7).option("--name <name>", "folder name").option("--order <n>", "display order (lower values appear first)").option("--props <json>", 'additionalProperties JSON: free-form client metadata, e.g. {"color":"blue","icon":"chart-line"}').option("--props-file <path>", "path to a file with the additionalProperties JSON").action(async function action(folder, commandOptions) {
9915
10117
  const { api, json, readOnly } = createNavigationApi(this, filePath);
9916
10118
  ensureWritable6("navigation folders update", readOnly, "write");
9917
10119
  const allFolders = await api.listFolders();
@@ -9939,14 +10141,15 @@ function registerNavigationCommands(program, options = {}) {
9939
10141
  }
9940
10142
  writeLine8(stdout, `Deleted navigation folder "${resolved.name ?? resolved.id}".`);
9941
10143
  });
9942
- navigation.command("resources").description("Manage navigation resources").command("move").description("Move a resource into a folder").argument("<resource>", "resource UUID").requiredOption("--type <type>", "resource type").requiredOption("--to <folder>", "target folder UUID or exact name").action(async function action(resourceId, commandOptions) {
10144
+ navigation.command("resources").description("Manage navigation resources").command("move").description(
10145
+ "Move a schema into a navigation folder. Only schemas can be moved (the navigation menu holds databases); schedules and sub-schemas follow their parent schema. Use the root folder UUID 00000000-0000-0000-0000-000000000000 to move it back to the workspace root."
10146
+ ).argument("<resource>", "schema UUID").requiredOption("--to <folder>", "target folder UUID or exact name").action(async function action(resourceId, commandOptions) {
9943
10147
  const { api, json, readOnly } = createNavigationApi(this, filePath);
9944
10148
  ensureWritable6("navigation resources move", readOnly, "write");
9945
10149
  const allFolders = await api.listFolders();
9946
10150
  const resolved = resolveFolder2(allFolders, parseUuidOrSlugSelector7(commandOptions.to));
9947
10151
  const data = await api.moveResource({
9948
10152
  resourceId,
9949
- resourceType: commandOptions.type.toUpperCase(),
9950
10153
  targetFolderId: resolved.id
9951
10154
  });
9952
10155
  if (json) {
@@ -11479,7 +11682,7 @@ function registerTeamspaceCommands(program, options = {}) {
11479
11682
  const stdout = getCommandIo12(options.stdout);
11480
11683
  const teamspace = program.command("teamspace").description("Manage teamspace folders and resources");
11481
11684
  const folders = teamspace.command("folders").description("Manage teamspace folders");
11482
- folders.command("list").description("List teamspace folders").option("--include-resources", "include nested resources").action(async function action(commandOptions) {
11685
+ folders.command("list").description("List teamspace folders").option("--include-resources", "include the published resources inside each folder").action(async function action(commandOptions) {
11483
11686
  const { api, json } = createTeamspaceApi(this, filePath);
11484
11687
  const data = await api.listFolders(Boolean(commandOptions.includeResources));
11485
11688
  if (json) {
@@ -11488,7 +11691,7 @@ function registerTeamspaceCommands(program, options = {}) {
11488
11691
  }
11489
11692
  emitTable5(stdout, data);
11490
11693
  });
11491
- folders.command("get").description("Get a teamspace folder by exact name or UUID").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector10).option("--include-resources", "include nested resources").action(async function action(folder, commandOptions) {
11694
+ folders.command("get").description("Get a teamspace folder by exact name or UUID").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector10).option("--include-resources", "include the published resources inside each folder").action(async function action(folder, commandOptions) {
11492
11695
  const { api, json } = createTeamspaceApi(this, filePath);
11493
11696
  const resolvedFolder = await resolveFolderSelector2(api, folder);
11494
11697
  const allFolders = await api.listFolders(Boolean(commandOptions.includeResources));
@@ -11499,7 +11702,7 @@ function registerTeamspaceCommands(program, options = {}) {
11499
11702
  }
11500
11703
  emitTable5(stdout, data);
11501
11704
  });
11502
- folders.command("create").description("Create a teamspace folder").requiredOption("--name <name>", "folder name").option("--order <n>", "folder order", parseNonNegativeInteger3).option("--props <json>", "folder properties payload").option("--props-file <path>", "path to a folder properties JSON payload").action(async function action(commandOptions) {
11705
+ folders.command("create").description("Create a teamspace folder").requiredOption("--name <name>", "folder name").option("--order <n>", "display order (lower values appear first)", parseNonNegativeInteger3).option("--props <json>", 'additionalProperties JSON: free-form client metadata, e.g. {"icon":"folder-users","color":"gold"}').option("--props-file <path>", "path to a file with the additionalProperties JSON").action(async function action(commandOptions) {
11503
11706
  const { api, json, readOnly } = createTeamspaceApi(this, filePath);
11504
11707
  ensureWritable9("teamspace folders create", readOnly, "write");
11505
11708
  const data = await api.createFolder(buildFolderCreateInput(commandOptions));
@@ -11509,7 +11712,7 @@ function registerTeamspaceCommands(program, options = {}) {
11509
11712
  }
11510
11713
  writeLine12(stdout, `Created folder "${getFolderIdentifier(data)}".`);
11511
11714
  });
11512
- folders.command("update").description("Update a teamspace folder").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector10).option("--name <name>", "folder name").option("--order <n>", "folder order", parseNonNegativeInteger3).option("--props <json>", "folder properties payload").option("--props-file <path>", "path to a folder properties JSON payload").action(async function action(folder, commandOptions) {
11715
+ folders.command("update").description("Update a teamspace folder").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector10).option("--name <name>", "folder name").option("--order <n>", "display order (lower values appear first)", parseNonNegativeInteger3).option("--props <json>", 'additionalProperties JSON: free-form client metadata, e.g. {"icon":"folder-users","color":"gold"}').option("--props-file <path>", "path to a file with the additionalProperties JSON").action(async function action(folder, commandOptions) {
11513
11716
  const { api, json, readOnly } = createTeamspaceApi(this, filePath);
11514
11717
  ensureWritable9("teamspace folders update", readOnly, "write");
11515
11718
  const resolvedFolder = await resolveFolderSelector2(api, folder);
@@ -11532,7 +11735,13 @@ function registerTeamspaceCommands(program, options = {}) {
11532
11735
  writeLine12(stdout, `Deleted folder "${resolvedFolder.value}".`);
11533
11736
  });
11534
11737
  const resources = teamspace.command("resources").description("Manage teamspace resources");
11535
- resources.command("publish").description("Publish a resource to a teamspace folder").argument("<resource>", "resource UUID or exact name", parseUuidOrSlugSelector10).requiredOption("--to <folder>", "target folder", parseUuidOrSlugSelector10).action(async function action(resource, commandOptions) {
11738
+ resources.command("publish").description(
11739
+ "Publish a resource to a teamspace folder. Publishing an already-published resource moves it to the new folder."
11740
+ ).argument("<resource>", "schema UUID, schema slug, or display UUID", parseUuidOrSlugSelector10).requiredOption(
11741
+ "--to <folder>",
11742
+ "target folder UUID or exact name (root folder UUID is 00000000-0000-0000-0000-000000000000)",
11743
+ parseUuidOrSlugSelector10
11744
+ ).action(async function action(resource, commandOptions) {
11536
11745
  const { api, json, readOnly } = createTeamspaceApi(this, filePath);
11537
11746
  ensureWritable9("teamspace resources publish", readOnly, "write");
11538
11747
  const folder = await resolveFolderSelector2(api, commandOptions.to);
@@ -11546,7 +11755,7 @@ function registerTeamspaceCommands(program, options = {}) {
11546
11755
  }
11547
11756
  writeLine12(stdout, `Published resource "${resource.value}" to folder "${folder.value}".`);
11548
11757
  });
11549
- resources.command("unpublish").description("Unpublish a resource from teamspace").argument("<resource>", "resource UUID or exact name", parseUuidOrSlugSelector10).action(async function action(resource) {
11758
+ resources.command("unpublish").description("Unpublish a resource from teamspace (removes it from its shared folder)").argument("<resource>", "schema UUID, schema slug, or display UUID", parseUuidOrSlugSelector10).action(async function action(resource) {
11550
11759
  const { api, json, readOnly } = createTeamspaceApi(this, filePath);
11551
11760
  ensureWritable9("teamspace resources unpublish", readOnly, "write");
11552
11761
  const data = await api.unpublishResource(resource.value);