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.
@@ -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
- ### KPI with filters
483
+ ### Widget filters
484
484
 
485
- The `--filter` flag doesn't work on KPI widgets. Pass filters in `--raw`:
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
- --raw '{"query":{"filters":[{"fieldId":"<field-uuid>","operator":"EQUALS","value":"2"}]}}'
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 bars CHART widget with a time-serie x-axis and two y-axis series.",
3391
- 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 --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"}'`,
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": "MONTH",
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 that match the full comparisonOperator contract (requires --raw because --filter only accepts free-form expressions).",
3517
- command: `zinkee --json displays widgets update 0f6f062f-1478-4df2-96a1-c495d037d260 11111111-1111-4111-a111-111111111111 --raw '{"query":{"filters":[{"origin":{"schemaId":"contacts","fieldId":"status"},"comparisonOperator":"EQUAL","values":["2"]},{"origin":{"schemaId":"contacts","fieldId":"amount"},"comparisonOperator":"GREATER_OR_EQUAL","values":["500"]}]}}'`,
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 weekly lines.",
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 WEEK --x-axis-time-series --y-axis-serie '{"typeCalc":"SUM","fieldCalc":"amount","color":"#2E7D32","axisType":"PRIMARY"}'`,
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": "WEEK",
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((entry) => ({ raw: entry }));
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?.length || options.sort?.length || options.filter?.length) {
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
- sorts: options.sort,
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", (v, p = []) => [...p, v], []).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) {
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", (v, p = []) => [...p, v], []).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) {
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", (v, p = []) => [...p, v], []).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>").option("--x-axis-field <uuid>").option("--x-axis-date-format <granularity>").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) {
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", (v, p = []) => [...p, v], []).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>").option("--x-axis-field <uuid>").option("--x-axis-date-format <granularity>").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) {
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;