zinkee 0.1.38 → 0.1.39

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/dist/index.js CHANGED
@@ -3554,6 +3554,48 @@ var specificExamples = {
3554
3554
  response: `{
3555
3555
  "displayId": "0f6f062f-1478-4df2-96a1-c495d037d260",
3556
3556
  "widgetId": "11111111-1111-4111-a111-111111111111"
3557
+ }`
3558
+ },
3559
+ {
3560
+ description: "Create a TABLE widget with locked fields: contact-name locked permanently (no conditions) and status locked while invoice-number is empty, with before/after lock messages.",
3561
+ command: `zinkee --json displays widgets create 0f6f062f-1478-4df2-96a1-c495d037d260 --type table --name Invoices --origin-resource 2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e --layout '{"x":0,"y":0,"w":12,"h":8}' --field contact-name --field invoice-number --field status --field amount --lock-field contact-name --lock-condition "status:invoice-number:is_empty" --lock-message-before "status:Status locks until the invoice number is set." --lock-message-after "status:Status is locked because the invoice number is missing."`,
3562
+ raw: `{
3563
+ "type": "TABLE_OR_SUBTABLE",
3564
+ "source": {
3565
+ "originResourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
3566
+ "isOriginSubSchema": false
3567
+ },
3568
+ "placement": {
3569
+ "layout": { "x": 0, "y": 0, "w": 12, "h": 8 }
3570
+ },
3571
+ "presentation": { "name": "Invoices" },
3572
+ "view": {
3573
+ "fields": ["contact-name", "invoice-number", "status", "amount"]
3574
+ },
3575
+ "behavior": {
3576
+ "lockedFields": [
3577
+ {
3578
+ "field": { "fieldId": "contact-name" },
3579
+ "conditions": []
3580
+ },
3581
+ {
3582
+ "field": { "fieldId": "status" },
3583
+ "conditions": [
3584
+ {
3585
+ "origin": { "fieldId": "invoice-number" },
3586
+ "comparisonOperator": "IS_EMPTY",
3587
+ "values": []
3588
+ }
3589
+ ],
3590
+ "messageBeforeLock": "Status locks until the invoice number is set.",
3591
+ "messageAfterLock": "Status is locked because the invoice number is missing."
3592
+ }
3593
+ ]
3594
+ }
3595
+ }`,
3596
+ response: `{
3597
+ "displayId": "0f6f062f-1478-4df2-96a1-c495d037d260",
3598
+ "widgetId": "11111111-1111-4111-a111-111111111111"
3557
3599
  }`
3558
3600
  },
