zinkee 0.1.36 → 0.1.37
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 +70 -0
- package/dist/index.js +2420 -735
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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",
|
|
@@ -436,6 +471,62 @@ var commandRegistry = {
|
|
|
436
471
|
supportsRaw: false,
|
|
437
472
|
output: writeOutput
|
|
438
473
|
},
|
|
474
|
+
"document-templates list": {
|
|
475
|
+
command: "document-templates list",
|
|
476
|
+
accessLevel: "read",
|
|
477
|
+
supportsExample: true,
|
|
478
|
+
supportsRaw: false,
|
|
479
|
+
output: readOutput
|
|
480
|
+
},
|
|
481
|
+
"document-templates get": {
|
|
482
|
+
command: "document-templates get",
|
|
483
|
+
accessLevel: "read",
|
|
484
|
+
supportsExample: true,
|
|
485
|
+
supportsRaw: false,
|
|
486
|
+
output: readOutput
|
|
487
|
+
},
|
|
488
|
+
"document-templates create": {
|
|
489
|
+
command: "document-templates create",
|
|
490
|
+
accessLevel: "write",
|
|
491
|
+
supportsExample: true,
|
|
492
|
+
supportsRaw: true,
|
|
493
|
+
output: writeOutput
|
|
494
|
+
},
|
|
495
|
+
"document-templates update": {
|
|
496
|
+
command: "document-templates update",
|
|
497
|
+
accessLevel: "write",
|
|
498
|
+
supportsExample: true,
|
|
499
|
+
supportsRaw: false,
|
|
500
|
+
output: writeOutput
|
|
501
|
+
},
|
|
502
|
+
"document-templates delete": {
|
|
503
|
+
command: "document-templates delete",
|
|
504
|
+
accessLevel: "destructive",
|
|
505
|
+
supportsExample: true,
|
|
506
|
+
supportsRaw: false,
|
|
507
|
+
output: writeOutput
|
|
508
|
+
},
|
|
509
|
+
"document-templates assets add": {
|
|
510
|
+
command: "document-templates assets add",
|
|
511
|
+
accessLevel: "write",
|
|
512
|
+
supportsExample: true,
|
|
513
|
+
supportsRaw: false,
|
|
514
|
+
output: writeOutput
|
|
515
|
+
},
|
|
516
|
+
"document-templates assets delete": {
|
|
517
|
+
command: "document-templates assets delete",
|
|
518
|
+
accessLevel: "destructive",
|
|
519
|
+
supportsExample: true,
|
|
520
|
+
supportsRaw: false,
|
|
521
|
+
output: writeOutput
|
|
522
|
+
},
|
|
523
|
+
"document-templates assets download": {
|
|
524
|
+
command: "document-templates assets download",
|
|
525
|
+
accessLevel: "read",
|
|
526
|
+
supportsExample: true,
|
|
527
|
+
supportsRaw: false,
|
|
528
|
+
output: "binary"
|
|
529
|
+
},
|
|
439
530
|
"files upload": {
|
|
440
531
|
command: "files upload",
|
|
441
532
|
accessLevel: "write",
|
|
@@ -576,6 +667,13 @@ var commandRegistry = {
|
|
|
576
667
|
supportsRaw: false,
|
|
577
668
|
output: writeOutput
|
|
578
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
|
+
},
|
|
579
677
|
"schemas delete": {
|
|
580
678
|
command: "schemas delete",
|
|
581
679
|
accessLevel: "destructive",
|
|
@@ -2311,6 +2409,7 @@ var specificExamples = {
|
|
|
2311
2409
|
},
|
|
2312
2410
|
"auditable": true,
|
|
2313
2411
|
"commentable": true,
|
|
2412
|
+
"highlightedField": "c60b8526-5835-4c9f-aecd-9a16c7704a34",
|
|
2314
2413
|
"fields": [
|
|
2315
2414
|
{
|
|
2316
2415
|
"id": "c60b8526-5835-4c9f-aecd-9a16c7704a34",
|
|
@@ -2325,7 +2424,8 @@ var specificExamples = {
|
|
|
2325
2424
|
"conditionalFormatting": []
|
|
2326
2425
|
}
|
|
2327
2426
|
}
|
|
2328
|
-
]
|
|
2427
|
+
],
|
|
2428
|
+
"uniqueFields": []
|
|
2329
2429
|
}`
|
|
2330
2430
|
},
|
|
2331
2431
|
{
|
|
@@ -2341,6 +2441,86 @@ var specificExamples = {
|
|
|
2341
2441
|
command: "zinkee --json schemas update contacts --auditable true",
|
|
2342
2442
|
raw: `{
|
|
2343
2443
|
"auditable": true
|
|
2444
|
+
}`
|
|
2445
|
+
},
|
|
2446
|
+
{
|
|
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).",
|
|
2448
|
+
command: "zinkee --json schemas update contacts --highlighted-field contact-name",
|
|
2449
|
+
raw: `{
|
|
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": []
|
|
2344
2524
|
}`
|
|
2345
2525
|
}
|
|
2346
2526
|
]),
|
|
@@ -2570,7 +2750,7 @@ var specificExamples = {
|
|
|
2570
2750
|
},
|
|
2571
2751
|
{
|
|
2572
2752
|
description: "Filter by status with a free-text search term.",
|
|
2573
|
-
command: `zinkee --json records query contacts --select id,contact-name,status --where "status in OPEN" --
|
|
2753
|
+
command: `zinkee --json records query contacts --select id,contact-name,status --where "status in OPEN" --search garcia --limit 25`,
|
|
2574
2754
|
raw: `{
|
|
2575
2755
|
"select": ["id", "contact-name", "status"],
|
|
2576
2756
|
"where": [
|
|
@@ -2652,35 +2832,78 @@ var specificExamples = {
|
|
|
2652
2832
|
]),
|
|
2653
2833
|
"records create": buildCommandExamples([
|
|
2654
2834
|
{
|
|
2655
|
-
description: "
|
|
2835
|
+
description: "Create a single record with --set/--set-json (the single-record flags build one record, sent as a one-element 'records' array).",
|
|
2656
2836
|
command: `zinkee --json records create contacts --set contact-name="Ada Lovelace" --set contact-email=ada@example.com`,
|
|
2657
2837
|
raw: `{
|
|
2658
|
-
"
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2838
|
+
"records": [
|
|
2839
|
+
{
|
|
2840
|
+
"contact-name": "Ada Lovelace",
|
|
2841
|
+
"contact-email": "ada@example.com"
|
|
2842
|
+
}
|
|
2843
|
+
]
|
|
2662
2844
|
}`,
|
|
2663
2845
|
response: `{
|
|
2664
|
-
"
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
}
|
|
2846
|
+
"created": [
|
|
2847
|
+
"550e8400-e29b-41d4-a716-446655440000"
|
|
2848
|
+
],
|
|
2849
|
+
"errors": []
|
|
2669
2850
|
}`
|
|
2670
2851
|
},
|
|
2671
2852
|
{
|
|
2672
|
-
description: "Create a
|
|
2673
|
-
command: `zinkee --json records create contacts --
|
|
2853
|
+
description: "Create many records from a JSON array file (one object per record, slug -> value). Best-effort: valid records are created and invalid ones are reported per index in 'errors'. ReferenceField values accept the target record id (a bare UUID, or the compound 'recordId::anything' whose label is ignored) or an exact display value; the server stores the canonical 'recordId::displayValue'.",
|
|
2854
|
+
command: `zinkee --json records create contacts --records-file ./records.json`,
|
|
2674
2855
|
raw: `{
|
|
2675
|
-
"
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2856
|
+
"records": [
|
|
2857
|
+
{
|
|
2858
|
+
"contact-name": "Ada Lovelace",
|
|
2859
|
+
"contact-email": "ada@example.com"
|
|
2860
|
+
},
|
|
2861
|
+
{
|
|
2862
|
+
"contact-name": "Grace Hopper",
|
|
2863
|
+
"contact-email": "grace@example.com",
|
|
2864
|
+
"status": 2,
|
|
2865
|
+
"amount": 1999.99,
|
|
2866
|
+
"due-date": "2026-06-01T09:00:00Z",
|
|
2867
|
+
"customer-ref": "8ad602a1-f6e3-43f6-9ab2-f1c5afc99621",
|
|
2868
|
+
"owner": "6c8a3e0d-4e5f-4a1b-9c2d-3e4f5a6b7c8d"
|
|
2869
|
+
}
|
|
2870
|
+
]
|
|
2871
|
+
}`,
|
|
2872
|
+
response: `{
|
|
2873
|
+
"created": [
|
|
2874
|
+
"550e8400-e29b-41d4-a716-446655440000"
|
|
2875
|
+
],
|
|
2876
|
+
"errors": [
|
|
2877
|
+
{
|
|
2878
|
+
"index": 1,
|
|
2879
|
+
"reason": "record_field_not_found",
|
|
2880
|
+
"message": "Field 'contact-emial' was not found in schema '2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e'.",
|
|
2881
|
+
"action": "Use a valid field slug from the schema and retry."
|
|
2882
|
+
}
|
|
2883
|
+
]
|
|
2884
|
+
}`
|
|
2885
|
+
},
|
|
2886
|
+
{
|
|
2887
|
+
description: "Set a ReferenceField by the target record id (a bare UUID, or the compound 'recordId::anything' whose label is ignored) or by an exact display value. The server resolves and stores the canonical 'recordId::displayValue'. Unknown references are rejected per index with reason 'data_field_reference_not_found'.",
|
|
2888
|
+
command: `zinkee --json records create deals --set deal-name="Acme renewal" --set customer-ref=00000000-0000-0000-0000-000000000000`,
|
|
2889
|
+
raw: `{
|
|
2890
|
+
"records": [
|
|
2891
|
+
{
|
|
2892
|
+
"deal-name": "Acme renewal",
|
|
2893
|
+
"customer-ref": "00000000-0000-0000-0000-000000000000"
|
|
2894
|
+
}
|
|
2895
|
+
]
|
|
2896
|
+
}`,
|
|
2897
|
+
response: `{
|
|
2898
|
+
"created": [],
|
|
2899
|
+
"errors": [
|
|
2900
|
+
{
|
|
2901
|
+
"index": 0,
|
|
2902
|
+
"reason": "data_field_reference_not_found",
|
|
2903
|
+
"message": "Referenced record was not found in the target schema.",
|
|
2904
|
+
"action": "Use an existing record id or an existing display value for this reference field."
|
|
2905
|
+
}
|
|
2906
|
+
]
|
|
2684
2907
|
}`
|
|
2685
2908
|
}
|
|
2686
2909
|
]),
|
|
@@ -2722,6 +2945,22 @@ var specificExamples = {
|
|
|
2722
2945
|
command: "zinkee --json records update contacts 550e8400-e29b-41d4-a716-446655440000 --unset contact-email --unset due-date",
|
|
2723
2946
|
raw: `{
|
|
2724
2947
|
"unset": ["contact-email", "due-date"]
|
|
2948
|
+
}`
|
|
2949
|
+
},
|
|
2950
|
+
{
|
|
2951
|
+
description: "Set a ReferenceField on an existing record. Pass the target record id (a bare UUID, or the compound 'recordId::anything' whose label is ignored) or an exact display value; the response shows the canonical 'recordId::displayValue' the server stored. If the reference doesn't exist the whole update is rejected with reason 'data_field_reference_not_found'.",
|
|
2952
|
+
command: "zinkee --json records update deals 550e8400-e29b-41d4-a716-446655440000 --set customer-ref=8ad602a1-f6e3-43f6-9ab2-f1c5afc99621",
|
|
2953
|
+
raw: `{
|
|
2954
|
+
"set": {
|
|
2955
|
+
"customer-ref": "8ad602a1-f6e3-43f6-9ab2-f1c5afc99621"
|
|
2956
|
+
}
|
|
2957
|
+
}`,
|
|
2958
|
+
response: `{
|
|
2959
|
+
"recordId": "550e8400-e29b-41d4-a716-446655440000",
|
|
2960
|
+
"values": {
|
|
2961
|
+
"deal-name": "Acme renewal",
|
|
2962
|
+
"customer-ref": "8ad602a1-f6e3-43f6-9ab2-f1c5afc99621::Acme Corp"
|
|
2963
|
+
}
|
|
2725
2964
|
}`
|
|
2726
2965
|
}
|
|
2727
2966
|
]),
|
|
@@ -2863,11 +3102,10 @@ var specificExamples = {
|
|
|
2863
3102
|
]),
|
|
2864
3103
|
"navigation resources move": buildCommandExamples([
|
|
2865
3104
|
{
|
|
2866
|
-
description: "Move a schema into a navigation folder.",
|
|
2867
|
-
command: "zinkee --json navigation resources move 2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e --
|
|
3105
|
+
description: "Move a schema into a navigation folder. Only schemas can be moved; the navigation menu holds databases.",
|
|
3106
|
+
command: "zinkee --json navigation resources move 2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e --to Sales",
|
|
2868
3107
|
raw: `{
|
|
2869
3108
|
"resourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
|
|
2870
|
-
"resourceType": "SCHEMA",
|
|
2871
3109
|
"targetFolderId": "84a0fca4-37ef-4c83-a8ed-9ef67ad9324a"
|
|
2872
3110
|
}`,
|
|
2873
3111
|
response: `{
|
|
@@ -2876,39 +3114,11 @@ var specificExamples = {
|
|
|
2876
3114
|
}`
|
|
2877
3115
|
},
|
|
2878
3116
|
{
|
|
2879
|
-
description: "Move a
|
|
2880
|
-
command: "zinkee --json navigation resources move
|
|
2881
|
-
raw: `{
|
|
2882
|
-
"resourceId": "3f8a2c1b-9d4e-4a5b-8c6d-7e8f90123456",
|
|
2883
|
-
"resourceType": "WORKFLOW",
|
|
2884
|
-
"targetFolderId": "b8c9d0e1-f2a3-4b5c-6d7e-8f9012345678"
|
|
2885
|
-
}`
|
|
2886
|
-
},
|
|
2887
|
-
{
|
|
2888
|
-
description: "Move a display.",
|
|
2889
|
-
command: "zinkee --json navigation resources move 0f6f062f-1478-4df2-96a1-c495d037d260 --type DISPLAY --to Operations",
|
|
2890
|
-
raw: `{
|
|
2891
|
-
"resourceId": "0f6f062f-1478-4df2-96a1-c495d037d260",
|
|
2892
|
-
"resourceType": "DISPLAY",
|
|
2893
|
-
"targetFolderId": "b8c9d0e1-f2a3-4b5c-6d7e-8f9012345678"
|
|
2894
|
-
}`
|
|
2895
|
-
},
|
|
2896
|
-
{
|
|
2897
|
-
description: "Move a resource back to the root folder (root is always UUID 00000000-0000-0000-0000-000000000000).",
|
|
2898
|
-
command: "zinkee --json navigation resources move 5223cbc8-8c6c-4694-93bc-dd176364df9b --type SCHEMA --to 00000000-0000-0000-0000-000000000000",
|
|
3117
|
+
description: "Move a schema back to the root folder (root is always UUID 00000000-0000-0000-0000-000000000000).",
|
|
3118
|
+
command: "zinkee --json navigation resources move 5223cbc8-8c6c-4694-93bc-dd176364df9b --to 00000000-0000-0000-0000-000000000000",
|
|
2899
3119
|
raw: `{
|
|
2900
3120
|
"resourceId": "5223cbc8-8c6c-4694-93bc-dd176364df9b",
|
|
2901
|
-
"resourceType": "SCHEMA",
|
|
2902
3121
|
"targetFolderId": "00000000-0000-0000-0000-000000000000"
|
|
2903
|
-
}`
|
|
2904
|
-
},
|
|
2905
|
-
{
|
|
2906
|
-
description: "Move a schedule resource.",
|
|
2907
|
-
command: "zinkee --json navigation resources move a1b2c3d4-e5f6-7890-1234-567890abcdef --type SCHEDULE --to Operations",
|
|
2908
|
-
raw: `{
|
|
2909
|
-
"resourceId": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
|
|
2910
|
-
"resourceType": "SCHEDULE",
|
|
2911
|
-
"targetFolderId": "b8c9d0e1-f2a3-4b5c-6d7e-8f9012345678"
|
|
2912
3122
|
}`
|
|
2913
3123
|
}
|
|
2914
3124
|
]),
|
|
@@ -3306,12 +3516,12 @@ var specificExamples = {
|
|
|
3306
3516
|
}`
|
|
3307
3517
|
},
|
|
3308
3518
|
{
|
|
3309
|
-
description: "Change a DATE variable to use
|
|
3310
|
-
command: "zinkee --json displays variables update 0f6f062f-1478-4df2-96a1-c495d037d260 bbbbbbbb-2222-4222-a222-222222222222 --date-mode dynamic --date-dynamic-option
|
|
3519
|
+
description: "Change a DATE variable to use last12Months.",
|
|
3520
|
+
command: "zinkee --json displays variables update 0f6f062f-1478-4df2-96a1-c495d037d260 bbbbbbbb-2222-4222-a222-222222222222 --date-mode dynamic --date-dynamic-option last12Months",
|
|
3311
3521
|
raw: `{
|
|
3312
3522
|
"date": {
|
|
3313
3523
|
"mode": "dynamic",
|
|
3314
|
-
"dynamicOption": "
|
|
3524
|
+
"dynamicOption": "last12Months"
|
|
3315
3525
|
}
|
|
3316
3526
|
}`
|
|
3317
3527
|
}
|
|
@@ -3319,7 +3529,7 @@ var specificExamples = {
|
|
|
3319
3529
|
"displays widgets create": buildCommandExamples([
|
|
3320
3530
|
{
|
|
3321
3531
|
description: "Create a TABLE widget (CLI normalises --type table to TABLE_OR_SUBTABLE).",
|
|
3322
|
-
command: `zinkee --json displays widgets create 0f6f062f-1478-4df2-96a1-c495d037d260 --type table --name Customers --origin-resource 2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e --layout '{"x":0,"y":0,"w":12,"h":8}' --field
|
|
3532
|
+
command: `zinkee --json displays widgets create 0f6f062f-1478-4df2-96a1-c495d037d260 --type table --name Customers --origin-resource 2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e --layout '{"x":0,"y":0,"w":12,"h":8}' --field contact-name --field status --field amount --sort '{"fieldId":"contact-name","direction":"ASC"}'`,
|
|
3323
3533
|
raw: `{
|
|
3324
3534
|
"type": "TABLE_OR_SUBTABLE",
|
|
3325
3535
|
"source": {
|
|
@@ -3334,11 +3544,11 @@ var specificExamples = {
|
|
|
3334
3544
|
},
|
|
3335
3545
|
"query": {
|
|
3336
3546
|
"sorts": [
|
|
3337
|
-
{ "fieldId": "
|
|
3547
|
+
{ "fieldId": "contact-name", "direction": "ASC" }
|
|
3338
3548
|
]
|
|
3339
3549
|
},
|
|
3340
3550
|
"view": {
|
|
3341
|
-
"fields": ["
|
|
3551
|
+
"fields": ["contact-name", "status", "amount"]
|
|
3342
3552
|
}
|
|
3343
3553
|
}`,
|
|
3344
3554
|
response: `{
|
|
@@ -3387,8 +3597,8 @@ var specificExamples = {
|
|
|
3387
3597
|
}`
|
|
3388
3598
|
},
|
|
3389
3599
|
{
|
|
3390
|
-
description: "Create a
|
|
3391
|
-
command: `zinkee --json displays widgets create 0f6f062f-1478-4df2-96a1-c495d037d260 --type CHART --name "Revenue by
|
|
3600
|
+
description: "Create a CHART widget with a daily time-serie x-axis.",
|
|
3601
|
+
command: `zinkee --json displays widgets create 0f6f062f-1478-4df2-96a1-c495d037d260 --type CHART --name "Revenue by day" --origin-resource 2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e --layout '{"x":0,"y":0,"w":8,"h":6}' --chart-type lines --x-axis-field due-date --x-axis-date-format DATE --x-axis-time-series --y-axis-serie '{"typeCalc":"SUM","fieldCalc":"amount","color":"#4B9CD3","axisType":"PRIMARY"}' --legend '{"position":"bottom"}'`,
|
|
3392
3602
|
raw: `{
|
|
3393
3603
|
"type": "CHART",
|
|
3394
3604
|
"source": {
|
|
@@ -3398,11 +3608,11 @@ var specificExamples = {
|
|
|
3398
3608
|
"placement": {
|
|
3399
3609
|
"layout": { "x": 0, "y": 0, "w": 8, "h": 6 }
|
|
3400
3610
|
},
|
|
3401
|
-
"presentation": { "name": "Revenue by
|
|
3611
|
+
"presentation": { "name": "Revenue by day" },
|
|
3402
3612
|
"chart": {
|
|
3403
|
-
"chartType": "
|
|
3613
|
+
"chartType": "lines",
|
|
3404
3614
|
"xAxisFieldId": "due-date",
|
|
3405
|
-
"xAxisDateFormat": "
|
|
3615
|
+
"xAxisDateFormat": "DATE",
|
|
3406
3616
|
"xAxisAsTimeSerie": true,
|
|
3407
3617
|
"yAxisSeries": [
|
|
3408
3618
|
{
|
|
@@ -3410,12 +3620,6 @@ var specificExamples = {
|
|
|
3410
3620
|
"fieldCalc": "amount",
|
|
3411
3621
|
"color": "#4B9CD3",
|
|
3412
3622
|
"axisType": "PRIMARY"
|
|
3413
|
-
},
|
|
3414
|
-
{
|
|
3415
|
-
"typeCalc": "COUNT",
|
|
3416
|
-
"fieldCalc": "id",
|
|
3417
|
-
"color": "#E57373",
|
|
3418
|
-
"axisType": "SECONDARY"
|
|
3419
3623
|
}
|
|
3420
3624
|
],
|
|
3421
3625
|
"legend": { "position": "bottom" }
|
|
@@ -3423,71 +3627,246 @@ var specificExamples = {
|
|
|
3423
3627
|
}`
|
|
3424
3628
|
},
|
|
3425
3629
|
{
|
|
3426
|
-
description: "Create a
|
|
3427
|
-
command: `zinkee --json displays widgets create 0f6f062f-1478-4df2-96a1-c495d037d260 --type
|
|
3630
|
+
description: "Create a bars CHART widget with a monthly time-serie x-axis and two y-axis series.",
|
|
3631
|
+
command: `zinkee --json displays widgets create 0f6f062f-1478-4df2-96a1-c495d037d260 --type CHART --name "Revenue by month" --origin-resource 2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e --layout '{"x":0,"y":0,"w":8,"h":6}' --chart-type bars --x-axis-field due-date --x-axis-date-format MONTH_YEAR --x-axis-time-series --y-axis-serie '{"typeCalc":"SUM","fieldCalc":"amount","color":"#4B9CD3","axisType":"PRIMARY"}' --y-axis-serie '{"typeCalc":"COUNT","fieldCalc":"contact-name","color":"#E57373","axisType":"SECONDARY"}' --legend '{"position":"bottom"}'`,
|
|
3428
3632
|
raw: `{
|
|
3429
|
-
"type": "
|
|
3633
|
+
"type": "CHART",
|
|
3430
3634
|
"source": {
|
|
3431
3635
|
"originResourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
|
|
3432
3636
|
"isOriginSubSchema": false
|
|
3433
3637
|
},
|
|
3434
3638
|
"placement": {
|
|
3435
|
-
"layout": { "x": 0, "y": 0, "w":
|
|
3639
|
+
"layout": { "x": 0, "y": 0, "w": 8, "h": 6 }
|
|
3436
3640
|
},
|
|
3437
|
-
"presentation": { "name": "
|
|
3438
|
-
"
|
|
3439
|
-
"
|
|
3641
|
+
"presentation": { "name": "Revenue by month" },
|
|
3642
|
+
"chart": {
|
|
3643
|
+
"chartType": "bars",
|
|
3644
|
+
"xAxisFieldId": "due-date",
|
|
3645
|
+
"xAxisDateFormat": "MONTH_YEAR",
|
|
3646
|
+
"xAxisAsTimeSerie": true,
|
|
3647
|
+
"yAxisSeries": [
|
|
3648
|
+
{
|
|
3649
|
+
"typeCalc": "SUM",
|
|
3650
|
+
"fieldCalc": "amount",
|
|
3651
|
+
"color": "#4B9CD3",
|
|
3652
|
+
"axisType": "PRIMARY"
|
|
3653
|
+
},
|
|
3654
|
+
{
|
|
3655
|
+
"typeCalc": "COUNT",
|
|
3656
|
+
"fieldCalc": "contact-name",
|
|
3657
|
+
"color": "#E57373",
|
|
3658
|
+
"axisType": "SECONDARY"
|
|
3659
|
+
}
|
|
3660
|
+
],
|
|
3661
|
+
"legend": { "position": "bottom" }
|
|
3440
3662
|
}
|
|
3441
3663
|
}`
|
|
3442
3664
|
},
|
|
3443
3665
|
{
|
|
3444
|
-
description: "Create a
|
|
3445
|
-
command: `zinkee --json displays widgets create 0f6f062f-1478-4df2-96a1-c495d037d260 --
|
|
3666
|
+
description: "Create a bars CHART widget with a quarterly time-serie x-axis.",
|
|
3667
|
+
command: `zinkee --json displays widgets create 0f6f062f-1478-4df2-96a1-c495d037d260 --type CHART --name "Revenue by quarter" --origin-resource 2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e --layout '{"x":0,"y":0,"w":8,"h":6}' --chart-type bars --x-axis-field due-date --x-axis-date-format QUARTER_YEAR --x-axis-time-series --y-axis-serie '{"typeCalc":"SUM","fieldCalc":"amount","color":"#4B9CD3","axisType":"PRIMARY"}' --legend '{"position":"bottom"}'`,
|
|
3446
3668
|
raw: `{
|
|
3447
|
-
"type": "
|
|
3669
|
+
"type": "CHART",
|
|
3448
3670
|
"source": {
|
|
3449
3671
|
"originResourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
|
|
3450
3672
|
"isOriginSubSchema": false
|
|
3451
3673
|
},
|
|
3452
3674
|
"placement": {
|
|
3453
|
-
"layout": { "x": 0, "y": 0, "w":
|
|
3675
|
+
"layout": { "x": 0, "y": 0, "w": 8, "h": 6 }
|
|
3454
3676
|
},
|
|
3455
|
-
"presentation": { "name": "
|
|
3456
|
-
"
|
|
3457
|
-
"
|
|
3677
|
+
"presentation": { "name": "Revenue by quarter" },
|
|
3678
|
+
"chart": {
|
|
3679
|
+
"chartType": "bars",
|
|
3680
|
+
"xAxisFieldId": "due-date",
|
|
3681
|
+
"xAxisDateFormat": "QUARTER_YEAR",
|
|
3682
|
+
"xAxisAsTimeSerie": true,
|
|
3683
|
+
"yAxisSeries": [
|
|
3458
3684
|
{
|
|
3459
|
-
"
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
"comparisonOperator": "ANY_OF",
|
|
3464
|
-
"values": ["1", "2", "3"]
|
|
3685
|
+
"typeCalc": "SUM",
|
|
3686
|
+
"fieldCalc": "amount",
|
|
3687
|
+
"color": "#4B9CD3",
|
|
3688
|
+
"axisType": "PRIMARY"
|
|
3465
3689
|
}
|
|
3466
|
-
]
|
|
3467
|
-
|
|
3468
|
-
"view": {
|
|
3469
|
-
"fields": ["contact-name", "status", "amount"],
|
|
3470
|
-
"groupsExpanded": { "1": true, "2": true, "3": false }
|
|
3690
|
+
],
|
|
3691
|
+
"legend": { "position": "bottom" }
|
|
3471
3692
|
}
|
|
3472
3693
|
}`
|
|
3473
3694
|
},
|
|
3474
3695
|
{
|
|
3475
|
-
description: "Create a
|
|
3476
|
-
command: `zinkee --json displays widgets create 0f6f062f-1478-4df2-96a1-c495d037d260 --
|
|
3696
|
+
description: "Create a CHART widget with a yearly time-serie x-axis.",
|
|
3697
|
+
command: `zinkee --json displays widgets create 0f6f062f-1478-4df2-96a1-c495d037d260 --type CHART --name "Revenue by year" --origin-resource 2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e --layout '{"x":0,"y":0,"w":8,"h":6}' --chart-type lines --x-axis-field due-date --x-axis-date-format YEAR --x-axis-time-series --y-axis-serie '{"typeCalc":"SUM","fieldCalc":"amount","color":"#4B9CD3","axisType":"PRIMARY"}' --legend '{"position":"bottom"}'`,
|
|
3477
3698
|
raw: `{
|
|
3478
|
-
"type": "
|
|
3699
|
+
"type": "CHART",
|
|
3479
3700
|
"source": {
|
|
3480
3701
|
"originResourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
|
|
3481
3702
|
"isOriginSubSchema": false
|
|
3482
3703
|
},
|
|
3483
3704
|
"placement": {
|
|
3484
|
-
"layout": { "x": 0, "y": 0, "w":
|
|
3705
|
+
"layout": { "x": 0, "y": 0, "w": 8, "h": 6 }
|
|
3706
|
+
},
|
|
3707
|
+
"presentation": { "name": "Revenue by year" },
|
|
3708
|
+
"chart": {
|
|
3709
|
+
"chartType": "lines",
|
|
3710
|
+
"xAxisFieldId": "due-date",
|
|
3711
|
+
"xAxisDateFormat": "YEAR",
|
|
3712
|
+
"xAxisAsTimeSerie": true,
|
|
3713
|
+
"yAxisSeries": [
|
|
3714
|
+
{
|
|
3715
|
+
"typeCalc": "SUM",
|
|
3716
|
+
"fieldCalc": "amount",
|
|
3717
|
+
"color": "#4B9CD3",
|
|
3718
|
+
"axisType": "PRIMARY"
|
|
3719
|
+
}
|
|
3720
|
+
],
|
|
3721
|
+
"legend": { "position": "bottom" }
|
|
3722
|
+
}
|
|
3723
|
+
}`
|
|
3724
|
+
},
|
|
3725
|
+
{
|
|
3726
|
+
description: "Create a TIMELINE widget via flags. The typed view state lives in view.viewAdditionalProperties.viewState; field references there must be UUIDs (slugs are only resolved in --field). cardConfig uses category1/category2/category4 (no category3). Use --view-state for UI scalars (granularity, sidebarWidth, show* ...).",
|
|
3727
|
+
command: `zinkee --json displays widgets create 0f6f062f-1478-4df2-96a1-c495d037d260 --type TIMELINE --name "Customer schedule" --origin-resource 2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e --layout '{"x":0,"y":0,"w":12,"h":6}' --field c60b8526-5835-4c9f-aecd-9a16c7704a34 --field a8f1d7e3-2b5c-4d9e-8a1b-3c4d5e6f7890 --field c52efe3f-2825-4c60-a7e3-34dd4c1ce043 --field d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90 --start-date-field d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90 --end-date-field e5f6a7b8-c9d0-1e2f-3a4b-5c6d7e8f9012 --label-field c60b8526-5835-4c9f-aecd-9a16c7704a34 --group-field a8f1d7e3-2b5c-4d9e-8a1b-3c4d5e6f7890 --subgroup-field c60b8526-5835-4c9f-aecd-9a16c7704a34 --progress-field c52efe3f-2825-4c60-a7e3-34dd4c1ce043 --card-title-field c60b8526-5835-4c9f-aecd-9a16c7704a34 --card-category1-field a8f1d7e3-2b5c-4d9e-8a1b-3c4d5e6f7890 --card-category2-field d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90 --card-category4-field c52efe3f-2825-4c60-a7e3-34dd4c1ce043 --card-description-field c60b8526-5835-4c9f-aecd-9a16c7704a34 --view-state '{"granularity":"month","sidebarWidth":300,"showUngroupedEvents":true,"showUnsubgroupedEvents":true}'`,
|
|
3728
|
+
raw: `{
|
|
3729
|
+
"type": "TIMELINE",
|
|
3730
|
+
"source": {
|
|
3731
|
+
"originResourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
|
|
3732
|
+
"isOriginSubSchema": false
|
|
3733
|
+
},
|
|
3734
|
+
"placement": {
|
|
3735
|
+
"layout": { "x": 0, "y": 0, "w": 12, "h": 6 }
|
|
3736
|
+
},
|
|
3737
|
+
"presentation": { "name": "Customer schedule" },
|
|
3738
|
+
"view": {
|
|
3739
|
+
"fields": [
|
|
3740
|
+
"c60b8526-5835-4c9f-aecd-9a16c7704a34",
|
|
3741
|
+
"a8f1d7e3-2b5c-4d9e-8a1b-3c4d5e6f7890",
|
|
3742
|
+
"c52efe3f-2825-4c60-a7e3-34dd4c1ce043",
|
|
3743
|
+
"d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90"
|
|
3744
|
+
],
|
|
3745
|
+
"viewAdditionalProperties": {
|
|
3746
|
+
"viewState": {
|
|
3747
|
+
"granularity": "month",
|
|
3748
|
+
"sidebarWidth": 300,
|
|
3749
|
+
"showUngroupedEvents": true,
|
|
3750
|
+
"showUnsubgroupedEvents": true,
|
|
3751
|
+
"fieldMapping": {
|
|
3752
|
+
"startDateField": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
|
|
3753
|
+
"endDateField": "e5f6a7b8-c9d0-1e2f-3a4b-5c6d7e8f9012",
|
|
3754
|
+
"labelField": "c60b8526-5835-4c9f-aecd-9a16c7704a34",
|
|
3755
|
+
"groupField": "a8f1d7e3-2b5c-4d9e-8a1b-3c4d5e6f7890",
|
|
3756
|
+
"subgroupField": "c60b8526-5835-4c9f-aecd-9a16c7704a34",
|
|
3757
|
+
"progressField": "c52efe3f-2825-4c60-a7e3-34dd4c1ce043",
|
|
3758
|
+
"cardConfig": {
|
|
3759
|
+
"titleField": "c60b8526-5835-4c9f-aecd-9a16c7704a34",
|
|
3760
|
+
"category1Field": "a8f1d7e3-2b5c-4d9e-8a1b-3c4d5e6f7890",
|
|
3761
|
+
"category2Field": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
|
|
3762
|
+
"category4Field": "c52efe3f-2825-4c60-a7e3-34dd4c1ce043",
|
|
3763
|
+
"descriptionField": "c60b8526-5835-4c9f-aecd-9a16c7704a34"
|
|
3764
|
+
}
|
|
3765
|
+
}
|
|
3766
|
+
}
|
|
3767
|
+
}
|
|
3768
|
+
}
|
|
3769
|
+
}`
|
|
3770
|
+
},
|
|
3771
|
+
{
|
|
3772
|
+
description: "Create a KANBAN widget via flags. The typed view state lives in view.viewAdditionalProperties.viewState; field references there must be UUIDs (slugs are only resolved in --field). cardConfig uses category1/category2/category3 (no category4). --aggregation-method/--aggregation-field set the card aggregation; use --view-state for UI scalars.",
|
|
3773
|
+
command: `zinkee --json displays widgets create 0f6f062f-1478-4df2-96a1-c495d037d260 --type KANBAN --name "Status board" --origin-resource 2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e --layout '{"x":0,"y":0,"w":12,"h":8}' --field c60b8526-5835-4c9f-aecd-9a16c7704a34 --field a8f1d7e3-2b5c-4d9e-8a1b-3c4d5e6f7890 --field c52efe3f-2825-4c60-a7e3-34dd4c1ce043 --field d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90 --column-field a8f1d7e3-2b5c-4d9e-8a1b-3c4d5e6f7890 --swimlane-field c60b8526-5835-4c9f-aecd-9a16c7704a34 --card-title-field c60b8526-5835-4c9f-aecd-9a16c7704a34 --card-category1-field a8f1d7e3-2b5c-4d9e-8a1b-3c4d5e6f7890 --card-category2-field d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90 --card-category3-field c52efe3f-2825-4c60-a7e3-34dd4c1ce043 --card-description-field c60b8526-5835-4c9f-aecd-9a16c7704a34 --aggregation-method sum --aggregation-field c52efe3f-2825-4c60-a7e3-34dd4c1ce043 --view-state '{"hideEmptyColumns":false,"showNoValueColumn":true,"showNoValueSwimlane":true}'`,
|
|
3774
|
+
raw: `{
|
|
3775
|
+
"type": "KANBAN",
|
|
3776
|
+
"source": {
|
|
3777
|
+
"originResourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
|
|
3778
|
+
"isOriginSubSchema": false
|
|
3779
|
+
},
|
|
3780
|
+
"placement": {
|
|
3781
|
+
"layout": { "x": 0, "y": 0, "w": 12, "h": 8 }
|
|
3782
|
+
},
|
|
3783
|
+
"presentation": { "name": "Status board" },
|
|
3784
|
+
"view": {
|
|
3785
|
+
"fields": [
|
|
3786
|
+
"c60b8526-5835-4c9f-aecd-9a16c7704a34",
|
|
3787
|
+
"a8f1d7e3-2b5c-4d9e-8a1b-3c4d5e6f7890",
|
|
3788
|
+
"c52efe3f-2825-4c60-a7e3-34dd4c1ce043",
|
|
3789
|
+
"d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90"
|
|
3790
|
+
],
|
|
3791
|
+
"viewAdditionalProperties": {
|
|
3792
|
+
"viewState": {
|
|
3793
|
+
"hideEmptyColumns": false,
|
|
3794
|
+
"showNoValueColumn": true,
|
|
3795
|
+
"showNoValueSwimlane": true,
|
|
3796
|
+
"fieldMapping": {
|
|
3797
|
+
"columnField": "a8f1d7e3-2b5c-4d9e-8a1b-3c4d5e6f7890",
|
|
3798
|
+
"swimlaneField": "c60b8526-5835-4c9f-aecd-9a16c7704a34",
|
|
3799
|
+
"cardConfig": {
|
|
3800
|
+
"titleField": "c60b8526-5835-4c9f-aecd-9a16c7704a34",
|
|
3801
|
+
"category1Field": "a8f1d7e3-2b5c-4d9e-8a1b-3c4d5e6f7890",
|
|
3802
|
+
"category2Field": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
|
|
3803
|
+
"category3Field": "c52efe3f-2825-4c60-a7e3-34dd4c1ce043",
|
|
3804
|
+
"descriptionField": "c60b8526-5835-4c9f-aecd-9a16c7704a34"
|
|
3805
|
+
},
|
|
3806
|
+
"aggregationConfig": {
|
|
3807
|
+
"method": "sum",
|
|
3808
|
+
"fieldId": "c52efe3f-2825-4c60-a7e3-34dd4c1ce043"
|
|
3809
|
+
}
|
|
3810
|
+
}
|
|
3811
|
+
}
|
|
3812
|
+
}
|
|
3813
|
+
}
|
|
3814
|
+
}`
|
|
3815
|
+
},
|
|
3816
|
+
{
|
|
3817
|
+
description: "Create a HIERARCHY widget via flags. Declare columns once (--hierarchy-label, repeatable --hierarchy-info <id:name>, --hierarchy-number <id:name:aggregation>), map the root level (the view's own table) with --hierarchy-root-* and add each child level as a JSON object with --hierarchy-child. label is required per level; info/number mappings are optional. Column ids (e.g. col_1779975207355_zfndknslw) are unique opaque identifiers you choose \u2014 not the column name \u2014 and are reused as columnId in every mapping. All field references must be UUIDs.",
|
|
3818
|
+
command: `zinkee --json displays widgets create 0f6f062f-1478-4df2-96a1-c495d037d260 --type HIERARCHY --name "Org tree" --origin-resource 2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e --layout '{"x":0,"y":0,"w":12,"h":6}' --field c60b8526-5835-4c9f-aecd-9a16c7704a34 --field a8f1d7e3-2b5c-4d9e-8a1b-3c4d5e6f7890 --field c52efe3f-2825-4c60-a7e3-34dd4c1ce043 --hierarchy-label "Name" --hierarchy-info "col_1779975207355_zfndknslw:Status" --hierarchy-info "col_1779975243018_qm4t7xb2pa:Description" --hierarchy-number "col_1779975261490_h8kd3nv9ws:Total amount:SUM" --hierarchy-root-name "Customers" --hierarchy-root-label-field c60b8526-5835-4c9f-aecd-9a16c7704a34 --hierarchy-root-info "col_1779975207355_zfndknslw:a8f1d7e3-2b5c-4d9e-8a1b-3c4d5e6f7890" --hierarchy-root-number "col_1779975261490_h8kd3nv9ws:c52efe3f-2825-4c60-a7e3-34dd4c1ce043" --hierarchy-child '{"name":"Projects","schemaId":"3ec9cdef-7e0a-4cdd-8019-8fb9281f5d6f","childFieldId":"80deefae-af3d-4000-b322-bfe1594f8073","labelFieldId":"50dbef0b-7e0a-4fdd-8019-8fb9281f5d70","infoMappings":[{"columnId":"col_1779975243018_qm4t7xb2pa","fieldId":"60dcef0c-8f1b-4eee-9120-9fc0392f6e71"}],"numberMappings":[{"columnId":"col_1779975261490_h8kd3nv9ws","fieldId":"70ddef0d-9f2c-4fff-a221-afd0493f7f72"}]}'`,
|
|
3819
|
+
raw: `{
|
|
3820
|
+
"type": "HIERARCHY",
|
|
3821
|
+
"source": {
|
|
3822
|
+
"originResourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
|
|
3823
|
+
"isOriginSubSchema": false
|
|
3824
|
+
},
|
|
3825
|
+
"placement": {
|
|
3826
|
+
"layout": { "x": 0, "y": 0, "w": 12, "h": 6 }
|
|
3485
3827
|
},
|
|
3486
3828
|
"presentation": { "name": "Org tree" },
|
|
3487
3829
|
"view": {
|
|
3488
|
-
"fields": [
|
|
3830
|
+
"fields": [
|
|
3831
|
+
"c60b8526-5835-4c9f-aecd-9a16c7704a34",
|
|
3832
|
+
"a8f1d7e3-2b5c-4d9e-8a1b-3c4d5e6f7890",
|
|
3833
|
+
"c52efe3f-2825-4c60-a7e3-34dd4c1ce043"
|
|
3834
|
+
],
|
|
3489
3835
|
"hierarchyConfig": {
|
|
3490
|
-
"
|
|
3836
|
+
"columns": {
|
|
3837
|
+
"label": "Name",
|
|
3838
|
+
"infos": [
|
|
3839
|
+
{ "id": "col_1779975207355_zfndknslw", "name": "Status" },
|
|
3840
|
+
{ "id": "col_1779975243018_qm4t7xb2pa", "name": "Description" }
|
|
3841
|
+
],
|
|
3842
|
+
"numbers": [
|
|
3843
|
+
{ "id": "col_1779975261490_h8kd3nv9ws", "name": "Total amount", "aggregation": "SUM" }
|
|
3844
|
+
]
|
|
3845
|
+
},
|
|
3846
|
+
"rootLevel": {
|
|
3847
|
+
"name": "Customers",
|
|
3848
|
+
"labelFieldId": "c60b8526-5835-4c9f-aecd-9a16c7704a34",
|
|
3849
|
+
"infoMappings": [
|
|
3850
|
+
{ "columnId": "col_1779975207355_zfndknslw", "fieldId": "a8f1d7e3-2b5c-4d9e-8a1b-3c4d5e6f7890" }
|
|
3851
|
+
],
|
|
3852
|
+
"numberMappings": [
|
|
3853
|
+
{ "columnId": "col_1779975261490_h8kd3nv9ws", "fieldId": "c52efe3f-2825-4c60-a7e3-34dd4c1ce043" }
|
|
3854
|
+
]
|
|
3855
|
+
},
|
|
3856
|
+
"childLevels": [
|
|
3857
|
+
{
|
|
3858
|
+
"name": "Projects",
|
|
3859
|
+
"schemaId": "3ec9cdef-7e0a-4cdd-8019-8fb9281f5d6f",
|
|
3860
|
+
"childFieldId": "80deefae-af3d-4000-b322-bfe1594f8073",
|
|
3861
|
+
"labelFieldId": "50dbef0b-7e0a-4fdd-8019-8fb9281f5d70",
|
|
3862
|
+
"infoMappings": [
|
|
3863
|
+
{ "columnId": "col_1779975243018_qm4t7xb2pa", "fieldId": "60dcef0c-8f1b-4eee-9120-9fc0392f6e71" }
|
|
3864
|
+
],
|
|
3865
|
+
"numberMappings": [
|
|
3866
|
+
{ "columnId": "col_1779975261490_h8kd3nv9ws", "fieldId": "70ddef0d-9f2c-4fff-a221-afd0493f7f72" }
|
|
3867
|
+
]
|
|
3868
|
+
}
|
|
3869
|
+
]
|
|
3491
3870
|
}
|
|
3492
3871
|
}
|
|
3493
3872
|
}`
|
|
@@ -3496,13 +3875,13 @@ var specificExamples = {
|
|
|
3496
3875
|
"displays widgets update": buildCommandExamples([
|
|
3497
3876
|
{
|
|
3498
3877
|
description: "Move placement, update view columns, rename the widget and lock it.",
|
|
3499
|
-
command: `zinkee --json displays widgets update 0f6f062f-1478-4df2-96a1-c495d037d260 11111111-1111-4111-a111-111111111111 --layout '{"x":1,"y":2,"w":8,"h":4}' --field
|
|
3878
|
+
command: `zinkee --json displays widgets update 0f6f062f-1478-4df2-96a1-c495d037d260 11111111-1111-4111-a111-111111111111 --layout '{"x":1,"y":2,"w":8,"h":4}' --field contact-name --field status --field amount --name "Revenue Updated" --widget-read-only`,
|
|
3500
3879
|
raw: `{
|
|
3501
3880
|
"placement": {
|
|
3502
3881
|
"layout": { "x": 1, "y": 2, "w": 8, "h": 4 }
|
|
3503
3882
|
},
|
|
3504
3883
|
"view": {
|
|
3505
|
-
"fields": ["
|
|
3884
|
+
"fields": ["contact-name", "status", "amount"]
|
|
3506
3885
|
},
|
|
3507
3886
|
"presentation": { "name": "Revenue Updated" },
|
|
3508
3887
|
"behavior": { "readOnly": true }
|
|
@@ -3513,29 +3892,38 @@ var specificExamples = {
|
|
|
3513
3892
|
}`
|
|
3514
3893
|
},
|
|
3515
3894
|
{
|
|
3516
|
-
description: "Add query filters
|
|
3517
|
-
command: `zinkee --json displays widgets update 0f6f062f-1478-4df2-96a1-c495d037d260 11111111-1111-4111-a111-111111111111 --
|
|
3895
|
+
description: "Add query filters with --filter. The CLI parses the expression and emits the structured comparisonOperator payload the API expects.",
|
|
3896
|
+
command: `zinkee --json displays widgets update 0f6f062f-1478-4df2-96a1-c495d037d260 11111111-1111-4111-a111-111111111111 --filter "status:eq:2" --filter "amount:gte:500"`,
|
|
3518
3897
|
raw: `{
|
|
3519
3898
|
"query": {
|
|
3520
3899
|
"filters": [
|
|
3521
3900
|
{
|
|
3522
|
-
"origin": {
|
|
3523
|
-
"schemaId": "contacts",
|
|
3524
|
-
"fieldId": "status"
|
|
3525
|
-
},
|
|
3901
|
+
"origin": { "fieldId": "status" },
|
|
3526
3902
|
"comparisonOperator": "EQUAL",
|
|
3527
3903
|
"values": ["2"]
|
|
3528
3904
|
},
|
|
3529
3905
|
{
|
|
3530
|
-
"origin": {
|
|
3531
|
-
"schemaId": "contacts",
|
|
3532
|
-
"fieldId": "amount"
|
|
3533
|
-
},
|
|
3906
|
+
"origin": { "fieldId": "amount" },
|
|
3534
3907
|
"comparisonOperator": "GREATER_OR_EQUAL",
|
|
3535
3908
|
"values": ["500"]
|
|
3536
3909
|
}
|
|
3537
3910
|
]
|
|
3538
3911
|
}
|
|
3912
|
+
}`
|
|
3913
|
+
},
|
|
3914
|
+
{
|
|
3915
|
+
description: "Fall back to --raw for comparators the parser does not cover yet (e.g. NOT_CONTAINS, RANGE).",
|
|
3916
|
+
command: `zinkee --json displays widgets update 0f6f062f-1478-4df2-96a1-c495d037d260 11111111-1111-4111-a111-111111111111 --raw '{"query":{"filters":[{"origin":{"fieldId":"due-date"},"comparisonOperator":"RANGE","values":["2025-01-01","2025-12-31"]}]}}'`,
|
|
3917
|
+
raw: `{
|
|
3918
|
+
"query": {
|
|
3919
|
+
"filters": [
|
|
3920
|
+
{
|
|
3921
|
+
"origin": { "fieldId": "due-date" },
|
|
3922
|
+
"comparisonOperator": "RANGE",
|
|
3923
|
+
"values": ["2025-01-01", "2025-12-31"]
|
|
3924
|
+
}
|
|
3925
|
+
]
|
|
3926
|
+
}
|
|
3539
3927
|
}`
|
|
3540
3928
|
},
|
|
3541
3929
|
{
|
|
@@ -3561,13 +3949,13 @@ var specificExamples = {
|
|
|
3561
3949
|
}`
|
|
3562
3950
|
},
|
|
3563
3951
|
{
|
|
3564
|
-
description: "Replace the chart series with
|
|
3565
|
-
command: `zinkee --json displays widgets update 0f6f062f-1478-4df2-96a1-c495d037d260 22222222-2222-4222-a222-222222222222 --chart-type lines --x-axis-field due-date --x-axis-date-format
|
|
3952
|
+
description: "Replace the chart series with quarterly lines.",
|
|
3953
|
+
command: `zinkee --json displays widgets update 0f6f062f-1478-4df2-96a1-c495d037d260 22222222-2222-4222-a222-222222222222 --chart-type lines --x-axis-field due-date --x-axis-date-format QUARTER_YEAR --x-axis-time-series --y-axis-serie '{"typeCalc":"SUM","fieldCalc":"amount","color":"#2E7D32","axisType":"PRIMARY"}'`,
|
|
3566
3954
|
raw: `{
|
|
3567
3955
|
"chart": {
|
|
3568
3956
|
"chartType": "lines",
|
|
3569
3957
|
"xAxisFieldId": "due-date",
|
|
3570
|
-
"xAxisDateFormat": "
|
|
3958
|
+
"xAxisDateFormat": "QUARTER_YEAR",
|
|
3571
3959
|
"xAxisAsTimeSerie": true,
|
|
3572
3960
|
"yAxisSeries": [
|
|
3573
3961
|
{
|
|
@@ -3733,6 +4121,7 @@ var specificExamples = {
|
|
|
3733
4121
|
},
|
|
3734
4122
|
"auditable": true,
|
|
3735
4123
|
"commentable": true,
|
|
4124
|
+
"highlightedField": "c60b8526-5835-4c9f-aecd-9a16c7704a34",
|
|
3736
4125
|
"fields": [
|
|
3737
4126
|
{
|
|
3738
4127
|
"id": "c60b8526-5835-4c9f-aecd-9a16c7704a34",
|
|
@@ -3922,7 +4311,7 @@ var specificExamples = {
|
|
|
3922
4311
|
"required": false,
|
|
3923
4312
|
"system": false,
|
|
3924
4313
|
"config": {
|
|
3925
|
-
"formulaText": "date_format(d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90, "AAAA-MM")",
|
|
4314
|
+
"formulaText": "date_format(d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90, \\"AAAA-MM\\")",
|
|
3926
4315
|
"uiFormatKind": "date",
|
|
3927
4316
|
"status": "ACTIVE",
|
|
3928
4317
|
"defaultValue": null,
|
|
@@ -4041,6 +4430,10 @@ var specificExamples = {
|
|
|
4041
4430
|
"conditionalFormatting": []
|
|
4042
4431
|
}
|
|
4043
4432
|
}
|
|
4433
|
+
],
|
|
4434
|
+
"uniqueFields": [
|
|
4435
|
+
"c60b8526-5835-4c9f-aecd-9a16c7704a34",
|
|
4436
|
+
"1d2e3f4a-5b6c-7d8e-9f01-23456789abcd"
|
|
4044
4437
|
]
|
|
4045
4438
|
}`
|
|
4046
4439
|
}
|
|
@@ -4199,10 +4592,24 @@ var specificExamples = {
|
|
|
4199
4592
|
]),
|
|
4200
4593
|
"records delete": buildCommandExamples([
|
|
4201
4594
|
{
|
|
4202
|
-
description: "Delete
|
|
4203
|
-
command: `zinkee --json records delete contacts
|
|
4595
|
+
description: "Delete one or more records by id (--record is repeatable).",
|
|
4596
|
+
command: `zinkee --json records delete contacts --record 550e8400-e29b-41d4-a716-446655440000 --record 6c8a3e0d-4e5f-4a1b-9c2d-3e4f5a6b7c8d`,
|
|
4204
4597
|
response: `{
|
|
4205
|
-
"
|
|
4598
|
+
"recordIds": [
|
|
4599
|
+
"550e8400-e29b-41d4-a716-446655440000",
|
|
4600
|
+
"6c8a3e0d-4e5f-4a1b-9c2d-3e4f5a6b7c8d"
|
|
4601
|
+
],
|
|
4602
|
+
"deleted": true
|
|
4603
|
+
}`
|
|
4604
|
+
},
|
|
4605
|
+
{
|
|
4606
|
+
description: "Delete many records listing one uuid per line in a file (merged with any --record flags and de-duplicated).",
|
|
4607
|
+
command: `zinkee --json records delete contacts --records-file ./record-ids.txt`,
|
|
4608
|
+
response: `{
|
|
4609
|
+
"recordIds": [
|
|
4610
|
+
"550e8400-e29b-41d4-a716-446655440000",
|
|
4611
|
+
"6c8a3e0d-4e5f-4a1b-9c2d-3e4f5a6b7c8d"
|
|
4612
|
+
],
|
|
4206
4613
|
"deleted": true
|
|
4207
4614
|
}`
|
|
4208
4615
|
}
|
|
@@ -4298,7 +4705,7 @@ var specificExamples = {
|
|
|
4298
4705
|
"resources": [
|
|
4299
4706
|
{
|
|
4300
4707
|
"id": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
|
|
4301
|
-
"name": "
|
|
4708
|
+
"name": "Customer records",
|
|
4302
4709
|
"type": "SCHEMA",
|
|
4303
4710
|
"isInSpace": false,
|
|
4304
4711
|
"additionalProperties": {}
|
|
@@ -4322,19 +4729,10 @@ var specificExamples = {
|
|
|
4322
4729
|
"resources": [
|
|
4323
4730
|
{
|
|
4324
4731
|
"id": "3f8a2c1b-9d4e-4a5b-8c6d-7e8f90123456",
|
|
4325
|
-
"name": "
|
|
4326
|
-
"type": "
|
|
4732
|
+
"name": "Shipments",
|
|
4733
|
+
"type": "SCHEMA",
|
|
4327
4734
|
"isInSpace": false,
|
|
4328
4735
|
"additionalProperties": {}
|
|
4329
|
-
},
|
|
4330
|
-
{
|
|
4331
|
-
"id": "0f6f062f-1478-4df2-96a1-c495d037d260",
|
|
4332
|
-
"name": "Executive Revenue",
|
|
4333
|
-
"type": "DISPLAY",
|
|
4334
|
-
"isInSpace": true,
|
|
4335
|
-
"additionalProperties": {
|
|
4336
|
-
"pinned": true
|
|
4337
|
-
}
|
|
4338
4736
|
}
|
|
4339
4737
|
],
|
|
4340
4738
|
"additionalProperties": {
|
|
@@ -4381,8 +4779,13 @@ var specificExamples = {
|
|
|
4381
4779
|
"name": "Shared Dashboards",
|
|
4382
4780
|
"order": 1,
|
|
4383
4781
|
"isRoot": false,
|
|
4384
|
-
"resourceCount":
|
|
4782
|
+
"resourceCount": 2,
|
|
4385
4783
|
"resources": [
|
|
4784
|
+
{
|
|
4785
|
+
"id": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
|
|
4786
|
+
"name": "Customer records",
|
|
4787
|
+
"type": "SCHEMA"
|
|
4788
|
+
},
|
|
4386
4789
|
{
|
|
4387
4790
|
"id": "0f6f062f-1478-4df2-96a1-c495d037d260",
|
|
4388
4791
|
"name": "Executive Revenue",
|
|
@@ -4554,7 +4957,7 @@ var specificExamples = {
|
|
|
4554
4957
|
"hideDeleteButton": false
|
|
4555
4958
|
},
|
|
4556
4959
|
"view": {
|
|
4557
|
-
"fields": ["
|
|
4960
|
+
"fields": ["contact-name", "status", "amount"],
|
|
4558
4961
|
"columnSize": { "contact-name": 240 }
|
|
4559
4962
|
}
|
|
4560
4963
|
}
|
|
@@ -4601,6 +5004,83 @@ var specificExamples = {
|
|
|
4601
5004
|
command: "zinkee --json displays delete 0f6f062f-1478-4df2-96a1-c495d037d260"
|
|
4602
5005
|
}
|
|
4603
5006
|
]),
|
|
5007
|
+
"displays folders list": buildCommandExamples([
|
|
5008
|
+
{
|
|
5009
|
+
description: "List flat display folders (non-root folders plus the root bucket).",
|
|
5010
|
+
command: "zinkee --json displays folders list",
|
|
5011
|
+
response: `[
|
|
5012
|
+
{
|
|
5013
|
+
"id": "e7a1c3d2-5f4b-4a6c-9d8e-1f2a3b4c5d6e",
|
|
5014
|
+
"name": "Executive Dashboards",
|
|
5015
|
+
"isRoot": false,
|
|
5016
|
+
"displayCount": 2
|
|
5017
|
+
},
|
|
5018
|
+
{
|
|
5019
|
+
"id": "8b22282b-3db3-4dd7-87f7-b29365dcf3f6",
|
|
5020
|
+
"name": null,
|
|
5021
|
+
"isRoot": true,
|
|
5022
|
+
"displayCount": 4
|
|
5023
|
+
}
|
|
5024
|
+
]`
|
|
5025
|
+
}
|
|
5026
|
+
]),
|
|
5027
|
+
"displays folders create": buildCommandExamples([
|
|
5028
|
+
{
|
|
5029
|
+
description: "Create one flat display folder.",
|
|
5030
|
+
command: 'zinkee --json displays folders create --name "Executive Dashboards"',
|
|
5031
|
+
raw: `{
|
|
5032
|
+
"name": "Executive Dashboards"
|
|
5033
|
+
}`,
|
|
5034
|
+
response: `{
|
|
5035
|
+
"id": "e7a1c3d2-5f4b-4a6c-9d8e-1f2a3b4c5d6e",
|
|
5036
|
+
"name": "Executive Dashboards",
|
|
5037
|
+
"isRoot": false,
|
|
5038
|
+
"displayCount": 0
|
|
5039
|
+
}`
|
|
5040
|
+
}
|
|
5041
|
+
]),
|
|
5042
|
+
"displays folders update": buildCommandExamples([
|
|
5043
|
+
{
|
|
5044
|
+
description: "Rename a display folder. The folder argument accepts a UUID or an exact name.",
|
|
5045
|
+
command: 'zinkee --json displays folders update "Executive Dashboards" --name "Executive Dashboards (2026)"',
|
|
5046
|
+
raw: `{
|
|
5047
|
+
"name": "Executive Dashboards (2026)"
|
|
5048
|
+
}`,
|
|
5049
|
+
response: `{
|
|
5050
|
+
"id": "e7a1c3d2-5f4b-4a6c-9d8e-1f2a3b4c5d6e",
|
|
5051
|
+
"name": "Executive Dashboards (2026)",
|
|
5052
|
+
"isRoot": false,
|
|
5053
|
+
"displayCount": 2
|
|
5054
|
+
}`
|
|
5055
|
+
}
|
|
5056
|
+
]),
|
|
5057
|
+
"displays folders delete": buildCommandExamples([
|
|
5058
|
+
{
|
|
5059
|
+
description: "Delete a non-root display folder. Its displays move back to the root folder.",
|
|
5060
|
+
command: 'zinkee --json displays folders delete "Executive Dashboards"',
|
|
5061
|
+
response: `{
|
|
5062
|
+
"id": "e7a1c3d2-5f4b-4a6c-9d8e-1f2a3b4c5d6e",
|
|
5063
|
+
"name": "Executive Dashboards",
|
|
5064
|
+
"isRoot": false,
|
|
5065
|
+
"displayCount": 2
|
|
5066
|
+
}`
|
|
5067
|
+
}
|
|
5068
|
+
]),
|
|
5069
|
+
"displays folders move": buildCommandExamples([
|
|
5070
|
+
{
|
|
5071
|
+
description: "Move one display into a target folder by exact folder name.",
|
|
5072
|
+
command: 'zinkee --json displays folders move 0f6f062f-1478-4df2-96a1-c495d037d260 --to "Executive Dashboards"',
|
|
5073
|
+
raw: `{
|
|
5074
|
+
"displayId": "0f6f062f-1478-4df2-96a1-c495d037d260",
|
|
5075
|
+
"targetFolderId": "e7a1c3d2-5f4b-4a6c-9d8e-1f2a3b4c5d6e"
|
|
5076
|
+
}`,
|
|
5077
|
+
response: `{
|
|
5078
|
+
"id": "e7a1c3d2-5f4b-4a6c-9d8e-1f2a3b4c5d6e",
|
|
5079
|
+
"name": "Executive Dashboards",
|
|
5080
|
+
"isRoot": false
|
|
5081
|
+
}`
|
|
5082
|
+
}
|
|
5083
|
+
]),
|
|
4604
5084
|
"displays layout get": buildCommandExamples([
|
|
4605
5085
|
{
|
|
4606
5086
|
description: "Get the layout block of a display (template + tabs/freeformLayouts/slots).",
|
|
@@ -4694,7 +5174,7 @@ var specificExamples = {
|
|
|
4694
5174
|
"hideDeleteButton": false
|
|
4695
5175
|
},
|
|
4696
5176
|
"view": {
|
|
4697
|
-
"fields": ["
|
|
5177
|
+
"fields": ["contact-name", "status", "amount"],
|
|
4698
5178
|
"columnSize": { "contact-name": 240 }
|
|
4699
5179
|
}
|
|
4700
5180
|
}`
|
|
@@ -5351,6 +5831,43 @@ var specificExamples = {
|
|
|
5351
5831
|
"steps": ["one", "two"]
|
|
5352
5832
|
}
|
|
5353
5833
|
}
|
|
5834
|
+
}`
|
|
5835
|
+
},
|
|
5836
|
+
{
|
|
5837
|
+
description: "Add a send-message action. --to maps to fieldMapping.recipients and --message maps to fieldMapping.body. Values are wrapped in {rawValue, source} like every other automation field mapping; use --map / --map-json for extra keys.",
|
|
5838
|
+
command: `zinkee --json automations actions add automation-1 --type send_message --name "Notify customer" --to customer@example.com --subject "Your order status has changed" --message "Hello, your order is now processed."`,
|
|
5839
|
+
raw: `{
|
|
5840
|
+
"type": "send_message",
|
|
5841
|
+
"name": "Notify customer",
|
|
5842
|
+
"config": {
|
|
5843
|
+
"fieldMapping": {
|
|
5844
|
+
"recipients": {
|
|
5845
|
+
"rawValue": "customer@example.com",
|
|
5846
|
+
"source": null
|
|
5847
|
+
},
|
|
5848
|
+
"subject": {
|
|
5849
|
+
"rawValue": "Your order status has changed",
|
|
5850
|
+
"source": null
|
|
5851
|
+
},
|
|
5852
|
+
"body": {
|
|
5853
|
+
"rawValue": "Hello, your order is now processed.",
|
|
5854
|
+
"source": null
|
|
5855
|
+
}
|
|
5856
|
+
}
|
|
5857
|
+
}
|
|
5858
|
+
}`
|
|
5859
|
+
},
|
|
5860
|
+
{
|
|
5861
|
+
description: "Add a generate-document action. The renderer reads the template, writes the file, and stores its id in the target FileField of the target schema.",
|
|
5862
|
+
command: 'zinkee --json automations actions add automation-1 --type generate_document --name "Generate invoice PDF" --document-template 6c08673e-f8a6-44d2-8c91-d09eca911f8f --target-schema 68d2c7be-4392-42de-b5ae-625ad79cfc3c --target-file-field c8edbde8-a361-4e9f-a39a-2e88971f21a7',
|
|
5863
|
+
raw: `{
|
|
5864
|
+
"type": "generate_document",
|
|
5865
|
+
"name": "Generate invoice PDF",
|
|
5866
|
+
"config": {
|
|
5867
|
+
"documentTemplateId": "6c08673e-f8a6-44d2-8c91-d09eca911f8f",
|
|
5868
|
+
"targetSchemaId": "68d2c7be-4392-42de-b5ae-625ad79cfc3c",
|
|
5869
|
+
"targetFileFieldId": "c8edbde8-a361-4e9f-a39a-2e88971f21a7"
|
|
5870
|
+
}
|
|
5354
5871
|
}`
|
|
5355
5872
|
}
|
|
5356
5873
|
]),
|
|
@@ -5401,6 +5918,30 @@ var specificExamples = {
|
|
|
5401
5918
|
"authMode": "STORED",
|
|
5402
5919
|
"connectionId": "connection-1"
|
|
5403
5920
|
}
|
|
5921
|
+
}`
|
|
5922
|
+
},
|
|
5923
|
+
{
|
|
5924
|
+
description: "Replace a send-message action. --to maps to fieldMapping.recipients and --message maps to fieldMapping.body; values are wrapped in {rawValue, source}.",
|
|
5925
|
+
command: `zinkee --json automations actions update automation-1 action-1 --type send_message --name "Notify customer" --to customer@example.com --subject "Your order status has changed" --message "Hello, your order is now processed."`,
|
|
5926
|
+
raw: `{
|
|
5927
|
+
"type": "send_message",
|
|
5928
|
+
"name": "Notify customer",
|
|
5929
|
+
"config": {
|
|
5930
|
+
"fieldMapping": {
|
|
5931
|
+
"recipients": {
|
|
5932
|
+
"rawValue": "customer@example.com",
|
|
5933
|
+
"source": null
|
|
5934
|
+
},
|
|
5935
|
+
"subject": {
|
|
5936
|
+
"rawValue": "Your order status has changed",
|
|
5937
|
+
"source": null
|
|
5938
|
+
},
|
|
5939
|
+
"body": {
|
|
5940
|
+
"rawValue": "Hello, your order is now processed.",
|
|
5941
|
+
"source": null
|
|
5942
|
+
}
|
|
5943
|
+
}
|
|
5944
|
+
}
|
|
5404
5945
|
}`
|
|
5405
5946
|
}
|
|
5406
5947
|
]),
|
|
@@ -5553,7 +6094,8 @@ var specificExamples = {
|
|
|
5553
6094
|
description: "Move one automation into a target folder by exact folder name.",
|
|
5554
6095
|
command: 'zinkee --json automations folders move automation-1 --to "Codex Frontend Demo"',
|
|
5555
6096
|
raw: `{
|
|
5556
|
-
"automationId": "automation-1"
|
|
6097
|
+
"automationId": "automation-1",
|
|
6098
|
+
"targetFolderId": "cdfc14e3-3169-4ffb-8d9b-b11858a9240f"
|
|
5557
6099
|
}`,
|
|
5558
6100
|
response: `{
|
|
5559
6101
|
"id": "cdfc14e3-3169-4ffb-8d9b-b11858a9240f",
|
|
@@ -5561,70 +6103,248 @@ var specificExamples = {
|
|
|
5561
6103
|
"isRoot": false
|
|
5562
6104
|
}`
|
|
5563
6105
|
}
|
|
5564
|
-
])
|
|
5565
|
-
|
|
5566
|
-
|
|
5567
|
-
|
|
5568
|
-
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
|
|
5572
|
-
|
|
5573
|
-
|
|
5574
|
-
|
|
5575
|
-
|
|
5576
|
-
|
|
5577
|
-
|
|
5578
|
-
);
|
|
5579
|
-
return buildCommandExamples(
|
|
5580
|
-
flat.map(({ example }, index) => {
|
|
5581
|
-
const slug = typeof example.payload.slug === "string" ? example.payload.slug : "field";
|
|
5582
|
-
const command = `zinkee --json schemas fields create contacts --raw '${JSON.stringify(example.payload)}'`;
|
|
5583
|
-
if (index === 0) {
|
|
5584
|
-
return {
|
|
5585
|
-
description: example.name,
|
|
5586
|
-
command,
|
|
5587
|
-
response: `{
|
|
5588
|
-
"schemaId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
|
|
5589
|
-
"fieldId": "a8f1d7e3-2b5c-4d9e-8a1b-3c4d5e6f7890",
|
|
5590
|
-
"slug": "${slug}"
|
|
5591
|
-
}`
|
|
5592
|
-
};
|
|
6106
|
+
]),
|
|
6107
|
+
"document-templates list": buildCommandExamples([
|
|
6108
|
+
{
|
|
6109
|
+
description: "List every document template in the workspace. Each asset's link is a relative path to the asset download endpoint, ready to call without composition.",
|
|
6110
|
+
command: "zinkee --json document-templates list",
|
|
6111
|
+
response: `[
|
|
6112
|
+
{
|
|
6113
|
+
"id": "7c4a8d3f-1b2e-4a5c-9d6e-1f2a3b4c5d6e",
|
|
6114
|
+
"name": "Quarterly report",
|
|
6115
|
+
"assets": [
|
|
6116
|
+
{
|
|
6117
|
+
"id": "9e8d7c6b-5a4f-3e2d-1c0b-9a8b7c6d5e4f",
|
|
6118
|
+
"name": "Requirements.docx",
|
|
6119
|
+
"link": "/api/v2/document-templates/7c4a8d3f-1b2e-4a5c-9d6e-1f2a3b4c5d6e/assets/9e8d7c6b-5a4f-3e2d-1c0b-9a8b7c6d5e4f/download"
|
|
5593
6120
|
}
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5598
|
-
|
|
5599
|
-
);
|
|
5600
|
-
}
|
|
5601
|
-
function getCommandExamples(commandName, filters = {}) {
|
|
5602
|
-
if (commandName === "schemas fields create") {
|
|
5603
|
-
return buildSchemaFieldCreateExamples(filters.type);
|
|
6121
|
+
],
|
|
6122
|
+
"createdAt": "2026-01-15T10:00:00Z",
|
|
6123
|
+
"updatedAt": "2026-01-20T14:30:00Z",
|
|
6124
|
+
"createdBy": "creator@example.com",
|
|
6125
|
+
"updatedBy": "updater@example.com"
|
|
5604
6126
|
}
|
|
5605
|
-
|
|
5606
|
-
}
|
|
5607
|
-
function getResolvedCommandExamples(commandName, filters = {}) {
|
|
5608
|
-
return getCommandExamples(commandName, filters);
|
|
5609
|
-
}
|
|
5610
|
-
|
|
5611
|
-
// src/cli-examples.ts
|
|
5612
|
-
function getStdout(stdout) {
|
|
5613
|
-
return stdout ?? process.stdout;
|
|
5614
|
-
}
|
|
5615
|
-
function extractExampleFilters(tokens) {
|
|
5616
|
-
const filters = {};
|
|
5617
|
-
for (let index = 0; index < tokens.length; index += 1) {
|
|
5618
|
-
const token = tokens[index];
|
|
5619
|
-
if (token === "--type") {
|
|
5620
|
-
const value = tokens[index + 1];
|
|
5621
|
-
if (value && !value.startsWith("-")) {
|
|
5622
|
-
filters.type = value;
|
|
5623
|
-
index += 1;
|
|
5624
|
-
}
|
|
6127
|
+
]`
|
|
5625
6128
|
}
|
|
5626
|
-
|
|
5627
|
-
|
|
6129
|
+
]),
|
|
6130
|
+
"document-templates get": buildCommandExamples([
|
|
6131
|
+
{
|
|
6132
|
+
description: "Look up one template by UUID. The CLI filters the list endpoint locally (the backend does not expose a get-one route).",
|
|
6133
|
+
command: "zinkee --json document-templates get 7c4a8d3f-1b2e-4a5c-9d6e-1f2a3b4c5d6e",
|
|
6134
|
+
response: `{
|
|
6135
|
+
"id": "7c4a8d3f-1b2e-4a5c-9d6e-1f2a3b4c5d6e",
|
|
6136
|
+
"name": "Quarterly report",
|
|
6137
|
+
"assets": [
|
|
6138
|
+
{
|
|
6139
|
+
"id": "9e8d7c6b-5a4f-3e2d-1c0b-9a8b7c6d5e4f",
|
|
6140
|
+
"name": "Requirements.docx",
|
|
6141
|
+
"link": "/api/v2/document-templates/7c4a8d3f-1b2e-4a5c-9d6e-1f2a3b4c5d6e/assets/9e8d7c6b-5a4f-3e2d-1c0b-9a8b7c6d5e4f/download"
|
|
6142
|
+
}
|
|
6143
|
+
],
|
|
6144
|
+
"createdAt": "2026-01-15T10:00:00Z",
|
|
6145
|
+
"updatedAt": "2026-01-20T14:30:00Z",
|
|
6146
|
+
"createdBy": "creator@example.com",
|
|
6147
|
+
"updatedBy": "creator@example.com"
|
|
6148
|
+
}`
|
|
6149
|
+
},
|
|
6150
|
+
{
|
|
6151
|
+
description: "Look up by exact template name. Names are unique within the workspace; ambiguity is reported as an error.",
|
|
6152
|
+
command: 'zinkee --json document-templates get "Quarterly report"'
|
|
6153
|
+
}
|
|
6154
|
+
]),
|
|
6155
|
+
"document-templates create": buildCommandExamples([
|
|
6156
|
+
{
|
|
6157
|
+
description: "Typical create: empty template by name. Assets are uploaded afterwards via document-templates assets add.",
|
|
6158
|
+
command: 'zinkee --json document-templates create --name "Quarterly report"',
|
|
6159
|
+
raw: `{
|
|
6160
|
+
"name": "Quarterly report",
|
|
6161
|
+
"assets": []
|
|
6162
|
+
}`,
|
|
6163
|
+
response: `{
|
|
6164
|
+
"id": "7c4a8d3f-1b2e-4a5c-9d6e-1f2a3b4c5d6e",
|
|
6165
|
+
"name": "Quarterly report",
|
|
6166
|
+
"assets": [],
|
|
6167
|
+
"createdAt": "2026-01-15T10:00:00Z",
|
|
6168
|
+
"updatedAt": "2026-01-15T10:00:00Z",
|
|
6169
|
+
"createdBy": "creator@example.com",
|
|
6170
|
+
"updatedBy": "creator@example.com"
|
|
6171
|
+
}`
|
|
6172
|
+
},
|
|
6173
|
+
{
|
|
6174
|
+
description: "Create with pre-existing asset records via --raw. Used for import/migration flows where the assets already exist elsewhere; the typical UX is to create empty and upload via assets add.",
|
|
6175
|
+
command: `zinkee --json document-templates create --raw '{"name":"Annual report","assets":[{"id":"9e8d7c6b-5a4f-3e2d-1c0b-9a8b7c6d5e4f","name":"Cover.docx","link":"/existing/cover.docx"},{"id":"3f2e1d0c-9b8a-7654-3210-fedcba987654","name":"Appendix.docx","link":"/existing/appendix.docx"}]}'`,
|
|
6176
|
+
raw: `{
|
|
6177
|
+
"name": "Annual report",
|
|
6178
|
+
"assets": [
|
|
6179
|
+
{
|
|
6180
|
+
"id": "9e8d7c6b-5a4f-3e2d-1c0b-9a8b7c6d5e4f",
|
|
6181
|
+
"name": "Cover.docx",
|
|
6182
|
+
"link": "/existing/cover.docx"
|
|
6183
|
+
},
|
|
6184
|
+
{
|
|
6185
|
+
"id": "3f2e1d0c-9b8a-7654-3210-fedcba987654",
|
|
6186
|
+
"name": "Appendix.docx",
|
|
6187
|
+
"link": "/existing/appendix.docx"
|
|
6188
|
+
}
|
|
6189
|
+
]
|
|
6190
|
+
}`
|
|
6191
|
+
}
|
|
6192
|
+
]),
|
|
6193
|
+
"document-templates update": buildCommandExamples([
|
|
6194
|
+
{
|
|
6195
|
+
description: "Rename a template. The template argument accepts a UUID or an exact current name. Only the name is updatable through this endpoint; assets are managed via the assets subcommands.",
|
|
6196
|
+
command: 'zinkee --json document-templates update "Quarterly report" --name "Annual report"',
|
|
6197
|
+
raw: `{
|
|
6198
|
+
"name": "Annual report"
|
|
6199
|
+
}`,
|
|
6200
|
+
response: `{
|
|
6201
|
+
"id": "7c4a8d3f-1b2e-4a5c-9d6e-1f2a3b4c5d6e",
|
|
6202
|
+
"name": "Annual report",
|
|
6203
|
+
"assets": [
|
|
6204
|
+
{
|
|
6205
|
+
"id": "9e8d7c6b-5a4f-3e2d-1c0b-9a8b7c6d5e4f",
|
|
6206
|
+
"name": "Requirements.docx",
|
|
6207
|
+
"link": "/api/v2/document-templates/7c4a8d3f-1b2e-4a5c-9d6e-1f2a3b4c5d6e/assets/9e8d7c6b-5a4f-3e2d-1c0b-9a8b7c6d5e4f/download"
|
|
6208
|
+
}
|
|
6209
|
+
],
|
|
6210
|
+
"createdAt": "2026-01-15T10:00:00Z",
|
|
6211
|
+
"updatedAt": "2026-01-22T09:15:00Z",
|
|
6212
|
+
"createdBy": "creator@example.com",
|
|
6213
|
+
"updatedBy": "updater@example.com"
|
|
6214
|
+
}`
|
|
6215
|
+
}
|
|
6216
|
+
]),
|
|
6217
|
+
"document-templates delete": buildCommandExamples([
|
|
6218
|
+
{
|
|
6219
|
+
description: "Delete a template and remove its asset files from storage. Record fields that reference previously generated documents are not modified.",
|
|
6220
|
+
command: "zinkee --json document-templates delete 7c4a8d3f-1b2e-4a5c-9d6e-1f2a3b4c5d6e",
|
|
6221
|
+
response: `{
|
|
6222
|
+
"id": "7c4a8d3f-1b2e-4a5c-9d6e-1f2a3b4c5d6e",
|
|
6223
|
+
"deleted": true
|
|
6224
|
+
}`
|
|
6225
|
+
}
|
|
6226
|
+
]),
|
|
6227
|
+
"document-templates assets add": buildCommandExamples([
|
|
6228
|
+
{
|
|
6229
|
+
description: 'Upload a local file as an asset of a template. The CLI sends a multipart form with a part named "file"; the asset display name defaults to the uploaded filename.',
|
|
6230
|
+
command: 'zinkee --json document-templates assets add "Quarterly report" ./contract.docx',
|
|
6231
|
+
response: `{
|
|
6232
|
+
"id": "7c4a8d3f-1b2e-4a5c-9d6e-1f2a3b4c5d6e",
|
|
6233
|
+
"name": "Quarterly report",
|
|
6234
|
+
"assets": [
|
|
6235
|
+
{
|
|
6236
|
+
"id": "9e8d7c6b-5a4f-3e2d-1c0b-9a8b7c6d5e4f",
|
|
6237
|
+
"name": "contract.docx",
|
|
6238
|
+
"link": "/api/v2/document-templates/7c4a8d3f-1b2e-4a5c-9d6e-1f2a3b4c5d6e/assets/9e8d7c6b-5a4f-3e2d-1c0b-9a8b7c6d5e4f/download"
|
|
6239
|
+
}
|
|
6240
|
+
],
|
|
6241
|
+
"createdAt": "2026-01-15T10:00:00Z",
|
|
6242
|
+
"updatedAt": "2026-01-22T09:15:00Z",
|
|
6243
|
+
"createdBy": "creator@example.com",
|
|
6244
|
+
"updatedBy": "updater@example.com"
|
|
6245
|
+
}`
|
|
6246
|
+
},
|
|
6247
|
+
{
|
|
6248
|
+
description: "Override the asset display name with --name (otherwise the uploaded filename is used).",
|
|
6249
|
+
command: 'zinkee --json document-templates assets add "Quarterly report" ./contract.docx --name "Customer Contract"'
|
|
6250
|
+
}
|
|
6251
|
+
]),
|
|
6252
|
+
"document-templates assets delete": buildCommandExamples([
|
|
6253
|
+
{
|
|
6254
|
+
description: "Delete one asset from a template and remove its file from storage.",
|
|
6255
|
+
command: "zinkee --json document-templates assets delete 7c4a8d3f-1b2e-4a5c-9d6e-1f2a3b4c5d6e 9e8d7c6b-5a4f-3e2d-1c0b-9a8b7c6d5e4f",
|
|
6256
|
+
response: `{
|
|
6257
|
+
"id": "9e8d7c6b-5a4f-3e2d-1c0b-9a8b7c6d5e4f",
|
|
6258
|
+
"deleted": true
|
|
6259
|
+
}`
|
|
6260
|
+
}
|
|
6261
|
+
]),
|
|
6262
|
+
"document-templates assets download": buildCommandExamples([
|
|
6263
|
+
{
|
|
6264
|
+
description: "Download asset bytes to disk. The CLI streams the raw bytes to --output; in --json mode --output is required and the JSON envelope only carries metadata.",
|
|
6265
|
+
command: "zinkee --json document-templates assets download 7c4a8d3f-1b2e-4a5c-9d6e-1f2a3b4c5d6e 9e8d7c6b-5a4f-3e2d-1c0b-9a8b7c6d5e4f --output ./contract.docx"
|
|
6266
|
+
},
|
|
6267
|
+
{
|
|
6268
|
+
description: "Stream asset bytes to stdout (omit --json and --output). Useful for piping into other tools.",
|
|
6269
|
+
command: "zinkee document-templates assets download 7c4a8d3f-1b2e-4a5c-9d6e-1f2a3b4c5d6e 9e8d7c6b-5a4f-3e2d-1c0b-9a8b7c6d5e4f > contract.docx"
|
|
6270
|
+
}
|
|
6271
|
+
])
|
|
6272
|
+
};
|
|
6273
|
+
function fallbackExamples(commandName) {
|
|
6274
|
+
switch (commandName) {
|
|
6275
|
+
default:
|
|
6276
|
+
return [];
|
|
6277
|
+
}
|
|
6278
|
+
}
|
|
6279
|
+
function buildSchemaFieldCreateExamples(type) {
|
|
6280
|
+
const definitions = getSchemaFieldTypeDefinitions();
|
|
6281
|
+
const selectedDefinition = resolveSchemaFieldType(type);
|
|
6282
|
+
const filteredDefinitions = selectedDefinition ? definitions.filter((definition) => definition.key === selectedDefinition.key) : definitions;
|
|
6283
|
+
const flat = filteredDefinitions.flatMap(
|
|
6284
|
+
(definition) => definition.examplePayloads.map((example) => ({ definition, example }))
|
|
6285
|
+
);
|
|
6286
|
+
return buildCommandExamples(
|
|
6287
|
+
flat.map(({ example }, index) => {
|
|
6288
|
+
const slug = typeof example.payload.slug === "string" ? example.payload.slug : "field";
|
|
6289
|
+
const command = `zinkee --json schemas fields create contacts --raw '${JSON.stringify(example.payload)}'`;
|
|
6290
|
+
if (index === 0) {
|
|
6291
|
+
return {
|
|
6292
|
+
description: example.name,
|
|
6293
|
+
command,
|
|
6294
|
+
response: `{
|
|
6295
|
+
"schemaId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
|
|
6296
|
+
"fieldId": "a8f1d7e3-2b5c-4d9e-8a1b-3c4d5e6f7890",
|
|
6297
|
+
"slug": "${slug}"
|
|
6298
|
+
}`
|
|
6299
|
+
};
|
|
6300
|
+
}
|
|
6301
|
+
return {
|
|
6302
|
+
description: example.name,
|
|
6303
|
+
command
|
|
6304
|
+
};
|
|
6305
|
+
})
|
|
6306
|
+
);
|
|
6307
|
+
}
|
|
6308
|
+
function getCommandExamples(commandName, filters = {}) {
|
|
6309
|
+
const examples = commandName === "schemas fields create" ? buildSchemaFieldCreateExamples(filters.type) : specificExamples[commandName] ?? fallbackExamples(commandName);
|
|
6310
|
+
return examples.map((example) => withResponseEnvelope(example, commandName));
|
|
6311
|
+
}
|
|
6312
|
+
function withResponseEnvelope(example, commandName) {
|
|
6313
|
+
if (example.response === void 0) {
|
|
6314
|
+
return example;
|
|
6315
|
+
}
|
|
6316
|
+
let payload;
|
|
6317
|
+
try {
|
|
6318
|
+
payload = JSON.parse(example.response);
|
|
6319
|
+
} catch {
|
|
6320
|
+
return example;
|
|
6321
|
+
}
|
|
6322
|
+
return {
|
|
6323
|
+
...example,
|
|
6324
|
+
response: JSON.stringify(buildJsonSuccess(payload, { command: commandName }), null, 2)
|
|
6325
|
+
};
|
|
6326
|
+
}
|
|
6327
|
+
function getResolvedCommandExamples(commandName, filters = {}) {
|
|
6328
|
+
return getCommandExamples(commandName, filters);
|
|
6329
|
+
}
|
|
6330
|
+
|
|
6331
|
+
// src/cli-examples.ts
|
|
6332
|
+
function getStdout(stdout) {
|
|
6333
|
+
return stdout ?? process.stdout;
|
|
6334
|
+
}
|
|
6335
|
+
function extractExampleFilters(tokens) {
|
|
6336
|
+
const filters = {};
|
|
6337
|
+
for (let index = 0; index < tokens.length; index += 1) {
|
|
6338
|
+
const token = tokens[index];
|
|
6339
|
+
if (token === "--type") {
|
|
6340
|
+
const value = tokens[index + 1];
|
|
6341
|
+
if (value && !value.startsWith("-")) {
|
|
6342
|
+
filters.type = value;
|
|
6343
|
+
index += 1;
|
|
6344
|
+
}
|
|
6345
|
+
}
|
|
6346
|
+
}
|
|
6347
|
+
return filters;
|
|
5628
6348
|
}
|
|
5629
6349
|
function extractExampleRequest(argv, optionMeta = createDefaultOptionMetadata()) {
|
|
5630
6350
|
if (!argv.includes("--example")) {
|
|
@@ -5634,7 +6354,22 @@ function extractExampleRequest(argv, optionMeta = createDefaultOptionMetadata())
|
|
|
5634
6354
|
const operands = collectOperandTokens(userArgs, optionMeta, { skipFlag: "--example" });
|
|
5635
6355
|
const cmdPath = findCommandPath(operands, commandRegistry);
|
|
5636
6356
|
if (!cmdPath) {
|
|
5637
|
-
|
|
6357
|
+
const typed = operands.map((operand) => operand.token).join(" ");
|
|
6358
|
+
if (typed.length === 0) {
|
|
6359
|
+
throw new CliError("invalid_cli_usage", 'Provide a command after "--example".');
|
|
6360
|
+
}
|
|
6361
|
+
const subcommands = Object.keys(commandRegistry).filter(
|
|
6362
|
+
(name) => name.startsWith(`${typed} `)
|
|
6363
|
+
);
|
|
6364
|
+
if (subcommands.length > 0) {
|
|
6365
|
+
const list = subcommands.map((name) => ` zinkee --example ${name}`).join("\n");
|
|
6366
|
+
throw new CliError(
|
|
6367
|
+
"invalid_cli_usage",
|
|
6368
|
+
`"${typed}" is a command group, not a runnable command. Available subcommands:
|
|
6369
|
+
${list}`
|
|
6370
|
+
);
|
|
6371
|
+
}
|
|
6372
|
+
throw new CliError("invalid_cli_usage", `Unknown command "${typed}".`);
|
|
5638
6373
|
}
|
|
5639
6374
|
const remainingTokens = userArgs.slice(cmdPath.lastArgvIndex + 1);
|
|
5640
6375
|
return {
|
|
@@ -5680,7 +6415,7 @@ ${index + 1}. ${example.description}
|
|
|
5680
6415
|
|
|
5681
6416
|
// src/program.ts
|
|
5682
6417
|
import { createRequire } from "module";
|
|
5683
|
-
import { Command as
|
|
6418
|
+
import { Command as Command11 } from "commander";
|
|
5684
6419
|
|
|
5685
6420
|
// src/config.ts
|
|
5686
6421
|
import { mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
@@ -6034,7 +6769,7 @@ var AutomationsApi = class {
|
|
|
6034
6769
|
}
|
|
6035
6770
|
moveAutomation(input) {
|
|
6036
6771
|
return this.client.requestJson(
|
|
6037
|
-
|
|
6772
|
+
"/api/v2/automation-folders/automations:move",
|
|
6038
6773
|
jsonOptions(input, "POST")
|
|
6039
6774
|
);
|
|
6040
6775
|
}
|
|
@@ -6441,11 +7176,11 @@ function hasSetPath(target, path) {
|
|
|
6441
7176
|
return Object.hasOwn(target, path);
|
|
6442
7177
|
}
|
|
6443
7178
|
let current = target;
|
|
6444
|
-
for (const
|
|
6445
|
-
if (!isJsonObject2(current) || !Object.hasOwn(current,
|
|
7179
|
+
for (const segment4 of segments) {
|
|
7180
|
+
if (!isJsonObject2(current) || !Object.hasOwn(current, segment4)) {
|
|
6446
7181
|
return false;
|
|
6447
7182
|
}
|
|
6448
|
-
current = current[
|
|
7183
|
+
current = current[segment4];
|
|
6449
7184
|
}
|
|
6450
7185
|
return true;
|
|
6451
7186
|
}
|
|
@@ -6908,6 +7643,15 @@ function buildActionInput(options, mode) {
|
|
|
6908
7643
|
if (options.targetSchema !== void 0) {
|
|
6909
7644
|
config.targetSchemaId = options.targetSchema;
|
|
6910
7645
|
}
|
|
7646
|
+
if (options.to !== void 0) {
|
|
7647
|
+
mappings.recipients = options.to;
|
|
7648
|
+
}
|
|
7649
|
+
if (options.subject !== void 0) {
|
|
7650
|
+
mappings.subject = options.subject;
|
|
7651
|
+
}
|
|
7652
|
+
if (options.message !== void 0) {
|
|
7653
|
+
mappings.body = options.message;
|
|
7654
|
+
}
|
|
6911
7655
|
if (!isEmptyObject(mappings)) {
|
|
6912
7656
|
config.fieldMapping = mappings;
|
|
6913
7657
|
}
|
|
@@ -6951,6 +7695,12 @@ function buildActionInput(options, mode) {
|
|
|
6951
7695
|
if (!isEmptyObject(args)) {
|
|
6952
7696
|
config.pluginArgs = args;
|
|
6953
7697
|
}
|
|
7698
|
+
if (options.documentTemplate !== void 0) {
|
|
7699
|
+
config.documentTemplateId = options.documentTemplate;
|
|
7700
|
+
}
|
|
7701
|
+
if (options.targetFileField !== void 0) {
|
|
7702
|
+
config.targetFileFieldId = options.targetFileField;
|
|
7703
|
+
}
|
|
6954
7704
|
if (!isEmptyObject(config)) {
|
|
6955
7705
|
if (isJsonObject2(config.fieldMapping)) {
|
|
6956
7706
|
config.fieldMapping = normalizeAutomationFieldMapping(
|
|
@@ -7137,19 +7887,35 @@ function addTriggerPayloadOptions(command) {
|
|
|
7137
7887
|
[]
|
|
7138
7888
|
).option("--webhook-endpoint-id <uuid>", "webhook endpoint id").option("--raw <json>", "raw trigger JSON payload").option("--raw-file <path>", "path to raw trigger JSON payload");
|
|
7139
7889
|
}
|
|
7890
|
+
var ACTION_TYPES_HELP = `
|
|
7891
|
+
Action types and their flags:
|
|
7892
|
+
create_record --target-schema, --map, --map-json
|
|
7893
|
+
update_record --target-schema, --use-trigger-record, --map,
|
|
7894
|
+
--condition, --condition-json
|
|
7895
|
+
search_records --target-schema, --condition, --condition-json
|
|
7896
|
+
send_message --to, --subject, --message
|
|
7897
|
+
(--map / --map-json also accepted for extra keys)
|
|
7898
|
+
http_request --method, --url, --header, --body, --content-type,
|
|
7899
|
+
--timeout-ms, --var, --auth-mode, --connection
|
|
7900
|
+
execute_plugin --plugin, --arg, --arg-json
|
|
7901
|
+
generate_document --document-template, --target-schema, --target-file-field
|
|
7902
|
+
`;
|
|
7140
7903
|
function addActionPayloadOptions(command) {
|
|
7141
|
-
return command.option(
|
|
7904
|
+
return command.option(
|
|
7905
|
+
"--type <type>",
|
|
7906
|
+
"action type (create_record|update_record|search_records|send_message|http_request|execute_plugin|generate_document)"
|
|
7907
|
+
).option("--name <name>", "action name").option("--target-schema <uuid>", "target schema id").option("--map <field=value>", "field mapping", collectValues, []).option("--map-json <field=json>", "JSON field mapping", collectValues, []).option("--condition <field:comparator:value>", "action condition", collectValues, []).option("--condition-json <json>", "action condition as JSON", collectValues, []).option("--use-trigger-record", "use the triggering record").option("--method <method>", "HTTP method").option("--url <url>", "HTTP target URL").option("--header <key=value>", "HTTP header", collectValues, []).option("--body <json>", "HTTP request body as JSON").option("--body-file <path>", "path to HTTP request body JSON").option("--content-type <type>", "HTTP content type").option(
|
|
7142
7908
|
"--timeout-ms <n>",
|
|
7143
7909
|
"HTTP timeout in milliseconds",
|
|
7144
7910
|
parseNonNegativeInteger
|
|
7145
|
-
).option("--var <key=value>", "HTTP variable", collectValues, []).option("--auth-mode <mode>", "HTTP auth mode").option("--connection <uuid>", "connection id for HTTP auth").option("--plugin <id>", "plugin id for execute_plugin").option("--arg <key=value>", "plugin argument", collectValues, []).option("--arg-json <key=json>", "plugin argument as JSON", collectValues, []).option("--raw <json>", "raw action JSON payload").option("--raw-file <path>", "path to raw action JSON payload");
|
|
7911
|
+
).option("--var <key=value>", "HTTP variable", collectValues, []).option("--auth-mode <mode>", "HTTP auth mode").option("--connection <uuid>", "connection id for HTTP auth").option("--plugin <id>", "plugin id for execute_plugin").option("--arg <key=value>", "plugin argument", collectValues, []).option("--arg-json <key=json>", "plugin argument as JSON", collectValues, []).option("--to <recipient>", "send_message recipient (maps to fieldMapping.recipients)").option("--subject <text>", "send_message subject").option("--message <text>", "send_message body text (maps to fieldMapping.body)").option("--document-template <uuid>", "generate_document template id").option("--target-file-field <uuid>", "generate_document target FileField id").option("--raw <json>", "raw action JSON payload").option("--raw-file <path>", "path to raw action JSON payload").addHelpText("after", ACTION_TYPES_HELP);
|
|
7146
7912
|
}
|
|
7147
7913
|
function registerAutomationsCommands(program, options = {}) {
|
|
7148
7914
|
const filePath = options.configPath ?? defaultConfigPath;
|
|
7149
7915
|
const stdout = getCommandIo2(options.stdout);
|
|
7150
7916
|
const automations = program.command("automations").description("Manage automations, triggers, actions, and connections");
|
|
7151
|
-
const folders = automations.command("folders").description("Manage automation folders");
|
|
7152
|
-
folders.command("list").description("List automation folders").action(async function action() {
|
|
7917
|
+
const folders = automations.command("folders").description("Manage automation folders (flat: a folder only has a name, no order or properties)");
|
|
7918
|
+
folders.command("list").description("List automation folders (non-root folders plus the root bucket, whose name is null)").action(async function action() {
|
|
7153
7919
|
const { api, json } = createAutomationsApi(this, filePath);
|
|
7154
7920
|
const data = await api.listFolders();
|
|
7155
7921
|
if (json) {
|
|
@@ -7199,7 +7965,11 @@ function registerAutomationsCommands(program, options = {}) {
|
|
|
7199
7965
|
}
|
|
7200
7966
|
writeLine2(stdout, `Deleted automation folder "${folder.value}".`);
|
|
7201
7967
|
});
|
|
7202
|
-
folders.command("move").description("Move an automation into a folder").argument("<automation>", "automation UUID", parseUuidOrSlugSelector).requiredOption(
|
|
7968
|
+
folders.command("move").description("Move an automation into a folder").argument("<automation>", "automation UUID", parseUuidOrSlugSelector).requiredOption(
|
|
7969
|
+
"--to <folder>",
|
|
7970
|
+
"target folder UUID or exact name (use the root folder to move it out of any folder)",
|
|
7971
|
+
parseUuidOrSlugSelector
|
|
7972
|
+
).action(async function action(automation, commandOptions) {
|
|
7203
7973
|
const { api, json, readOnly } = createAutomationsApi(this, filePath);
|
|
7204
7974
|
ensureWritable("automations folders move", readOnly, "write");
|
|
7205
7975
|
if (!commandOptions.to) {
|
|
@@ -7884,9 +8654,117 @@ var DisplaysApi = class {
|
|
|
7884
8654
|
{ method: "DELETE" }
|
|
7885
8655
|
);
|
|
7886
8656
|
}
|
|
8657
|
+
listFolders() {
|
|
8658
|
+
return this.client.getJson("/api/v2/display-folders");
|
|
8659
|
+
}
|
|
8660
|
+
createFolder(body) {
|
|
8661
|
+
return this.client.requestJson(
|
|
8662
|
+
"/api/v2/display-folders",
|
|
8663
|
+
jsonOptions3(body, "POST")
|
|
8664
|
+
);
|
|
8665
|
+
}
|
|
8666
|
+
updateFolder(folder, body) {
|
|
8667
|
+
return this.client.requestJson(
|
|
8668
|
+
`/api/v2/display-folders/${selectorValue3(folder)}`,
|
|
8669
|
+
jsonOptions3(body, "PATCH")
|
|
8670
|
+
);
|
|
8671
|
+
}
|
|
8672
|
+
deleteFolder(folder) {
|
|
8673
|
+
return this.client.requestJson(
|
|
8674
|
+
`/api/v2/display-folders/${selectorValue3(folder)}`,
|
|
8675
|
+
{ method: "DELETE" }
|
|
8676
|
+
);
|
|
8677
|
+
}
|
|
8678
|
+
moveDisplay(input) {
|
|
8679
|
+
return this.client.requestJson(
|
|
8680
|
+
"/api/v2/display-folders/displays:move",
|
|
8681
|
+
jsonOptions3(input, "POST")
|
|
8682
|
+
);
|
|
8683
|
+
}
|
|
7887
8684
|
};
|
|
7888
8685
|
|
|
8686
|
+
// src/parsers/expressions.ts
|
|
8687
|
+
var supportedComparators = /* @__PURE__ */ new Set([
|
|
8688
|
+
"eq",
|
|
8689
|
+
"neq",
|
|
8690
|
+
"gt",
|
|
8691
|
+
"gte",
|
|
8692
|
+
"lt",
|
|
8693
|
+
"lte",
|
|
8694
|
+
"contains",
|
|
8695
|
+
"in",
|
|
8696
|
+
"is_empty",
|
|
8697
|
+
"is_not_empty"
|
|
8698
|
+
]);
|
|
8699
|
+
var noValueComparators = /* @__PURE__ */ new Set(["is_empty", "is_not_empty"]);
|
|
8700
|
+
function parseColonExpression(input) {
|
|
8701
|
+
const parts = input.split(":");
|
|
8702
|
+
if (parts.length < 2) {
|
|
8703
|
+
throw new Error(`Expected a field:comparator[:value] expression, got "${input}".`);
|
|
8704
|
+
}
|
|
8705
|
+
const field = parts[0]?.trim();
|
|
8706
|
+
const comparator = parts[1]?.trim();
|
|
8707
|
+
if (!field) {
|
|
8708
|
+
throw new Error(`Expected a field before ":", got "${input}".`);
|
|
8709
|
+
}
|
|
8710
|
+
if (!comparator) {
|
|
8711
|
+
throw new Error(`Expected a comparator after "${field}:", got "${input}".`);
|
|
8712
|
+
}
|
|
8713
|
+
return [field, comparator, parts.slice(2).join(":").trim()];
|
|
8714
|
+
}
|
|
8715
|
+
function parseSpaceExpression(input) {
|
|
8716
|
+
const parts = input.trim().split(/\s+/);
|
|
8717
|
+
if (parts.length < 2) {
|
|
8718
|
+
throw new Error(`Expected a field comparator expression, got "${input}".`);
|
|
8719
|
+
}
|
|
8720
|
+
const field = parts[0];
|
|
8721
|
+
const comparator = parts[1];
|
|
8722
|
+
if (!field) {
|
|
8723
|
+
throw new Error(`Expected a field comparator expression, got "${input}".`);
|
|
8724
|
+
}
|
|
8725
|
+
if (!comparator) {
|
|
8726
|
+
throw new Error(`Expected a comparator after "${field}", got "${input}".`);
|
|
8727
|
+
}
|
|
8728
|
+
return [field.trim(), comparator.trim(), parts.slice(2).join(" ").trim()];
|
|
8729
|
+
}
|
|
8730
|
+
function normalizeValue(comparator, rawValue) {
|
|
8731
|
+
if (noValueComparators.has(comparator)) {
|
|
8732
|
+
if (rawValue.length > 0) {
|
|
8733
|
+
throw new Error(`Comparator "${comparator}" does not accept a value.`);
|
|
8734
|
+
}
|
|
8735
|
+
return null;
|
|
8736
|
+
}
|
|
8737
|
+
if (comparator === "in") {
|
|
8738
|
+
const values = rawValue.split(",").map((value) => value.trim()).filter(Boolean);
|
|
8739
|
+
if (values.length === 0) {
|
|
8740
|
+
throw new Error(`Comparator "${comparator}" requires at least one value.`);
|
|
8741
|
+
}
|
|
8742
|
+
return values;
|
|
8743
|
+
}
|
|
8744
|
+
if (rawValue.length === 0) {
|
|
8745
|
+
throw new Error(`Comparator "${comparator}" requires a value.`);
|
|
8746
|
+
}
|
|
8747
|
+
return rawValue;
|
|
8748
|
+
}
|
|
8749
|
+
function parseExpression(input) {
|
|
8750
|
+
const trimmed = input.trim();
|
|
8751
|
+
const [field, comparatorCandidate, rawValue] = trimmed.includes(":") && !trimmed.includes(" ") ? parseColonExpression(trimmed) : parseSpaceExpression(trimmed);
|
|
8752
|
+
if (!supportedComparators.has(comparatorCandidate)) {
|
|
8753
|
+
throw new Error(
|
|
8754
|
+
`Unsupported comparator "${comparatorCandidate}" in expression "${input}".`
|
|
8755
|
+
);
|
|
8756
|
+
}
|
|
8757
|
+
const comparator = comparatorCandidate;
|
|
8758
|
+
return {
|
|
8759
|
+
field,
|
|
8760
|
+
comparator,
|
|
8761
|
+
value: normalizeValue(comparator, rawValue),
|
|
8762
|
+
raw: trimmed
|
|
8763
|
+
};
|
|
8764
|
+
}
|
|
8765
|
+
|
|
7889
8766
|
// src/commands/displays.ts
|
|
8767
|
+
var DATE_DYNAMIC_OPTIONS = "today, thisWeek, thisMonth, thisQuarter, thisSemester, thisYear, next7Days, next30Days, next6Months, next12Months, last12Months";
|
|
7890
8768
|
function getCommandIo4(stdout) {
|
|
7891
8769
|
return stdout ?? process.stdout;
|
|
7892
8770
|
}
|
|
@@ -7950,6 +8828,37 @@ function parseUuidOrSlugSelector3(input) {
|
|
|
7950
8828
|
throw new InvalidArgumentError3(message);
|
|
7951
8829
|
}
|
|
7952
8830
|
}
|
|
8831
|
+
var COMPARATOR_TO_DISPLAY_OPERATOR = {
|
|
8832
|
+
eq: "EQUAL",
|
|
8833
|
+
neq: "NOT_EQUAL",
|
|
8834
|
+
gt: "GREATER",
|
|
8835
|
+
gte: "GREATER_OR_EQUAL",
|
|
8836
|
+
lt: "LESS",
|
|
8837
|
+
lte: "LESS_OR_EQUAL",
|
|
8838
|
+
contains: "CONTAINS",
|
|
8839
|
+
in: "ANY_OF",
|
|
8840
|
+
is_empty: "IS_EMPTY",
|
|
8841
|
+
is_not_empty: "IS_NOT_EMPTY"
|
|
8842
|
+
};
|
|
8843
|
+
function toDisplayFilter(parsed) {
|
|
8844
|
+
const values = parsed.value === null ? [] : Array.isArray(parsed.value) ? [...parsed.value] : [parsed.value];
|
|
8845
|
+
return {
|
|
8846
|
+
origin: { fieldId: parsed.field },
|
|
8847
|
+
comparisonOperator: COMPARATOR_TO_DISPLAY_OPERATOR[parsed.comparator],
|
|
8848
|
+
values
|
|
8849
|
+
};
|
|
8850
|
+
}
|
|
8851
|
+
function parseFilterExpression(input) {
|
|
8852
|
+
try {
|
|
8853
|
+
return parseExpression(input);
|
|
8854
|
+
} catch (error) {
|
|
8855
|
+
const message = error instanceof Error ? error.message : "Invalid filter expression.";
|
|
8856
|
+
throw new InvalidArgumentError3(message);
|
|
8857
|
+
}
|
|
8858
|
+
}
|
|
8859
|
+
function collectFilters(value, previous = []) {
|
|
8860
|
+
return [...previous, parseFilterExpression(value)];
|
|
8861
|
+
}
|
|
7953
8862
|
function readRawObject2(raw, rawFile) {
|
|
7954
8863
|
if (raw && rawFile) {
|
|
7955
8864
|
throw new CliError("invalid_cli_usage", 'Use either "--raw" or "--raw-file", not both.');
|
|
@@ -7984,8 +8893,152 @@ function readNamedJsonOption(raw, rawFile, inlineFlag = "--option", fileFlag = "
|
|
|
7984
8893
|
function isEmptyObject3(value) {
|
|
7985
8894
|
return Object.keys(value).length === 0;
|
|
7986
8895
|
}
|
|
7987
|
-
function
|
|
7988
|
-
return
|
|
8896
|
+
function isPlainObject(value) {
|
|
8897
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8898
|
+
}
|
|
8899
|
+
function deepMerge(target, source) {
|
|
8900
|
+
const out = { ...target };
|
|
8901
|
+
for (const [key, value] of Object.entries(source)) {
|
|
8902
|
+
const existing = out[key];
|
|
8903
|
+
out[key] = isPlainObject(existing) && isPlainObject(value) ? deepMerge(existing, value) : value;
|
|
8904
|
+
}
|
|
8905
|
+
return out;
|
|
8906
|
+
}
|
|
8907
|
+
function assignDefined(target, key, value) {
|
|
8908
|
+
if (value !== void 0) target[key] = value;
|
|
8909
|
+
}
|
|
8910
|
+
function readNamedJsonObject(raw, rawFile, inlineFlag, fileFlag) {
|
|
8911
|
+
const parsed = readNamedJsonOption(raw, rawFile, inlineFlag, fileFlag);
|
|
8912
|
+
if (parsed === void 0) return void 0;
|
|
8913
|
+
if (!isPlainObject(parsed)) {
|
|
8914
|
+
throw new CliError("invalid_cli_usage", `${inlineFlag} payload must be a JSON object.`);
|
|
8915
|
+
}
|
|
8916
|
+
return parsed;
|
|
8917
|
+
}
|
|
8918
|
+
var HIERARCHY_AGGREGATIONS = /* @__PURE__ */ new Set([
|
|
8919
|
+
"SUM",
|
|
8920
|
+
"AVERAGE",
|
|
8921
|
+
"MINIMUM",
|
|
8922
|
+
"MAXIMUM",
|
|
8923
|
+
"COUNT",
|
|
8924
|
+
"COUNT_DISTINCT"
|
|
8925
|
+
]);
|
|
8926
|
+
function parseHierarchyInfo(value) {
|
|
8927
|
+
const idx = value.indexOf(":");
|
|
8928
|
+
if (idx <= 0 || idx === value.length - 1) {
|
|
8929
|
+
throw new CliError("invalid_cli_usage", `--hierarchy-info "${value}" must use the format <id:name>.`);
|
|
8930
|
+
}
|
|
8931
|
+
return { id: value.slice(0, idx).trim(), name: value.slice(idx + 1).trim() };
|
|
8932
|
+
}
|
|
8933
|
+
function parseHierarchyNumber(value) {
|
|
8934
|
+
const parts = value.split(":");
|
|
8935
|
+
if (parts.length < 3) {
|
|
8936
|
+
throw new CliError(
|
|
8937
|
+
"invalid_cli_usage",
|
|
8938
|
+
`--hierarchy-number "${value}" must use the format <id:name:aggregation>.`
|
|
8939
|
+
);
|
|
8940
|
+
}
|
|
8941
|
+
const id = parts[0]?.trim() ?? "";
|
|
8942
|
+
const aggregation = (parts[parts.length - 1]?.trim() ?? "").toUpperCase();
|
|
8943
|
+
const name = parts.slice(1, -1).join(":").trim();
|
|
8944
|
+
if (!id || !name) {
|
|
8945
|
+
throw new CliError(
|
|
8946
|
+
"invalid_cli_usage",
|
|
8947
|
+
`--hierarchy-number "${value}" must use the format <id:name:aggregation>.`
|
|
8948
|
+
);
|
|
8949
|
+
}
|
|
8950
|
+
if (!HIERARCHY_AGGREGATIONS.has(aggregation)) {
|
|
8951
|
+
throw new CliError(
|
|
8952
|
+
"invalid_cli_usage",
|
|
8953
|
+
`--hierarchy-number aggregation "${aggregation}" must be one of SUM, AVERAGE, MINIMUM, MAXIMUM, COUNT, COUNT_DISTINCT.`
|
|
8954
|
+
);
|
|
8955
|
+
}
|
|
8956
|
+
return { id, name, aggregation };
|
|
8957
|
+
}
|
|
8958
|
+
function parseHierarchyMapping(value, flag) {
|
|
8959
|
+
const idx = value.indexOf(":");
|
|
8960
|
+
if (idx <= 0 || idx === value.length - 1) {
|
|
8961
|
+
throw new CliError("invalid_cli_usage", `${flag} "${value}" must use the format <columnId:fieldId>.`);
|
|
8962
|
+
}
|
|
8963
|
+
return { columnId: value.slice(0, idx).trim(), fieldId: value.slice(idx + 1).trim() };
|
|
8964
|
+
}
|
|
8965
|
+
function buildWidgetFieldMapping(options) {
|
|
8966
|
+
const mapping = {};
|
|
8967
|
+
assignDefined(mapping, "columnField", options.columnField);
|
|
8968
|
+
assignDefined(mapping, "swimlaneField", options.swimlaneField);
|
|
8969
|
+
assignDefined(mapping, "startDateField", options.startDateField);
|
|
8970
|
+
assignDefined(mapping, "endDateField", options.endDateField);
|
|
8971
|
+
assignDefined(mapping, "labelField", options.labelField);
|
|
8972
|
+
assignDefined(mapping, "groupField", options.groupField);
|
|
8973
|
+
assignDefined(mapping, "subgroupField", options.subgroupField);
|
|
8974
|
+
assignDefined(mapping, "progressField", options.progressField);
|
|
8975
|
+
const cardConfig = {};
|
|
8976
|
+
assignDefined(cardConfig, "titleField", options.cardTitleField);
|
|
8977
|
+
assignDefined(cardConfig, "category1Field", options.cardCategory1Field);
|
|
8978
|
+
assignDefined(cardConfig, "category2Field", options.cardCategory2Field);
|
|
8979
|
+
assignDefined(cardConfig, "category3Field", options.cardCategory3Field);
|
|
8980
|
+
assignDefined(cardConfig, "category4Field", options.cardCategory4Field);
|
|
8981
|
+
assignDefined(cardConfig, "descriptionField", options.cardDescriptionField);
|
|
8982
|
+
if (Object.keys(cardConfig).length > 0) mapping.cardConfig = cardConfig;
|
|
8983
|
+
const aggregationConfig = {};
|
|
8984
|
+
assignDefined(aggregationConfig, "method", options.aggregationMethod);
|
|
8985
|
+
assignDefined(aggregationConfig, "fieldId", options.aggregationField);
|
|
8986
|
+
if (Object.keys(aggregationConfig).length > 0) mapping.aggregationConfig = aggregationConfig;
|
|
8987
|
+
return Object.keys(mapping).length > 0 ? mapping : void 0;
|
|
8988
|
+
}
|
|
8989
|
+
function buildHierarchyConfig(options) {
|
|
8990
|
+
const base = readNamedJsonObject(
|
|
8991
|
+
options.hierarchyConfig,
|
|
8992
|
+
options.hierarchyConfigFile,
|
|
8993
|
+
"--hierarchy-config",
|
|
8994
|
+
"--hierarchy-config-file"
|
|
8995
|
+
);
|
|
8996
|
+
const patch = {};
|
|
8997
|
+
const columns = {};
|
|
8998
|
+
assignDefined(columns, "label", options.hierarchyLabel);
|
|
8999
|
+
if (options.hierarchyInfo && options.hierarchyInfo.length > 0) {
|
|
9000
|
+
columns.infos = options.hierarchyInfo.map(parseHierarchyInfo);
|
|
9001
|
+
}
|
|
9002
|
+
if (options.hierarchyNumber && options.hierarchyNumber.length > 0) {
|
|
9003
|
+
columns.numbers = options.hierarchyNumber.map(parseHierarchyNumber);
|
|
9004
|
+
}
|
|
9005
|
+
if (Object.keys(columns).length > 0) patch.columns = columns;
|
|
9006
|
+
const rootLevel = {};
|
|
9007
|
+
assignDefined(rootLevel, "name", options.hierarchyRootName);
|
|
9008
|
+
assignDefined(rootLevel, "labelFieldId", options.hierarchyRootLabelField);
|
|
9009
|
+
if (options.hierarchyRootInfo && options.hierarchyRootInfo.length > 0) {
|
|
9010
|
+
rootLevel.infoMappings = options.hierarchyRootInfo.map(
|
|
9011
|
+
(entry) => parseHierarchyMapping(entry, "--hierarchy-root-info")
|
|
9012
|
+
);
|
|
9013
|
+
}
|
|
9014
|
+
if (options.hierarchyRootNumber && options.hierarchyRootNumber.length > 0) {
|
|
9015
|
+
rootLevel.numberMappings = options.hierarchyRootNumber.map(
|
|
9016
|
+
(entry) => parseHierarchyMapping(entry, "--hierarchy-root-number")
|
|
9017
|
+
);
|
|
9018
|
+
}
|
|
9019
|
+
if (Object.keys(rootLevel).length > 0) patch.rootLevel = rootLevel;
|
|
9020
|
+
if (options.hierarchyChild && options.hierarchyChild.length > 0) {
|
|
9021
|
+
patch.childLevels = options.hierarchyChild.map((entry, index) => {
|
|
9022
|
+
let parsed;
|
|
9023
|
+
try {
|
|
9024
|
+
parsed = JSON.parse(entry);
|
|
9025
|
+
} catch {
|
|
9026
|
+
throw new CliError("invalid_cli_usage", `--hierarchy-child payload #${index + 1} is invalid JSON.`);
|
|
9027
|
+
}
|
|
9028
|
+
if (!isPlainObject(parsed)) {
|
|
9029
|
+
throw new CliError(
|
|
9030
|
+
"invalid_cli_usage",
|
|
9031
|
+
`--hierarchy-child payload #${index + 1} must be a JSON object.`
|
|
9032
|
+
);
|
|
9033
|
+
}
|
|
9034
|
+
return parsed;
|
|
9035
|
+
});
|
|
9036
|
+
}
|
|
9037
|
+
if (base === void 0 && Object.keys(patch).length === 0) return void 0;
|
|
9038
|
+
return deepMerge(base ?? {}, patch);
|
|
9039
|
+
}
|
|
9040
|
+
function displayRows(displays) {
|
|
9041
|
+
return displays.map((display) => ({
|
|
7989
9042
|
id: display.id,
|
|
7990
9043
|
name: display.name ?? "",
|
|
7991
9044
|
layoutTemplate: display.layoutTemplate ?? "",
|
|
@@ -7999,6 +9052,31 @@ function getDisplaySubresource(value) {
|
|
|
7999
9052
|
}
|
|
8000
9053
|
return value.filter((entry) => Boolean(entry) && typeof entry === "object");
|
|
8001
9054
|
}
|
|
9055
|
+
function displayFolderRows(folders) {
|
|
9056
|
+
return folders.map((folder) => ({
|
|
9057
|
+
id: folder.id ?? "",
|
|
9058
|
+
name: folder.name ?? "",
|
|
9059
|
+
isRoot: folder.isRoot ?? "",
|
|
9060
|
+
displayCount: folder.displayCount ?? ""
|
|
9061
|
+
}));
|
|
9062
|
+
}
|
|
9063
|
+
async function resolveDisplayFolderId(api, selector) {
|
|
9064
|
+
if (selector.kind === "uuid") {
|
|
9065
|
+
return selector.value;
|
|
9066
|
+
}
|
|
9067
|
+
const folders = await api.listFolders();
|
|
9068
|
+
const matches = folders.filter((folder) => folder.name === selector.value);
|
|
9069
|
+
if (matches.length === 1 && typeof matches[0]?.id === "string" && matches[0].id.length > 0) {
|
|
9070
|
+
return matches[0].id;
|
|
9071
|
+
}
|
|
9072
|
+
if (matches.length > 1) {
|
|
9073
|
+
throw new CliError(
|
|
9074
|
+
"invalid_cli_usage",
|
|
9075
|
+
`Folder "${selector.value}" is ambiguous. Found ${matches.length} matches.`
|
|
9076
|
+
);
|
|
9077
|
+
}
|
|
9078
|
+
throw new CliError("invalid_cli_usage", `Folder "${selector.value}" was not found.`);
|
|
9079
|
+
}
|
|
8002
9080
|
function buildVariableBody(options) {
|
|
8003
9081
|
const body = {
|
|
8004
9082
|
...readRawObject2(options.raw, options.rawFile)
|
|
@@ -8016,7 +9094,7 @@ function buildVariableBody(options) {
|
|
|
8016
9094
|
};
|
|
8017
9095
|
}
|
|
8018
9096
|
if (options.filter && options.filter.length > 0) {
|
|
8019
|
-
body.filters = options.filter.map(
|
|
9097
|
+
body.filters = options.filter.map(toDisplayFilter);
|
|
8020
9098
|
}
|
|
8021
9099
|
if (options.dateMode || options.dateDynamicOption || options.dateSpecific || options.dateRangeStart || options.dateRangeEnd) {
|
|
8022
9100
|
body.date = {
|
|
@@ -8065,15 +9143,39 @@ function buildWidgetBody(options) {
|
|
|
8065
9143
|
layout
|
|
8066
9144
|
};
|
|
8067
9145
|
}
|
|
8068
|
-
|
|
8069
|
-
|
|
8070
|
-
|
|
8071
|
-
|
|
8072
|
-
|
|
9146
|
+
const viewPatch = {};
|
|
9147
|
+
if (options.field && options.field.length > 0) {
|
|
9148
|
+
viewPatch.fields = options.field;
|
|
9149
|
+
}
|
|
9150
|
+
const fieldMapping = buildWidgetFieldMapping(options);
|
|
9151
|
+
const viewStateBase = readNamedJsonObject(
|
|
9152
|
+
options.viewState,
|
|
9153
|
+
options.viewStateFile,
|
|
9154
|
+
"--view-state",
|
|
9155
|
+
"--view-state-file"
|
|
9156
|
+
);
|
|
9157
|
+
let viewState = viewStateBase ? { ...viewStateBase } : void 0;
|
|
9158
|
+
if (fieldMapping) {
|
|
9159
|
+
viewState = deepMerge(viewState ?? {}, { fieldMapping });
|
|
9160
|
+
}
|
|
9161
|
+
if (viewState !== void 0) {
|
|
9162
|
+
viewPatch.viewAdditionalProperties = { viewState };
|
|
9163
|
+
}
|
|
9164
|
+
const hierarchyConfig = buildHierarchyConfig(options);
|
|
9165
|
+
if (hierarchyConfig !== void 0) {
|
|
9166
|
+
viewPatch.hierarchyConfig = hierarchyConfig;
|
|
9167
|
+
}
|
|
9168
|
+
if (Object.keys(viewPatch).length > 0) {
|
|
9169
|
+
const existingView = typeof body.view === "object" && body.view ? body.view : {};
|
|
9170
|
+
body.view = deepMerge(existingView, viewPatch);
|
|
9171
|
+
}
|
|
9172
|
+
const queryMerge = {};
|
|
9173
|
+
if (options.sort && options.sort.length > 0) queryMerge.sorts = options.sort;
|
|
9174
|
+
if (options.filter && options.filter.length > 0) queryMerge.filters = options.filter.map(toDisplayFilter);
|
|
9175
|
+
if (Object.keys(queryMerge).length > 0) {
|
|
8073
9176
|
body.query = {
|
|
8074
9177
|
...typeof body.query === "object" && body.query ? body.query : {},
|
|
8075
|
-
|
|
8076
|
-
filters: options.filter?.map((entry) => ({ raw: entry }))
|
|
9178
|
+
...queryMerge
|
|
8077
9179
|
};
|
|
8078
9180
|
}
|
|
8079
9181
|
if (options.widgetReadOnly !== void 0 || options.hideAddButton !== void 0 || options.hideDeleteButton !== void 0 || options.hideSortButton !== void 0 || options.hideFilterButton !== void 0 || options.hideSeeButton !== void 0) {
|
|
@@ -8200,6 +9302,72 @@ function registerDisplaysCommands(program, options = {}) {
|
|
|
8200
9302
|
}
|
|
8201
9303
|
writeLine4(stdout, `Deleted display "${display.value}".`);
|
|
8202
9304
|
});
|
|
9305
|
+
const folders = displays.command("folders").description("Manage display folders (flat: a folder only has a name, no order or properties)");
|
|
9306
|
+
folders.command("list").description("List display folders (non-root folders plus the root bucket, whose name is null)").action(async function action() {
|
|
9307
|
+
const { api, json } = createDisplaysApi(this, filePath);
|
|
9308
|
+
const data = await api.listFolders();
|
|
9309
|
+
if (json) {
|
|
9310
|
+
emitJson4(stdout, "displays folders list", data);
|
|
9311
|
+
return;
|
|
9312
|
+
}
|
|
9313
|
+
printTable(displayFolderRows(data), ["id", "name", "isRoot", "displayCount"], stdout);
|
|
9314
|
+
});
|
|
9315
|
+
folders.command("create").description("Create a display folder").requiredOption("--name <name>", "folder name").action(async function action(commandOptions) {
|
|
9316
|
+
const { api, json, readOnly } = createDisplaysApi(this, filePath);
|
|
9317
|
+
ensureWritable3("displays folders create", readOnly, "write");
|
|
9318
|
+
if (commandOptions.name === void 0) {
|
|
9319
|
+
throw new CliError("invalid_cli_usage", 'Provide folder name via "--name".');
|
|
9320
|
+
}
|
|
9321
|
+
const data = await api.createFolder({ name: commandOptions.name });
|
|
9322
|
+
if (json) {
|
|
9323
|
+
emitJson4(stdout, "displays folders create", data);
|
|
9324
|
+
return;
|
|
9325
|
+
}
|
|
9326
|
+
writeLine4(stdout, `Created display folder "${String(data.name ?? commandOptions.name)}".`);
|
|
9327
|
+
});
|
|
9328
|
+
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) {
|
|
9329
|
+
const { api, json, readOnly } = createDisplaysApi(this, filePath);
|
|
9330
|
+
ensureWritable3("displays folders update", readOnly, "write");
|
|
9331
|
+
if (commandOptions.name === void 0) {
|
|
9332
|
+
throw new CliError("invalid_cli_usage", 'Provide folder name via "--name".');
|
|
9333
|
+
}
|
|
9334
|
+
const folderId = await resolveDisplayFolderId(api, folder);
|
|
9335
|
+
const data = await api.updateFolder({ kind: "uuid", value: folderId }, { name: commandOptions.name });
|
|
9336
|
+
if (json) {
|
|
9337
|
+
emitJson4(stdout, "displays folders update", data);
|
|
9338
|
+
return;
|
|
9339
|
+
}
|
|
9340
|
+
writeLine4(stdout, `Updated display folder "${String(data.name ?? folder.value)}".`);
|
|
9341
|
+
});
|
|
9342
|
+
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) {
|
|
9343
|
+
const { api, json, readOnly } = createDisplaysApi(this, filePath);
|
|
9344
|
+
ensureWritable3("displays folders delete", readOnly, "destructive");
|
|
9345
|
+
const folderId = await resolveDisplayFolderId(api, folder);
|
|
9346
|
+
const data = await api.deleteFolder({ kind: "uuid", value: folderId });
|
|
9347
|
+
if (json) {
|
|
9348
|
+
emitJson4(stdout, "displays folders delete", data);
|
|
9349
|
+
return;
|
|
9350
|
+
}
|
|
9351
|
+
writeLine4(stdout, `Deleted display folder "${folder.value}".`);
|
|
9352
|
+
});
|
|
9353
|
+
folders.command("move").description("Move a display into a folder").argument("<display>", "display UUID", parseUuidOrSlugSelector3).requiredOption(
|
|
9354
|
+
"--to <folder>",
|
|
9355
|
+
"target folder UUID or exact name (use the root folder to move it out of any folder)",
|
|
9356
|
+
parseUuidOrSlugSelector3
|
|
9357
|
+
).action(async function action(display, commandOptions) {
|
|
9358
|
+
const { api, json, readOnly } = createDisplaysApi(this, filePath);
|
|
9359
|
+
ensureWritable3("displays folders move", readOnly, "write");
|
|
9360
|
+
if (!commandOptions.to) {
|
|
9361
|
+
throw new CliError("invalid_cli_usage", 'Provide target folder via "--to".');
|
|
9362
|
+
}
|
|
9363
|
+
const targetFolderId = await resolveDisplayFolderId(api, commandOptions.to);
|
|
9364
|
+
const data = await api.moveDisplay({ displayId: display.value, targetFolderId });
|
|
9365
|
+
if (json) {
|
|
9366
|
+
emitJson4(stdout, "displays folders move", data);
|
|
9367
|
+
return;
|
|
9368
|
+
}
|
|
9369
|
+
writeLine4(stdout, `Moved display "${display.value}" to folder "${targetFolderId}".`);
|
|
9370
|
+
});
|
|
8203
9371
|
const layout = displays.command("layout").description("Manage display layout");
|
|
8204
9372
|
layout.command("get").description("Get display layout").argument("<display>", "display uuid or slug", parseUuidOrSlugSelector3).action(async function action(display) {
|
|
8205
9373
|
const { api, json } = createDisplaysApi(this, filePath);
|
|
@@ -8288,7 +9456,7 @@ function registerDisplaysCommands(program, options = {}) {
|
|
|
8288
9456
|
}
|
|
8289
9457
|
printTable([match], void 0, stdout);
|
|
8290
9458
|
});
|
|
8291
|
-
variables.command("create").description("Create variable").argument("<display>", "display uuid or slug", parseUuidOrSlugSelector3).option("--type <type>").option("--name <name>").option("--allow-multiple").option("--static").option("--default <value>").option("--default-value <value>", "repeatable default value", (v, p = []) => [...p, v], []).option("--source-schema <id>").option("--source-field <id>").option("--filter <expr>", "repeatable filter",
|
|
9459
|
+
variables.command("create").description("Create variable").argument("<display>", "display uuid or slug", parseUuidOrSlugSelector3).option("--type <type>").option("--name <name>").option("--allow-multiple").option("--static").option("--default <value>").option("--default-value <value>", "repeatable default value", (v, p = []) => [...p, v], []).option("--source-schema <id>").option("--source-field <id>").option("--filter <expr>", "repeatable filter", collectFilters, []).option("--date-mode <mode>").option("--date-dynamic-option <option>", `dynamic date period (${DATE_DYNAMIC_OPTIONS})`).option("--date-specific <iso>").option("--date-range-start <iso>").option("--date-range-end <iso>").option("--raw <json>").option("--raw-file <path>").action(async function action(display, commandOptions) {
|
|
8292
9460
|
const { api, json, readOnly } = createDisplaysApi(this, filePath);
|
|
8293
9461
|
ensureWritable3("displays variables create", readOnly, "write");
|
|
8294
9462
|
const data = await api.createVariable(display, buildVariableBody(commandOptions));
|
|
@@ -8298,7 +9466,7 @@ function registerDisplaysCommands(program, options = {}) {
|
|
|
8298
9466
|
}
|
|
8299
9467
|
writeLine4(stdout, `Created variable on display "${display.value}".`);
|
|
8300
9468
|
});
|
|
8301
|
-
variables.command("update").description("Update variable").argument("<display>", "display uuid or slug", parseUuidOrSlugSelector3).argument("<variable>", "variable id").option("--type <type>").option("--name <name>").option("--allow-multiple").option("--static").option("--default <value>").option("--default-value <value>", "repeatable default value", (v, p = []) => [...p, v], []).option("--source-schema <id>").option("--source-field <id>").option("--filter <expr>", "repeatable filter",
|
|
9469
|
+
variables.command("update").description("Update variable").argument("<display>", "display uuid or slug", parseUuidOrSlugSelector3).argument("<variable>", "variable id").option("--type <type>").option("--name <name>").option("--allow-multiple").option("--static").option("--default <value>").option("--default-value <value>", "repeatable default value", (v, p = []) => [...p, v], []).option("--source-schema <id>").option("--source-field <id>").option("--filter <expr>", "repeatable filter", collectFilters, []).option("--date-mode <mode>").option("--date-dynamic-option <option>", `dynamic date period (${DATE_DYNAMIC_OPTIONS})`).option("--date-specific <iso>").option("--date-range-start <iso>").option("--date-range-end <iso>").option("--raw <json>").option("--raw-file <path>").action(async function action(display, variableId, commandOptions) {
|
|
8302
9470
|
const { api, json, readOnly } = createDisplaysApi(this, filePath);
|
|
8303
9471
|
ensureWritable3("displays variables update", readOnly, "write");
|
|
8304
9472
|
const data = await api.updateVariable(display, variableId, buildVariableBody(commandOptions));
|
|
@@ -8338,117 +9506,520 @@ function registerDisplaysCommands(program, options = {}) {
|
|
|
8338
9506
|
}
|
|
8339
9507
|
printTable([data], void 0, stdout);
|
|
8340
9508
|
});
|
|
8341
|
-
widgets.command("create").description("Create widget").argument("<display>", "display uuid or slug", parseUuidOrSlugSelector3).requiredOption("--type <type>", "widget type").option("--name <name>").option("--description <text>").option("--icon <icon>").option("--color <color>").option("--origin-resource <uuid>").option("--origin-subschema").option("--tab <tabId>").option("--slot <slotId>").option("--layout <json>").option("--layout-file <path>").option("--field <field>", "repeatable field", (v, p = []) => [...p, v], []).option("--sort <sort>", "repeatable sort", (v, p = []) => [...p, v], []).option("--filter <expr>", "repeatable filter",
|
|
9509
|
+
widgets.command("create").description("Create widget").argument("<display>", "display uuid or slug", parseUuidOrSlugSelector3).requiredOption("--type <type>", "widget type").option("--name <name>").option("--description <text>").option("--icon <icon>").option("--color <color>").option("--origin-resource <uuid>").option("--origin-subschema").option("--tab <tabId>").option("--slot <slotId>").option("--layout <json>").option("--layout-file <path>").option("--field <field>", "repeatable field", (v, p = []) => [...p, v], []).option("--sort <sort>", "repeatable sort", (v, p = []) => [...p, v], []).option("--filter <expr>", "repeatable filter", collectFilters, []).option("--widget-read-only").option("--hide-add-button").option("--hide-delete-button").option("--hide-sort-button").option("--hide-filter-button").option("--hide-see-button").option("--calc <type>").option("--calc-field <uuid>").option("--kpi-config <json>").option("--chart-type <type>", "chart type (lines, bars, stackedBars, combined)").option("--x-axis-field <uuid>").option("--x-axis-date-format <granularity>", "time granularity (DATE, MONTH_YEAR, QUARTER_YEAR, YEAR)").option("--x-axis-time-series").option("--y-axis-serie <json>", "repeatable y axis serie", (v, p = []) => [...p, v], []).option("--legend <json>").option("--column-field <uuid>", "KANBAN column field (UUID, not slug)").option("--swimlane-field <uuid>", "KANBAN swimlane field (UUID, not slug)").option("--start-date-field <uuid>", "TIMELINE start date field (UUID, not slug)").option("--end-date-field <uuid>", "TIMELINE end date field (UUID, not slug)").option("--label-field <uuid>", "TIMELINE label field (UUID, not slug)").option("--group-field <uuid>", "TIMELINE group field (UUID, not slug)").option("--subgroup-field <uuid>", "TIMELINE subgroup field (UUID, not slug)").option("--progress-field <uuid>", "TIMELINE progress field (UUID, not slug)").option("--card-title-field <uuid>", "KANBAN/TIMELINE card title field (UUID, not slug)").option("--card-category1-field <uuid>", "KANBAN/TIMELINE card category 1 field (UUID, not slug)").option("--card-category2-field <uuid>", "KANBAN/TIMELINE card category 2 field (UUID, not slug)").option("--card-category3-field <uuid>", "KANBAN card category 3 field (UUID, not slug)").option("--card-category4-field <uuid>", "TIMELINE card category 4 field (UUID, not slug)").option("--card-description-field <uuid>", "KANBAN/TIMELINE card description field (UUID, not slug)").option("--aggregation-method <method>", "KANBAN card aggregation method (e.g. sum)").option("--aggregation-field <uuid>", "KANBAN card aggregation field (UUID, not slug)").option("--view-state <json>", "KANBAN/TIMELINE viewState UI scalars (columnOrder, granularity, sidebarWidth, show* ...)").option("--view-state-file <path>", "read --view-state JSON from a file").option("--hierarchy-label <name>", "HIERARCHY label column name").option("--hierarchy-info <id:name>", "HIERARCHY info column; id is a unique opaque column id you choose (e.g. col_1779975207355_zfndknslw), not the name, and is reused as columnId in mappings (repeatable)", (v, p = []) => [...p, v], []).option("--hierarchy-number <id:name:aggregation>", "HIERARCHY number column; id is a unique opaque column id (e.g. col_1779975207355_zfndknslw), not the name; aggregation SUM|AVERAGE|MINIMUM|MAXIMUM|COUNT|COUNT_DISTINCT (repeatable)", (v, p = []) => [...p, v], []).option("--hierarchy-root-name <name>", "HIERARCHY root level name").option("--hierarchy-root-label-field <uuid>", "HIERARCHY root level label field (UUID, not slug)").option("--hierarchy-root-info <columnId:fieldId>", "HIERARCHY root info mapping; columnId must match a --hierarchy-info id (repeatable)", (v, p = []) => [...p, v], []).option("--hierarchy-root-number <columnId:fieldId>", "HIERARCHY root number mapping; columnId must match a --hierarchy-number id (repeatable)", (v, p = []) => [...p, v], []).option("--hierarchy-child <json>", "HIERARCHY child level JSON {name,schemaId,childFieldId,labelFieldId,infoMappings,numberMappings} (repeatable)", (v, p = []) => [...p, v], []).option("--hierarchy-config <json>", "HIERARCHY full hierarchyConfig JSON (escape hatch)").option("--hierarchy-config-file <path>", "read --hierarchy-config JSON from a file").option("--raw <json>").option("--raw-file <path>").action(async function action(display, commandOptions) {
|
|
8342
9510
|
const { api, json, readOnly } = createDisplaysApi(this, filePath);
|
|
8343
9511
|
ensureWritable3("displays widgets create", readOnly, "write");
|
|
8344
9512
|
const data = await api.createWidget(display, buildWidgetBody(commandOptions));
|
|
8345
9513
|
if (json) {
|
|
8346
|
-
emitJson4(stdout, "displays widgets create", data);
|
|
9514
|
+
emitJson4(stdout, "displays widgets create", data);
|
|
9515
|
+
return;
|
|
9516
|
+
}
|
|
9517
|
+
writeLine4(stdout, `Created widget on display "${display.value}".`);
|
|
9518
|
+
});
|
|
9519
|
+
widgets.command("update").description("Update widget").argument("<display>", "display uuid or slug", parseUuidOrSlugSelector3).argument("<widget>", "widget id").option("--type <type>").option("--name <name>").option("--description <text>").option("--icon <icon>").option("--color <color>").option("--origin-resource <uuid>").option("--origin-subschema").option("--tab <tabId>").option("--slot <slotId>").option("--layout <json>").option("--layout-file <path>").option("--field <field>", "repeatable field", (v, p = []) => [...p, v], []).option("--sort <sort>", "repeatable sort", (v, p = []) => [...p, v], []).option("--filter <expr>", "repeatable filter", collectFilters, []).option("--widget-read-only").option("--hide-add-button").option("--hide-delete-button").option("--hide-sort-button").option("--hide-filter-button").option("--hide-see-button").option("--calc <type>").option("--calc-field <uuid>").option("--kpi-config <json>").option("--chart-type <type>", "chart type (lines, bars, stackedBars, combined)").option("--x-axis-field <uuid>").option("--x-axis-date-format <granularity>", "time granularity (DATE, MONTH_YEAR, QUARTER_YEAR, YEAR)").option("--x-axis-time-series").option("--y-axis-serie <json>", "repeatable y axis serie", (v, p = []) => [...p, v], []).option("--legend <json>").option("--column-field <uuid>", "KANBAN column field (UUID, not slug)").option("--swimlane-field <uuid>", "KANBAN swimlane field (UUID, not slug)").option("--start-date-field <uuid>", "TIMELINE start date field (UUID, not slug)").option("--end-date-field <uuid>", "TIMELINE end date field (UUID, not slug)").option("--label-field <uuid>", "TIMELINE label field (UUID, not slug)").option("--group-field <uuid>", "TIMELINE group field (UUID, not slug)").option("--subgroup-field <uuid>", "TIMELINE subgroup field (UUID, not slug)").option("--progress-field <uuid>", "TIMELINE progress field (UUID, not slug)").option("--card-title-field <uuid>", "KANBAN/TIMELINE card title field (UUID, not slug)").option("--card-category1-field <uuid>", "KANBAN/TIMELINE card category 1 field (UUID, not slug)").option("--card-category2-field <uuid>", "KANBAN/TIMELINE card category 2 field (UUID, not slug)").option("--card-category3-field <uuid>", "KANBAN card category 3 field (UUID, not slug)").option("--card-category4-field <uuid>", "TIMELINE card category 4 field (UUID, not slug)").option("--card-description-field <uuid>", "KANBAN/TIMELINE card description field (UUID, not slug)").option("--aggregation-method <method>", "KANBAN card aggregation method (e.g. sum)").option("--aggregation-field <uuid>", "KANBAN card aggregation field (UUID, not slug)").option("--view-state <json>", "KANBAN/TIMELINE viewState UI scalars (columnOrder, granularity, sidebarWidth, show* ...)").option("--view-state-file <path>", "read --view-state JSON from a file").option("--hierarchy-label <name>", "HIERARCHY label column name").option("--hierarchy-info <id:name>", "HIERARCHY info column; id is a unique opaque column id you choose (e.g. col_1779975207355_zfndknslw), not the name, and is reused as columnId in mappings (repeatable)", (v, p = []) => [...p, v], []).option("--hierarchy-number <id:name:aggregation>", "HIERARCHY number column; id is a unique opaque column id (e.g. col_1779975207355_zfndknslw), not the name; aggregation SUM|AVERAGE|MINIMUM|MAXIMUM|COUNT|COUNT_DISTINCT (repeatable)", (v, p = []) => [...p, v], []).option("--hierarchy-root-name <name>", "HIERARCHY root level name").option("--hierarchy-root-label-field <uuid>", "HIERARCHY root level label field (UUID, not slug)").option("--hierarchy-root-info <columnId:fieldId>", "HIERARCHY root info mapping; columnId must match a --hierarchy-info id (repeatable)", (v, p = []) => [...p, v], []).option("--hierarchy-root-number <columnId:fieldId>", "HIERARCHY root number mapping; columnId must match a --hierarchy-number id (repeatable)", (v, p = []) => [...p, v], []).option("--hierarchy-child <json>", "HIERARCHY child level JSON {name,schemaId,childFieldId,labelFieldId,infoMappings,numberMappings} (repeatable)", (v, p = []) => [...p, v], []).option("--hierarchy-config <json>", "HIERARCHY full hierarchyConfig JSON (escape hatch)").option("--hierarchy-config-file <path>", "read --hierarchy-config JSON from a file").option("--raw <json>").option("--raw-file <path>").action(async function action(display, widgetId, commandOptions) {
|
|
9520
|
+
const { api, json, readOnly } = createDisplaysApi(this, filePath);
|
|
9521
|
+
ensureWritable3("displays widgets update", readOnly, "write");
|
|
9522
|
+
const data = await api.updateWidget(display, widgetId, buildWidgetBody(commandOptions));
|
|
9523
|
+
if (json) {
|
|
9524
|
+
emitJson4(stdout, "displays widgets update", data);
|
|
9525
|
+
return;
|
|
9526
|
+
}
|
|
9527
|
+
writeLine4(stdout, `Updated widget "${widgetId}".`);
|
|
9528
|
+
});
|
|
9529
|
+
widgets.command("delete").description("Delete widget").argument("<display>", "display uuid or slug", parseUuidOrSlugSelector3).argument("<widget>", "widget id").action(async function action(display, widgetId) {
|
|
9530
|
+
const { api, json, readOnly } = createDisplaysApi(this, filePath);
|
|
9531
|
+
ensureWritable3("displays widgets delete", readOnly, "destructive");
|
|
9532
|
+
const data = await api.deleteWidget(display, widgetId);
|
|
9533
|
+
if (json) {
|
|
9534
|
+
emitJson4(stdout, "displays widgets delete", data);
|
|
9535
|
+
return;
|
|
9536
|
+
}
|
|
9537
|
+
writeLine4(stdout, `Deleted widget "${widgetId}".`);
|
|
9538
|
+
});
|
|
9539
|
+
const targets = displays.command("navigation-targets").description("Manage navigation targets");
|
|
9540
|
+
targets.command("list").description("List navigation targets").argument("<display>", "display uuid or slug", parseUuidOrSlugSelector3).action(async function action(display) {
|
|
9541
|
+
const { api, json } = createDisplaysApi(this, filePath);
|
|
9542
|
+
const data = await api.getDisplay(display);
|
|
9543
|
+
const items = getDisplaySubresource(data.navigationTargets);
|
|
9544
|
+
if (json) {
|
|
9545
|
+
emitJson4(stdout, "displays navigation-targets list", items);
|
|
9546
|
+
return;
|
|
9547
|
+
}
|
|
9548
|
+
printTable(items, void 0, stdout);
|
|
9549
|
+
});
|
|
9550
|
+
targets.command("create").description("Create navigation target").argument("<display>", "display uuid or slug", parseUuidOrSlugSelector3).requiredOption("--source-widget <id>").requiredOption("--target-display <id>").requiredOption("--target-variable <id>").option("--label <label>").action(async function action(display, commandOptions) {
|
|
9551
|
+
const { api, json, readOnly } = createDisplaysApi(this, filePath);
|
|
9552
|
+
ensureWritable3("displays navigation-targets create", readOnly, "write");
|
|
9553
|
+
const data = await api.createNavigationTarget(display, buildNavigationTargetBody(commandOptions));
|
|
9554
|
+
if (json) {
|
|
9555
|
+
emitJson4(stdout, "displays navigation-targets create", data);
|
|
9556
|
+
return;
|
|
9557
|
+
}
|
|
9558
|
+
writeLine4(stdout, `Created navigation target on display "${display.value}".`);
|
|
9559
|
+
});
|
|
9560
|
+
targets.command("update").description("Update navigation target").argument("<display>", "display uuid or slug", parseUuidOrSlugSelector3).argument("<target>", "target id").option("--source-widget <id>").option("--target-display <id>").option("--target-variable <id>").option("--label <label>").action(async function action(display, targetId, commandOptions) {
|
|
9561
|
+
const { api, json, readOnly } = createDisplaysApi(this, filePath);
|
|
9562
|
+
ensureWritable3("displays navigation-targets update", readOnly, "write");
|
|
9563
|
+
const data = await api.updateNavigationTarget(display, targetId, buildNavigationTargetBody(commandOptions));
|
|
9564
|
+
if (json) {
|
|
9565
|
+
emitJson4(stdout, "displays navigation-targets update", data);
|
|
9566
|
+
return;
|
|
9567
|
+
}
|
|
9568
|
+
writeLine4(stdout, `Updated navigation target "${targetId}".`);
|
|
9569
|
+
});
|
|
9570
|
+
targets.command("delete").description("Delete navigation target").argument("<display>", "display uuid or slug", parseUuidOrSlugSelector3).argument("<target>", "target id").action(async function action(display, targetId) {
|
|
9571
|
+
const { api, json, readOnly } = createDisplaysApi(this, filePath);
|
|
9572
|
+
ensureWritable3("displays navigation-targets delete", readOnly, "destructive");
|
|
9573
|
+
const data = await api.deleteNavigationTarget(display, targetId);
|
|
9574
|
+
if (json) {
|
|
9575
|
+
emitJson4(stdout, "displays navigation-targets delete", data);
|
|
9576
|
+
return;
|
|
9577
|
+
}
|
|
9578
|
+
writeLine4(stdout, `Deleted navigation target "${targetId}".`);
|
|
9579
|
+
});
|
|
9580
|
+
const cross = displays.command("cross-widget-filter").description("Manage cross widget filter");
|
|
9581
|
+
cross.command("get").description("Get cross widget filter").argument("<display>", "display uuid or slug", parseUuidOrSlugSelector3).action(async function action(display) {
|
|
9582
|
+
const { api, json } = createDisplaysApi(this, filePath);
|
|
9583
|
+
const data = await api.getDisplay(display);
|
|
9584
|
+
const item = data.crossWidgetFilter ?? null;
|
|
9585
|
+
if (json) {
|
|
9586
|
+
emitJson4(stdout, "displays cross-widget-filter get", item);
|
|
9587
|
+
return;
|
|
9588
|
+
}
|
|
9589
|
+
printTable(item ? [item] : [], void 0, stdout);
|
|
9590
|
+
});
|
|
9591
|
+
cross.command("set").description("Set cross widget filter").argument("<display>", "display uuid or slug", parseUuidOrSlugSelector3).requiredOption("--source-widget <id>").requiredOption("--source-field <id>").requiredOption("--target <widget:field>", "repeatable target", (v, p = []) => [...p, v], []).action(async function action(display, commandOptions) {
|
|
9592
|
+
const { api, json, readOnly } = createDisplaysApi(this, filePath);
|
|
9593
|
+
ensureWritable3("displays cross-widget-filter set", readOnly, "write");
|
|
9594
|
+
const data = await api.setCrossWidgetFilter(display, buildCrossWidgetFilterBody(commandOptions));
|
|
9595
|
+
if (json) {
|
|
9596
|
+
emitJson4(stdout, "displays cross-widget-filter set", data);
|
|
9597
|
+
return;
|
|
9598
|
+
}
|
|
9599
|
+
writeLine4(stdout, `Updated cross widget filter for display "${display.value}".`);
|
|
9600
|
+
});
|
|
9601
|
+
cross.command("delete").description("Delete cross widget filter").argument("<display>", "display uuid or slug", parseUuidOrSlugSelector3).action(async function action(display) {
|
|
9602
|
+
const { api, json, readOnly } = createDisplaysApi(this, filePath);
|
|
9603
|
+
ensureWritable3("displays cross-widget-filter delete", readOnly, "destructive");
|
|
9604
|
+
const data = await api.deleteCrossWidgetFilter(display);
|
|
9605
|
+
if (json) {
|
|
9606
|
+
emitJson4(stdout, "displays cross-widget-filter delete", data);
|
|
9607
|
+
return;
|
|
9608
|
+
}
|
|
9609
|
+
writeLine4(stdout, `Deleted cross widget filter for display "${display.value}".`);
|
|
9610
|
+
});
|
|
9611
|
+
}
|
|
9612
|
+
|
|
9613
|
+
// src/commands/document-templates.ts
|
|
9614
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync2 } from "fs";
|
|
9615
|
+
import { basename } from "path";
|
|
9616
|
+
import { InvalidArgumentError as InvalidArgumentError4 } from "commander";
|
|
9617
|
+
|
|
9618
|
+
// src/api/document-templates.ts
|
|
9619
|
+
function jsonOptions4(body, method) {
|
|
9620
|
+
return {
|
|
9621
|
+
method,
|
|
9622
|
+
headers: {
|
|
9623
|
+
"content-type": "application/json"
|
|
9624
|
+
},
|
|
9625
|
+
body: JSON.stringify(body)
|
|
9626
|
+
};
|
|
9627
|
+
}
|
|
9628
|
+
function selectorValue4(selector) {
|
|
9629
|
+
return encodeURIComponent(selector.value);
|
|
9630
|
+
}
|
|
9631
|
+
function segment3(value) {
|
|
9632
|
+
return encodeURIComponent(value);
|
|
9633
|
+
}
|
|
9634
|
+
var DocumentTemplatesApi = class {
|
|
9635
|
+
constructor(client) {
|
|
9636
|
+
this.client = client;
|
|
9637
|
+
}
|
|
9638
|
+
listTemplates() {
|
|
9639
|
+
return this.client.getJson("/api/v2/document-templates");
|
|
9640
|
+
}
|
|
9641
|
+
createTemplate(input) {
|
|
9642
|
+
return this.client.requestJson(
|
|
9643
|
+
"/api/v2/document-templates",
|
|
9644
|
+
jsonOptions4(input, "POST")
|
|
9645
|
+
);
|
|
9646
|
+
}
|
|
9647
|
+
updateTemplate(template, input) {
|
|
9648
|
+
return this.client.requestJson(
|
|
9649
|
+
`/api/v2/document-templates/${selectorValue4(template)}`,
|
|
9650
|
+
jsonOptions4(input, "PATCH")
|
|
9651
|
+
);
|
|
9652
|
+
}
|
|
9653
|
+
deleteTemplate(template) {
|
|
9654
|
+
return this.client.requestJson(
|
|
9655
|
+
`/api/v2/document-templates/${selectorValue4(template)}`,
|
|
9656
|
+
{ method: "DELETE" }
|
|
9657
|
+
);
|
|
9658
|
+
}
|
|
9659
|
+
addAsset(template, input) {
|
|
9660
|
+
return this.client.requestJson(
|
|
9661
|
+
`/api/v2/document-templates/${selectorValue4(template)}/assets`,
|
|
9662
|
+
{ method: "POST", body: input }
|
|
9663
|
+
);
|
|
9664
|
+
}
|
|
9665
|
+
deleteAsset(template, assetId) {
|
|
9666
|
+
return this.client.requestJson(
|
|
9667
|
+
`/api/v2/document-templates/${selectorValue4(template)}/assets/${segment3(assetId)}`,
|
|
9668
|
+
{ method: "DELETE" }
|
|
9669
|
+
);
|
|
9670
|
+
}
|
|
9671
|
+
downloadAsset(template, assetId) {
|
|
9672
|
+
return this.client.requestBinary(
|
|
9673
|
+
`/api/v2/document-templates/${selectorValue4(template)}/assets/${segment3(assetId)}/download`
|
|
9674
|
+
);
|
|
9675
|
+
}
|
|
9676
|
+
};
|
|
9677
|
+
|
|
9678
|
+
// src/commands/document-templates.ts
|
|
9679
|
+
function getCommandIo5(stdout) {
|
|
9680
|
+
return stdout ?? process.stdout;
|
|
9681
|
+
}
|
|
9682
|
+
function writeLine5(stdout, value) {
|
|
9683
|
+
stdout.write(`${value}
|
|
9684
|
+
`);
|
|
9685
|
+
}
|
|
9686
|
+
function writeBinary(stdout, value) {
|
|
9687
|
+
stdout.write(Buffer.from(value));
|
|
9688
|
+
}
|
|
9689
|
+
function getGlobalOptions5(command) {
|
|
9690
|
+
return command.optsWithGlobals();
|
|
9691
|
+
}
|
|
9692
|
+
function emitJson5(stdout, commandName, data, configPath, meta = {}) {
|
|
9693
|
+
writeLine5(
|
|
9694
|
+
stdout,
|
|
9695
|
+
JSON.stringify(buildJsonSuccess(data, { command: commandName, configPath, ...meta }))
|
|
9696
|
+
);
|
|
9697
|
+
}
|
|
9698
|
+
function toConfigurationError5(filePath, error) {
|
|
9699
|
+
if (error instanceof CliError) {
|
|
9700
|
+
throw error;
|
|
9701
|
+
}
|
|
9702
|
+
if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
|
|
9703
|
+
throw new CliError("configuration_error", `Config file not found at ${filePath}.`);
|
|
9704
|
+
}
|
|
9705
|
+
if (error instanceof Error) {
|
|
9706
|
+
throw new CliError("configuration_error", error.message);
|
|
9707
|
+
}
|
|
9708
|
+
throw error;
|
|
9709
|
+
}
|
|
9710
|
+
function createDocumentTemplatesApi(command, filePath) {
|
|
9711
|
+
try {
|
|
9712
|
+
const config = readRuntimeConfig(filePath);
|
|
9713
|
+
const runtime = resolveRuntimeContext(config, getGlobalOptions5(command));
|
|
9714
|
+
if (!runtime.baseUrl) {
|
|
9715
|
+
throw new CliError(
|
|
9716
|
+
"configuration_error",
|
|
9717
|
+
`Resolved profile "${runtime.profile}" is missing a base URL.`
|
|
9718
|
+
);
|
|
9719
|
+
}
|
|
9720
|
+
return {
|
|
9721
|
+
api: new DocumentTemplatesApi(
|
|
9722
|
+
new ApiClient({
|
|
9723
|
+
baseUrl: runtime.baseUrl,
|
|
9724
|
+
apiKey: runtime.apiKey
|
|
9725
|
+
})
|
|
9726
|
+
),
|
|
9727
|
+
json: runtime.json,
|
|
9728
|
+
readOnly: runtime.readOnly
|
|
9729
|
+
};
|
|
9730
|
+
} catch (error) {
|
|
9731
|
+
toConfigurationError5(filePath, error);
|
|
9732
|
+
}
|
|
9733
|
+
}
|
|
9734
|
+
function ensureWritable4(commandName, readOnly, commandMode) {
|
|
9735
|
+
if (readOnly) {
|
|
9736
|
+
throw new CliError(
|
|
9737
|
+
"command_not_allowed_in_read_only_mode",
|
|
9738
|
+
`Command "${commandName}" is not allowed in read-only mode.`,
|
|
9739
|
+
{
|
|
9740
|
+
commandMode,
|
|
9741
|
+
executionMode: "read-only"
|
|
9742
|
+
}
|
|
9743
|
+
);
|
|
9744
|
+
}
|
|
9745
|
+
}
|
|
9746
|
+
function parseUuidOrSlugSelector4(input) {
|
|
9747
|
+
try {
|
|
9748
|
+
return normalizeUuidOrSlug(input);
|
|
9749
|
+
} catch (error) {
|
|
9750
|
+
const message = error instanceof Error ? error.message : "Invalid selector.";
|
|
9751
|
+
throw new InvalidArgumentError4(message);
|
|
9752
|
+
}
|
|
9753
|
+
}
|
|
9754
|
+
function isJsonObject4(value) {
|
|
9755
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9756
|
+
}
|
|
9757
|
+
function isEmptyObject4(value) {
|
|
9758
|
+
return Object.keys(value).length === 0;
|
|
9759
|
+
}
|
|
9760
|
+
function parseJsonValue2(input, sourceLabel) {
|
|
9761
|
+
try {
|
|
9762
|
+
return JSON.parse(input);
|
|
9763
|
+
} catch (error) {
|
|
9764
|
+
const message = error instanceof Error ? error.message : "Invalid JSON.";
|
|
9765
|
+
throw new CliError(
|
|
9766
|
+
"invalid_cli_usage",
|
|
9767
|
+
`Failed to parse JSON from ${sourceLabel}: ${message}`
|
|
9768
|
+
);
|
|
9769
|
+
}
|
|
9770
|
+
}
|
|
9771
|
+
function readTextFile2(filePath, label) {
|
|
9772
|
+
try {
|
|
9773
|
+
return readFileSync5(filePath, "utf8");
|
|
9774
|
+
} catch (error) {
|
|
9775
|
+
const message = error instanceof Error ? error.message : "Unable to read file.";
|
|
9776
|
+
throw new CliError(
|
|
9777
|
+
"invalid_cli_usage",
|
|
9778
|
+
`Failed to read ${label} from ${filePath}: ${message}`
|
|
9779
|
+
);
|
|
9780
|
+
}
|
|
9781
|
+
}
|
|
9782
|
+
function readJsonObjectOption2(raw, rawFile, rawLabel, rawFileLabel) {
|
|
9783
|
+
if (raw && rawFile) {
|
|
9784
|
+
throw new CliError(
|
|
9785
|
+
"invalid_cli_usage",
|
|
9786
|
+
`Provide either "${rawLabel}" or "${rawFileLabel}", not both.`
|
|
9787
|
+
);
|
|
9788
|
+
}
|
|
9789
|
+
let parsed;
|
|
9790
|
+
if (raw) {
|
|
9791
|
+
parsed = parseJsonValue2(raw, rawLabel);
|
|
9792
|
+
} else if (rawFile) {
|
|
9793
|
+
parsed = parseJsonValue2(readTextFile2(rawFile, rawFileLabel), `${rawFileLabel} ${rawFile}`);
|
|
9794
|
+
} else {
|
|
9795
|
+
return {};
|
|
9796
|
+
}
|
|
9797
|
+
if (!isJsonObject4(parsed)) {
|
|
9798
|
+
throw new CliError(
|
|
9799
|
+
"invalid_cli_usage",
|
|
9800
|
+
`Expected ${raw ? rawLabel : rawFileLabel} to contain a JSON object.`
|
|
9801
|
+
);
|
|
9802
|
+
}
|
|
9803
|
+
return parsed;
|
|
9804
|
+
}
|
|
9805
|
+
function readLocalFile(filePath) {
|
|
9806
|
+
try {
|
|
9807
|
+
return readFileSync5(filePath);
|
|
9808
|
+
} catch (error) {
|
|
9809
|
+
const message = error instanceof Error ? error.message : "Unable to read file.";
|
|
9810
|
+
throw new CliError("invalid_cli_usage", `Failed to read file at ${filePath}: ${message}`);
|
|
9811
|
+
}
|
|
9812
|
+
}
|
|
9813
|
+
function writeDownloadedFile(outputPath, value) {
|
|
9814
|
+
try {
|
|
9815
|
+
writeFileSync2(outputPath, Buffer.from(value));
|
|
9816
|
+
} catch (error) {
|
|
9817
|
+
const message = error instanceof Error ? error.message : "Unable to write file.";
|
|
9818
|
+
throw new CliError(
|
|
9819
|
+
"invalid_cli_usage",
|
|
9820
|
+
`Failed to write downloaded file to ${outputPath}: ${message}`
|
|
9821
|
+
);
|
|
9822
|
+
}
|
|
9823
|
+
}
|
|
9824
|
+
function templateRows(templates) {
|
|
9825
|
+
return templates.map((template) => ({
|
|
9826
|
+
id: template.id ?? "",
|
|
9827
|
+
name: template.name ?? "",
|
|
9828
|
+
assetCount: Array.isArray(template.assets) ? template.assets.length : 0,
|
|
9829
|
+
updatedAt: template.updatedAt ?? ""
|
|
9830
|
+
}));
|
|
9831
|
+
}
|
|
9832
|
+
function resolveTemplate(templates, selector) {
|
|
9833
|
+
if (selector.kind === "uuid") {
|
|
9834
|
+
const match = templates.find((template) => template.id === selector.value);
|
|
9835
|
+
if (match) {
|
|
9836
|
+
return match;
|
|
9837
|
+
}
|
|
9838
|
+
throw new CliError(
|
|
9839
|
+
"invalid_cli_usage",
|
|
9840
|
+
`Document template "${selector.value}" was not found.`
|
|
9841
|
+
);
|
|
9842
|
+
}
|
|
9843
|
+
const matches = templates.filter((template) => template.name === selector.value);
|
|
9844
|
+
if (matches.length === 1) {
|
|
9845
|
+
return matches[0];
|
|
9846
|
+
}
|
|
9847
|
+
if (matches.length > 1) {
|
|
9848
|
+
throw new CliError(
|
|
9849
|
+
"invalid_cli_usage",
|
|
9850
|
+
`Document template "${selector.value}" is ambiguous. Found ${matches.length} matches.`
|
|
9851
|
+
);
|
|
9852
|
+
}
|
|
9853
|
+
throw new CliError(
|
|
9854
|
+
"invalid_cli_usage",
|
|
9855
|
+
`Document template "${selector.value}" was not found.`
|
|
9856
|
+
);
|
|
9857
|
+
}
|
|
9858
|
+
async function resolveTemplateSelector(api, selector) {
|
|
9859
|
+
if (selector.kind === "uuid") {
|
|
9860
|
+
return selector;
|
|
9861
|
+
}
|
|
9862
|
+
const templates = await api.listTemplates();
|
|
9863
|
+
const resolved = resolveTemplate(templates, selector);
|
|
9864
|
+
if (typeof resolved.id !== "string" || resolved.id.length === 0) {
|
|
9865
|
+
throw new CliError(
|
|
9866
|
+
"invalid_cli_usage",
|
|
9867
|
+
`Document template "${selector.value}" is missing an id in the API response.`
|
|
9868
|
+
);
|
|
9869
|
+
}
|
|
9870
|
+
return { kind: "uuid", value: resolved.id };
|
|
9871
|
+
}
|
|
9872
|
+
function buildCreateInput(options) {
|
|
9873
|
+
const raw = readJsonObjectOption2(options.raw, options.rawFile, "--raw", "--raw-file");
|
|
9874
|
+
const input = { ...raw };
|
|
9875
|
+
if (options.name !== void 0) {
|
|
9876
|
+
input.name = options.name;
|
|
9877
|
+
}
|
|
9878
|
+
if (typeof input.name !== "string" || input.name.trim().length === 0) {
|
|
9879
|
+
throw new CliError("invalid_cli_usage", 'Provide template name via "--name".');
|
|
9880
|
+
}
|
|
9881
|
+
if (input.assets === void 0) {
|
|
9882
|
+
input.assets = [];
|
|
9883
|
+
}
|
|
9884
|
+
return input;
|
|
9885
|
+
}
|
|
9886
|
+
function buildUpdateInput(options) {
|
|
9887
|
+
const input = {};
|
|
9888
|
+
if (options.name !== void 0) {
|
|
9889
|
+
input.name = options.name;
|
|
9890
|
+
}
|
|
9891
|
+
if (isEmptyObject4(input)) {
|
|
9892
|
+
throw new CliError("invalid_cli_usage", 'Provide template updates via "--name".');
|
|
9893
|
+
}
|
|
9894
|
+
return input;
|
|
9895
|
+
}
|
|
9896
|
+
function registerDocumentTemplatesCommands(program, options = {}) {
|
|
9897
|
+
const filePath = options.configPath ?? defaultConfigPath;
|
|
9898
|
+
const stdout = getCommandIo5(options.stdout);
|
|
9899
|
+
const templates = program.command("document-templates").description("Manage document templates and their assets");
|
|
9900
|
+
templates.command("list").description("List document templates").action(async function action() {
|
|
9901
|
+
const { api, json } = createDocumentTemplatesApi(this, filePath);
|
|
9902
|
+
const data = await api.listTemplates();
|
|
9903
|
+
if (json) {
|
|
9904
|
+
emitJson5(stdout, "document-templates list", data, filePath);
|
|
8347
9905
|
return;
|
|
8348
9906
|
}
|
|
8349
|
-
|
|
9907
|
+
printTable(templateRows(data), ["id", "name", "assetCount", "updatedAt"], stdout);
|
|
8350
9908
|
});
|
|
8351
|
-
|
|
8352
|
-
const { api, json
|
|
8353
|
-
|
|
8354
|
-
const data =
|
|
9909
|
+
templates.command("get").description("Get a document template by UUID or exact name").argument("<template>", "template UUID or exact name", parseUuidOrSlugSelector4).action(async function action(template) {
|
|
9910
|
+
const { api, json } = createDocumentTemplatesApi(this, filePath);
|
|
9911
|
+
const list = await api.listTemplates();
|
|
9912
|
+
const data = resolveTemplate(list, template);
|
|
8355
9913
|
if (json) {
|
|
8356
|
-
|
|
9914
|
+
emitJson5(stdout, "document-templates get", data, filePath);
|
|
8357
9915
|
return;
|
|
8358
9916
|
}
|
|
8359
|
-
|
|
9917
|
+
printTable([data], void 0, stdout);
|
|
8360
9918
|
});
|
|
8361
|
-
|
|
8362
|
-
const { api, json, readOnly } =
|
|
8363
|
-
|
|
8364
|
-
const data = await api.
|
|
9919
|
+
templates.command("create").description("Create a document template").option("--name <name>", "template name").option("--raw <json>", "raw create JSON payload").option("--raw-file <path>", "path to raw create JSON payload").action(async function action(commandOptions) {
|
|
9920
|
+
const { api, json, readOnly } = createDocumentTemplatesApi(this, filePath);
|
|
9921
|
+
ensureWritable4("document-templates create", readOnly, "write");
|
|
9922
|
+
const data = await api.createTemplate(buildCreateInput(commandOptions));
|
|
8365
9923
|
if (json) {
|
|
8366
|
-
|
|
9924
|
+
emitJson5(stdout, "document-templates create", data, filePath);
|
|
8367
9925
|
return;
|
|
8368
9926
|
}
|
|
8369
|
-
|
|
9927
|
+
writeLine5(stdout, `Created document template "${String(data.name ?? commandOptions.name)}".`);
|
|
8370
9928
|
});
|
|
8371
|
-
|
|
8372
|
-
|
|
8373
|
-
|
|
8374
|
-
const
|
|
8375
|
-
const
|
|
9929
|
+
templates.command("update").description("Rename a document template").argument("<template>", "template UUID or exact name", parseUuidOrSlugSelector4).option("--name <name>", "new template name").action(async function action(template, commandOptions) {
|
|
9930
|
+
const { api, json, readOnly } = createDocumentTemplatesApi(this, filePath);
|
|
9931
|
+
ensureWritable4("document-templates update", readOnly, "write");
|
|
9932
|
+
const resolved = await resolveTemplateSelector(api, template);
|
|
9933
|
+
const data = await api.updateTemplate(resolved, buildUpdateInput(commandOptions));
|
|
8376
9934
|
if (json) {
|
|
8377
|
-
|
|
9935
|
+
emitJson5(stdout, "document-templates update", data, filePath);
|
|
8378
9936
|
return;
|
|
8379
9937
|
}
|
|
8380
|
-
|
|
9938
|
+
writeLine5(stdout, `Updated document template "${String(data.name ?? template.value)}".`);
|
|
8381
9939
|
});
|
|
8382
|
-
|
|
8383
|
-
const { api, json, readOnly } =
|
|
8384
|
-
|
|
8385
|
-
const
|
|
9940
|
+
templates.command("delete").description("Delete a document template (and its assets)").argument("<template>", "template UUID or exact name", parseUuidOrSlugSelector4).action(async function action(template) {
|
|
9941
|
+
const { api, json, readOnly } = createDocumentTemplatesApi(this, filePath);
|
|
9942
|
+
ensureWritable4("document-templates delete", readOnly, "destructive");
|
|
9943
|
+
const resolved = await resolveTemplateSelector(api, template);
|
|
9944
|
+
const data = await api.deleteTemplate(resolved);
|
|
8386
9945
|
if (json) {
|
|
8387
|
-
|
|
9946
|
+
emitJson5(stdout, "document-templates delete", data, filePath);
|
|
8388
9947
|
return;
|
|
8389
9948
|
}
|
|
8390
|
-
|
|
9949
|
+
writeLine5(stdout, `Deleted document template "${template.value}".`);
|
|
8391
9950
|
});
|
|
8392
|
-
|
|
8393
|
-
|
|
8394
|
-
|
|
8395
|
-
|
|
8396
|
-
|
|
8397
|
-
|
|
8398
|
-
|
|
9951
|
+
const assets = templates.command("assets").description("Manage document template assets");
|
|
9952
|
+
assets.command("add").description("Upload an asset file to a document template").argument("<template>", "template UUID or exact name", parseUuidOrSlugSelector4).argument("<path>", "path to the local file").option("--name <name>", "override the asset display name").action(async function action(template, localPath, commandOptions) {
|
|
9953
|
+
const { api, json, readOnly } = createDocumentTemplatesApi(this, filePath);
|
|
9954
|
+
ensureWritable4("document-templates assets add", readOnly, "write");
|
|
9955
|
+
const contents = readLocalFile(localPath);
|
|
9956
|
+
const formData = new FormData();
|
|
9957
|
+
formData.append("file", new Blob([contents]), basename(localPath));
|
|
9958
|
+
if (commandOptions.name !== void 0) {
|
|
9959
|
+
formData.append("name", commandOptions.name);
|
|
8399
9960
|
}
|
|
8400
|
-
|
|
8401
|
-
|
|
8402
|
-
targets.command("delete").description("Delete navigation target").argument("<display>", "display uuid or slug", parseUuidOrSlugSelector3).argument("<target>", "target id").action(async function action(display, targetId) {
|
|
8403
|
-
const { api, json, readOnly } = createDisplaysApi(this, filePath);
|
|
8404
|
-
ensureWritable3("displays navigation-targets delete", readOnly, "destructive");
|
|
8405
|
-
const data = await api.deleteNavigationTarget(display, targetId);
|
|
9961
|
+
const resolved = await resolveTemplateSelector(api, template);
|
|
9962
|
+
const data = await api.addAsset(resolved, formData);
|
|
8406
9963
|
if (json) {
|
|
8407
|
-
|
|
9964
|
+
emitJson5(stdout, "document-templates assets add", data, filePath);
|
|
8408
9965
|
return;
|
|
8409
9966
|
}
|
|
8410
|
-
|
|
9967
|
+
writeLine5(
|
|
9968
|
+
stdout,
|
|
9969
|
+
`Added asset "${commandOptions.name ?? basename(localPath)}" to template "${template.value}".`
|
|
9970
|
+
);
|
|
8411
9971
|
});
|
|
8412
|
-
|
|
8413
|
-
|
|
8414
|
-
|
|
8415
|
-
const
|
|
8416
|
-
const
|
|
9972
|
+
assets.command("delete").description("Delete one asset from a document template").argument("<template>", "template UUID or exact name", parseUuidOrSlugSelector4).argument("<asset>", "asset UUID").action(async function action(template, assetId) {
|
|
9973
|
+
const { api, json, readOnly } = createDocumentTemplatesApi(this, filePath);
|
|
9974
|
+
ensureWritable4("document-templates assets delete", readOnly, "destructive");
|
|
9975
|
+
const resolved = await resolveTemplateSelector(api, template);
|
|
9976
|
+
const data = await api.deleteAsset(resolved, assetId);
|
|
8417
9977
|
if (json) {
|
|
8418
|
-
|
|
9978
|
+
emitJson5(stdout, "document-templates assets delete", data, filePath);
|
|
8419
9979
|
return;
|
|
8420
9980
|
}
|
|
8421
|
-
|
|
9981
|
+
writeLine5(stdout, `Deleted asset "${assetId}" from template "${template.value}".`);
|
|
8422
9982
|
});
|
|
8423
|
-
|
|
8424
|
-
const { api, json
|
|
8425
|
-
|
|
8426
|
-
|
|
8427
|
-
|
|
8428
|
-
|
|
8429
|
-
|
|
9983
|
+
assets.command("download").description("Download the raw bytes of a document template asset").argument("<template>", "template UUID or exact name", parseUuidOrSlugSelector4).argument("<asset>", "asset UUID").option("--output <path>", "write the downloaded bytes to a path").action(async function action(template, assetId, commandOptions) {
|
|
9984
|
+
const { api, json } = createDocumentTemplatesApi(this, filePath);
|
|
9985
|
+
if (json && !commandOptions.output) {
|
|
9986
|
+
throw new CliError(
|
|
9987
|
+
"invalid_cli_usage",
|
|
9988
|
+
'Provide "--output" when using "--json" with "document-templates assets download".'
|
|
9989
|
+
);
|
|
8430
9990
|
}
|
|
8431
|
-
|
|
8432
|
-
|
|
8433
|
-
|
|
8434
|
-
|
|
8435
|
-
|
|
8436
|
-
|
|
8437
|
-
|
|
8438
|
-
|
|
9991
|
+
const resolved = await resolveTemplateSelector(api, template);
|
|
9992
|
+
const data = await api.downloadAsset(resolved, assetId);
|
|
9993
|
+
if (commandOptions.output) {
|
|
9994
|
+
writeDownloadedFile(commandOptions.output, data);
|
|
9995
|
+
if (json) {
|
|
9996
|
+
emitJson5(
|
|
9997
|
+
stdout,
|
|
9998
|
+
"document-templates assets download",
|
|
9999
|
+
{
|
|
10000
|
+
template: resolved.value,
|
|
10001
|
+
asset: assetId,
|
|
10002
|
+
output: commandOptions.output,
|
|
10003
|
+
bytes: data.byteLength
|
|
10004
|
+
},
|
|
10005
|
+
filePath
|
|
10006
|
+
);
|
|
10007
|
+
return;
|
|
10008
|
+
}
|
|
10009
|
+
writeLine5(stdout, `Downloaded asset to "${commandOptions.output}".`);
|
|
8439
10010
|
return;
|
|
8440
10011
|
}
|
|
8441
|
-
|
|
10012
|
+
writeBinary(stdout, data);
|
|
8442
10013
|
});
|
|
8443
10014
|
}
|
|
8444
10015
|
|
|
8445
10016
|
// src/commands/files.ts
|
|
8446
|
-
import { readFileSync as
|
|
8447
|
-
import { basename } from "path";
|
|
8448
|
-
import { InvalidArgumentError as
|
|
10017
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync3 } from "fs";
|
|
10018
|
+
import { basename as basename2 } from "path";
|
|
10019
|
+
import { InvalidArgumentError as InvalidArgumentError5 } from "commander";
|
|
8449
10020
|
|
|
8450
10021
|
// src/api/files.ts
|
|
8451
|
-
function
|
|
10022
|
+
function selectorValue5(selector) {
|
|
8452
10023
|
return selector.value;
|
|
8453
10024
|
}
|
|
8454
10025
|
var FilesApi = class {
|
|
@@ -8462,11 +10033,11 @@ var FilesApi = class {
|
|
|
8462
10033
|
});
|
|
8463
10034
|
}
|
|
8464
10035
|
downloadFile(file) {
|
|
8465
|
-
return this.client.requestBinary(`/api/v2/files/${
|
|
10036
|
+
return this.client.requestBinary(`/api/v2/files/${selectorValue5(file)}`);
|
|
8466
10037
|
}
|
|
8467
10038
|
deleteFile(file) {
|
|
8468
10039
|
return this.client.requestJson(
|
|
8469
|
-
`/api/v2/files/${
|
|
10040
|
+
`/api/v2/files/${selectorValue5(file)}`,
|
|
8470
10041
|
{ method: "DELETE" }
|
|
8471
10042
|
);
|
|
8472
10043
|
}
|
|
@@ -8476,26 +10047,26 @@ var FilesApi = class {
|
|
|
8476
10047
|
};
|
|
8477
10048
|
|
|
8478
10049
|
// src/commands/files.ts
|
|
8479
|
-
function
|
|
10050
|
+
function getCommandIo6(stdout) {
|
|
8480
10051
|
return stdout ?? process.stdout;
|
|
8481
10052
|
}
|
|
8482
|
-
function
|
|
10053
|
+
function writeLine6(stdout, value) {
|
|
8483
10054
|
stdout.write(`${value}
|
|
8484
10055
|
`);
|
|
8485
10056
|
}
|
|
8486
|
-
function
|
|
10057
|
+
function writeBinary2(stdout, value) {
|
|
8487
10058
|
stdout.write(Buffer.from(value));
|
|
8488
10059
|
}
|
|
8489
|
-
function
|
|
10060
|
+
function getGlobalOptions6(command) {
|
|
8490
10061
|
return command.optsWithGlobals();
|
|
8491
10062
|
}
|
|
8492
|
-
function
|
|
8493
|
-
|
|
10063
|
+
function emitJson6(stdout, commandName, data, configPath, meta = {}) {
|
|
10064
|
+
writeLine6(
|
|
8494
10065
|
stdout,
|
|
8495
10066
|
JSON.stringify(buildJsonSuccess(data, { command: commandName, configPath, ...meta }))
|
|
8496
10067
|
);
|
|
8497
10068
|
}
|
|
8498
|
-
function
|
|
10069
|
+
function toConfigurationError6(filePath, error) {
|
|
8499
10070
|
if (error instanceof CliError) {
|
|
8500
10071
|
throw error;
|
|
8501
10072
|
}
|
|
@@ -8510,7 +10081,7 @@ function toConfigurationError5(filePath, error) {
|
|
|
8510
10081
|
function createFilesApi(command, filePath) {
|
|
8511
10082
|
try {
|
|
8512
10083
|
const config = readRuntimeConfig(filePath);
|
|
8513
|
-
const runtime = resolveRuntimeContext(config,
|
|
10084
|
+
const runtime = resolveRuntimeContext(config, getGlobalOptions6(command));
|
|
8514
10085
|
if (!runtime.baseUrl) {
|
|
8515
10086
|
throw new CliError(
|
|
8516
10087
|
"configuration_error",
|
|
@@ -8528,10 +10099,10 @@ function createFilesApi(command, filePath) {
|
|
|
8528
10099
|
readOnly: runtime.readOnly
|
|
8529
10100
|
};
|
|
8530
10101
|
} catch (error) {
|
|
8531
|
-
|
|
10102
|
+
toConfigurationError6(filePath, error);
|
|
8532
10103
|
}
|
|
8533
10104
|
}
|
|
8534
|
-
function
|
|
10105
|
+
function ensureWritable5(commandName, readOnly, commandMode) {
|
|
8535
10106
|
if (readOnly) {
|
|
8536
10107
|
throw new CliError(
|
|
8537
10108
|
"command_not_allowed_in_read_only_mode",
|
|
@@ -8543,28 +10114,28 @@ function ensureWritable4(commandName, readOnly, commandMode) {
|
|
|
8543
10114
|
);
|
|
8544
10115
|
}
|
|
8545
10116
|
}
|
|
8546
|
-
function
|
|
10117
|
+
function parseUuidOrSlugSelector5(input) {
|
|
8547
10118
|
try {
|
|
8548
10119
|
return normalizeUuidOrSlug(input);
|
|
8549
10120
|
} catch (error) {
|
|
8550
10121
|
const message = error instanceof Error ? error.message : "Invalid selector.";
|
|
8551
|
-
throw new
|
|
10122
|
+
throw new InvalidArgumentError5(message);
|
|
8552
10123
|
}
|
|
8553
10124
|
}
|
|
8554
10125
|
function isRecord3(value) {
|
|
8555
10126
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8556
10127
|
}
|
|
8557
|
-
function
|
|
10128
|
+
function readLocalFile2(filePath) {
|
|
8558
10129
|
try {
|
|
8559
|
-
return
|
|
10130
|
+
return readFileSync6(filePath);
|
|
8560
10131
|
} catch (error) {
|
|
8561
10132
|
const message = error instanceof Error ? error.message : "Unable to read file.";
|
|
8562
10133
|
throw new CliError("invalid_cli_usage", `Failed to read file at ${filePath}: ${message}`);
|
|
8563
10134
|
}
|
|
8564
10135
|
}
|
|
8565
|
-
function
|
|
10136
|
+
function writeDownloadedFile2(outputPath, value) {
|
|
8566
10137
|
try {
|
|
8567
|
-
|
|
10138
|
+
writeFileSync3(outputPath, Buffer.from(value));
|
|
8568
10139
|
} catch (error) {
|
|
8569
10140
|
const message = error instanceof Error ? error.message : "Unable to write file.";
|
|
8570
10141
|
throw new CliError(
|
|
@@ -8575,20 +10146,20 @@ function writeDownloadedFile(outputPath, value) {
|
|
|
8575
10146
|
}
|
|
8576
10147
|
function registerFilesCommands(program, options = {}) {
|
|
8577
10148
|
const filePath = options.configPath ?? defaultConfigPath;
|
|
8578
|
-
const stdout =
|
|
10149
|
+
const stdout = getCommandIo6(options.stdout);
|
|
8579
10150
|
const files = program.command("files").description("Manage files and storage");
|
|
8580
10151
|
files.command("upload").description("Upload a local file").argument("<path>", "path to the local file").action(function action(path) {
|
|
8581
10152
|
const { api, json, readOnly } = createFilesApi(this, filePath);
|
|
8582
|
-
|
|
8583
|
-
const contents =
|
|
10153
|
+
ensureWritable5("files upload", readOnly, "write");
|
|
10154
|
+
const contents = readLocalFile2(path);
|
|
8584
10155
|
const formData = new FormData();
|
|
8585
|
-
formData.append("file", new Blob([contents]),
|
|
10156
|
+
formData.append("file", new Blob([contents]), basename2(path));
|
|
8586
10157
|
return api.uploadFile(formData).then((data) => {
|
|
8587
10158
|
if (json) {
|
|
8588
|
-
|
|
10159
|
+
emitJson6(stdout, "files upload", data, filePath);
|
|
8589
10160
|
return;
|
|
8590
10161
|
}
|
|
8591
|
-
|
|
10162
|
+
writeLine6(stdout, `Uploaded file "${basename2(path)}".`);
|
|
8592
10163
|
});
|
|
8593
10164
|
});
|
|
8594
10165
|
files.command("download").description("Download a file").argument("<file>", "file identifier").option("--output <path>", "write the downloaded file to a path").action(function action(file, commandOptions) {
|
|
@@ -8599,12 +10170,12 @@ function registerFilesCommands(program, options = {}) {
|
|
|
8599
10170
|
'Provide "--output" when using "--json" with "files download".'
|
|
8600
10171
|
);
|
|
8601
10172
|
}
|
|
8602
|
-
const fileSelector =
|
|
10173
|
+
const fileSelector = parseUuidOrSlugSelector5(file);
|
|
8603
10174
|
return api.downloadFile(fileSelector).then((data) => {
|
|
8604
10175
|
if (commandOptions.output) {
|
|
8605
|
-
|
|
10176
|
+
writeDownloadedFile2(commandOptions.output, data);
|
|
8606
10177
|
if (json) {
|
|
8607
|
-
|
|
10178
|
+
emitJson6(
|
|
8608
10179
|
stdout,
|
|
8609
10180
|
"files download",
|
|
8610
10181
|
{
|
|
@@ -8616,45 +10187,45 @@ function registerFilesCommands(program, options = {}) {
|
|
|
8616
10187
|
);
|
|
8617
10188
|
return;
|
|
8618
10189
|
}
|
|
8619
|
-
|
|
10190
|
+
writeLine6(stdout, `Downloaded file to "${commandOptions.output}".`);
|
|
8620
10191
|
return;
|
|
8621
10192
|
}
|
|
8622
|
-
|
|
10193
|
+
writeBinary2(stdout, data);
|
|
8623
10194
|
});
|
|
8624
10195
|
});
|
|
8625
10196
|
files.command("delete").description("Delete a file").argument("<file>", "file identifier").action(function action(file) {
|
|
8626
10197
|
const { api, json, readOnly } = createFilesApi(this, filePath);
|
|
8627
|
-
|
|
8628
|
-
const fileSelector =
|
|
10198
|
+
ensureWritable5("files delete", readOnly, "destructive");
|
|
10199
|
+
const fileSelector = parseUuidOrSlugSelector5(file);
|
|
8629
10200
|
return api.deleteFile(fileSelector).then((data) => {
|
|
8630
10201
|
if (json) {
|
|
8631
|
-
|
|
10202
|
+
emitJson6(stdout, "files delete", data, filePath);
|
|
8632
10203
|
return;
|
|
8633
10204
|
}
|
|
8634
|
-
|
|
10205
|
+
writeLine6(stdout, `Deleted file "${fileSelector.value}".`);
|
|
8635
10206
|
});
|
|
8636
10207
|
});
|
|
8637
10208
|
files.command("storage").description("Show storage usage information").action(function action() {
|
|
8638
10209
|
const { api, json } = createFilesApi(this, filePath);
|
|
8639
10210
|
return api.getStorageInfo().then((data) => {
|
|
8640
10211
|
if (json) {
|
|
8641
|
-
|
|
10212
|
+
emitJson6(stdout, "files storage", data, filePath);
|
|
8642
10213
|
return;
|
|
8643
10214
|
}
|
|
8644
10215
|
if (isRecord3(data)) {
|
|
8645
10216
|
printTable([data], Object.keys(data), stdout);
|
|
8646
10217
|
return;
|
|
8647
10218
|
}
|
|
8648
|
-
|
|
10219
|
+
writeLine6(stdout, String(data));
|
|
8649
10220
|
});
|
|
8650
10221
|
});
|
|
8651
10222
|
}
|
|
8652
10223
|
|
|
8653
10224
|
// src/commands/logs.ts
|
|
8654
|
-
import { InvalidArgumentError as
|
|
10225
|
+
import { InvalidArgumentError as InvalidArgumentError6 } from "commander";
|
|
8655
10226
|
|
|
8656
10227
|
// src/api/logs.ts
|
|
8657
|
-
function
|
|
10228
|
+
function selectorValue6(selector) {
|
|
8658
10229
|
return selector.value;
|
|
8659
10230
|
}
|
|
8660
10231
|
var LogsApi = class {
|
|
@@ -8663,29 +10234,29 @@ var LogsApi = class {
|
|
|
8663
10234
|
}
|
|
8664
10235
|
listLogs(schema, recordId) {
|
|
8665
10236
|
return this.client.getJson(
|
|
8666
|
-
`/api/v2/schemas/${
|
|
10237
|
+
`/api/v2/schemas/${selectorValue6(schema)}/records/${recordId}/logs`
|
|
8667
10238
|
);
|
|
8668
10239
|
}
|
|
8669
10240
|
};
|
|
8670
10241
|
|
|
8671
10242
|
// src/commands/logs.ts
|
|
8672
|
-
function
|
|
10243
|
+
function getCommandIo7(stdout) {
|
|
8673
10244
|
return stdout ?? process.stdout;
|
|
8674
10245
|
}
|
|
8675
|
-
function
|
|
10246
|
+
function writeLine7(stdout, value) {
|
|
8676
10247
|
stdout.write(`${value}
|
|
8677
10248
|
`);
|
|
8678
10249
|
}
|
|
8679
|
-
function
|
|
10250
|
+
function getGlobalOptions7(command) {
|
|
8680
10251
|
return command.optsWithGlobals();
|
|
8681
10252
|
}
|
|
8682
|
-
function
|
|
8683
|
-
|
|
10253
|
+
function emitJson7(stdout, commandName, data, ..._extra) {
|
|
10254
|
+
writeLine7(
|
|
8684
10255
|
stdout,
|
|
8685
10256
|
JSON.stringify(buildJsonSuccess(data, { command: commandName }))
|
|
8686
10257
|
);
|
|
8687
10258
|
}
|
|
8688
|
-
function
|
|
10259
|
+
function toConfigurationError7(filePath, error) {
|
|
8689
10260
|
if (error instanceof CliError) {
|
|
8690
10261
|
throw error;
|
|
8691
10262
|
}
|
|
@@ -8700,7 +10271,7 @@ function toConfigurationError6(filePath, error) {
|
|
|
8700
10271
|
function createLogsApi(command, filePath) {
|
|
8701
10272
|
try {
|
|
8702
10273
|
const config = readRuntimeConfig(filePath);
|
|
8703
|
-
const runtime = resolveRuntimeContext(config,
|
|
10274
|
+
const runtime = resolveRuntimeContext(config, getGlobalOptions7(command));
|
|
8704
10275
|
if (!runtime.baseUrl) {
|
|
8705
10276
|
throw new CliError(
|
|
8706
10277
|
"configuration_error",
|
|
@@ -8717,25 +10288,25 @@ function createLogsApi(command, filePath) {
|
|
|
8717
10288
|
json: runtime.json
|
|
8718
10289
|
};
|
|
8719
10290
|
} catch (error) {
|
|
8720
|
-
|
|
10291
|
+
toConfigurationError7(filePath, error);
|
|
8721
10292
|
}
|
|
8722
10293
|
}
|
|
8723
|
-
function
|
|
10294
|
+
function parseUuidOrSlugSelector6(input) {
|
|
8724
10295
|
try {
|
|
8725
10296
|
return normalizeUuidOrSlug(input);
|
|
8726
10297
|
} catch (error) {
|
|
8727
10298
|
const message = error instanceof Error ? error.message : "Invalid selector.";
|
|
8728
|
-
throw new
|
|
10299
|
+
throw new InvalidArgumentError6(message);
|
|
8729
10300
|
}
|
|
8730
10301
|
}
|
|
8731
|
-
function
|
|
10302
|
+
function isJsonObject5(value) {
|
|
8732
10303
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8733
10304
|
}
|
|
8734
10305
|
function toTableRows3(data) {
|
|
8735
10306
|
if (Array.isArray(data)) {
|
|
8736
|
-
return data.map((entry) =>
|
|
10307
|
+
return data.map((entry) => isJsonObject5(entry) ? entry : { value: entry });
|
|
8737
10308
|
}
|
|
8738
|
-
if (
|
|
10309
|
+
if (isJsonObject5(data)) {
|
|
8739
10310
|
return [data];
|
|
8740
10311
|
}
|
|
8741
10312
|
return [{ value: data }];
|
|
@@ -8745,13 +10316,13 @@ function emitTable3(stdout, data) {
|
|
|
8745
10316
|
}
|
|
8746
10317
|
function registerLogsCommands(program, options = {}) {
|
|
8747
10318
|
const filePath = options.configPath ?? defaultConfigPath;
|
|
8748
|
-
const stdout =
|
|
10319
|
+
const stdout = getCommandIo7(options.stdout);
|
|
8749
10320
|
const logs = program.command("logs").description("Inspect record change logs");
|
|
8750
|
-
logs.command("list").description("List change logs for a record").argument("<schema>", "schema uuid or slug",
|
|
10321
|
+
logs.command("list").description("List change logs for a record").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector6).argument("<record>", "record uuid or slug", parseUuidOrSlugSelector6).action(async function action(schema, record) {
|
|
8751
10322
|
const { api, json } = createLogsApi(this, filePath);
|
|
8752
10323
|
const data = await api.listLogs(schema, record.value);
|
|
8753
10324
|
if (json) {
|
|
8754
|
-
|
|
10325
|
+
emitJson7(stdout, "logs list", data, filePath);
|
|
8755
10326
|
return;
|
|
8756
10327
|
}
|
|
8757
10328
|
emitTable3(stdout, data);
|
|
@@ -8759,11 +10330,11 @@ function registerLogsCommands(program, options = {}) {
|
|
|
8759
10330
|
}
|
|
8760
10331
|
|
|
8761
10332
|
// src/commands/navigation.ts
|
|
8762
|
-
import { readFileSync as
|
|
8763
|
-
import { InvalidArgumentError as
|
|
10333
|
+
import { readFileSync as readFileSync7 } from "fs";
|
|
10334
|
+
import { InvalidArgumentError as InvalidArgumentError7 } from "commander";
|
|
8764
10335
|
|
|
8765
10336
|
// src/api/navigation.ts
|
|
8766
|
-
function
|
|
10337
|
+
function jsonOptions5(body, method) {
|
|
8767
10338
|
return {
|
|
8768
10339
|
method,
|
|
8769
10340
|
headers: {
|
|
@@ -8772,7 +10343,7 @@ function jsonOptions4(body, method) {
|
|
|
8772
10343
|
body: JSON.stringify(body)
|
|
8773
10344
|
};
|
|
8774
10345
|
}
|
|
8775
|
-
function
|
|
10346
|
+
function selectorValue7(selector) {
|
|
8776
10347
|
return selector.value;
|
|
8777
10348
|
}
|
|
8778
10349
|
var NavigationApi = class {
|
|
@@ -8785,44 +10356,44 @@ var NavigationApi = class {
|
|
|
8785
10356
|
createFolder(body) {
|
|
8786
10357
|
return this.client.requestJson(
|
|
8787
10358
|
"/api/v2/navigation/folders",
|
|
8788
|
-
|
|
10359
|
+
jsonOptions5(body, "POST")
|
|
8789
10360
|
);
|
|
8790
10361
|
}
|
|
8791
10362
|
updateFolder(folder, body) {
|
|
8792
10363
|
return this.client.requestJson(
|
|
8793
|
-
`/api/v2/navigation/folders/${
|
|
8794
|
-
|
|
10364
|
+
`/api/v2/navigation/folders/${selectorValue7(folder)}`,
|
|
10365
|
+
jsonOptions5(body, "PATCH")
|
|
8795
10366
|
);
|
|
8796
10367
|
}
|
|
8797
10368
|
deleteFolder(folder) {
|
|
8798
10369
|
return this.client.requestJson(
|
|
8799
|
-
`/api/v2/navigation/folders/${
|
|
10370
|
+
`/api/v2/navigation/folders/${selectorValue7(folder)}`,
|
|
8800
10371
|
{ method: "DELETE" }
|
|
8801
10372
|
);
|
|
8802
10373
|
}
|
|
8803
10374
|
moveResource(body) {
|
|
8804
10375
|
return this.client.requestJson(
|
|
8805
10376
|
"/api/v2/navigation/resources:move",
|
|
8806
|
-
|
|
10377
|
+
jsonOptions5(body, "POST")
|
|
8807
10378
|
);
|
|
8808
10379
|
}
|
|
8809
10380
|
};
|
|
8810
10381
|
|
|
8811
10382
|
// src/commands/navigation.ts
|
|
8812
|
-
function
|
|
10383
|
+
function getCommandIo8(stdout) {
|
|
8813
10384
|
return stdout ?? process.stdout;
|
|
8814
10385
|
}
|
|
8815
|
-
function
|
|
10386
|
+
function writeLine8(stdout, value) {
|
|
8816
10387
|
stdout.write(`${value}
|
|
8817
10388
|
`);
|
|
8818
10389
|
}
|
|
8819
|
-
function
|
|
10390
|
+
function getGlobalOptions8(command) {
|
|
8820
10391
|
return command.optsWithGlobals();
|
|
8821
10392
|
}
|
|
8822
|
-
function
|
|
8823
|
-
|
|
10393
|
+
function emitJson8(stdout, commandName, data, configPath) {
|
|
10394
|
+
writeLine8(stdout, JSON.stringify(buildJsonSuccess(data, { command: commandName, configPath })));
|
|
8824
10395
|
}
|
|
8825
|
-
function
|
|
10396
|
+
function toConfigurationError8(filePath, error) {
|
|
8826
10397
|
if (error instanceof CliError) {
|
|
8827
10398
|
throw error;
|
|
8828
10399
|
}
|
|
@@ -8837,7 +10408,7 @@ function toConfigurationError7(filePath, error) {
|
|
|
8837
10408
|
function createNavigationApi(command, filePath) {
|
|
8838
10409
|
try {
|
|
8839
10410
|
const config = readRuntimeConfig(filePath);
|
|
8840
|
-
const runtime = resolveRuntimeContext(config,
|
|
10411
|
+
const runtime = resolveRuntimeContext(config, getGlobalOptions8(command));
|
|
8841
10412
|
if (!runtime.baseUrl) {
|
|
8842
10413
|
throw new CliError("configuration_error", `Resolved profile "${runtime.profile}" is missing a base URL.`);
|
|
8843
10414
|
}
|
|
@@ -8852,10 +10423,10 @@ function createNavigationApi(command, filePath) {
|
|
|
8852
10423
|
readOnly: runtime.readOnly
|
|
8853
10424
|
};
|
|
8854
10425
|
} catch (error) {
|
|
8855
|
-
|
|
10426
|
+
toConfigurationError8(filePath, error);
|
|
8856
10427
|
}
|
|
8857
10428
|
}
|
|
8858
|
-
function
|
|
10429
|
+
function ensureWritable6(commandName, readOnly, mode) {
|
|
8859
10430
|
if (readOnly) {
|
|
8860
10431
|
throw new CliError(
|
|
8861
10432
|
"command_not_allowed_in_read_only_mode",
|
|
@@ -8864,12 +10435,12 @@ function ensureWritable5(commandName, readOnly, mode) {
|
|
|
8864
10435
|
);
|
|
8865
10436
|
}
|
|
8866
10437
|
}
|
|
8867
|
-
function
|
|
10438
|
+
function parseUuidOrSlugSelector7(input) {
|
|
8868
10439
|
try {
|
|
8869
10440
|
return normalizeUuidOrSlug(input);
|
|
8870
10441
|
} catch (error) {
|
|
8871
10442
|
const message = error instanceof Error ? error.message : "Invalid selector.";
|
|
8872
|
-
throw new
|
|
10443
|
+
throw new InvalidArgumentError7(message);
|
|
8873
10444
|
}
|
|
8874
10445
|
}
|
|
8875
10446
|
function parseInteger(value, flagName) {
|
|
@@ -8886,7 +10457,7 @@ function readJsonObject(raw, rawFile) {
|
|
|
8886
10457
|
if (raw && rawFile) {
|
|
8887
10458
|
throw new CliError("invalid_cli_usage", 'Use either "--props" or "--props-file", not both.');
|
|
8888
10459
|
}
|
|
8889
|
-
const source = rawFile ?
|
|
10460
|
+
const source = rawFile ? readFileSync7(rawFile, "utf8") : raw;
|
|
8890
10461
|
if (!source) {
|
|
8891
10462
|
return {};
|
|
8892
10463
|
}
|
|
@@ -8948,41 +10519,41 @@ function folderRows2(folders) {
|
|
|
8948
10519
|
}
|
|
8949
10520
|
function registerNavigationCommands(program, options = {}) {
|
|
8950
10521
|
const filePath = options.configPath ?? defaultConfigPath;
|
|
8951
|
-
const stdout =
|
|
10522
|
+
const stdout = getCommandIo8(options.stdout);
|
|
8952
10523
|
const navigation = program.command("navigation").description("Manage workspace navigation");
|
|
8953
10524
|
const folders = navigation.command("folders").description("Manage navigation folders");
|
|
8954
10525
|
folders.command("list").description("List navigation folders").action(async function action() {
|
|
8955
10526
|
const { api, json } = createNavigationApi(this, filePath);
|
|
8956
10527
|
const data = await api.listFolders();
|
|
8957
10528
|
if (json) {
|
|
8958
|
-
|
|
10529
|
+
emitJson8(stdout, "navigation folders list", data, filePath);
|
|
8959
10530
|
return;
|
|
8960
10531
|
}
|
|
8961
10532
|
printTable(folderRows2(data), ["id", "order", "name", "resourceCount"], stdout);
|
|
8962
10533
|
});
|
|
8963
|
-
folders.command("get").description("Get a navigation folder by UUID or exact name").argument("<folder>", "folder UUID or exact name",
|
|
10534
|
+
folders.command("get").description("Get a navigation folder by UUID or exact name").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector7).action(async function action(folder) {
|
|
8964
10535
|
const { api, json } = createNavigationApi(this, filePath);
|
|
8965
10536
|
const data = await api.listFolders();
|
|
8966
10537
|
const resolved = resolveFolder2(data, folder);
|
|
8967
10538
|
if (json) {
|
|
8968
|
-
|
|
10539
|
+
emitJson8(stdout, "navigation folders get", resolved, filePath);
|
|
8969
10540
|
return;
|
|
8970
10541
|
}
|
|
8971
10542
|
printTable(folderRows2([resolved]), ["id", "order", "name", "resourceCount"], stdout);
|
|
8972
10543
|
});
|
|
8973
|
-
folders.command("create").description("Create a navigation folder").requiredOption("--name <name>", "folder name").option("--order <n>", "
|
|
10544
|
+
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) {
|
|
8974
10545
|
const { api, json, readOnly } = createNavigationApi(this, filePath);
|
|
8975
|
-
|
|
10546
|
+
ensureWritable6("navigation folders create", readOnly, "write");
|
|
8976
10547
|
const data = await api.createFolder(buildFolderBody(commandOptions));
|
|
8977
10548
|
if (json) {
|
|
8978
|
-
|
|
10549
|
+
emitJson8(stdout, "navigation folders create", data, filePath);
|
|
8979
10550
|
return;
|
|
8980
10551
|
}
|
|
8981
|
-
|
|
10552
|
+
writeLine8(stdout, `Created navigation folder "${String(data.name ?? commandOptions.name)}".`);
|
|
8982
10553
|
});
|
|
8983
|
-
folders.command("update").description("Update a navigation folder").argument("<folder>", "folder UUID or exact name",
|
|
10554
|
+
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) {
|
|
8984
10555
|
const { api, json, readOnly } = createNavigationApi(this, filePath);
|
|
8985
|
-
|
|
10556
|
+
ensureWritable6("navigation folders update", readOnly, "write");
|
|
8986
10557
|
const allFolders = await api.listFolders();
|
|
8987
10558
|
const resolved = resolveFolder2(allFolders, folder);
|
|
8988
10559
|
const body = buildFolderBody(commandOptions);
|
|
@@ -8991,54 +10562,55 @@ function registerNavigationCommands(program, options = {}) {
|
|
|
8991
10562
|
}
|
|
8992
10563
|
const data = await api.updateFolder({ kind: "uuid", value: resolved.id }, body);
|
|
8993
10564
|
if (json) {
|
|
8994
|
-
|
|
10565
|
+
emitJson8(stdout, "navigation folders update", data, filePath);
|
|
8995
10566
|
return;
|
|
8996
10567
|
}
|
|
8997
|
-
|
|
10568
|
+
writeLine8(stdout, `Updated navigation folder "${String(data.name ?? resolved.name ?? resolved.id)}".`);
|
|
8998
10569
|
});
|
|
8999
|
-
folders.command("delete").description("Delete a navigation folder").argument("<folder>", "folder UUID or exact name",
|
|
10570
|
+
folders.command("delete").description("Delete a navigation folder").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector7).action(async function action(folder) {
|
|
9000
10571
|
const { api, json, readOnly } = createNavigationApi(this, filePath);
|
|
9001
|
-
|
|
10572
|
+
ensureWritable6("navigation folders delete", readOnly, "destructive");
|
|
9002
10573
|
const allFolders = await api.listFolders();
|
|
9003
10574
|
const resolved = resolveFolder2(allFolders, folder);
|
|
9004
10575
|
const data = await api.deleteFolder({ kind: "uuid", value: resolved.id });
|
|
9005
10576
|
if (json) {
|
|
9006
|
-
|
|
10577
|
+
emitJson8(stdout, "navigation folders delete", data, filePath);
|
|
9007
10578
|
return;
|
|
9008
10579
|
}
|
|
9009
|
-
|
|
10580
|
+
writeLine8(stdout, `Deleted navigation folder "${resolved.name ?? resolved.id}".`);
|
|
9010
10581
|
});
|
|
9011
|
-
navigation.command("resources").description("Manage navigation resources").command("move").description(
|
|
10582
|
+
navigation.command("resources").description("Manage navigation resources").command("move").description(
|
|
10583
|
+
"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."
|
|
10584
|
+
).argument("<resource>", "schema UUID").requiredOption("--to <folder>", "target folder UUID or exact name").action(async function action(resourceId, commandOptions) {
|
|
9012
10585
|
const { api, json, readOnly } = createNavigationApi(this, filePath);
|
|
9013
|
-
|
|
10586
|
+
ensureWritable6("navigation resources move", readOnly, "write");
|
|
9014
10587
|
const allFolders = await api.listFolders();
|
|
9015
|
-
const resolved = resolveFolder2(allFolders,
|
|
10588
|
+
const resolved = resolveFolder2(allFolders, parseUuidOrSlugSelector7(commandOptions.to));
|
|
9016
10589
|
const data = await api.moveResource({
|
|
9017
10590
|
resourceId,
|
|
9018
|
-
resourceType: commandOptions.type.toUpperCase(),
|
|
9019
10591
|
targetFolderId: resolved.id
|
|
9020
10592
|
});
|
|
9021
10593
|
if (json) {
|
|
9022
|
-
|
|
10594
|
+
emitJson8(stdout, "navigation resources move", data, filePath);
|
|
9023
10595
|
return;
|
|
9024
10596
|
}
|
|
9025
|
-
|
|
10597
|
+
writeLine8(stdout, `Moved resource "${resourceId}" to "${resolved.name ?? resolved.id}".`);
|
|
9026
10598
|
});
|
|
9027
10599
|
}
|
|
9028
10600
|
|
|
9029
10601
|
// src/commands/profiles.ts
|
|
9030
|
-
function
|
|
10602
|
+
function getCommandIo9(stdout) {
|
|
9031
10603
|
return stdout ?? process.stdout;
|
|
9032
10604
|
}
|
|
9033
|
-
function
|
|
10605
|
+
function writeLine9(stdout, value) {
|
|
9034
10606
|
stdout.write(`${value}
|
|
9035
10607
|
`);
|
|
9036
10608
|
}
|
|
9037
|
-
function
|
|
10609
|
+
function getGlobalOptions9(command) {
|
|
9038
10610
|
return command.optsWithGlobals();
|
|
9039
10611
|
}
|
|
9040
|
-
function
|
|
9041
|
-
|
|
10612
|
+
function emitJson9(stdout, commandName, data, configPath) {
|
|
10613
|
+
writeLine9(
|
|
9042
10614
|
stdout,
|
|
9043
10615
|
JSON.stringify(buildJsonSuccess(data, { command: commandName, configPath }))
|
|
9044
10616
|
);
|
|
@@ -9094,15 +10666,15 @@ function emitProfilesTable(stdout, data) {
|
|
|
9094
10666
|
}
|
|
9095
10667
|
function registerProfilesCommands(program, options = {}) {
|
|
9096
10668
|
const filePath = options.configPath ?? defaultConfigPath;
|
|
9097
|
-
const stdout =
|
|
10669
|
+
const stdout = getCommandIo9(options.stdout);
|
|
9098
10670
|
const profiles = program.command("profiles").description("Manage local CLI profiles");
|
|
9099
10671
|
profiles.command("list").description("List configured profiles").action(function action() {
|
|
9100
10672
|
const config = readRequiredConfig(filePath);
|
|
9101
10673
|
const data = Object.entries(config.profiles).map(
|
|
9102
10674
|
([name, profile]) => toDisplayProfile(name, profile, config.defaultProfile)
|
|
9103
10675
|
);
|
|
9104
|
-
if (
|
|
9105
|
-
|
|
10676
|
+
if (getGlobalOptions9(this).json) {
|
|
10677
|
+
emitJson9(stdout, "profiles list", data, filePath);
|
|
9106
10678
|
return;
|
|
9107
10679
|
}
|
|
9108
10680
|
emitProfilesTable(stdout, data);
|
|
@@ -9111,8 +10683,8 @@ function registerProfilesCommands(program, options = {}) {
|
|
|
9111
10683
|
const config = readRequiredConfig(filePath);
|
|
9112
10684
|
const profile = getRequiredProfile(config, profileName);
|
|
9113
10685
|
const data = toDisplayProfile(profileName, profile, config.defaultProfile);
|
|
9114
|
-
if (
|
|
9115
|
-
|
|
10686
|
+
if (getGlobalOptions9(this).json) {
|
|
10687
|
+
emitJson9(stdout, "profiles get", data, filePath);
|
|
9116
10688
|
return;
|
|
9117
10689
|
}
|
|
9118
10690
|
emitProfilesTable(stdout, [data]);
|
|
@@ -9126,11 +10698,11 @@ function registerProfilesCommands(program, options = {}) {
|
|
|
9126
10698
|
profile: profileName,
|
|
9127
10699
|
defaultProfile: nextConfig.defaultProfile
|
|
9128
10700
|
};
|
|
9129
|
-
if (
|
|
9130
|
-
|
|
10701
|
+
if (getGlobalOptions9(this).json) {
|
|
10702
|
+
emitJson9(stdout, "profiles use", data, filePath);
|
|
9131
10703
|
return;
|
|
9132
10704
|
}
|
|
9133
|
-
|
|
10705
|
+
writeLine9(stdout, `Using profile "${profileName}".`);
|
|
9134
10706
|
});
|
|
9135
10707
|
profiles.command("add").description("Add a profile to the local config").argument("<profile>", "profile name").requiredOption("--api-key <token>", "API key").option("--base-url <url>", "base URL").action(function action(profileName, commandOptions) {
|
|
9136
10708
|
const config = loadConfigForAdd(filePath);
|
|
@@ -9154,11 +10726,11 @@ function registerProfilesCommands(program, options = {}) {
|
|
|
9154
10726
|
nextConfig.profiles[profileName] ?? {},
|
|
9155
10727
|
nextConfig.defaultProfile
|
|
9156
10728
|
);
|
|
9157
|
-
if (
|
|
9158
|
-
|
|
10729
|
+
if (getGlobalOptions9(this).json) {
|
|
10730
|
+
emitJson9(stdout, "profiles add", data, filePath);
|
|
9159
10731
|
return;
|
|
9160
10732
|
}
|
|
9161
|
-
|
|
10733
|
+
writeLine9(stdout, `Added profile "${profileName}".`);
|
|
9162
10734
|
});
|
|
9163
10735
|
profiles.command("update").description("Update an existing profile").argument("<profile>", "profile name").option("--api-key <token>", "API key").option("--base-url <url>", "base URL").action(function action(profileName, commandOptions) {
|
|
9164
10736
|
if (commandOptions.apiKey === void 0 && commandOptions.baseUrl === void 0) {
|
|
@@ -9180,11 +10752,11 @@ function registerProfilesCommands(program, options = {}) {
|
|
|
9180
10752
|
nextConfig.profiles[profileName] ?? {},
|
|
9181
10753
|
nextConfig.defaultProfile
|
|
9182
10754
|
);
|
|
9183
|
-
if (
|
|
9184
|
-
|
|
10755
|
+
if (getGlobalOptions9(this).json) {
|
|
10756
|
+
emitJson9(stdout, "profiles update", data, filePath);
|
|
9185
10757
|
return;
|
|
9186
10758
|
}
|
|
9187
|
-
|
|
10759
|
+
writeLine9(stdout, `Updated profile "${profileName}".`);
|
|
9188
10760
|
});
|
|
9189
10761
|
profiles.command("remove").description("Remove a profile from the local config").argument("<profile>", "profile name").action(function action(profileName) {
|
|
9190
10762
|
const config = readRequiredConfig(filePath);
|
|
@@ -9195,20 +10767,20 @@ function registerProfilesCommands(program, options = {}) {
|
|
|
9195
10767
|
profile: profileName,
|
|
9196
10768
|
defaultProfile: nextConfig.defaultProfile
|
|
9197
10769
|
};
|
|
9198
|
-
if (
|
|
9199
|
-
|
|
10770
|
+
if (getGlobalOptions9(this).json) {
|
|
10771
|
+
emitJson9(stdout, "profiles remove", data, filePath);
|
|
9200
10772
|
return;
|
|
9201
10773
|
}
|
|
9202
|
-
|
|
10774
|
+
writeLine9(stdout, `Removed profile "${profileName}".`);
|
|
9203
10775
|
});
|
|
9204
10776
|
}
|
|
9205
10777
|
|
|
9206
10778
|
// src/commands/records.ts
|
|
9207
|
-
import { readFileSync as
|
|
9208
|
-
import { InvalidArgumentError as
|
|
10779
|
+
import { readFileSync as readFileSync8 } from "fs";
|
|
10780
|
+
import { InvalidArgumentError as InvalidArgumentError8 } from "commander";
|
|
9209
10781
|
|
|
9210
10782
|
// src/api/records.ts
|
|
9211
|
-
function
|
|
10783
|
+
function jsonOptions6(body, method) {
|
|
9212
10784
|
return {
|
|
9213
10785
|
method,
|
|
9214
10786
|
headers: {
|
|
@@ -9217,7 +10789,7 @@ function jsonOptions5(body, method) {
|
|
|
9217
10789
|
body: JSON.stringify(body)
|
|
9218
10790
|
};
|
|
9219
10791
|
}
|
|
9220
|
-
function
|
|
10792
|
+
function selectorValue8(selector) {
|
|
9221
10793
|
return selector.value;
|
|
9222
10794
|
}
|
|
9223
10795
|
var RecordsApi = class {
|
|
@@ -9232,7 +10804,7 @@ var RecordsApi = class {
|
|
|
9232
10804
|
if (query.offset !== void 0) {
|
|
9233
10805
|
params.set("offset", String(query.offset));
|
|
9234
10806
|
}
|
|
9235
|
-
const path = `/api/v2/schemas/${
|
|
10807
|
+
const path = `/api/v2/schemas/${selectorValue8(schema)}/records`;
|
|
9236
10808
|
const queryString = params.toString();
|
|
9237
10809
|
return this.client.getJson(
|
|
9238
10810
|
queryString ? `${path}?${queryString}` : path
|
|
@@ -9241,36 +10813,36 @@ var RecordsApi = class {
|
|
|
9241
10813
|
queryRecords(schema, query) {
|
|
9242
10814
|
const body = this.normalizeQueryInput(query);
|
|
9243
10815
|
return this.client.requestJson(
|
|
9244
|
-
`/api/v2/schemas/${
|
|
9245
|
-
|
|
10816
|
+
`/api/v2/schemas/${selectorValue8(schema)}/records:query`,
|
|
10817
|
+
jsonOptions6(body, "POST")
|
|
9246
10818
|
);
|
|
9247
10819
|
}
|
|
9248
10820
|
getRecord(schema, record) {
|
|
9249
10821
|
return this.client.getJson(
|
|
9250
|
-
`/api/v2/schemas/${
|
|
10822
|
+
`/api/v2/schemas/${selectorValue8(schema)}/records/${selectorValue8(record)}`
|
|
9251
10823
|
);
|
|
9252
10824
|
}
|
|
9253
|
-
|
|
10825
|
+
createRecords(schema, records) {
|
|
9254
10826
|
return this.client.requestJson(
|
|
9255
|
-
`/api/v2/schemas/${
|
|
9256
|
-
|
|
10827
|
+
`/api/v2/schemas/${selectorValue8(schema)}/records`,
|
|
10828
|
+
jsonOptions6({ records }, "POST")
|
|
9257
10829
|
);
|
|
9258
10830
|
}
|
|
9259
10831
|
updateRecord(schema, record, input) {
|
|
9260
10832
|
return this.client.requestJson(
|
|
9261
|
-
`/api/v2/schemas/${
|
|
9262
|
-
|
|
10833
|
+
`/api/v2/schemas/${selectorValue8(schema)}/records/${selectorValue8(record)}`,
|
|
10834
|
+
jsonOptions6(input, "PATCH")
|
|
9263
10835
|
);
|
|
9264
10836
|
}
|
|
9265
|
-
|
|
10837
|
+
deleteRecords(schema, recordIds) {
|
|
9266
10838
|
return this.client.requestJson(
|
|
9267
|
-
`/api/v2/schemas/${
|
|
9268
|
-
{
|
|
10839
|
+
`/api/v2/schemas/${selectorValue8(schema)}/records:delete`,
|
|
10840
|
+
jsonOptions6({ recordIds }, "POST")
|
|
9269
10841
|
);
|
|
9270
10842
|
}
|
|
9271
10843
|
clearRecords(schema) {
|
|
9272
10844
|
return this.client.requestJson(
|
|
9273
|
-
`/api/v2/schemas/${
|
|
10845
|
+
`/api/v2/schemas/${selectorValue8(schema)}/records:clear`,
|
|
9274
10846
|
{ method: "DELETE" }
|
|
9275
10847
|
);
|
|
9276
10848
|
}
|
|
@@ -9303,7 +10875,7 @@ var RecordsApi = class {
|
|
|
9303
10875
|
};
|
|
9304
10876
|
|
|
9305
10877
|
// src/api/schemas.ts
|
|
9306
|
-
function
|
|
10878
|
+
function jsonOptions7(body, method) {
|
|
9307
10879
|
return {
|
|
9308
10880
|
method,
|
|
9309
10881
|
headers: {
|
|
@@ -9312,7 +10884,7 @@ function jsonOptions6(body, method) {
|
|
|
9312
10884
|
body: JSON.stringify(body)
|
|
9313
10885
|
};
|
|
9314
10886
|
}
|
|
9315
|
-
function
|
|
10887
|
+
function selectorValue9(selector) {
|
|
9316
10888
|
return selector.value;
|
|
9317
10889
|
}
|
|
9318
10890
|
var SchemasApi = class {
|
|
@@ -9323,150 +10895,76 @@ var SchemasApi = class {
|
|
|
9323
10895
|
return this.client.getJson("/api/v2/schemas");
|
|
9324
10896
|
}
|
|
9325
10897
|
getSchema(schema) {
|
|
9326
|
-
return this.client.getJson(`/api/v2/schemas/${
|
|
10898
|
+
return this.client.getJson(`/api/v2/schemas/${selectorValue9(schema)}`);
|
|
9327
10899
|
}
|
|
9328
10900
|
createSchema(input) {
|
|
9329
|
-
return this.client.requestJson("/api/v2/schemas",
|
|
10901
|
+
return this.client.requestJson("/api/v2/schemas", jsonOptions7(input, "POST"));
|
|
9330
10902
|
}
|
|
9331
10903
|
updateSchema(schema, input) {
|
|
9332
10904
|
return this.client.requestJson(
|
|
9333
|
-
`/api/v2/schemas/${
|
|
9334
|
-
|
|
9335
|
-
);
|
|
9336
|
-
}
|
|
9337
|
-
deleteSchema(schema) {
|
|
9338
|
-
return this.client.requestJson(
|
|
9339
|
-
`/api/v2/schemas/${selectorValue8(schema)}`,
|
|
9340
|
-
{ method: "DELETE" }
|
|
9341
|
-
);
|
|
9342
|
-
}
|
|
9343
|
-
async listFields(schema) {
|
|
9344
|
-
const result = await this.getSchema(schema);
|
|
9345
|
-
return Array.isArray(result.fields) ? result.fields : [];
|
|
9346
|
-
}
|
|
9347
|
-
getField(schema, field) {
|
|
9348
|
-
return this.client.getJson(
|
|
9349
|
-
`/api/v2/schemas/${selectorValue8(schema)}/fields/${selectorValue8(field)}`
|
|
9350
|
-
);
|
|
9351
|
-
}
|
|
9352
|
-
createField(schema, input) {
|
|
9353
|
-
return this.client.requestJson(
|
|
9354
|
-
`/api/v2/schemas/${selectorValue8(schema)}/fields`,
|
|
9355
|
-
jsonOptions6(input, "POST")
|
|
10905
|
+
`/api/v2/schemas/${selectorValue9(schema)}`,
|
|
10906
|
+
jsonOptions7(input, "PATCH")
|
|
9356
10907
|
);
|
|
9357
10908
|
}
|
|
9358
|
-
|
|
10909
|
+
setUniqueFields(schema, input) {
|
|
9359
10910
|
return this.client.requestJson(
|
|
9360
|
-
`/api/v2/schemas/${
|
|
9361
|
-
|
|
10911
|
+
`/api/v2/schemas/${selectorValue9(schema)}/unique-fields`,
|
|
10912
|
+
jsonOptions7(input, "PUT")
|
|
9362
10913
|
);
|
|
9363
10914
|
}
|
|
9364
|
-
|
|
10915
|
+
deleteSchema(schema) {
|
|
9365
10916
|
return this.client.requestJson(
|
|
9366
|
-
`/api/v2/schemas/${
|
|
9367
|
-
{ method: "DELETE" }
|
|
9368
|
-
);
|
|
9369
|
-
}
|
|
9370
|
-
};
|
|
9371
|
-
|
|
9372
|
-
// src/parsers/expressions.ts
|
|
9373
|
-
var supportedComparators = /* @__PURE__ */ new Set([
|
|
9374
|
-
"eq",
|
|
9375
|
-
"neq",
|
|
9376
|
-
"gt",
|
|
9377
|
-
"gte",
|
|
9378
|
-
"lt",
|
|
9379
|
-
"lte",
|
|
9380
|
-
"contains",
|
|
9381
|
-
"in",
|
|
9382
|
-
"is_empty",
|
|
9383
|
-
"is_not_empty"
|
|
9384
|
-
]);
|
|
9385
|
-
var noValueComparators = /* @__PURE__ */ new Set(["is_empty", "is_not_empty"]);
|
|
9386
|
-
function parseColonExpression(input) {
|
|
9387
|
-
const parts = input.split(":");
|
|
9388
|
-
if (parts.length < 2) {
|
|
9389
|
-
throw new Error(`Expected a field:comparator[:value] expression, got "${input}".`);
|
|
9390
|
-
}
|
|
9391
|
-
const field = parts[0]?.trim();
|
|
9392
|
-
const comparator = parts[1]?.trim();
|
|
9393
|
-
if (!field) {
|
|
9394
|
-
throw new Error(`Expected a field before ":", got "${input}".`);
|
|
9395
|
-
}
|
|
9396
|
-
if (!comparator) {
|
|
9397
|
-
throw new Error(`Expected a comparator after "${field}:", got "${input}".`);
|
|
9398
|
-
}
|
|
9399
|
-
return [field, comparator, parts.slice(2).join(":").trim()];
|
|
9400
|
-
}
|
|
9401
|
-
function parseSpaceExpression(input) {
|
|
9402
|
-
const parts = input.trim().split(/\s+/);
|
|
9403
|
-
if (parts.length < 2) {
|
|
9404
|
-
throw new Error(`Expected a field comparator expression, got "${input}".`);
|
|
9405
|
-
}
|
|
9406
|
-
const field = parts[0];
|
|
9407
|
-
const comparator = parts[1];
|
|
9408
|
-
if (!field) {
|
|
9409
|
-
throw new Error(`Expected a field comparator expression, got "${input}".`);
|
|
10917
|
+
`/api/v2/schemas/${selectorValue9(schema)}`,
|
|
10918
|
+
{ method: "DELETE" }
|
|
10919
|
+
);
|
|
9410
10920
|
}
|
|
9411
|
-
|
|
9412
|
-
|
|
10921
|
+
async listFields(schema) {
|
|
10922
|
+
const result = await this.getSchema(schema);
|
|
10923
|
+
return Array.isArray(result.fields) ? result.fields : [];
|
|
9413
10924
|
}
|
|
9414
|
-
|
|
9415
|
-
|
|
9416
|
-
|
|
9417
|
-
|
|
9418
|
-
if (rawValue.length > 0) {
|
|
9419
|
-
throw new Error(`Comparator "${comparator}" does not accept a value.`);
|
|
9420
|
-
}
|
|
9421
|
-
return null;
|
|
10925
|
+
getField(schema, field) {
|
|
10926
|
+
return this.client.getJson(
|
|
10927
|
+
`/api/v2/schemas/${selectorValue9(schema)}/fields/${selectorValue9(field)}`
|
|
10928
|
+
);
|
|
9422
10929
|
}
|
|
9423
|
-
|
|
9424
|
-
|
|
9425
|
-
|
|
9426
|
-
|
|
9427
|
-
|
|
9428
|
-
return values;
|
|
10930
|
+
createField(schema, input) {
|
|
10931
|
+
return this.client.requestJson(
|
|
10932
|
+
`/api/v2/schemas/${selectorValue9(schema)}/fields`,
|
|
10933
|
+
jsonOptions7(input, "POST")
|
|
10934
|
+
);
|
|
9429
10935
|
}
|
|
9430
|
-
|
|
9431
|
-
|
|
10936
|
+
updateField(schema, field, input) {
|
|
10937
|
+
return this.client.requestJson(
|
|
10938
|
+
`/api/v2/schemas/${selectorValue9(schema)}/fields/${selectorValue9(field)}`,
|
|
10939
|
+
jsonOptions7(input, "PATCH")
|
|
10940
|
+
);
|
|
9432
10941
|
}
|
|
9433
|
-
|
|
9434
|
-
|
|
9435
|
-
|
|
9436
|
-
|
|
9437
|
-
const [field, comparatorCandidate, rawValue] = trimmed.includes(":") && !trimmed.includes(" ") ? parseColonExpression(trimmed) : parseSpaceExpression(trimmed);
|
|
9438
|
-
if (!supportedComparators.has(comparatorCandidate)) {
|
|
9439
|
-
throw new Error(
|
|
9440
|
-
`Unsupported comparator "${comparatorCandidate}" in expression "${input}".`
|
|
10942
|
+
deleteField(schema, field) {
|
|
10943
|
+
return this.client.requestJson(
|
|
10944
|
+
`/api/v2/schemas/${selectorValue9(schema)}/fields/${selectorValue9(field)}`,
|
|
10945
|
+
{ method: "DELETE" }
|
|
9441
10946
|
);
|
|
9442
10947
|
}
|
|
9443
|
-
|
|
9444
|
-
return {
|
|
9445
|
-
field,
|
|
9446
|
-
comparator,
|
|
9447
|
-
value: normalizeValue(comparator, rawValue),
|
|
9448
|
-
raw: trimmed
|
|
9449
|
-
};
|
|
9450
|
-
}
|
|
10948
|
+
};
|
|
9451
10949
|
|
|
9452
10950
|
// src/commands/records.ts
|
|
9453
|
-
function
|
|
10951
|
+
function getCommandIo10(stdout) {
|
|
9454
10952
|
return stdout ?? process.stdout;
|
|
9455
10953
|
}
|
|
9456
|
-
function
|
|
10954
|
+
function writeLine10(stdout, value) {
|
|
9457
10955
|
stdout.write(`${value}
|
|
9458
10956
|
`);
|
|
9459
10957
|
}
|
|
9460
|
-
function
|
|
10958
|
+
function getGlobalOptions10(command) {
|
|
9461
10959
|
return command.optsWithGlobals();
|
|
9462
10960
|
}
|
|
9463
|
-
function
|
|
9464
|
-
|
|
10961
|
+
function emitJson10(stdout, commandName, data, configPath, meta = {}) {
|
|
10962
|
+
writeLine10(
|
|
9465
10963
|
stdout,
|
|
9466
10964
|
JSON.stringify(buildJsonSuccess(data, { command: commandName, configPath, ...meta }))
|
|
9467
10965
|
);
|
|
9468
10966
|
}
|
|
9469
|
-
function
|
|
10967
|
+
function toConfigurationError9(filePath, error) {
|
|
9470
10968
|
if (error instanceof CliError) {
|
|
9471
10969
|
throw error;
|
|
9472
10970
|
}
|
|
@@ -9481,7 +10979,7 @@ function toConfigurationError8(filePath, error) {
|
|
|
9481
10979
|
function createRecordsApi(command, filePath) {
|
|
9482
10980
|
try {
|
|
9483
10981
|
const config = readRuntimeConfig(filePath);
|
|
9484
|
-
const runtime = resolveRuntimeContext(config,
|
|
10982
|
+
const runtime = resolveRuntimeContext(config, getGlobalOptions10(command));
|
|
9485
10983
|
if (!runtime.baseUrl) {
|
|
9486
10984
|
throw new CliError(
|
|
9487
10985
|
"configuration_error",
|
|
@@ -9500,10 +10998,10 @@ function createRecordsApi(command, filePath) {
|
|
|
9500
10998
|
readOnly: runtime.readOnly
|
|
9501
10999
|
};
|
|
9502
11000
|
} catch (error) {
|
|
9503
|
-
|
|
11001
|
+
toConfigurationError9(filePath, error);
|
|
9504
11002
|
}
|
|
9505
11003
|
}
|
|
9506
|
-
function
|
|
11004
|
+
function ensureWritable7(commandName, readOnly, commandMode) {
|
|
9507
11005
|
if (readOnly) {
|
|
9508
11006
|
throw new CliError(
|
|
9509
11007
|
"command_not_allowed_in_read_only_mode",
|
|
@@ -9515,24 +11013,24 @@ function ensureWritable6(commandName, readOnly, commandMode) {
|
|
|
9515
11013
|
);
|
|
9516
11014
|
}
|
|
9517
11015
|
}
|
|
9518
|
-
function
|
|
11016
|
+
function parseUuidOrSlugSelector8(input) {
|
|
9519
11017
|
try {
|
|
9520
11018
|
return normalizeUuidOrSlug(input);
|
|
9521
11019
|
} catch (error) {
|
|
9522
11020
|
const message = error instanceof Error ? error.message : "Invalid selector.";
|
|
9523
|
-
throw new
|
|
11021
|
+
throw new InvalidArgumentError8(message);
|
|
9524
11022
|
}
|
|
9525
11023
|
}
|
|
9526
11024
|
function parseNonNegativeInteger2(input) {
|
|
9527
11025
|
if (!/^\d+$/.test(input.trim())) {
|
|
9528
|
-
throw new
|
|
11026
|
+
throw new InvalidArgumentError8(`Expected a non-negative integer, received "${input}".`);
|
|
9529
11027
|
}
|
|
9530
11028
|
return Number(input);
|
|
9531
11029
|
}
|
|
9532
11030
|
function parseCommaSeparatedValues(input, label) {
|
|
9533
11031
|
const values = input.split(",").map((value) => value.trim()).filter(Boolean);
|
|
9534
11032
|
if (values.length === 0) {
|
|
9535
|
-
throw new
|
|
11033
|
+
throw new InvalidArgumentError8(`Expected ${label} to contain at least one value.`);
|
|
9536
11034
|
}
|
|
9537
11035
|
return values;
|
|
9538
11036
|
}
|
|
@@ -9541,7 +11039,7 @@ function parseExpressionValue(input) {
|
|
|
9541
11039
|
return parseExpression(input);
|
|
9542
11040
|
} catch (error) {
|
|
9543
11041
|
const message = error instanceof Error ? error.message : "Invalid expression.";
|
|
9544
|
-
throw new
|
|
11042
|
+
throw new InvalidArgumentError8(message);
|
|
9545
11043
|
}
|
|
9546
11044
|
}
|
|
9547
11045
|
function parseKeyValueAssignment(input) {
|
|
@@ -9549,7 +11047,7 @@ function parseKeyValueAssignment(input) {
|
|
|
9549
11047
|
return parseKeyValue(input);
|
|
9550
11048
|
} catch (error) {
|
|
9551
11049
|
const message = error instanceof Error ? error.message : "Invalid assignment.";
|
|
9552
|
-
throw new
|
|
11050
|
+
throw new InvalidArgumentError8(message);
|
|
9553
11051
|
}
|
|
9554
11052
|
}
|
|
9555
11053
|
function parseJsonKeyValueAssignment(input) {
|
|
@@ -9557,14 +11055,75 @@ function parseJsonKeyValueAssignment(input) {
|
|
|
9557
11055
|
return parseJsonAssignment(input);
|
|
9558
11056
|
} catch (error) {
|
|
9559
11057
|
const message = error instanceof Error ? error.message : "Invalid JSON assignment.";
|
|
9560
|
-
throw new
|
|
11058
|
+
throw new InvalidArgumentError8(message);
|
|
11059
|
+
}
|
|
11060
|
+
}
|
|
11061
|
+
function dedupeStrings(values) {
|
|
11062
|
+
return [...new Set(values)];
|
|
11063
|
+
}
|
|
11064
|
+
function toRecordUuid(value) {
|
|
11065
|
+
try {
|
|
11066
|
+
const normalized = normalizeUuidOrSlug(value);
|
|
11067
|
+
return normalized.kind === "uuid" ? normalized.value : null;
|
|
11068
|
+
} catch {
|
|
11069
|
+
return null;
|
|
11070
|
+
}
|
|
11071
|
+
}
|
|
11072
|
+
function collectRecordIds(value, previous = []) {
|
|
11073
|
+
const uuid = toRecordUuid(value.trim());
|
|
11074
|
+
if (!uuid) {
|
|
11075
|
+
throw new InvalidArgumentError8(`Expected a record UUID, received "${value}".`);
|
|
11076
|
+
}
|
|
11077
|
+
return [...previous, uuid];
|
|
11078
|
+
}
|
|
11079
|
+
function readRecordIdsFromFile(path) {
|
|
11080
|
+
let contents;
|
|
11081
|
+
try {
|
|
11082
|
+
contents = readFileSync8(path, "utf8");
|
|
11083
|
+
} catch (error) {
|
|
11084
|
+
const message = error instanceof Error ? error.message : "Unable to read file.";
|
|
11085
|
+
throw new CliError(
|
|
11086
|
+
"invalid_cli_usage",
|
|
11087
|
+
`Failed to read record ids from ${path}: ${message}`
|
|
11088
|
+
);
|
|
11089
|
+
}
|
|
11090
|
+
const ids = [];
|
|
11091
|
+
contents.split(/\r?\n/).forEach((line, index) => {
|
|
11092
|
+
const value = line.trim();
|
|
11093
|
+
if (!value) {
|
|
11094
|
+
return;
|
|
11095
|
+
}
|
|
11096
|
+
const uuid = toRecordUuid(value);
|
|
11097
|
+
if (!uuid) {
|
|
11098
|
+
throw new CliError(
|
|
11099
|
+
"invalid_cli_usage",
|
|
11100
|
+
`Invalid record UUID "${value}" at ${path}:${index + 1}.`
|
|
11101
|
+
);
|
|
11102
|
+
}
|
|
11103
|
+
ids.push(uuid);
|
|
11104
|
+
});
|
|
11105
|
+
return ids;
|
|
11106
|
+
}
|
|
11107
|
+
function resolveDeleteRecordIds(options) {
|
|
11108
|
+
const flagIds = options.record ?? [];
|
|
11109
|
+
const fileIds = options.recordsFile ? readRecordIdsFromFile(options.recordsFile) : [];
|
|
11110
|
+
const recordIds = dedupeStrings([...flagIds, ...fileIds]);
|
|
11111
|
+
if (recordIds.length === 0) {
|
|
11112
|
+
throw new CliError(
|
|
11113
|
+
"invalid_cli_usage",
|
|
11114
|
+
'Provide at least one record id via "--record <uuid>" (repeatable) or "--records-file <path>".'
|
|
11115
|
+
);
|
|
9561
11116
|
}
|
|
11117
|
+
return recordIds;
|
|
9562
11118
|
}
|
|
9563
11119
|
function collectStringValues(value, previous = []) {
|
|
9564
11120
|
return [...previous, value];
|
|
9565
11121
|
}
|
|
11122
|
+
function collectSelectValues(value, previous = []) {
|
|
11123
|
+
return dedupeStrings([...previous, ...parseCommaSeparatedValues(value, "--select")]);
|
|
11124
|
+
}
|
|
9566
11125
|
function collectSortValues(value, previous = []) {
|
|
9567
|
-
return [...previous, ...parseCommaSeparatedValues(value, "--sort")];
|
|
11126
|
+
return dedupeStrings([...previous, ...parseCommaSeparatedValues(value, "--sort")]);
|
|
9568
11127
|
}
|
|
9569
11128
|
function collectWhereExpressions(value, previous = []) {
|
|
9570
11129
|
return [...previous, parseExpressionValue(value)];
|
|
@@ -9575,7 +11134,7 @@ function collectKeyValueAssignments(value, previous = []) {
|
|
|
9575
11134
|
function collectJsonAssignments(value, previous = []) {
|
|
9576
11135
|
return [...previous, parseJsonKeyValueAssignment(value)];
|
|
9577
11136
|
}
|
|
9578
|
-
function
|
|
11137
|
+
function isJsonObject6(value) {
|
|
9579
11138
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9580
11139
|
}
|
|
9581
11140
|
function parseRawJsonObject2(input, sourceLabel) {
|
|
@@ -9589,7 +11148,7 @@ function parseRawJsonObject2(input, sourceLabel) {
|
|
|
9589
11148
|
`Failed to parse JSON from ${sourceLabel}: ${message}`
|
|
9590
11149
|
);
|
|
9591
11150
|
}
|
|
9592
|
-
if (!
|
|
11151
|
+
if (!isJsonObject6(parsed)) {
|
|
9593
11152
|
throw new CliError(
|
|
9594
11153
|
"invalid_cli_usage",
|
|
9595
11154
|
`Expected ${sourceLabel} to contain a JSON object.`
|
|
@@ -9610,7 +11169,7 @@ function readRawObject3(raw, rawFile) {
|
|
|
9610
11169
|
if (rawFile) {
|
|
9611
11170
|
let contents;
|
|
9612
11171
|
try {
|
|
9613
|
-
contents =
|
|
11172
|
+
contents = readFileSync8(rawFile, "utf8");
|
|
9614
11173
|
} catch (error) {
|
|
9615
11174
|
const message = error instanceof Error ? error.message : "Unable to read file.";
|
|
9616
11175
|
throw new CliError(
|
|
@@ -9622,7 +11181,7 @@ function readRawObject3(raw, rawFile) {
|
|
|
9622
11181
|
}
|
|
9623
11182
|
return {};
|
|
9624
11183
|
}
|
|
9625
|
-
function
|
|
11184
|
+
function isEmptyObject5(value) {
|
|
9626
11185
|
return Object.keys(value).length === 0;
|
|
9627
11186
|
}
|
|
9628
11187
|
function buildAssignmentObject(assignments = [], jsonAssignments = []) {
|
|
@@ -9654,6 +11213,9 @@ function buildRecordQueryInput(options, allowRaw) {
|
|
|
9654
11213
|
if (where && where.length > 0) {
|
|
9655
11214
|
input.where = where;
|
|
9656
11215
|
}
|
|
11216
|
+
if (options.search !== void 0) {
|
|
11217
|
+
input.search = { term: options.search };
|
|
11218
|
+
}
|
|
9657
11219
|
if (options.sort && options.sort.length > 0) {
|
|
9658
11220
|
input.sort = [...options.sort];
|
|
9659
11221
|
}
|
|
@@ -9665,53 +11227,80 @@ function buildRecordQueryInput(options, allowRaw) {
|
|
|
9665
11227
|
}
|
|
9666
11228
|
return input;
|
|
9667
11229
|
}
|
|
9668
|
-
function
|
|
9669
|
-
|
|
9670
|
-
|
|
9671
|
-
|
|
9672
|
-
}
|
|
9673
|
-
|
|
11230
|
+
function readRecordsFromFile(path) {
|
|
11231
|
+
let contents;
|
|
11232
|
+
try {
|
|
11233
|
+
contents = readFileSync8(path, "utf8");
|
|
11234
|
+
} catch (error) {
|
|
11235
|
+
const message = error instanceof Error ? error.message : "Unable to read file.";
|
|
9674
11236
|
throw new CliError(
|
|
9675
11237
|
"invalid_cli_usage",
|
|
9676
|
-
|
|
11238
|
+
`Failed to read records from ${path}: ${message}`
|
|
9677
11239
|
);
|
|
9678
11240
|
}
|
|
9679
|
-
|
|
9680
|
-
|
|
9681
|
-
|
|
9682
|
-
|
|
9683
|
-
|
|
9684
|
-
|
|
11241
|
+
let parsed;
|
|
11242
|
+
try {
|
|
11243
|
+
parsed = JSON.parse(contents);
|
|
11244
|
+
} catch (error) {
|
|
11245
|
+
const message = error instanceof Error ? error.message : "Invalid JSON.";
|
|
11246
|
+
throw new CliError(
|
|
11247
|
+
"invalid_cli_usage",
|
|
11248
|
+
`Failed to parse JSON from --records-file ${path}: ${message}`
|
|
11249
|
+
);
|
|
9685
11250
|
}
|
|
9686
|
-
if (!
|
|
11251
|
+
if (!Array.isArray(parsed)) {
|
|
9687
11252
|
throw new CliError(
|
|
9688
11253
|
"invalid_cli_usage",
|
|
9689
|
-
|
|
11254
|
+
`Expected --records-file ${path} to contain a JSON array of record objects.`
|
|
9690
11255
|
);
|
|
9691
11256
|
}
|
|
9692
|
-
|
|
11257
|
+
if (parsed.length === 0) {
|
|
11258
|
+
throw new CliError(
|
|
11259
|
+
"invalid_cli_usage",
|
|
11260
|
+
`--records-file ${path} must contain at least one record.`
|
|
11261
|
+
);
|
|
11262
|
+
}
|
|
11263
|
+
return parsed.map((record, index) => {
|
|
11264
|
+
if (!isJsonObject6(record)) {
|
|
11265
|
+
throw new CliError(
|
|
11266
|
+
"invalid_cli_usage",
|
|
11267
|
+
`Record at index ${index} in --records-file ${path} must be a JSON object.`
|
|
11268
|
+
);
|
|
11269
|
+
}
|
|
11270
|
+
return record;
|
|
11271
|
+
});
|
|
9693
11272
|
}
|
|
9694
|
-
function
|
|
9695
|
-
const
|
|
9696
|
-
if (
|
|
9697
|
-
|
|
11273
|
+
function buildCreateRecords(options) {
|
|
11274
|
+
const hasSingleRecordFlags = (options.set?.length ?? 0) > 0 || (options.setJson?.length ?? 0) > 0 || options.raw !== void 0 || options.rawFile !== void 0;
|
|
11275
|
+
if (options.recordsFile !== void 0) {
|
|
11276
|
+
if (hasSingleRecordFlags) {
|
|
11277
|
+
throw new CliError(
|
|
11278
|
+
"invalid_cli_usage",
|
|
11279
|
+
'Provide either "--records-file" or the single-record flags (--set/--set-json/--raw/--raw-file), not both.'
|
|
11280
|
+
);
|
|
11281
|
+
}
|
|
11282
|
+
return readRecordsFromFile(options.recordsFile);
|
|
9698
11283
|
}
|
|
9699
|
-
|
|
11284
|
+
const values = {
|
|
11285
|
+
...readRawObject3(options.raw, options.rawFile),
|
|
11286
|
+
...buildAssignmentObject(options.set, options.setJson)
|
|
11287
|
+
};
|
|
11288
|
+
if (isEmptyObject5(values)) {
|
|
9700
11289
|
throw new CliError(
|
|
9701
11290
|
"invalid_cli_usage",
|
|
9702
|
-
'
|
|
11291
|
+
'Provide record fields via "--set", "--set-json", "--raw", "--raw-file", or load multiple records with "--records-file".'
|
|
9703
11292
|
);
|
|
9704
11293
|
}
|
|
9705
|
-
return [
|
|
11294
|
+
return [values];
|
|
9706
11295
|
}
|
|
9707
11296
|
function buildRecordUpdateInput(options) {
|
|
9708
11297
|
const raw = readRawObject3(options.raw, options.rawFile);
|
|
9709
|
-
const input = {
|
|
11298
|
+
const input = {};
|
|
9710
11299
|
const setPayload = {
|
|
9711
|
-
...
|
|
11300
|
+
...raw,
|
|
9712
11301
|
...buildAssignmentObject(options.set, options.setJson)
|
|
9713
11302
|
};
|
|
9714
|
-
const unsetPayload = [...
|
|
11303
|
+
const unsetPayload = [...options.unset ?? []];
|
|
9715
11304
|
for (const key of Object.keys(setPayload)) {
|
|
9716
11305
|
const unsetIndex = unsetPayload.indexOf(key);
|
|
9717
11306
|
if (unsetIndex !== -1) {
|
|
@@ -9728,7 +11317,7 @@ function buildRecordUpdateInput(options) {
|
|
|
9728
11317
|
} else {
|
|
9729
11318
|
delete input.unset;
|
|
9730
11319
|
}
|
|
9731
|
-
if (
|
|
11320
|
+
if (isEmptyObject5(input)) {
|
|
9732
11321
|
throw new CliError(
|
|
9733
11322
|
"invalid_cli_usage",
|
|
9734
11323
|
'Provide record updates via "--set", "--set-json", "--unset", "--raw", or "--raw-file".'
|
|
@@ -9738,9 +11327,9 @@ function buildRecordUpdateInput(options) {
|
|
|
9738
11327
|
}
|
|
9739
11328
|
function toTableRows4(data) {
|
|
9740
11329
|
if (Array.isArray(data)) {
|
|
9741
|
-
return data.map((entry) =>
|
|
11330
|
+
return data.map((entry) => isJsonObject6(entry) ? entry : { value: entry });
|
|
9742
11331
|
}
|
|
9743
|
-
if (
|
|
11332
|
+
if (isJsonObject6(data)) {
|
|
9744
11333
|
return [data];
|
|
9745
11334
|
}
|
|
9746
11335
|
return [{ value: data }];
|
|
@@ -9770,9 +11359,9 @@ async function resolveSchemaSelector(api, selector) {
|
|
|
9770
11359
|
}
|
|
9771
11360
|
function registerRecordsCommands(program, options = {}) {
|
|
9772
11361
|
const filePath = options.configPath ?? defaultConfigPath;
|
|
9773
|
-
const stdout =
|
|
11362
|
+
const stdout = getCommandIo10(options.stdout);
|
|
9774
11363
|
const records = program.command("records").description("Manage schema records");
|
|
9775
|
-
records.command("list").description("List records for a schema with simple pagination").argument("<schema>", "schema uuid or slug",
|
|
11364
|
+
records.command("list").description("List records for a schema with simple pagination").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector8).option("--limit <number>", "limit results", parseNonNegativeInteger2).option("--offset <number>", "offset results", parseNonNegativeInteger2).action(async function action(schema, commandOptions) {
|
|
9776
11365
|
const { api, schemasApi, json } = createRecordsApi(this, filePath);
|
|
9777
11366
|
const resolvedSchema = await resolveSchemaSelector(schemasApi, schema);
|
|
9778
11367
|
const data = await api.listRecords(
|
|
@@ -9781,7 +11370,7 @@ function registerRecordsCommands(program, options = {}) {
|
|
|
9781
11370
|
);
|
|
9782
11371
|
const recordsData = getQueryRecords(data);
|
|
9783
11372
|
if (json) {
|
|
9784
|
-
|
|
11373
|
+
emitJson10(
|
|
9785
11374
|
stdout,
|
|
9786
11375
|
"records list",
|
|
9787
11376
|
recordsData,
|
|
@@ -9792,7 +11381,10 @@ function registerRecordsCommands(program, options = {}) {
|
|
|
9792
11381
|
}
|
|
9793
11382
|
emitTable4(stdout, recordsData);
|
|
9794
11383
|
});
|
|
9795
|
-
records.command("query").description("Query records for a schema").argument("<schema>", "schema uuid or slug",
|
|
11384
|
+
records.command("query").description("Query records for a schema").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector8).option("--select <fields>", "field selection (comma-separated, repeatable)", collectSelectValues, []).option("--where <expression>", "where expression", collectWhereExpressions, []).option(
|
|
11385
|
+
"--search <term>",
|
|
11386
|
+
"free-text search term (matched across the schema's searchable fields)"
|
|
11387
|
+
).option("--sort <field:direction>", "sort field(s)", collectSortValues, []).option("--limit <number>", "limit results", parseNonNegativeInteger2).option("--offset <number>", "offset results", parseNonNegativeInteger2).option("--raw <json>", "raw JSON object payload").option("--raw-file <path>", "path to a raw JSON object payload").action(async function action(schema, commandOptions) {
|
|
9796
11388
|
const { api, schemasApi, json } = createRecordsApi(this, filePath);
|
|
9797
11389
|
const resolvedSchema = await resolveSchemaSelector(schemasApi, schema);
|
|
9798
11390
|
const data = await api.queryRecords(
|
|
@@ -9801,7 +11393,7 @@ function registerRecordsCommands(program, options = {}) {
|
|
|
9801
11393
|
);
|
|
9802
11394
|
const recordsData = getQueryRecords(data);
|
|
9803
11395
|
if (json) {
|
|
9804
|
-
|
|
11396
|
+
emitJson10(
|
|
9805
11397
|
stdout,
|
|
9806
11398
|
"records query",
|
|
9807
11399
|
recordsData,
|
|
@@ -9812,33 +11404,50 @@ function registerRecordsCommands(program, options = {}) {
|
|
|
9812
11404
|
}
|
|
9813
11405
|
emitTable4(stdout, recordsData);
|
|
9814
11406
|
});
|
|
9815
|
-
records.command("get").description("Get a record by UUID or slug").argument("<schema>", "schema uuid or slug",
|
|
11407
|
+
records.command("get").description("Get a record by UUID or slug").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector8).argument("<record>", "record uuid or slug", parseUuidOrSlugSelector8).action(async function action(schema, record) {
|
|
9816
11408
|
const { api, schemasApi, json } = createRecordsApi(this, filePath);
|
|
9817
11409
|
const resolvedSchema = await resolveSchemaSelector(schemasApi, schema);
|
|
9818
11410
|
const data = await api.getRecord(resolvedSchema, record);
|
|
9819
11411
|
if (json) {
|
|
9820
|
-
|
|
11412
|
+
emitJson10(stdout, "records get", data, filePath);
|
|
9821
11413
|
return;
|
|
9822
11414
|
}
|
|
9823
11415
|
emitTable4(stdout, data);
|
|
9824
11416
|
});
|
|
9825
|
-
records.command("create").description("Create
|
|
11417
|
+
records.command("create").description("Create one or more records").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector8).option(
|
|
11418
|
+
"--set <field=value>",
|
|
11419
|
+
"set a string field (reference fields: a record id, 'recordId::label', or an exact display value)",
|
|
11420
|
+
collectKeyValueAssignments,
|
|
11421
|
+
[]
|
|
11422
|
+
).option("--set-json <field=json>", "set a structured field", collectJsonAssignments, []).option("--raw <json>", "raw JSON object payload").option("--raw-file <path>", "path to a raw JSON object payload").option(
|
|
11423
|
+
"--records-file <path>",
|
|
11424
|
+
"path to a JSON array of record objects (mutually exclusive with --set/--set-json/--raw/--raw-file)"
|
|
11425
|
+
).action(async function action(schema, commandOptions) {
|
|
9826
11426
|
const { api, schemasApi, json, readOnly } = createRecordsApi(this, filePath);
|
|
9827
|
-
|
|
11427
|
+
ensureWritable7("records create", readOnly, "write");
|
|
11428
|
+
const records2 = buildCreateRecords(commandOptions);
|
|
9828
11429
|
const resolvedSchema = await resolveSchemaSelector(schemasApi, schema);
|
|
9829
|
-
const data = await api.
|
|
9830
|
-
resolvedSchema,
|
|
9831
|
-
buildRecordCreateInput(commandOptions)
|
|
9832
|
-
);
|
|
11430
|
+
const data = await api.createRecords(resolvedSchema, records2);
|
|
9833
11431
|
if (json) {
|
|
9834
|
-
|
|
11432
|
+
emitJson10(stdout, "records create", data, filePath);
|
|
9835
11433
|
return;
|
|
9836
11434
|
}
|
|
9837
|
-
|
|
11435
|
+
writeLine10(stdout, `Created ${data.created.length} record(s) in schema "${schema.value}".`);
|
|
11436
|
+
if (data.errors.length > 0) {
|
|
11437
|
+
writeLine10(stdout, `${data.errors.length} record(s) rejected:`);
|
|
11438
|
+
for (const error of data.errors) {
|
|
11439
|
+
writeLine10(stdout, ` - index ${error.index}: ${error.message}`);
|
|
11440
|
+
}
|
|
11441
|
+
}
|
|
9838
11442
|
});
|
|
9839
|
-
records.command("update").description("Update a record").argument("<schema>", "schema uuid or slug",
|
|
11443
|
+
records.command("update").description("Update a record").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector8).argument("<record>", "record uuid or slug", parseUuidOrSlugSelector8).option(
|
|
11444
|
+
"--set <field=value>",
|
|
11445
|
+
"set a string field (reference fields: a record id, 'recordId::label', or an exact display value)",
|
|
11446
|
+
collectKeyValueAssignments,
|
|
11447
|
+
[]
|
|
11448
|
+
).option("--set-json <field=json>", "set a structured field", collectJsonAssignments, []).option("--unset <field>", "unset a field", collectStringValues, []).option("--raw <json>", "raw JSON object of fields to set").option("--raw-file <path>", "path to a JSON object of fields to set").action(async function action(schema, record, commandOptions) {
|
|
9840
11449
|
const { api, schemasApi, json, readOnly } = createRecordsApi(this, filePath);
|
|
9841
|
-
|
|
11450
|
+
ensureWritable7("records update", readOnly, "write");
|
|
9842
11451
|
const resolvedSchema = await resolveSchemaSelector(schemasApi, schema);
|
|
9843
11452
|
const data = await api.updateRecord(
|
|
9844
11453
|
resolvedSchema,
|
|
@@ -9846,60 +11455,71 @@ function registerRecordsCommands(program, options = {}) {
|
|
|
9846
11455
|
buildRecordUpdateInput(commandOptions)
|
|
9847
11456
|
);
|
|
9848
11457
|
if (json) {
|
|
9849
|
-
|
|
11458
|
+
emitJson10(stdout, "records update", data, filePath);
|
|
9850
11459
|
return;
|
|
9851
11460
|
}
|
|
9852
|
-
|
|
11461
|
+
writeLine10(stdout, `Updated record "${getRecordIdentifier(data)}".`);
|
|
9853
11462
|
});
|
|
9854
|
-
records.command("delete").description("Delete
|
|
11463
|
+
records.command("delete").description("Delete one or more records").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector8).option("--record <uuid>", "record uuid to delete (repeatable)", collectRecordIds, []).option(
|
|
11464
|
+
"--records-file <path>",
|
|
11465
|
+
"path to a file with one record uuid per line (merged with --record)"
|
|
11466
|
+
).action(async function action(schema, commandOptions) {
|
|
9855
11467
|
const { api, schemasApi, json, readOnly } = createRecordsApi(this, filePath);
|
|
9856
|
-
|
|
11468
|
+
ensureWritable7("records delete", readOnly, "destructive");
|
|
11469
|
+
const recordIds = resolveDeleteRecordIds(commandOptions);
|
|
9857
11470
|
const resolvedSchema = await resolveSchemaSelector(schemasApi, schema);
|
|
9858
|
-
await api.
|
|
9859
|
-
const data = {
|
|
9860
|
-
schema: resolvedSchema.value,
|
|
9861
|
-
record: record.value,
|
|
9862
|
-
deleted: true
|
|
9863
|
-
};
|
|
11471
|
+
const data = await api.deleteRecords(resolvedSchema, recordIds);
|
|
9864
11472
|
if (json) {
|
|
9865
|
-
|
|
11473
|
+
emitJson10(stdout, "records delete", data, filePath);
|
|
9866
11474
|
return;
|
|
9867
11475
|
}
|
|
9868
|
-
|
|
11476
|
+
writeLine10(
|
|
11477
|
+
stdout,
|
|
11478
|
+
`Deleted ${recordIds.length} record(s) from schema "${schema.value}".`
|
|
11479
|
+
);
|
|
9869
11480
|
});
|
|
9870
|
-
records.command("clear").description("Delete all records from a schema's table").argument("<schema>", "schema uuid or slug",
|
|
11481
|
+
records.command("clear").description("Delete all records from a schema's table").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector8).action(async function action(schema) {
|
|
9871
11482
|
const { api, schemasApi, json, readOnly } = createRecordsApi(this, filePath);
|
|
9872
|
-
|
|
11483
|
+
ensureWritable7("records clear", readOnly, "destructive");
|
|
9873
11484
|
const resolvedSchema = await resolveSchemaSelector(schemasApi, schema);
|
|
9874
11485
|
const data = await api.clearRecords(resolvedSchema);
|
|
9875
11486
|
if (json) {
|
|
9876
|
-
|
|
11487
|
+
emitJson10(stdout, "records clear", data, filePath);
|
|
9877
11488
|
return;
|
|
9878
11489
|
}
|
|
9879
|
-
|
|
11490
|
+
writeLine10(stdout, `Cleared all records from schema "${schema.value}".`);
|
|
9880
11491
|
});
|
|
9881
11492
|
}
|
|
9882
11493
|
|
|
9883
11494
|
// src/commands/schemas.ts
|
|
9884
|
-
import { readFileSync as
|
|
9885
|
-
import { InvalidArgumentError as
|
|
9886
|
-
|
|
11495
|
+
import { readFileSync as readFileSync9 } from "fs";
|
|
11496
|
+
import { InvalidArgumentError as InvalidArgumentError9 } from "commander";
|
|
11497
|
+
var HIGHLIGHTED_FIELD_HELP = `
|
|
11498
|
+
Highlighted field:
|
|
11499
|
+
The schema's "main" field. The frontend uses its value as each record's
|
|
11500
|
+
display name, in two places:
|
|
11501
|
+
- Activity panel: the record's title in the activity side panel
|
|
11502
|
+
(the panel with the record's logs and comments).
|
|
11503
|
+
- Detail view: the record's name in the left-hand record list you
|
|
11504
|
+
browse to open each record's form.
|
|
11505
|
+
`;
|
|
11506
|
+
function getCommandIo11(stdout) {
|
|
9887
11507
|
return stdout ?? process.stdout;
|
|
9888
11508
|
}
|
|
9889
|
-
function
|
|
11509
|
+
function writeLine11(stdout, value) {
|
|
9890
11510
|
stdout.write(`${value}
|
|
9891
11511
|
`);
|
|
9892
11512
|
}
|
|
9893
|
-
function
|
|
11513
|
+
function getGlobalOptions11(command) {
|
|
9894
11514
|
return command.optsWithGlobals();
|
|
9895
11515
|
}
|
|
9896
|
-
function
|
|
9897
|
-
|
|
11516
|
+
function emitJson11(stdout, commandName, data, configPath) {
|
|
11517
|
+
writeLine11(
|
|
9898
11518
|
stdout,
|
|
9899
11519
|
JSON.stringify(buildJsonSuccess(data, { command: commandName, configPath }))
|
|
9900
11520
|
);
|
|
9901
11521
|
}
|
|
9902
|
-
function
|
|
11522
|
+
function toConfigurationError10(filePath, error) {
|
|
9903
11523
|
if (error instanceof CliError) {
|
|
9904
11524
|
throw error;
|
|
9905
11525
|
}
|
|
@@ -9914,7 +11534,7 @@ function toConfigurationError9(filePath, error) {
|
|
|
9914
11534
|
function createSchemasApi(command, filePath) {
|
|
9915
11535
|
try {
|
|
9916
11536
|
const config = readRuntimeConfig(filePath);
|
|
9917
|
-
const runtime = resolveRuntimeContext(config,
|
|
11537
|
+
const runtime = resolveRuntimeContext(config, getGlobalOptions11(command));
|
|
9918
11538
|
if (!runtime.baseUrl) {
|
|
9919
11539
|
throw new CliError(
|
|
9920
11540
|
"configuration_error",
|
|
@@ -9933,10 +11553,10 @@ function createSchemasApi(command, filePath) {
|
|
|
9933
11553
|
readOnly: runtime.readOnly
|
|
9934
11554
|
};
|
|
9935
11555
|
} catch (error) {
|
|
9936
|
-
|
|
11556
|
+
toConfigurationError10(filePath, error);
|
|
9937
11557
|
}
|
|
9938
11558
|
}
|
|
9939
|
-
function
|
|
11559
|
+
function ensureWritable8(commandName, readOnly, commandMode) {
|
|
9940
11560
|
if (readOnly) {
|
|
9941
11561
|
throw new CliError(
|
|
9942
11562
|
"command_not_allowed_in_read_only_mode",
|
|
@@ -9948,14 +11568,17 @@ function ensureWritable7(commandName, readOnly, commandMode) {
|
|
|
9948
11568
|
);
|
|
9949
11569
|
}
|
|
9950
11570
|
}
|
|
9951
|
-
function
|
|
11571
|
+
function parseUuidOrSlugSelector9(input) {
|
|
9952
11572
|
try {
|
|
9953
11573
|
return normalizeUuidOrSlug(input);
|
|
9954
11574
|
} catch (error) {
|
|
9955
11575
|
const message = error instanceof Error ? error.message : "Invalid selector.";
|
|
9956
|
-
throw new
|
|
11576
|
+
throw new InvalidArgumentError9(message);
|
|
9957
11577
|
}
|
|
9958
11578
|
}
|
|
11579
|
+
function collectFieldSelectors(value, previous = []) {
|
|
11580
|
+
return [...previous, parseUuidOrSlugSelector9(value)];
|
|
11581
|
+
}
|
|
9959
11582
|
function parseBooleanFlag(input) {
|
|
9960
11583
|
const normalized = input.trim().toLowerCase();
|
|
9961
11584
|
if (["true", "1", "yes", "y", "on"].includes(normalized)) {
|
|
@@ -9964,9 +11587,9 @@ function parseBooleanFlag(input) {
|
|
|
9964
11587
|
if (["false", "0", "no", "n", "off"].includes(normalized)) {
|
|
9965
11588
|
return false;
|
|
9966
11589
|
}
|
|
9967
|
-
throw new
|
|
11590
|
+
throw new InvalidArgumentError9(`Expected a boolean value, received "${input}".`);
|
|
9968
11591
|
}
|
|
9969
|
-
function
|
|
11592
|
+
function isJsonObject7(value) {
|
|
9970
11593
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9971
11594
|
}
|
|
9972
11595
|
function parseRawJsonObject3(input, sourceLabel) {
|
|
@@ -9980,7 +11603,7 @@ function parseRawJsonObject3(input, sourceLabel) {
|
|
|
9980
11603
|
`Failed to parse JSON from ${sourceLabel}: ${message}`
|
|
9981
11604
|
);
|
|
9982
11605
|
}
|
|
9983
|
-
if (!
|
|
11606
|
+
if (!isJsonObject7(parsed)) {
|
|
9984
11607
|
throw new CliError(
|
|
9985
11608
|
"invalid_cli_usage",
|
|
9986
11609
|
`Expected ${sourceLabel} to contain a JSON object.`
|
|
@@ -10001,7 +11624,7 @@ function readRawObject4(raw, rawFile) {
|
|
|
10001
11624
|
if (rawFile) {
|
|
10002
11625
|
let contents;
|
|
10003
11626
|
try {
|
|
10004
|
-
contents =
|
|
11627
|
+
contents = readFileSync9(rawFile, "utf8");
|
|
10005
11628
|
} catch (error) {
|
|
10006
11629
|
const message = error instanceof Error ? error.message : "Unable to read file.";
|
|
10007
11630
|
throw new CliError(
|
|
@@ -10060,7 +11683,7 @@ function applyFieldDefaultValue(input, defaultValue) {
|
|
|
10060
11683
|
return;
|
|
10061
11684
|
}
|
|
10062
11685
|
const config = input.config;
|
|
10063
|
-
if (config !== void 0 && !
|
|
11686
|
+
if (config !== void 0 && !isJsonObject7(config)) {
|
|
10064
11687
|
throw new CliError(
|
|
10065
11688
|
"invalid_cli_usage",
|
|
10066
11689
|
'Expected field "config" to be a JSON object when using "--default".'
|
|
@@ -10100,7 +11723,7 @@ function buildFieldCreateInput(options) {
|
|
|
10100
11723
|
input.required = options.required;
|
|
10101
11724
|
}
|
|
10102
11725
|
applyFieldDefaultValue(input, options.default);
|
|
10103
|
-
if ("config" in input &&
|
|
11726
|
+
if ("config" in input && isJsonObject7(input.config) && isEmptyObject6(input.config)) {
|
|
10104
11727
|
delete input.config;
|
|
10105
11728
|
}
|
|
10106
11729
|
return input;
|
|
@@ -10173,35 +11796,35 @@ async function resolveFieldSelector(api, schema, selector) {
|
|
|
10173
11796
|
value: match.id
|
|
10174
11797
|
};
|
|
10175
11798
|
}
|
|
10176
|
-
function
|
|
11799
|
+
function isEmptyObject6(value) {
|
|
10177
11800
|
return Object.keys(value).length === 0;
|
|
10178
11801
|
}
|
|
10179
11802
|
function registerSchemasCommands(program, options = {}) {
|
|
10180
11803
|
const filePath = options.configPath ?? defaultConfigPath;
|
|
10181
|
-
const stdout =
|
|
11804
|
+
const stdout = getCommandIo11(options.stdout);
|
|
10182
11805
|
const schemas = program.command("schemas").description("Manage schemas and schema fields");
|
|
10183
11806
|
schemas.command("list").description("List schemas").action(async function action() {
|
|
10184
11807
|
const { api, json } = createSchemasApi(this, filePath);
|
|
10185
11808
|
const data = await api.listSchemas();
|
|
10186
11809
|
if (json) {
|
|
10187
|
-
|
|
11810
|
+
emitJson11(stdout, "schemas list", data, filePath);
|
|
10188
11811
|
return;
|
|
10189
11812
|
}
|
|
10190
11813
|
emitSchemasTable(stdout, data);
|
|
10191
11814
|
});
|
|
10192
|
-
schemas.command("get").description("Get a schema by UUID or slug").argument("<schema>", "schema uuid or slug",
|
|
11815
|
+
schemas.command("get").description("Get a schema by UUID or slug").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector9).action(async function action(schema) {
|
|
10193
11816
|
const { api, json } = createSchemasApi(this, filePath);
|
|
10194
11817
|
const resolvedSchema = await resolveSchemaSelector2(api, schema);
|
|
10195
11818
|
const data = await api.getSchema(resolvedSchema);
|
|
10196
11819
|
if (json) {
|
|
10197
|
-
|
|
11820
|
+
emitJson11(stdout, "schemas get", data, filePath);
|
|
10198
11821
|
return;
|
|
10199
11822
|
}
|
|
10200
11823
|
emitSchemasTable(stdout, [data]);
|
|
10201
11824
|
});
|
|
10202
11825
|
schemas.command("create").description("Create a schema").requiredOption("--name <name>", "schema name").requiredOption("--slug <slug>", "schema slug").option("--auditable", "mark schema as auditable").option("--commentable", "mark schema as commentable").action(async function action(commandOptions) {
|
|
10203
11826
|
const { api, json, readOnly } = createSchemasApi(this, filePath);
|
|
10204
|
-
|
|
11827
|
+
ensureWritable8("schemas create", readOnly, "write");
|
|
10205
11828
|
const input = {
|
|
10206
11829
|
name: commandOptions.name,
|
|
10207
11830
|
slug: commandOptions.slug,
|
|
@@ -10210,32 +11833,87 @@ function registerSchemasCommands(program, options = {}) {
|
|
|
10210
11833
|
};
|
|
10211
11834
|
const data = await api.createSchema(input);
|
|
10212
11835
|
if (json) {
|
|
10213
|
-
|
|
11836
|
+
emitJson11(stdout, "schemas create", data, filePath);
|
|
10214
11837
|
return;
|
|
10215
11838
|
}
|
|
10216
|
-
|
|
11839
|
+
writeLine11(stdout, `Created schema "${data.slug ?? commandOptions.slug}".`);
|
|
10217
11840
|
});
|
|
10218
|
-
schemas.command("update").description("Update a schema").argument("<schema>", "schema uuid or slug",
|
|
11841
|
+
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(
|
|
11842
|
+
"--highlighted-field <field>",
|
|
11843
|
+
"its value is used as each record's display name in the UI (field uuid or slug)",
|
|
11844
|
+
parseUuidOrSlugSelector9
|
|
11845
|
+
).action(async function action(schema, commandOptions) {
|
|
10219
11846
|
const { api, json, readOnly } = createSchemasApi(this, filePath);
|
|
10220
|
-
|
|
11847
|
+
ensureWritable8("schemas update", readOnly, "write");
|
|
10221
11848
|
const resolvedSchema = await resolveSchemaSelector2(api, schema);
|
|
10222
11849
|
const input = buildSchemaUpdateInput(commandOptions);
|
|
10223
|
-
if (
|
|
11850
|
+
if (commandOptions.highlightedField !== void 0) {
|
|
11851
|
+
const resolvedField = await resolveFieldSelector(
|
|
11852
|
+
api,
|
|
11853
|
+
resolvedSchema,
|
|
11854
|
+
commandOptions.highlightedField
|
|
11855
|
+
);
|
|
11856
|
+
input.highlightedField = resolvedField.value;
|
|
11857
|
+
}
|
|
11858
|
+
if (isEmptyObject6(input)) {
|
|
10224
11859
|
throw new CliError(
|
|
10225
11860
|
"invalid_cli_usage",
|
|
10226
|
-
'Provide at least one schema field to update via "--name", "--slug", "--auditable", or "--
|
|
11861
|
+
'Provide at least one schema field to update via "--name", "--slug", "--auditable", "--commentable", or "--highlighted-field".'
|
|
10227
11862
|
);
|
|
10228
11863
|
}
|
|
10229
11864
|
const data = await api.updateSchema(resolvedSchema, input);
|
|
10230
11865
|
if (json) {
|
|
10231
|
-
|
|
11866
|
+
emitJson11(stdout, "schemas update", data, filePath);
|
|
11867
|
+
return;
|
|
11868
|
+
}
|
|
11869
|
+
writeLine11(stdout, `Updated schema "${data.slug ?? schema.value}".`);
|
|
11870
|
+
}).addHelpText("after", HIGHLIGHTED_FIELD_HELP);
|
|
11871
|
+
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(
|
|
11872
|
+
"--field <field>",
|
|
11873
|
+
"field uuid or slug to include in the unique constraint (repeatable)",
|
|
11874
|
+
collectFieldSelectors,
|
|
11875
|
+
[]
|
|
11876
|
+
).option("--clear", "clear the unique constraint (sends an empty field list)").action(async function action(schema, commandOptions) {
|
|
11877
|
+
const { api, json, readOnly } = createSchemasApi(this, filePath);
|
|
11878
|
+
ensureWritable8("schemas set-unique-fields", readOnly, "write");
|
|
11879
|
+
const selectors = commandOptions.field ?? [];
|
|
11880
|
+
if (commandOptions.clear && selectors.length > 0) {
|
|
11881
|
+
throw new CliError(
|
|
11882
|
+
"invalid_cli_usage",
|
|
11883
|
+
'Use either "--field" or "--clear", not both.'
|
|
11884
|
+
);
|
|
11885
|
+
}
|
|
11886
|
+
if (!commandOptions.clear && selectors.length === 0) {
|
|
11887
|
+
throw new CliError(
|
|
11888
|
+
"invalid_cli_usage",
|
|
11889
|
+
'Provide at least one field via "--field", or pass "--clear" to remove the unique constraint.'
|
|
11890
|
+
);
|
|
11891
|
+
}
|
|
11892
|
+
const resolvedSchema = await resolveSchemaSelector2(api, schema);
|
|
11893
|
+
const resolvedFields = await Promise.all(
|
|
11894
|
+
selectors.map((selector) => resolveFieldSelector(api, resolvedSchema, selector))
|
|
11895
|
+
);
|
|
11896
|
+
const input = {
|
|
11897
|
+
fieldIds: resolvedFields.map((field) => field.value)
|
|
11898
|
+
};
|
|
11899
|
+
const data = await api.setUniqueFields(resolvedSchema, input);
|
|
11900
|
+
if (json) {
|
|
11901
|
+
emitJson11(stdout, "schemas set-unique-fields", data, filePath);
|
|
11902
|
+
return;
|
|
11903
|
+
}
|
|
11904
|
+
if (input.fieldIds.length === 0) {
|
|
11905
|
+
writeLine11(stdout, `Cleared unique fields on schema "${schema.value}".`);
|
|
10232
11906
|
return;
|
|
10233
11907
|
}
|
|
10234
|
-
|
|
11908
|
+
const count = input.fieldIds.length;
|
|
11909
|
+
writeLine11(
|
|
11910
|
+
stdout,
|
|
11911
|
+
`Set unique fields on schema "${schema.value}" (${count} field${count === 1 ? "" : "s"}).`
|
|
11912
|
+
);
|
|
10235
11913
|
});
|
|
10236
|
-
schemas.command("delete").description("Delete a schema").argument("<schema>", "schema uuid or slug",
|
|
11914
|
+
schemas.command("delete").description("Delete a schema").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector9).action(async function action(schema) {
|
|
10237
11915
|
const { api, json, readOnly } = createSchemasApi(this, filePath);
|
|
10238
|
-
|
|
11916
|
+
ensureWritable8("schemas delete", readOnly, "destructive");
|
|
10239
11917
|
const resolvedSchema = await resolveSchemaSelector2(api, schema);
|
|
10240
11918
|
await api.deleteSchema(resolvedSchema);
|
|
10241
11919
|
const data = {
|
|
@@ -10243,36 +11921,36 @@ function registerSchemasCommands(program, options = {}) {
|
|
|
10243
11921
|
deleted: true
|
|
10244
11922
|
};
|
|
10245
11923
|
if (json) {
|
|
10246
|
-
|
|
11924
|
+
emitJson11(stdout, "schemas delete", data, filePath);
|
|
10247
11925
|
return;
|
|
10248
11926
|
}
|
|
10249
|
-
|
|
11927
|
+
writeLine11(stdout, `Deleted schema "${schema.value}".`);
|
|
10250
11928
|
});
|
|
10251
11929
|
const fields = schemas.command("fields").description("Manage schema fields");
|
|
10252
|
-
fields.command("list").description("List fields for a schema").argument("<schema>", "schema uuid or slug",
|
|
11930
|
+
fields.command("list").description("List fields for a schema").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector9).action(async function action(schema) {
|
|
10253
11931
|
const { api, json } = createSchemasApi(this, filePath);
|
|
10254
11932
|
const resolvedSchema = await resolveSchemaSelector2(api, schema);
|
|
10255
11933
|
const data = await api.listFields(resolvedSchema);
|
|
10256
11934
|
if (json) {
|
|
10257
|
-
|
|
11935
|
+
emitJson11(stdout, "schemas fields list", data, filePath);
|
|
10258
11936
|
return;
|
|
10259
11937
|
}
|
|
10260
11938
|
emitFieldsTable(stdout, data);
|
|
10261
11939
|
});
|
|
10262
|
-
fields.command("get").description("Get a field by UUID or slug").argument("<schema>", "schema uuid or slug",
|
|
11940
|
+
fields.command("get").description("Get a field by UUID or slug").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector9).argument("<field>", "field uuid or slug", parseUuidOrSlugSelector9).action(async function action(schema, field) {
|
|
10263
11941
|
const { api, json } = createSchemasApi(this, filePath);
|
|
10264
11942
|
const resolvedSchema = await resolveSchemaSelector2(api, schema);
|
|
10265
11943
|
const resolvedField = await resolveFieldSelector(api, resolvedSchema, field);
|
|
10266
11944
|
const data = await api.getField(resolvedSchema, resolvedField);
|
|
10267
11945
|
if (json) {
|
|
10268
|
-
|
|
11946
|
+
emitJson11(stdout, "schemas fields get", data, filePath);
|
|
10269
11947
|
return;
|
|
10270
11948
|
}
|
|
10271
11949
|
emitFieldsTable(stdout, [data]);
|
|
10272
11950
|
});
|
|
10273
|
-
fields.command("create").description(`Create a field in a schema.${buildSchemaFieldCreateHelpText()}`).argument("<schema>", "schema uuid or slug",
|
|
11951
|
+
fields.command("create").description(`Create a field in a schema.${buildSchemaFieldCreateHelpText()}`).argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector9).option("--type <type>", `field type (${formatSchemaFieldTypes()})`).option("--slug <slug>", "field slug").option("--label <label>", "field label").option("--required <bool>", "required flag", parseBooleanFlag).option("--default <value>", "default field value").option("--raw <json>", "raw JSON object payload (see type-specific shapes in --help)").option("--raw-file <path>", "path to a raw JSON object payload").action(async function action(schema, commandOptions) {
|
|
10274
11952
|
const { api, json, readOnly } = createSchemasApi(this, filePath);
|
|
10275
|
-
|
|
11953
|
+
ensureWritable8("schemas fields create", readOnly, "write");
|
|
10276
11954
|
const input = buildFieldCreateInput(commandOptions);
|
|
10277
11955
|
const resolvedSchema = await resolveSchemaSelector2(api, schema);
|
|
10278
11956
|
let data;
|
|
@@ -10282,14 +11960,14 @@ function registerSchemasCommands(program, options = {}) {
|
|
|
10282
11960
|
toFieldCreateError(error, input);
|
|
10283
11961
|
}
|
|
10284
11962
|
if (json) {
|
|
10285
|
-
|
|
11963
|
+
emitJson11(stdout, "schemas fields create", data, filePath);
|
|
10286
11964
|
return;
|
|
10287
11965
|
}
|
|
10288
|
-
|
|
11966
|
+
writeLine11(stdout, `Created field "${data.slug ?? commandOptions.slug}".`);
|
|
10289
11967
|
});
|
|
10290
|
-
fields.command("update").description("Update a field in a schema").argument("<schema>", "schema uuid or slug",
|
|
11968
|
+
fields.command("update").description("Update a field in a schema").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector9).argument("<field>", "field uuid or slug", parseUuidOrSlugSelector9).option("--label <label>", "field label").option("--required <bool>", "required flag", parseBooleanFlag).option("--default <value>", "default field value").option("--raw <json>", "raw JSON object payload").option("--raw-file <path>", "path to a raw JSON object payload").action(async function action(schema, field, commandOptions) {
|
|
10291
11969
|
const { api, json, readOnly } = createSchemasApi(this, filePath);
|
|
10292
|
-
|
|
11970
|
+
ensureWritable8("schemas fields update", readOnly, "write");
|
|
10293
11971
|
const resolvedSchema = await resolveSchemaSelector2(api, schema);
|
|
10294
11972
|
const resolvedField = await resolveFieldSelector(api, resolvedSchema, field);
|
|
10295
11973
|
const currentField = await api.getField(resolvedSchema, resolvedField);
|
|
@@ -10298,7 +11976,7 @@ function registerSchemasCommands(program, options = {}) {
|
|
|
10298
11976
|
throw new CliError("invalid_cli_usage", `Field "${field.value}" is missing type metadata.`);
|
|
10299
11977
|
}
|
|
10300
11978
|
const input = buildFieldUpdateInput(currentType, commandOptions);
|
|
10301
|
-
if (
|
|
11979
|
+
if (isEmptyObject6(input)) {
|
|
10302
11980
|
throw new CliError(
|
|
10303
11981
|
"invalid_cli_usage",
|
|
10304
11982
|
'Provide at least one field update via "--label", "--required", "--raw", or "--raw-file".'
|
|
@@ -10306,14 +11984,14 @@ function registerSchemasCommands(program, options = {}) {
|
|
|
10306
11984
|
}
|
|
10307
11985
|
const data = await api.updateField(resolvedSchema, resolvedField, input);
|
|
10308
11986
|
if (json) {
|
|
10309
|
-
|
|
11987
|
+
emitJson11(stdout, "schemas fields update", data, filePath);
|
|
10310
11988
|
return;
|
|
10311
11989
|
}
|
|
10312
|
-
|
|
11990
|
+
writeLine11(stdout, `Updated field "${data.slug ?? field.value}".`);
|
|
10313
11991
|
});
|
|
10314
|
-
fields.command("delete").description("Delete a field from a schema").argument("<schema>", "schema uuid or slug",
|
|
11992
|
+
fields.command("delete").description("Delete a field from a schema").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector9).argument("<field>", "field uuid or slug", parseUuidOrSlugSelector9).action(async function action(schema, field) {
|
|
10315
11993
|
const { api, json, readOnly } = createSchemasApi(this, filePath);
|
|
10316
|
-
|
|
11994
|
+
ensureWritable8("schemas fields delete", readOnly, "destructive");
|
|
10317
11995
|
const resolvedSchema = await resolveSchemaSelector2(api, schema);
|
|
10318
11996
|
const resolvedField = await resolveFieldSelector(api, resolvedSchema, field);
|
|
10319
11997
|
await api.deleteField(resolvedSchema, resolvedField);
|
|
@@ -10323,19 +12001,19 @@ function registerSchemasCommands(program, options = {}) {
|
|
|
10323
12001
|
deleted: true
|
|
10324
12002
|
};
|
|
10325
12003
|
if (json) {
|
|
10326
|
-
|
|
12004
|
+
emitJson11(stdout, "schemas fields delete", data, filePath);
|
|
10327
12005
|
return;
|
|
10328
12006
|
}
|
|
10329
|
-
|
|
12007
|
+
writeLine11(stdout, `Deleted field "${field.value}" from schema "${schema.value}".`);
|
|
10330
12008
|
});
|
|
10331
12009
|
}
|
|
10332
12010
|
|
|
10333
12011
|
// src/commands/teamspace.ts
|
|
10334
|
-
import { readFileSync as
|
|
10335
|
-
import { InvalidArgumentError as
|
|
12012
|
+
import { readFileSync as readFileSync10 } from "fs";
|
|
12013
|
+
import { InvalidArgumentError as InvalidArgumentError10 } from "commander";
|
|
10336
12014
|
|
|
10337
12015
|
// src/api/teamspace.ts
|
|
10338
|
-
function
|
|
12016
|
+
function jsonOptions8(body, method) {
|
|
10339
12017
|
return {
|
|
10340
12018
|
method,
|
|
10341
12019
|
headers: {
|
|
@@ -10344,7 +12022,7 @@ function jsonOptions7(body, method) {
|
|
|
10344
12022
|
body: JSON.stringify(body)
|
|
10345
12023
|
};
|
|
10346
12024
|
}
|
|
10347
|
-
function
|
|
12025
|
+
function selectorValue10(selector) {
|
|
10348
12026
|
return selector.value;
|
|
10349
12027
|
}
|
|
10350
12028
|
var TeamspaceApi = class {
|
|
@@ -10365,53 +12043,53 @@ var TeamspaceApi = class {
|
|
|
10365
12043
|
createFolder(input) {
|
|
10366
12044
|
return this.client.requestJson(
|
|
10367
12045
|
"/api/v2/teamspaces/folders",
|
|
10368
|
-
|
|
12046
|
+
jsonOptions8(input, "POST")
|
|
10369
12047
|
);
|
|
10370
12048
|
}
|
|
10371
12049
|
updateFolder(folder, input) {
|
|
10372
12050
|
return this.client.requestJson(
|
|
10373
|
-
`/api/v2/teamspaces/folders/${
|
|
10374
|
-
|
|
12051
|
+
`/api/v2/teamspaces/folders/${selectorValue10(folder)}`,
|
|
12052
|
+
jsonOptions8(input, "PATCH")
|
|
10375
12053
|
);
|
|
10376
12054
|
}
|
|
10377
12055
|
deleteFolder(folder) {
|
|
10378
12056
|
return this.client.requestJson(
|
|
10379
|
-
`/api/v2/teamspaces/folders/${
|
|
12057
|
+
`/api/v2/teamspaces/folders/${selectorValue10(folder)}`,
|
|
10380
12058
|
{ method: "DELETE" }
|
|
10381
12059
|
);
|
|
10382
12060
|
}
|
|
10383
12061
|
publishResource(input) {
|
|
10384
12062
|
return this.client.requestJson(
|
|
10385
12063
|
"/api/v2/teamspaces/resources:publish",
|
|
10386
|
-
|
|
12064
|
+
jsonOptions8(input, "POST")
|
|
10387
12065
|
);
|
|
10388
12066
|
}
|
|
10389
12067
|
unpublishResource(resourceId) {
|
|
10390
12068
|
return this.client.requestJson(
|
|
10391
12069
|
"/api/v2/teamspaces/resources:unpublish",
|
|
10392
|
-
|
|
12070
|
+
jsonOptions8({ resourceId }, "POST")
|
|
10393
12071
|
);
|
|
10394
12072
|
}
|
|
10395
12073
|
};
|
|
10396
12074
|
|
|
10397
12075
|
// src/commands/teamspace.ts
|
|
10398
|
-
function
|
|
12076
|
+
function getCommandIo12(stdout) {
|
|
10399
12077
|
return stdout ?? process.stdout;
|
|
10400
12078
|
}
|
|
10401
|
-
function
|
|
12079
|
+
function writeLine12(stdout, value) {
|
|
10402
12080
|
stdout.write(`${value}
|
|
10403
12081
|
`);
|
|
10404
12082
|
}
|
|
10405
|
-
function
|
|
12083
|
+
function getGlobalOptions12(command) {
|
|
10406
12084
|
return command.optsWithGlobals();
|
|
10407
12085
|
}
|
|
10408
|
-
function
|
|
10409
|
-
|
|
12086
|
+
function emitJson12(stdout, commandName, data, configPath) {
|
|
12087
|
+
writeLine12(
|
|
10410
12088
|
stdout,
|
|
10411
12089
|
JSON.stringify(buildJsonSuccess(data, { command: commandName, configPath }))
|
|
10412
12090
|
);
|
|
10413
12091
|
}
|
|
10414
|
-
function
|
|
12092
|
+
function toConfigurationError11(filePath, error) {
|
|
10415
12093
|
if (error instanceof CliError) {
|
|
10416
12094
|
throw error;
|
|
10417
12095
|
}
|
|
@@ -10426,7 +12104,7 @@ function toConfigurationError10(filePath, error) {
|
|
|
10426
12104
|
function createTeamspaceApi(command, filePath) {
|
|
10427
12105
|
try {
|
|
10428
12106
|
const config = readRuntimeConfig(filePath);
|
|
10429
|
-
const runtime = resolveRuntimeContext(config,
|
|
12107
|
+
const runtime = resolveRuntimeContext(config, getGlobalOptions12(command));
|
|
10430
12108
|
if (!runtime.baseUrl) {
|
|
10431
12109
|
throw new CliError(
|
|
10432
12110
|
"configuration_error",
|
|
@@ -10444,10 +12122,10 @@ function createTeamspaceApi(command, filePath) {
|
|
|
10444
12122
|
readOnly: runtime.readOnly
|
|
10445
12123
|
};
|
|
10446
12124
|
} catch (error) {
|
|
10447
|
-
|
|
12125
|
+
toConfigurationError11(filePath, error);
|
|
10448
12126
|
}
|
|
10449
12127
|
}
|
|
10450
|
-
function
|
|
12128
|
+
function ensureWritable9(commandName, readOnly, commandMode) {
|
|
10451
12129
|
if (readOnly) {
|
|
10452
12130
|
throw new CliError(
|
|
10453
12131
|
"command_not_allowed_in_read_only_mode",
|
|
@@ -10459,21 +12137,21 @@ function ensureWritable8(commandName, readOnly, commandMode) {
|
|
|
10459
12137
|
);
|
|
10460
12138
|
}
|
|
10461
12139
|
}
|
|
10462
|
-
function
|
|
12140
|
+
function parseUuidOrSlugSelector10(input) {
|
|
10463
12141
|
try {
|
|
10464
12142
|
return normalizeUuidOrSlug(input);
|
|
10465
12143
|
} catch (error) {
|
|
10466
12144
|
const message = error instanceof Error ? error.message : "Invalid selector.";
|
|
10467
|
-
throw new
|
|
12145
|
+
throw new InvalidArgumentError10(message);
|
|
10468
12146
|
}
|
|
10469
12147
|
}
|
|
10470
12148
|
function parseNonNegativeInteger3(input) {
|
|
10471
12149
|
if (!/^\d+$/.test(input.trim())) {
|
|
10472
|
-
throw new
|
|
12150
|
+
throw new InvalidArgumentError10(`Expected a non-negative integer, received "${input}".`);
|
|
10473
12151
|
}
|
|
10474
12152
|
return Number(input);
|
|
10475
12153
|
}
|
|
10476
|
-
function
|
|
12154
|
+
function isJsonObject8(value) {
|
|
10477
12155
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10478
12156
|
}
|
|
10479
12157
|
function parseRawJsonObject4(input, sourceLabel) {
|
|
@@ -10487,7 +12165,7 @@ function parseRawJsonObject4(input, sourceLabel) {
|
|
|
10487
12165
|
`Failed to parse JSON from ${sourceLabel}: ${message}`
|
|
10488
12166
|
);
|
|
10489
12167
|
}
|
|
10490
|
-
if (!
|
|
12168
|
+
if (!isJsonObject8(parsed)) {
|
|
10491
12169
|
throw new CliError(
|
|
10492
12170
|
"invalid_cli_usage",
|
|
10493
12171
|
`Expected ${sourceLabel} to contain a JSON object.`
|
|
@@ -10508,7 +12186,7 @@ function readRawObject5(raw, rawFile) {
|
|
|
10508
12186
|
if (rawFile) {
|
|
10509
12187
|
let contents;
|
|
10510
12188
|
try {
|
|
10511
|
-
contents =
|
|
12189
|
+
contents = readFileSync10(rawFile, "utf8");
|
|
10512
12190
|
} catch (error) {
|
|
10513
12191
|
const message = error instanceof Error ? error.message : "Unable to read file.";
|
|
10514
12192
|
throw new CliError(
|
|
@@ -10520,7 +12198,7 @@ function readRawObject5(raw, rawFile) {
|
|
|
10520
12198
|
}
|
|
10521
12199
|
return void 0;
|
|
10522
12200
|
}
|
|
10523
|
-
function
|
|
12201
|
+
function isEmptyObject7(value) {
|
|
10524
12202
|
return Object.keys(value).length === 0;
|
|
10525
12203
|
}
|
|
10526
12204
|
function buildFolderCreateInput(options) {
|
|
@@ -10551,7 +12229,7 @@ function buildFolderUpdateInput(options) {
|
|
|
10551
12229
|
if (props !== void 0) {
|
|
10552
12230
|
input.additionalProperties = props;
|
|
10553
12231
|
}
|
|
10554
|
-
if (
|
|
12232
|
+
if (isEmptyObject7(input)) {
|
|
10555
12233
|
throw new CliError(
|
|
10556
12234
|
"invalid_cli_usage",
|
|
10557
12235
|
'Provide folder updates via "--name", "--order", "--props", or "--props-file".'
|
|
@@ -10561,9 +12239,9 @@ function buildFolderUpdateInput(options) {
|
|
|
10561
12239
|
}
|
|
10562
12240
|
function toTableRows5(data) {
|
|
10563
12241
|
if (Array.isArray(data)) {
|
|
10564
|
-
return data.map((entry) =>
|
|
12242
|
+
return data.map((entry) => isJsonObject8(entry) ? entry : { value: entry });
|
|
10565
12243
|
}
|
|
10566
|
-
if (
|
|
12244
|
+
if (isJsonObject8(data)) {
|
|
10567
12245
|
return [data];
|
|
10568
12246
|
}
|
|
10569
12247
|
return [{ value: data }];
|
|
@@ -10625,85 +12303,91 @@ async function resolveFolderSelector2(api, selector) {
|
|
|
10625
12303
|
}
|
|
10626
12304
|
function registerTeamspaceCommands(program, options = {}) {
|
|
10627
12305
|
const filePath = options.configPath ?? defaultConfigPath;
|
|
10628
|
-
const stdout =
|
|
12306
|
+
const stdout = getCommandIo12(options.stdout);
|
|
10629
12307
|
const teamspace = program.command("teamspace").description("Manage teamspace folders and resources");
|
|
10630
12308
|
const folders = teamspace.command("folders").description("Manage teamspace folders");
|
|
10631
|
-
folders.command("list").description("List teamspace folders").option("--include-resources", "include
|
|
12309
|
+
folders.command("list").description("List teamspace folders").option("--include-resources", "include the published resources inside each folder").action(async function action(commandOptions) {
|
|
10632
12310
|
const { api, json } = createTeamspaceApi(this, filePath);
|
|
10633
12311
|
const data = await api.listFolders(Boolean(commandOptions.includeResources));
|
|
10634
12312
|
if (json) {
|
|
10635
|
-
|
|
12313
|
+
emitJson12(stdout, "teamspace folders list", data, filePath);
|
|
10636
12314
|
return;
|
|
10637
12315
|
}
|
|
10638
12316
|
emitTable5(stdout, data);
|
|
10639
12317
|
});
|
|
10640
|
-
folders.command("get").description("Get a teamspace folder by exact name or UUID").argument("<folder>", "folder UUID or exact name",
|
|
12318
|
+
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) {
|
|
10641
12319
|
const { api, json } = createTeamspaceApi(this, filePath);
|
|
10642
12320
|
const resolvedFolder = await resolveFolderSelector2(api, folder);
|
|
10643
12321
|
const allFolders = await api.listFolders(Boolean(commandOptions.includeResources));
|
|
10644
12322
|
const data = findFolderEntity(allFolders, resolvedFolder);
|
|
10645
12323
|
if (json) {
|
|
10646
|
-
|
|
12324
|
+
emitJson12(stdout, "teamspace folders get", data, filePath);
|
|
10647
12325
|
return;
|
|
10648
12326
|
}
|
|
10649
12327
|
emitTable5(stdout, data);
|
|
10650
12328
|
});
|
|
10651
|
-
folders.command("create").description("Create a teamspace folder").requiredOption("--name <name>", "folder name").option("--order <n>", "
|
|
12329
|
+
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) {
|
|
10652
12330
|
const { api, json, readOnly } = createTeamspaceApi(this, filePath);
|
|
10653
|
-
|
|
12331
|
+
ensureWritable9("teamspace folders create", readOnly, "write");
|
|
10654
12332
|
const data = await api.createFolder(buildFolderCreateInput(commandOptions));
|
|
10655
12333
|
if (json) {
|
|
10656
|
-
|
|
12334
|
+
emitJson12(stdout, "teamspace folders create", data, filePath);
|
|
10657
12335
|
return;
|
|
10658
12336
|
}
|
|
10659
|
-
|
|
12337
|
+
writeLine12(stdout, `Created folder "${getFolderIdentifier(data)}".`);
|
|
10660
12338
|
});
|
|
10661
|
-
folders.command("update").description("Update a teamspace folder").argument("<folder>", "folder UUID or exact name",
|
|
12339
|
+
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) {
|
|
10662
12340
|
const { api, json, readOnly } = createTeamspaceApi(this, filePath);
|
|
10663
|
-
|
|
12341
|
+
ensureWritable9("teamspace folders update", readOnly, "write");
|
|
10664
12342
|
const resolvedFolder = await resolveFolderSelector2(api, folder);
|
|
10665
12343
|
const data = await api.updateFolder(resolvedFolder, buildFolderUpdateInput(commandOptions));
|
|
10666
12344
|
if (json) {
|
|
10667
|
-
|
|
12345
|
+
emitJson12(stdout, "teamspace folders update", data, filePath);
|
|
10668
12346
|
return;
|
|
10669
12347
|
}
|
|
10670
|
-
|
|
12348
|
+
writeLine12(stdout, `Updated folder "${getFolderIdentifier(data)}".`);
|
|
10671
12349
|
});
|
|
10672
|
-
folders.command("delete").description("Delete a teamspace folder").argument("<folder>", "folder UUID or exact name",
|
|
12350
|
+
folders.command("delete").description("Delete a teamspace folder").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector10).action(async function action(folder) {
|
|
10673
12351
|
const { api, json, readOnly } = createTeamspaceApi(this, filePath);
|
|
10674
|
-
|
|
12352
|
+
ensureWritable9("teamspace folders delete", readOnly, "destructive");
|
|
10675
12353
|
const resolvedFolder = await resolveFolderSelector2(api, folder);
|
|
10676
12354
|
const data = await api.deleteFolder(resolvedFolder);
|
|
10677
12355
|
if (json) {
|
|
10678
|
-
|
|
12356
|
+
emitJson12(stdout, "teamspace folders delete", data, filePath);
|
|
10679
12357
|
return;
|
|
10680
12358
|
}
|
|
10681
|
-
|
|
12359
|
+
writeLine12(stdout, `Deleted folder "${resolvedFolder.value}".`);
|
|
10682
12360
|
});
|
|
10683
12361
|
const resources = teamspace.command("resources").description("Manage teamspace resources");
|
|
10684
|
-
resources.command("publish").description(
|
|
12362
|
+
resources.command("publish").description(
|
|
12363
|
+
"Publish a resource to a teamspace folder. Publishing an already-published resource moves it to the new folder."
|
|
12364
|
+
).argument("<resource>", "schema UUID, schema slug, or display UUID", parseUuidOrSlugSelector10).requiredOption(
|
|
12365
|
+
"--to <folder>",
|
|
12366
|
+
"target folder UUID or exact name (root folder UUID is 00000000-0000-0000-0000-000000000000)",
|
|
12367
|
+
parseUuidOrSlugSelector10
|
|
12368
|
+
).action(async function action(resource, commandOptions) {
|
|
10685
12369
|
const { api, json, readOnly } = createTeamspaceApi(this, filePath);
|
|
10686
|
-
|
|
12370
|
+
ensureWritable9("teamspace resources publish", readOnly, "write");
|
|
10687
12371
|
const folder = await resolveFolderSelector2(api, commandOptions.to);
|
|
10688
12372
|
const data = await api.publishResource({
|
|
10689
12373
|
resourceId: resource.value,
|
|
10690
12374
|
targetFolderId: folder.value
|
|
10691
12375
|
});
|
|
10692
12376
|
if (json) {
|
|
10693
|
-
|
|
12377
|
+
emitJson12(stdout, "teamspace resources publish", data, filePath);
|
|
10694
12378
|
return;
|
|
10695
12379
|
}
|
|
10696
|
-
|
|
12380
|
+
writeLine12(stdout, `Published resource "${resource.value}" to folder "${folder.value}".`);
|
|
10697
12381
|
});
|
|
10698
|
-
resources.command("unpublish").description("Unpublish a resource from teamspace").argument("<resource>", "
|
|
12382
|
+
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) {
|
|
10699
12383
|
const { api, json, readOnly } = createTeamspaceApi(this, filePath);
|
|
10700
|
-
|
|
12384
|
+
ensureWritable9("teamspace resources unpublish", readOnly, "write");
|
|
10701
12385
|
const data = await api.unpublishResource(resource.value);
|
|
10702
12386
|
if (json) {
|
|
10703
|
-
|
|
12387
|
+
emitJson12(stdout, "teamspace resources unpublish", data, filePath);
|
|
10704
12388
|
return;
|
|
10705
12389
|
}
|
|
10706
|
-
|
|
12390
|
+
writeLine12(stdout, `Unpublished resource "${resource.value}".`);
|
|
10707
12391
|
});
|
|
10708
12392
|
}
|
|
10709
12393
|
|
|
@@ -10711,12 +12395,13 @@ function registerTeamspaceCommands(program, options = {}) {
|
|
|
10711
12395
|
var require2 = createRequire(import.meta.url);
|
|
10712
12396
|
var { version } = require2("../package.json");
|
|
10713
12397
|
function buildProgram(options = {}) {
|
|
10714
|
-
const program = new
|
|
12398
|
+
const program = new Command11();
|
|
10715
12399
|
program.name("zinkee").description("CLI for Zinkee API v2").version(version).enablePositionalOptions().showHelpAfterError().option("--profile <name>", "select a profile from config").option("--base-url <url>", "override the configured base URL").option("--api-key <token>", "override the configured API key").option("--read-only", "run in read-only mode").option("--example", "show examples for a command").option("--json", "emit JSON output").option("--install-completion [shell]", "install shell completion (bash, zsh, fish, powershell)").option("--show-completion [shell]", "print shell completion script for the current shell");
|
|
10716
12400
|
registerProfilesCommands(program, options);
|
|
10717
12401
|
registerAutomationsCommands(program, options);
|
|
10718
12402
|
registerConfigCommands(program, options);
|
|
10719
12403
|
registerDisplaysCommands(program, options);
|
|
12404
|
+
registerDocumentTemplatesCommands(program, options);
|
|
10720
12405
|
registerFilesCommands(program, options);
|
|
10721
12406
|
registerNavigationCommands(program, options);
|
|
10722
12407
|
registerSchemasCommands(program, options);
|
|
@@ -10861,9 +12546,9 @@ function getCompletions(program, request, deps = {}) {
|
|
|
10861
12546
|
|
|
10862
12547
|
// src/completion/install.ts
|
|
10863
12548
|
import { execFileSync } from "child_process";
|
|
10864
|
-
import { mkdirSync as mkdirSync2, readFileSync as
|
|
12549
|
+
import { mkdirSync as mkdirSync2, readFileSync as readFileSync11, writeFileSync as writeFileSync4 } from "fs";
|
|
10865
12550
|
import { homedir as homedir2, platform } from "os";
|
|
10866
|
-
import { basename as
|
|
12551
|
+
import { basename as basename3, dirname as dirname2, join as join2 } from "path";
|
|
10867
12552
|
|
|
10868
12553
|
// src/completion/scripts.ts
|
|
10869
12554
|
var PROGRAM = "zinkee";
|
|
@@ -10985,7 +12670,7 @@ function defaultPowerShellProfile(env) {
|
|
|
10985
12670
|
function detectShell(env) {
|
|
10986
12671
|
const fromEnv = env.shellEnv;
|
|
10987
12672
|
if (fromEnv) {
|
|
10988
|
-
const name =
|
|
12673
|
+
const name = basename3(fromEnv).toLowerCase().replace(/\.exe$/, "");
|
|
10989
12674
|
if (name === "bash") {
|
|
10990
12675
|
return "bash";
|
|
10991
12676
|
}
|
|
@@ -11083,7 +12768,7 @@ ${BLOCK_END}
|
|
|
11083
12768
|
}
|
|
11084
12769
|
function readFileOrEmpty(path) {
|
|
11085
12770
|
try {
|
|
11086
|
-
return
|
|
12771
|
+
return readFileSync11(path, "utf8");
|
|
11087
12772
|
} catch (error) {
|
|
11088
12773
|
if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
|
|
11089
12774
|
return "";
|
|
@@ -11093,7 +12778,7 @@ function readFileOrEmpty(path) {
|
|
|
11093
12778
|
}
|
|
11094
12779
|
function writeFileEnsuringDir(path, content) {
|
|
11095
12780
|
mkdirSync2(dirname2(path), { recursive: true });
|
|
11096
|
-
|
|
12781
|
+
writeFileSync4(path, content, "utf8");
|
|
11097
12782
|
}
|
|
11098
12783
|
function installCompletion(shell, env) {
|
|
11099
12784
|
const target = resolveTarget(shell, env);
|