zinkee 0.1.19 → 0.1.21
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 +47 -0
- package/README.md +12 -4
- package/dist/index.js +238 -104
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/displays.test.ts +223 -0
- package/src/commands/displays.ts +61 -12
- package/src/utils/examples.ts +120 -16
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(npm test *)",
|
|
5
|
+
"Bash(npm run *)",
|
|
6
|
+
"Bash(pnpm typecheck *)",
|
|
7
|
+
"Bash(pnpm test *)",
|
|
8
|
+
"Bash(npx tsc *)",
|
|
9
|
+
"Read(//home/guillermo/dev/z2-backend/api/src/main/java/com/zinkee/api/domain/model/v2/log/**)",
|
|
10
|
+
"Read(//home/guillermo/dev/z2-backend/**)",
|
|
11
|
+
"Bash(grep *)",
|
|
12
|
+
"Bash(npx vitest *)",
|
|
13
|
+
"Bash(npx tsx *)",
|
|
14
|
+
"Bash(node dist/index.js --help)",
|
|
15
|
+
"Bash(gh repo *)",
|
|
16
|
+
"WebFetch(domain:github.com)",
|
|
17
|
+
"Bash(git config *)",
|
|
18
|
+
"Read(//home/guillermo/.config/**)",
|
|
19
|
+
"Read(//home/guillermo/**)",
|
|
20
|
+
"Bash(curl *)",
|
|
21
|
+
"Bash(node dist/index.js --show-completion zsh)",
|
|
22
|
+
"Bash(node *)",
|
|
23
|
+
"Bash(_ZINKEE_COMPLETE=zsh_complete COMP_WORDS=\"zinkee\" COMP_CWORD=1 node *)",
|
|
24
|
+
"Bash(_ZINKEE_COMPLETE=zsh_complete COMP_WORDS=\"zinkee schemas\" COMP_CWORD=2 node *)",
|
|
25
|
+
"Bash(_ZINKEE_COMPLETE=zsh_complete COMP_WORDS=\"zinkee schemas fields\" COMP_CWORD=3 node dist/index.js)",
|
|
26
|
+
"Bash(_ZINKEE_COMPLETE=zsh_complete COMP_WORDS=\"zinkee schemas fields cr\" COMP_CWORD=3 node dist/index.js)",
|
|
27
|
+
"Bash(_ZINKEE_COMPLETE=zsh_complete COMP_WORDS=\"zinkee schemas list --j\" COMP_CWORD=3 node dist/index.js)",
|
|
28
|
+
"Bash(rm -rf /tmp/zinkee-install)",
|
|
29
|
+
"Bash(mkdir -p /tmp/zinkee-install)",
|
|
30
|
+
"Bash(HOME=/tmp/zinkee-install SHELL=/bin/zsh node dist/index.js --install-completion)",
|
|
31
|
+
"Read(//tmp/**)",
|
|
32
|
+
"Read(//tmp/zinkee-install/**)",
|
|
33
|
+
"Bash(rm -rf /tmp/zinkee-install-bash)",
|
|
34
|
+
"Bash(mkdir -p /tmp/zinkee-install-bash)",
|
|
35
|
+
"Bash(HOME=/tmp/zinkee-install-bash SHELL=/bin/bash node dist/index.js --install-completion)",
|
|
36
|
+
"Bash(rm -rf /tmp/zinkee-install-fish)",
|
|
37
|
+
"Bash(mkdir -p /tmp/zinkee-install-fish)",
|
|
38
|
+
"Bash(_ZINKEE_COMPLETE=zsh_complete node dist/index.js)",
|
|
39
|
+
"Bash(echo \"exit: $?\")",
|
|
40
|
+
"Bash(_ZINKEE_COMPLETE=zsh_complete COMP_WORDS=\"zinkee schemas\" COMP_CWORD=abc node dist/index.js)",
|
|
41
|
+
"Bash(_ZINKEE_COMPLETE=zsh_complete COMP_WORDS=\"zinkee config show --foo --bar baz quux ?\" COMP_CWORD=10 node dist/index.js)",
|
|
42
|
+
"Bash(git -C /home/guillermo/dev/cli status)",
|
|
43
|
+
"Bash(git -C /home/guillermo/dev/cli branch --show-current)",
|
|
44
|
+
"Bash(git -C /home/guillermo/dev/cli diff --stat)"
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
}
|
package/README.md
CHANGED
|
@@ -480,17 +480,25 @@ zinkee displays layout update <display-uuid> --template freeform --freeform-layo
|
|
|
480
480
|
}'
|
|
481
481
|
```
|
|
482
482
|
|
|
483
|
-
###
|
|
483
|
+
### Widget filters
|
|
484
484
|
|
|
485
|
-
|
|
485
|
+
Pass `--filter "<field>:<comparator>:<value>"` (repeatable) and the CLI turns it into the structured `query.filters[]` payload the API expects. Field accepts UUID or slug. Supported comparators: `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `contains`, `in` (comma-separated values), `is_empty`, `is_not_empty`.
|
|
486
486
|
|
|
487
487
|
```bash
|
|
488
|
-
--
|
|
488
|
+
zinkee --json displays widgets update <display-uuid> <widget-uuid> \
|
|
489
|
+
--filter "status:eq:2" \
|
|
490
|
+
--filter "amount:gte:500"
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
For comparators the parser does not cover yet (e.g. `NOT_CONTAINS`, `RANGE`) keep using `--raw`:
|
|
494
|
+
|
|
495
|
+
```bash
|
|
496
|
+
--raw '{"query":{"filters":[{"origin":{"fieldId":"<field>"},"comparisonOperator":"RANGE","values":["2025-01-01","2025-12-31"]}]}}'
|
|
489
497
|
```
|
|
490
498
|
|
|
491
499
|
### Slug support
|
|
492
500
|
|
|
493
|
-
Slugs are resolved to UUIDs in: `--field`, `--source-schema`, `--source-field`, `--x-axis-field`, `kpi.fieldCalc`, `chart.xAxisFieldId`, `chart.yAxisSeries[].fieldCalc`, `bindings.variableMap` values.
|
|
501
|
+
Slugs are resolved to UUIDs in: `--field`, `--source-schema`, `--source-field`, `--x-axis-field`, `--filter` field reference, `kpi.fieldCalc`, `chart.xAxisFieldId`, `chart.yAxisSeries[].fieldCalc`, `bindings.variableMap` values.
|
|
494
502
|
|
|
495
503
|
Display UUIDs are required for `displays widgets create/update` and `displays variables create`.
|
|
496
504
|
|
package/dist/index.js
CHANGED
|
@@ -3387,8 +3387,38 @@ var specificExamples = {
|
|
|
3387
3387
|
}`
|
|
3388
3388
|
},
|
|
3389
3389
|
{
|
|
3390
|
-
description: "Create a
|
|
3391
|
-
command: `zinkee --json displays widgets create 0f6f062f-1478-4df2-96a1-c495d037d260 --type CHART --name "Revenue by
|
|
3390
|
+
description: "Create a CHART widget with a daily time-serie x-axis.",
|
|
3391
|
+
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
|
+
raw: `{
|
|
3393
|
+
"type": "CHART",
|
|
3394
|
+
"source": {
|
|
3395
|
+
"originResourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
|
|
3396
|
+
"isOriginSubSchema": false
|
|
3397
|
+
},
|
|
3398
|
+
"placement": {
|
|
3399
|
+
"layout": { "x": 0, "y": 0, "w": 8, "h": 6 }
|
|
3400
|
+
},
|
|
3401
|
+
"presentation": { "name": "Revenue by day" },
|
|
3402
|
+
"chart": {
|
|
3403
|
+
"chartType": "lines",
|
|
3404
|
+
"xAxisFieldId": "due-date",
|
|
3405
|
+
"xAxisDateFormat": "DATE",
|
|
3406
|
+
"xAxisAsTimeSerie": true,
|
|
3407
|
+
"yAxisSeries": [
|
|
3408
|
+
{
|
|
3409
|
+
"typeCalc": "SUM",
|
|
3410
|
+
"fieldCalc": "amount",
|
|
3411
|
+
"color": "#4B9CD3",
|
|
3412
|
+
"axisType": "PRIMARY"
|
|
3413
|
+
}
|
|
3414
|
+
],
|
|
3415
|
+
"legend": { "position": "bottom" }
|
|
3416
|
+
}
|
|
3417
|
+
}`
|
|
3418
|
+
},
|
|
3419
|
+
{
|
|
3420
|
+
description: "Create a bars CHART widget with a monthly time-serie x-axis and two y-axis series.",
|
|
3421
|
+
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":"id","color":"#E57373","axisType":"SECONDARY"}' --legend '{"position":"bottom"}'`,
|
|
3392
3422
|
raw: `{
|
|
3393
3423
|
"type": "CHART",
|
|
3394
3424
|
"source": {
|
|
@@ -3402,7 +3432,7 @@ var specificExamples = {
|
|
|
3402
3432
|
"chart": {
|
|
3403
3433
|
"chartType": "bars",
|
|
3404
3434
|
"xAxisFieldId": "due-date",
|
|
3405
|
-
"xAxisDateFormat": "
|
|
3435
|
+
"xAxisDateFormat": "MONTH_YEAR",
|
|
3406
3436
|
"xAxisAsTimeSerie": true,
|
|
3407
3437
|
"yAxisSeries": [
|
|
3408
3438
|
{
|
|
@@ -3420,6 +3450,66 @@ var specificExamples = {
|
|
|
3420
3450
|
],
|
|
3421
3451
|
"legend": { "position": "bottom" }
|
|
3422
3452
|
}
|
|
3453
|
+
}`
|
|
3454
|
+
},
|
|
3455
|
+
{
|
|
3456
|
+
description: "Create a bars CHART widget with a quarterly time-serie x-axis.",
|
|
3457
|
+
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"}'`,
|
|
3458
|
+
raw: `{
|
|
3459
|
+
"type": "CHART",
|
|
3460
|
+
"source": {
|
|
3461
|
+
"originResourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
|
|
3462
|
+
"isOriginSubSchema": false
|
|
3463
|
+
},
|
|
3464
|
+
"placement": {
|
|
3465
|
+
"layout": { "x": 0, "y": 0, "w": 8, "h": 6 }
|
|
3466
|
+
},
|
|
3467
|
+
"presentation": { "name": "Revenue by quarter" },
|
|
3468
|
+
"chart": {
|
|
3469
|
+
"chartType": "bars",
|
|
3470
|
+
"xAxisFieldId": "due-date",
|
|
3471
|
+
"xAxisDateFormat": "QUARTER_YEAR",
|
|
3472
|
+
"xAxisAsTimeSerie": true,
|
|
3473
|
+
"yAxisSeries": [
|
|
3474
|
+
{
|
|
3475
|
+
"typeCalc": "SUM",
|
|
3476
|
+
"fieldCalc": "amount",
|
|
3477
|
+
"color": "#4B9CD3",
|
|
3478
|
+
"axisType": "PRIMARY"
|
|
3479
|
+
}
|
|
3480
|
+
],
|
|
3481
|
+
"legend": { "position": "bottom" }
|
|
3482
|
+
}
|
|
3483
|
+
}`
|
|
3484
|
+
},
|
|
3485
|
+
{
|
|
3486
|
+
description: "Create a CHART widget with a yearly time-serie x-axis.",
|
|
3487
|
+
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"}'`,
|
|
3488
|
+
raw: `{
|
|
3489
|
+
"type": "CHART",
|
|
3490
|
+
"source": {
|
|
3491
|
+
"originResourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
|
|
3492
|
+
"isOriginSubSchema": false
|
|
3493
|
+
},
|
|
3494
|
+
"placement": {
|
|
3495
|
+
"layout": { "x": 0, "y": 0, "w": 8, "h": 6 }
|
|
3496
|
+
},
|
|
3497
|
+
"presentation": { "name": "Revenue by year" },
|
|
3498
|
+
"chart": {
|
|
3499
|
+
"chartType": "lines",
|
|
3500
|
+
"xAxisFieldId": "due-date",
|
|
3501
|
+
"xAxisDateFormat": "YEAR",
|
|
3502
|
+
"xAxisAsTimeSerie": true,
|
|
3503
|
+
"yAxisSeries": [
|
|
3504
|
+
{
|
|
3505
|
+
"typeCalc": "SUM",
|
|
3506
|
+
"fieldCalc": "amount",
|
|
3507
|
+
"color": "#4B9CD3",
|
|
3508
|
+
"axisType": "PRIMARY"
|
|
3509
|
+
}
|
|
3510
|
+
],
|
|
3511
|
+
"legend": { "position": "bottom" }
|
|
3512
|
+
}
|
|
3423
3513
|
}`
|
|
3424
3514
|
},
|
|
3425
3515
|
{
|
|
@@ -3513,29 +3603,38 @@ var specificExamples = {
|
|
|
3513
3603
|
}`
|
|
3514
3604
|
},
|
|
3515
3605
|
{
|
|
3516
|
-
description: "Add query filters
|
|
3517
|
-
command: `zinkee --json displays widgets update 0f6f062f-1478-4df2-96a1-c495d037d260 11111111-1111-4111-a111-111111111111 --
|
|
3606
|
+
description: "Add query filters with --filter. The CLI parses the expression and emits the structured comparisonOperator payload the API expects.",
|
|
3607
|
+
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
3608
|
raw: `{
|
|
3519
3609
|
"query": {
|
|
3520
3610
|
"filters": [
|
|
3521
3611
|
{
|
|
3522
|
-
"origin": {
|
|
3523
|
-
"schemaId": "contacts",
|
|
3524
|
-
"fieldId": "status"
|
|
3525
|
-
},
|
|
3612
|
+
"origin": { "fieldId": "status" },
|
|
3526
3613
|
"comparisonOperator": "EQUAL",
|
|
3527
3614
|
"values": ["2"]
|
|
3528
3615
|
},
|
|
3529
3616
|
{
|
|
3530
|
-
"origin": {
|
|
3531
|
-
"schemaId": "contacts",
|
|
3532
|
-
"fieldId": "amount"
|
|
3533
|
-
},
|
|
3617
|
+
"origin": { "fieldId": "amount" },
|
|
3534
3618
|
"comparisonOperator": "GREATER_OR_EQUAL",
|
|
3535
3619
|
"values": ["500"]
|
|
3536
3620
|
}
|
|
3537
3621
|
]
|
|
3538
3622
|
}
|
|
3623
|
+
}`
|
|
3624
|
+
},
|
|
3625
|
+
{
|
|
3626
|
+
description: "Fall back to --raw for comparators the parser does not cover yet (e.g. NOT_CONTAINS, RANGE).",
|
|
3627
|
+
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"]}]}}'`,
|
|
3628
|
+
raw: `{
|
|
3629
|
+
"query": {
|
|
3630
|
+
"filters": [
|
|
3631
|
+
{
|
|
3632
|
+
"origin": { "fieldId": "due-date" },
|
|
3633
|
+
"comparisonOperator": "RANGE",
|
|
3634
|
+
"values": ["2025-01-01", "2025-12-31"]
|
|
3635
|
+
}
|
|
3636
|
+
]
|
|
3637
|
+
}
|
|
3539
3638
|
}`
|
|
3540
3639
|
},
|
|
3541
3640
|
{
|
|
@@ -3561,13 +3660,13 @@ var specificExamples = {
|
|
|
3561
3660
|
}`
|
|
3562
3661
|
},
|
|
3563
3662
|
{
|
|
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
|
|
3663
|
+
description: "Replace the chart series with quarterly lines.",
|
|
3664
|
+
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
3665
|
raw: `{
|
|
3567
3666
|
"chart": {
|
|
3568
3667
|
"chartType": "lines",
|
|
3569
3668
|
"xAxisFieldId": "due-date",
|
|
3570
|
-
"xAxisDateFormat": "
|
|
3669
|
+
"xAxisDateFormat": "QUARTER_YEAR",
|
|
3571
3670
|
"xAxisAsTimeSerie": true,
|
|
3572
3671
|
"yAxisSeries": [
|
|
3573
3672
|
{
|
|
@@ -7886,6 +7985,86 @@ var DisplaysApi = class {
|
|
|
7886
7985
|
}
|
|
7887
7986
|
};
|
|
7888
7987
|
|
|
7988
|
+
// src/parsers/expressions.ts
|
|
7989
|
+
var supportedComparators = /* @__PURE__ */ new Set([
|
|
7990
|
+
"eq",
|
|
7991
|
+
"neq",
|
|
7992
|
+
"gt",
|
|
7993
|
+
"gte",
|
|
7994
|
+
"lt",
|
|
7995
|
+
"lte",
|
|
7996
|
+
"contains",
|
|
7997
|
+
"in",
|
|
7998
|
+
"is_empty",
|
|
7999
|
+
"is_not_empty"
|
|
8000
|
+
]);
|
|
8001
|
+
var noValueComparators = /* @__PURE__ */ new Set(["is_empty", "is_not_empty"]);
|
|
8002
|
+
function parseColonExpression(input) {
|
|
8003
|
+
const parts = input.split(":");
|
|
8004
|
+
if (parts.length < 2) {
|
|
8005
|
+
throw new Error(`Expected a field:comparator[:value] expression, got "${input}".`);
|
|
8006
|
+
}
|
|
8007
|
+
const field = parts[0]?.trim();
|
|
8008
|
+
const comparator = parts[1]?.trim();
|
|
8009
|
+
if (!field) {
|
|
8010
|
+
throw new Error(`Expected a field before ":", got "${input}".`);
|
|
8011
|
+
}
|
|
8012
|
+
if (!comparator) {
|
|
8013
|
+
throw new Error(`Expected a comparator after "${field}:", got "${input}".`);
|
|
8014
|
+
}
|
|
8015
|
+
return [field, comparator, parts.slice(2).join(":").trim()];
|
|
8016
|
+
}
|
|
8017
|
+
function parseSpaceExpression(input) {
|
|
8018
|
+
const parts = input.trim().split(/\s+/);
|
|
8019
|
+
if (parts.length < 2) {
|
|
8020
|
+
throw new Error(`Expected a field comparator expression, got "${input}".`);
|
|
8021
|
+
}
|
|
8022
|
+
const field = parts[0];
|
|
8023
|
+
const comparator = parts[1];
|
|
8024
|
+
if (!field) {
|
|
8025
|
+
throw new Error(`Expected a field comparator expression, got "${input}".`);
|
|
8026
|
+
}
|
|
8027
|
+
if (!comparator) {
|
|
8028
|
+
throw new Error(`Expected a comparator after "${field}", got "${input}".`);
|
|
8029
|
+
}
|
|
8030
|
+
return [field.trim(), comparator.trim(), parts.slice(2).join(" ").trim()];
|
|
8031
|
+
}
|
|
8032
|
+
function normalizeValue(comparator, rawValue) {
|
|
8033
|
+
if (noValueComparators.has(comparator)) {
|
|
8034
|
+
if (rawValue.length > 0) {
|
|
8035
|
+
throw new Error(`Comparator "${comparator}" does not accept a value.`);
|
|
8036
|
+
}
|
|
8037
|
+
return null;
|
|
8038
|
+
}
|
|
8039
|
+
if (comparator === "in") {
|
|
8040
|
+
const values = rawValue.split(",").map((value) => value.trim()).filter(Boolean);
|
|
8041
|
+
if (values.length === 0) {
|
|
8042
|
+
throw new Error(`Comparator "${comparator}" requires at least one value.`);
|
|
8043
|
+
}
|
|
8044
|
+
return values;
|
|
8045
|
+
}
|
|
8046
|
+
if (rawValue.length === 0) {
|
|
8047
|
+
throw new Error(`Comparator "${comparator}" requires a value.`);
|
|
8048
|
+
}
|
|
8049
|
+
return rawValue;
|
|
8050
|
+
}
|
|
8051
|
+
function parseExpression(input) {
|
|
8052
|
+
const trimmed = input.trim();
|
|
8053
|
+
const [field, comparatorCandidate, rawValue] = trimmed.includes(":") && !trimmed.includes(" ") ? parseColonExpression(trimmed) : parseSpaceExpression(trimmed);
|
|
8054
|
+
if (!supportedComparators.has(comparatorCandidate)) {
|
|
8055
|
+
throw new Error(
|
|
8056
|
+
`Unsupported comparator "${comparatorCandidate}" in expression "${input}".`
|
|
8057
|
+
);
|
|
8058
|
+
}
|
|
8059
|
+
const comparator = comparatorCandidate;
|
|
8060
|
+
return {
|
|
8061
|
+
field,
|
|
8062
|
+
comparator,
|
|
8063
|
+
value: normalizeValue(comparator, rawValue),
|
|
8064
|
+
raw: trimmed
|
|
8065
|
+
};
|
|
8066
|
+
}
|
|
8067
|
+
|
|
7889
8068
|
// src/commands/displays.ts
|
|
7890
8069
|
function getCommandIo4(stdout) {
|
|
7891
8070
|
return stdout ?? process.stdout;
|
|
@@ -7950,6 +8129,37 @@ function parseUuidOrSlugSelector3(input) {
|
|
|
7950
8129
|
throw new InvalidArgumentError3(message);
|
|
7951
8130
|
}
|
|
7952
8131
|
}
|
|
8132
|
+
var COMPARATOR_TO_DISPLAY_OPERATOR = {
|
|
8133
|
+
eq: "EQUAL",
|
|
8134
|
+
neq: "NOT_EQUAL",
|
|
8135
|
+
gt: "GREATER",
|
|
8136
|
+
gte: "GREATER_OR_EQUAL",
|
|
8137
|
+
lt: "LESS",
|
|
8138
|
+
lte: "LESS_OR_EQUAL",
|
|
8139
|
+
contains: "CONTAINS",
|
|
8140
|
+
in: "ANY_OF",
|
|
8141
|
+
is_empty: "IS_EMPTY",
|
|
8142
|
+
is_not_empty: "IS_NOT_EMPTY"
|
|
8143
|
+
};
|
|
8144
|
+
function toDisplayFilter(parsed) {
|
|
8145
|
+
const values = parsed.value === null ? [] : Array.isArray(parsed.value) ? [...parsed.value] : [parsed.value];
|
|
8146
|
+
return {
|
|
8147
|
+
origin: { fieldId: parsed.field },
|
|
8148
|
+
comparisonOperator: COMPARATOR_TO_DISPLAY_OPERATOR[parsed.comparator],
|
|
8149
|
+
values
|
|
8150
|
+
};
|
|
8151
|
+
}
|
|
8152
|
+
function parseFilterExpression(input) {
|
|
8153
|
+
try {
|
|
8154
|
+
return parseExpression(input);
|
|
8155
|
+
} catch (error) {
|
|
8156
|
+
const message = error instanceof Error ? error.message : "Invalid filter expression.";
|
|
8157
|
+
throw new InvalidArgumentError3(message);
|
|
8158
|
+
}
|
|
8159
|
+
}
|
|
8160
|
+
function collectFilters(value, previous = []) {
|
|
8161
|
+
return [...previous, parseFilterExpression(value)];
|
|
8162
|
+
}
|
|
7953
8163
|
function readRawObject2(raw, rawFile) {
|
|
7954
8164
|
if (raw && rawFile) {
|
|
7955
8165
|
throw new CliError("invalid_cli_usage", 'Use either "--raw" or "--raw-file", not both.');
|
|
@@ -8016,7 +8226,7 @@ function buildVariableBody(options) {
|
|
|
8016
8226
|
};
|
|
8017
8227
|
}
|
|
8018
8228
|
if (options.filter && options.filter.length > 0) {
|
|
8019
|
-
body.filters = options.filter.map(
|
|
8229
|
+
body.filters = options.filter.map(toDisplayFilter);
|
|
8020
8230
|
}
|
|
8021
8231
|
if (options.dateMode || options.dateDynamicOption || options.dateSpecific || options.dateRangeStart || options.dateRangeEnd) {
|
|
8022
8232
|
body.date = {
|
|
@@ -8065,15 +8275,19 @@ function buildWidgetBody(options) {
|
|
|
8065
8275
|
layout
|
|
8066
8276
|
};
|
|
8067
8277
|
}
|
|
8068
|
-
if (options.field
|
|
8278
|
+
if (options.field && options.field.length > 0) {
|
|
8069
8279
|
body.view = {
|
|
8070
8280
|
...typeof body.view === "object" && body.view ? body.view : {},
|
|
8071
8281
|
fields: options.field
|
|
8072
8282
|
};
|
|
8283
|
+
}
|
|
8284
|
+
const queryMerge = {};
|
|
8285
|
+
if (options.sort && options.sort.length > 0) queryMerge.sorts = options.sort;
|
|
8286
|
+
if (options.filter && options.filter.length > 0) queryMerge.filters = options.filter.map(toDisplayFilter);
|
|
8287
|
+
if (Object.keys(queryMerge).length > 0) {
|
|
8073
8288
|
body.query = {
|
|
8074
8289
|
...typeof body.query === "object" && body.query ? body.query : {},
|
|
8075
|
-
|
|
8076
|
-
filters: options.filter?.map((entry) => ({ raw: entry }))
|
|
8290
|
+
...queryMerge
|
|
8077
8291
|
};
|
|
8078
8292
|
}
|
|
8079
8293
|
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) {
|
|
@@ -8288,7 +8502,7 @@ function registerDisplaysCommands(program, options = {}) {
|
|
|
8288
8502
|
}
|
|
8289
8503
|
printTable([match], void 0, stdout);
|
|
8290
8504
|
});
|
|
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",
|
|
8505
|
+
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>").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
8506
|
const { api, json, readOnly } = createDisplaysApi(this, filePath);
|
|
8293
8507
|
ensureWritable3("displays variables create", readOnly, "write");
|
|
8294
8508
|
const data = await api.createVariable(display, buildVariableBody(commandOptions));
|
|
@@ -8298,7 +8512,7 @@ function registerDisplaysCommands(program, options = {}) {
|
|
|
8298
8512
|
}
|
|
8299
8513
|
writeLine4(stdout, `Created variable on display "${display.value}".`);
|
|
8300
8514
|
});
|
|
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",
|
|
8515
|
+
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>").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
8516
|
const { api, json, readOnly } = createDisplaysApi(this, filePath);
|
|
8303
8517
|
ensureWritable3("displays variables update", readOnly, "write");
|
|
8304
8518
|
const data = await api.updateVariable(display, variableId, buildVariableBody(commandOptions));
|
|
@@ -8338,7 +8552,7 @@ function registerDisplaysCommands(program, options = {}) {
|
|
|
8338
8552
|
}
|
|
8339
8553
|
printTable([data], void 0, stdout);
|
|
8340
8554
|
});
|
|
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",
|
|
8555
|
+
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("--raw <json>").option("--raw-file <path>").action(async function action(display, commandOptions) {
|
|
8342
8556
|
const { api, json, readOnly } = createDisplaysApi(this, filePath);
|
|
8343
8557
|
ensureWritable3("displays widgets create", readOnly, "write");
|
|
8344
8558
|
const data = await api.createWidget(display, buildWidgetBody(commandOptions));
|
|
@@ -8348,7 +8562,7 @@ function registerDisplaysCommands(program, options = {}) {
|
|
|
8348
8562
|
}
|
|
8349
8563
|
writeLine4(stdout, `Created widget on display "${display.value}".`);
|
|
8350
8564
|
});
|
|
8351
|
-
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",
|
|
8565
|
+
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("--raw <json>").option("--raw-file <path>").action(async function action(display, widgetId, commandOptions) {
|
|
8352
8566
|
const { api, json, readOnly } = createDisplaysApi(this, filePath);
|
|
8353
8567
|
ensureWritable3("displays widgets update", readOnly, "write");
|
|
8354
8568
|
const data = await api.updateWidget(display, widgetId, buildWidgetBody(commandOptions));
|
|
@@ -9369,86 +9583,6 @@ var SchemasApi = class {
|
|
|
9369
9583
|
}
|
|
9370
9584
|
};
|
|
9371
9585
|
|
|
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}".`);
|
|
9410
|
-
}
|
|
9411
|
-
if (!comparator) {
|
|
9412
|
-
throw new Error(`Expected a comparator after "${field}", got "${input}".`);
|
|
9413
|
-
}
|
|
9414
|
-
return [field.trim(), comparator.trim(), parts.slice(2).join(" ").trim()];
|
|
9415
|
-
}
|
|
9416
|
-
function normalizeValue(comparator, rawValue) {
|
|
9417
|
-
if (noValueComparators.has(comparator)) {
|
|
9418
|
-
if (rawValue.length > 0) {
|
|
9419
|
-
throw new Error(`Comparator "${comparator}" does not accept a value.`);
|
|
9420
|
-
}
|
|
9421
|
-
return null;
|
|
9422
|
-
}
|
|
9423
|
-
if (comparator === "in") {
|
|
9424
|
-
const values = rawValue.split(",").map((value) => value.trim()).filter(Boolean);
|
|
9425
|
-
if (values.length === 0) {
|
|
9426
|
-
throw new Error(`Comparator "${comparator}" requires at least one value.`);
|
|
9427
|
-
}
|
|
9428
|
-
return values;
|
|
9429
|
-
}
|
|
9430
|
-
if (rawValue.length === 0) {
|
|
9431
|
-
throw new Error(`Comparator "${comparator}" requires a value.`);
|
|
9432
|
-
}
|
|
9433
|
-
return rawValue;
|
|
9434
|
-
}
|
|
9435
|
-
function parseExpression(input) {
|
|
9436
|
-
const trimmed = input.trim();
|
|
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}".`
|
|
9441
|
-
);
|
|
9442
|
-
}
|
|
9443
|
-
const comparator = comparatorCandidate;
|
|
9444
|
-
return {
|
|
9445
|
-
field,
|
|
9446
|
-
comparator,
|
|
9447
|
-
value: normalizeValue(comparator, rawValue),
|
|
9448
|
-
raw: trimmed
|
|
9449
|
-
};
|
|
9450
|
-
}
|
|
9451
|
-
|
|
9452
9586
|
// src/commands/records.ts
|
|
9453
9587
|
function getCommandIo9(stdout) {
|
|
9454
9588
|
return stdout ?? process.stdout;
|