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.
- package/.claude/settings.local.json +5 -1
- package/README.md +28 -4
- package/dist/index.js +270 -61
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/api/automations.ts +1 -1
- package/src/api/displays.ts +48 -0
- package/src/api/navigation.ts +0 -1
- package/src/command-registry.ts +35 -0
- package/src/commands/automations.test.ts +32 -0
- package/src/commands/automations.ts +9 -3
- package/src/commands/displays.test.ts +74 -0
- package/src/commands/displays.ts +143 -1
- package/src/commands/navigation.test.ts +2 -5
- package/src/commands/navigation.ts +11 -11
- package/src/commands/teamspace.ts +19 -13
- package/src/utils/examples.test.ts +13 -4
- package/src/utils/examples.ts +95 -50
|
@@ -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> --
|
|
351
|
+
zinkee navigation resources move <schema-uuid> --to "CRM"
|
|
352
352
|
|
|
353
|
-
#
|
|
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 --
|
|
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
|
|
2936
|
-
command: "zinkee --json navigation resources move
|
|
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": "
|
|
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": "
|
|
4481
|
-
"type": "
|
|
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":
|
|
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
|
-
|
|
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(
|
|
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>", "
|
|
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>", "
|
|
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(
|
|
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
|
|
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
|
|
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>", "
|
|
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>", "
|
|
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(
|
|
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>", "
|
|
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);
|