3559
3601
  {
@@ -3935,6 +3977,43 @@ var specificExamples = {
3935
3977
  "hideDeleteButton": true,
3936
3978
  "hideFilterButton": true
3937
3979
  }
3980
+ }`
3981
+ },
3982
+ {
3983
+ description: "Configure locked fields (replaces the stored configuration): contact-name locked permanently, status locked while invoice-number is empty. Empty conditions = always locked; conditions combine with AND. Enforcement happens in display widgets only, never in the database view.",
3984
+ command: `zinkee --json displays widgets update 0f6f062f-1478-4df2-96a1-c495d037d260 11111111-1111-4111-a111-111111111111 --lock-field contact-name --lock-condition "status:invoice-number:is_empty" --lock-message-before "status:Status locks until the invoice number is set." --lock-message-after "status:Status is locked because the invoice number is missing."`,
3985
+ raw: `{
3986
+ "behavior": {
3987
+ "lockedFields": [
3988
+ {
3989
+ "field": { "fieldId": "contact-name" },
3990
+ "conditions": []
3991
+ },
3992
+ {
3993
+ "field": { "fieldId": "status" },
3994
+ "conditions": [
3995
+ {
3996
+ "origin": { "fieldId": "invoice-number" },
3997
+ "comparisonOperator": "IS_EMPTY",
3998
+ "values": []
3999
+ }
4000
+ ],
4001
+ "messageBeforeLock": "Status locks until the invoice number is set.",
4002
+ "messageAfterLock": "Status is locked because the invoice number is missing."
4003
+ }
4004
+ ]
4005
+ }
4006
+ }`,
4007
+ response: `{
4008
+ "displayId": "0f6f062f-1478-4df2-96a1-c495d037d260",
4009
+ "widgetId": "11111111-1111-4111-a111-111111111111"
4010
+ }`
4011
+ },
4012
+ {
4013
+ description: "Clear the locked-fields configuration.",
4014
+ command: "zinkee --json displays widgets update 0f6f062f-1478-4df2-96a1-c495d037d260 11111111-1111-4111-a111-111111111111 --clear-locked-fields",
4015
+ raw: `{
4016
+ "behavior": { "lockedFields": [] }
3938
4017
  }`
3939
4018
  },
3940
4019
  {
@@ -8907,6 +8986,83 @@ function parseFilterExpression(input) {
8907
8986
  function collectFilters(value, previous = []) {
8908
8987
  return [...previous, parseFilterExpression(value)];
8909
8988
  }
8989
+ function parseLockConditionOption(input) {
8990
+ const trimmed = input.trim();
8991
+ let lockedField;
8992
+ let expressionText;
8993
+ if (trimmed.includes(":") && !trimmed.includes(" ")) {
8994
+ const separatorIndex = trimmed.indexOf(":");
8995
+ lockedField = trimmed.slice(0, separatorIndex).trim();
8996
+ expressionText = trimmed.slice(separatorIndex + 1).trim();
8997
+ } else {
8998
+ const parts = trimmed.split(/\s+/);
8999
+ lockedField = parts[0]?.trim() ?? "";
9000
+ expressionText = parts.slice(1).join(" ").trim();
9001
+ }
9002
+ if (!lockedField || !expressionText) {
9003
+ throw new InvalidArgumentError3(
9004
+ 'Expected "<lockedField>:<field>:<comparator>[:<value>]" (or space-separated), e.g. "status:invoice-number:is_empty".'
9005
+ );
9006
+ }
9007
+ return { lockedField, expression: parseFilterExpression(expressionText) };
9008
+ }
9009
+ function collectLockConditions(value, previous = []) {
9010
+ return [...previous, parseLockConditionOption(value)];
9011
+ }
9012
+ function parseLockMessageOption(input) {
9013
+ const separatorIndex = input.indexOf(":");
9014
+ const lockedField = separatorIndex > 0 ? input.slice(0, separatorIndex).trim() : "";
9015
+ const message = separatorIndex > 0 ? input.slice(separatorIndex + 1).trim() : "";
9016
+ if (!lockedField || !message) {
9017
+ throw new InvalidArgumentError3('Expected "<lockedField>:<message>", e.g. "status:Locked once approved.".');
9018
+ }
9019
+ return { lockedField, message };
9020
+ }
9021
+ function collectLockMessages(value, previous = []) {
9022
+ return [...previous, parseLockMessageOption(value)];
9023
+ }
9024
+ function buildLockedFields(options) {
9025
+ const hasLockFlags = (options.lockField?.length ?? 0) > 0 || (options.lockCondition?.length ?? 0) > 0 || (options.lockMessageBefore?.length ?? 0) > 0 || (options.lockMessageAfter?.length ?? 0) > 0;
9026
+ if (options.clearLockedFields) {
9027
+ if (hasLockFlags) {
9028
+ throw new CliError(
9029
+ "invalid_cli_usage",
9030
+ 'Use either "--clear-locked-fields" or the "--lock-*" flags, not both.'
9031
+ );
9032
+ }
9033
+ return [];
9034
+ }
9035
+ if (!hasLockFlags) {
9036
+ return void 0;
9037
+ }
9038
+ const rules = /* @__PURE__ */ new Map();
9039
+ const ensureRule = (lockedField) => {
9040
+ let rule = rules.get(lockedField);
9041
+ if (!rule) {
9042
+ rule = { conditions: [] };
9043
+ rules.set(lockedField, rule);
9044
+ }
9045
+ return rule;
9046
+ };
9047
+ for (const lockedField of options.lockField ?? []) {
9048
+ ensureRule(lockedField);
9049
+ }
9050
+ for (const { lockedField, expression } of options.lockCondition ?? []) {
9051
+ ensureRule(lockedField).conditions.push(toDisplayFilter(expression));
9052
+ }
9053
+ for (const { lockedField, message } of options.lockMessageBefore ?? []) {
9054
+ ensureRule(lockedField).messageBeforeLock = message;
9055
+ }
9056
+ for (const { lockedField, message } of options.lockMessageAfter ?? []) {
9057
+ ensureRule(lockedField).messageAfterLock = message;
9058
+ }
9059
+ return [...rules.entries()].map(([lockedField, rule]) => ({
9060
+ field: { fieldId: lockedField },
9061
+ conditions: rule.conditions,
9062
+ ...rule.messageBeforeLock !== void 0 ? { messageBeforeLock: rule.messageBeforeLock } : {},
9063
+ ...rule.messageAfterLock !== void 0 ? { messageAfterLock: rule.messageAfterLock } : {}
9064
+ }));
9065
+ }
8910
9066
  function readRawObject2(raw, rawFile) {
8911
9067
  if (raw && rawFile) {
8912
9068
  throw new CliError("invalid_cli_usage", 'Use either "--raw" or "--raw-file", not both.');
@@ -9237,6 +9393,13 @@ function buildWidgetBody(options) {
9237
9393
  hideSeeButton: options.hideSeeButton
9238
9394
  };
9239
9395
  }
9396
+ const lockedFields = buildLockedFields(options);
9397
+ if (lockedFields !== void 0) {
9398
+ body.behavior = {
9399
+ ...typeof body.behavior === "object" && body.behavior ? body.behavior : {},
9400
+ lockedFields
9401
+ };
9402
+ }
9240
9403
  if (options.calc || options.calcField || options.kpiConfig) {
9241
9404
  body.kpi = {
9242
9405
  ...typeof body.kpi === "object" && body.kpi ? body.kpi : {},
@@ -9588,7 +9751,7 @@ function registerDisplaysCommands(program, options = {}) {
9588
9751
  }
9589
9752
  printTable([data], void 0, stdout);
9590
9753
  });
9591
- 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) {
9754
+ 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("--lock-field <field>", "lock a field permanently in this widget (repeatable; field UUID or slug)", (v, p = []) => [...p, v], []).option("--lock-condition <expr>", 'conditional lock "<lockedField>:<field>:<comparator>[:<value>]"; locks <lockedField> when all its conditions match (AND, repeatable)', collectLockConditions, []).option("--lock-message-before <field:text>", "message shown while a conditional lock is not met yet (repeatable)", collectLockMessages, []).option("--lock-message-after <field:text>", "message shown once the field is locked (repeatable)", collectLockMessages, []).option("--clear-locked-fields", "clear the widget locked-fields configuration").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) {
9592
9755
  const { api, json, readOnly } = createDisplaysApi(this, filePath);
9593
9756
  ensureWritable3("displays widgets create", readOnly, "write");
9594
9757
  const data = await api.createWidget(display, buildWidgetBody(commandOptions));
@@ -9598,7 +9761,7 @@ function registerDisplaysCommands(program, options = {}) {
9598
9761
  }
9599
9762
  writeLine4(stdout, `Created widget on display "${display.value}".`);
9600
9763
  });
9601
- 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) {
9764
+ 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("--lock-field <field>", "lock a field permanently in this widget (repeatable; field UUID or slug)", (v, p = []) => [...p, v], []).option("--lock-condition <expr>", 'conditional lock "<lockedField>:<field>:<comparator>[:<value>]"; locks <lockedField> when all its conditions match (AND, repeatable)', collectLockConditions, []).option("--lock-message-before <field:text>", "message shown while a conditional lock is not met yet (repeatable)", collectLockMessages, []).option("--lock-message-after <field:text>", "message shown once the field is locked (repeatable)", collectLockMessages, []).option("--clear-locked-fields", "clear the widget locked-fields configuration").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) {
9602
9765
  const { api, json, readOnly } = createDisplaysApi(this, filePath);
9603
9766
  ensureWritable3("displays widgets update", readOnly, "write");
9604
9767
  const data = await api.updateWidget(display, widgetId, buildWidgetBody(commandOptions));