zinkee 0.1.19 → 0.1.20
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 +142 -98
- 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 +59 -10
- package/src/utils/examples.ts +21 -10
|
@@ -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
|
@@ -3513,29 +3513,38 @@ var specificExamples = {
|
|
|
3513
3513
|
}`
|
|
3514
3514
|
},
|
|
3515
3515
|
{
|
|
3516
|
-
description: "Add query filters
|
|
3517
|
-
command: `zinkee --json displays widgets update 0f6f062f-1478-4df2-96a1-c495d037d260 11111111-1111-4111-a111-111111111111 --
|
|
3516
|
+
description: "Add query filters with --filter. The CLI parses the expression and emits the structured comparisonOperator payload the API expects.",
|
|
3517
|
+
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
3518
|
raw: `{
|
|
3519
3519
|
"query": {
|
|
3520
3520
|
"filters": [
|
|
3521
3521
|
{
|
|
3522
|
-
"origin": {
|
|
3523
|
-
"schemaId": "contacts",
|
|
3524
|
-
"fieldId": "status"
|
|
3525
|
-
},
|
|
3522
|
+
"origin": { "fieldId": "status" },
|
|
3526
3523
|
"comparisonOperator": "EQUAL",
|
|
3527
3524
|
"values": ["2"]
|
|
3528
3525
|
},
|
|
3529
3526
|
{
|
|
3530
|
-
"origin": {
|
|
3531
|
-
"schemaId": "contacts",
|
|
3532
|
-
"fieldId": "amount"
|
|
3533
|
-
},
|
|
3527
|
+
"origin": { "fieldId": "amount" },
|
|
3534
3528
|
"comparisonOperator": "GREATER_OR_EQUAL",
|
|
3535
3529
|
"values": ["500"]
|
|
3536
3530
|
}
|
|
3537
3531
|
]
|
|
3538
3532
|
}
|
|
3533
|
+
}`
|
|
3534
|
+
},
|
|
3535
|
+
{
|
|
3536
|
+
description: "Fall back to --raw for comparators the parser does not cover yet (e.g. NOT_CONTAINS, RANGE).",
|
|
3537
|
+
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"]}]}}'`,
|
|
3538
|
+
raw: `{
|
|
3539
|
+
"query": {
|
|
3540
|
+
"filters": [
|
|
3541
|
+
{
|
|
3542
|
+
"origin": { "fieldId": "due-date" },
|
|
3543
|
+
"comparisonOperator": "RANGE",
|
|
3544
|
+
"values": ["2025-01-01", "2025-12-31"]
|
|
3545
|
+
}
|
|
3546
|
+
]
|
|
3547
|
+
}
|
|
3539
3548
|
}`
|
|
3540
3549
|
},
|
|
3541
3550
|
{
|
|
@@ -7886,6 +7895,86 @@ var DisplaysApi = class {
|
|
|
7886
7895
|
}
|
|
7887
7896
|
};
|
|
7888
7897
|
|
|
7898
|
+
// src/parsers/expressions.ts
|
|
7899
|
+
var supportedComparators = /* @__PURE__ */ new Set([
|
|
7900
|
+
"eq",
|
|
7901
|
+
"neq",
|
|
7902
|
+
"gt",
|
|
7903
|
+
"gte",
|
|
7904
|
+
"lt",
|
|
7905
|
+
"lte",
|
|
7906
|
+
"contains",
|
|
7907
|
+
"in",
|
|
7908
|
+
"is_empty",
|
|
7909
|
+
"is_not_empty"
|
|
7910
|
+
]);
|
|
7911
|
+
var noValueComparators = /* @__PURE__ */ new Set(["is_empty", "is_not_empty"]);
|
|
7912
|
+
function parseColonExpression(input) {
|
|
7913
|
+
const parts = input.split(":");
|
|
7914
|
+
if (parts.length < 2) {
|
|
7915
|
+
throw new Error(`Expected a field:comparator[:value] expression, got "${input}".`);
|
|
7916
|
+
}
|
|
7917
|
+
const field = parts[0]?.trim();
|
|
7918
|
+
const comparator = parts[1]?.trim();
|
|
7919
|
+
if (!field) {
|
|
7920
|
+
throw new Error(`Expected a field before ":", got "${input}".`);
|
|
7921
|
+
}
|
|
7922
|
+
if (!comparator) {
|
|
7923
|
+
throw new Error(`Expected a comparator after "${field}:", got "${input}".`);
|
|
7924
|
+
}
|
|
7925
|
+
return [field, comparator, parts.slice(2).join(":").trim()];
|
|
7926
|
+
}
|
|
7927
|
+
function parseSpaceExpression(input) {
|
|
7928
|
+
const parts = input.trim().split(/\s+/);
|
|
7929
|
+
if (parts.length < 2) {
|
|
7930
|
+
throw new Error(`Expected a field comparator expression, got "${input}".`);
|
|
7931
|
+
}
|
|
7932
|
+
const field = parts[0];
|
|
7933
|
+
const comparator = parts[1];
|
|
7934
|
+
if (!field) {
|
|
7935
|
+
throw new Error(`Expected a field comparator expression, got "${input}".`);
|
|
7936
|
+
}
|
|
7937
|
+
if (!comparator) {
|
|
7938
|
+
throw new Error(`Expected a comparator after "${field}", got "${input}".`);
|
|
7939
|
+
}
|
|
7940
|
+
return [field.trim(), comparator.trim(), parts.slice(2).join(" ").trim()];
|
|
7941
|
+
}
|
|
7942
|
+
function normalizeValue(comparator, rawValue) {
|
|
7943
|
+
if (noValueComparators.has(comparator)) {
|
|
7944
|
+
if (rawValue.length > 0) {
|
|
7945
|
+
throw new Error(`Comparator "${comparator}" does not accept a value.`);
|
|
7946
|
+
}
|
|
7947
|
+
return null;
|
|
7948
|
+
}
|
|
7949
|
+
if (comparator === "in") {
|
|
7950
|
+
const values = rawValue.split(",").map((value) => value.trim()).filter(Boolean);
|
|
7951
|
+
if (values.length === 0) {
|
|
7952
|
+
throw new Error(`Comparator "${comparator}" requires at least one value.`);
|
|
7953
|
+
}
|
|
7954
|
+
return values;
|
|
7955
|
+
}
|
|
7956
|
+
if (rawValue.length === 0) {
|
|
7957
|
+
throw new Error(`Comparator "${comparator}" requires a value.`);
|
|
7958
|
+
}
|
|
7959
|
+
return rawValue;
|
|
7960
|
+
}
|
|
7961
|
+
function parseExpression(input) {
|
|
7962
|
+
const trimmed = input.trim();
|
|
7963
|
+
const [field, comparatorCandidate, rawValue] = trimmed.includes(":") && !trimmed.includes(" ") ? parseColonExpression(trimmed) : parseSpaceExpression(trimmed);
|
|
7964
|
+
if (!supportedComparators.has(comparatorCandidate)) {
|
|
7965
|
+
throw new Error(
|
|
7966
|
+
`Unsupported comparator "${comparatorCandidate}" in expression "${input}".`
|
|
7967
|
+
);
|
|
7968
|
+
}
|
|
7969
|
+
const comparator = comparatorCandidate;
|
|
7970
|
+
return {
|
|
7971
|
+
field,
|
|
7972
|
+
comparator,
|
|
7973
|
+
value: normalizeValue(comparator, rawValue),
|
|
7974
|
+
raw: trimmed
|
|
7975
|
+
};
|
|
7976
|
+
}
|
|
7977
|
+
|
|
7889
7978
|
// src/commands/displays.ts
|
|
7890
7979
|
function getCommandIo4(stdout) {
|
|
7891
7980
|
return stdout ?? process.stdout;
|
|
@@ -7950,6 +8039,37 @@ function parseUuidOrSlugSelector3(input) {
|
|
|
7950
8039
|
throw new InvalidArgumentError3(message);
|
|
7951
8040
|
}
|
|
7952
8041
|
}
|
|
8042
|
+
var COMPARATOR_TO_DISPLAY_OPERATOR = {
|
|
8043
|
+
eq: "EQUAL",
|
|
8044
|
+
neq: "NOT_EQUAL",
|
|
8045
|
+
gt: "GREATER",
|
|
8046
|
+
gte: "GREATER_OR_EQUAL",
|
|
8047
|
+
lt: "LESS",
|
|
8048
|
+
lte: "LESS_OR_EQUAL",
|
|
8049
|
+
contains: "CONTAINS",
|
|
8050
|
+
in: "ANY_OF",
|
|
8051
|
+
is_empty: "IS_EMPTY",
|
|
8052
|
+
is_not_empty: "IS_NOT_EMPTY"
|
|
8053
|
+
};
|
|
8054
|
+
function toDisplayFilter(parsed) {
|
|
8055
|
+
const values = parsed.value === null ? [] : Array.isArray(parsed.value) ? [...parsed.value] : [parsed.value];
|
|
8056
|
+
return {
|
|
8057
|
+
origin: { fieldId: parsed.field },
|
|
8058
|
+
comparisonOperator: COMPARATOR_TO_DISPLAY_OPERATOR[parsed.comparator],
|
|
8059
|
+
values
|
|
8060
|
+
};
|
|
8061
|
+
}
|
|
8062
|
+
function parseFilterExpression(input) {
|
|
8063
|
+
try {
|
|
8064
|
+
return parseExpression(input);
|
|
8065
|
+
} catch (error) {
|
|
8066
|
+
const message = error instanceof Error ? error.message : "Invalid filter expression.";
|
|
8067
|
+
throw new InvalidArgumentError3(message);
|
|
8068
|
+
}
|
|
8069
|
+
}
|
|
8070
|
+
function collectFilters(value, previous = []) {
|
|
8071
|
+
return [...previous, parseFilterExpression(value)];
|
|
8072
|
+
}
|
|
7953
8073
|
function readRawObject2(raw, rawFile) {
|
|
7954
8074
|
if (raw && rawFile) {
|
|
7955
8075
|
throw new CliError("invalid_cli_usage", 'Use either "--raw" or "--raw-file", not both.');
|
|
@@ -8016,7 +8136,7 @@ function buildVariableBody(options) {
|
|
|
8016
8136
|
};
|
|
8017
8137
|
}
|
|
8018
8138
|
if (options.filter && options.filter.length > 0) {
|
|
8019
|
-
body.filters = options.filter.map(
|
|
8139
|
+
body.filters = options.filter.map(toDisplayFilter);
|
|
8020
8140
|
}
|
|
8021
8141
|
if (options.dateMode || options.dateDynamicOption || options.dateSpecific || options.dateRangeStart || options.dateRangeEnd) {
|
|
8022
8142
|
body.date = {
|
|
@@ -8065,15 +8185,19 @@ function buildWidgetBody(options) {
|
|
|
8065
8185
|
layout
|
|
8066
8186
|
};
|
|
8067
8187
|
}
|
|
8068
|
-
if (options.field
|
|
8188
|
+
if (options.field && options.field.length > 0) {
|
|
8069
8189
|
body.view = {
|
|
8070
8190
|
...typeof body.view === "object" && body.view ? body.view : {},
|
|
8071
8191
|
fields: options.field
|
|
8072
8192
|
};
|
|
8193
|
+
}
|
|
8194
|
+
const queryMerge = {};
|
|
8195
|
+
if (options.sort && options.sort.length > 0) queryMerge.sorts = options.sort;
|
|
8196
|
+
if (options.filter && options.filter.length > 0) queryMerge.filters = options.filter.map(toDisplayFilter);
|
|
8197
|
+
if (Object.keys(queryMerge).length > 0) {
|
|
8073
8198
|
body.query = {
|
|
8074
8199
|
...typeof body.query === "object" && body.query ? body.query : {},
|
|
8075
|
-
|
|
8076
|
-
filters: options.filter?.map((entry) => ({ raw: entry }))
|
|
8200
|
+
...queryMerge
|
|
8077
8201
|
};
|
|
8078
8202
|
}
|
|
8079
8203
|
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 +8412,7 @@ function registerDisplaysCommands(program, options = {}) {
|
|
|
8288
8412
|
}
|
|
8289
8413
|
printTable([match], void 0, stdout);
|
|
8290
8414
|
});
|
|
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",
|
|
8415
|
+
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
8416
|
const { api, json, readOnly } = createDisplaysApi(this, filePath);
|
|
8293
8417
|
ensureWritable3("displays variables create", readOnly, "write");
|
|
8294
8418
|
const data = await api.createVariable(display, buildVariableBody(commandOptions));
|
|
@@ -8298,7 +8422,7 @@ function registerDisplaysCommands(program, options = {}) {
|
|
|
8298
8422
|
}
|
|
8299
8423
|
writeLine4(stdout, `Created variable on display "${display.value}".`);
|
|
8300
8424
|
});
|
|
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",
|
|
8425
|
+
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
8426
|
const { api, json, readOnly } = createDisplaysApi(this, filePath);
|
|
8303
8427
|
ensureWritable3("displays variables update", readOnly, "write");
|
|
8304
8428
|
const data = await api.updateVariable(display, variableId, buildVariableBody(commandOptions));
|
|
@@ -8338,7 +8462,7 @@ function registerDisplaysCommands(program, options = {}) {
|
|
|
8338
8462
|
}
|
|
8339
8463
|
printTable([data], void 0, stdout);
|
|
8340
8464
|
});
|
|
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",
|
|
8465
|
+
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>").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) {
|
|
8342
8466
|
const { api, json, readOnly } = createDisplaysApi(this, filePath);
|
|
8343
8467
|
ensureWritable3("displays widgets create", readOnly, "write");
|
|
8344
8468
|
const data = await api.createWidget(display, buildWidgetBody(commandOptions));
|
|
@@ -8348,7 +8472,7 @@ function registerDisplaysCommands(program, options = {}) {
|
|
|
8348
8472
|
}
|
|
8349
8473
|
writeLine4(stdout, `Created widget on display "${display.value}".`);
|
|
8350
8474
|
});
|
|
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",
|
|
8475
|
+
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>").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) {
|
|
8352
8476
|
const { api, json, readOnly } = createDisplaysApi(this, filePath);
|
|
8353
8477
|
ensureWritable3("displays widgets update", readOnly, "write");
|
|
8354
8478
|
const data = await api.updateWidget(display, widgetId, buildWidgetBody(commandOptions));
|
|
@@ -9369,86 +9493,6 @@ var SchemasApi = class {
|
|
|
9369
9493
|
}
|
|
9370
9494
|
};
|
|
9371
9495
|
|
|
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
9496
|
// src/commands/records.ts
|
|
9453
9497
|
function getCommandIo9(stdout) {
|
|
9454
9498
|
return stdout ?? process.stdout;
|