zinkee 0.1.38 → 0.1.40

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
@@ -1224,6 +1224,17 @@ function buildJsonSuccess(data, meta = {}) {
1224
1224
  function buildJsonError(error, meta = {}) {
1225
1225
  return { error, meta };
1226
1226
  }
1227
+ var FOLDER_TABLE_KEYS = ["folderId", "folderName", "folderIsRoot"];
1228
+ function folderColumns(folder) {
1229
+ if (!folder) {
1230
+ return { folderId: "", folderName: "", folderIsRoot: "" };
1231
+ }
1232
+ return {
1233
+ folderId: folder.id ?? "",
1234
+ folderName: folder.name ?? (folder.isRoot === true ? "(root)" : ""),
1235
+ folderIsRoot: folder.isRoot === void 0 ? "" : String(folder.isRoot)
1236
+ };
1237
+ }
1227
1238
  function getWriter(writer) {
1228
1239
  return writer ?? process.stdout;
1229
1240
  }
@@ -3554,6 +3565,48 @@ var specificExamples = {
3554
3565
  response: `{
3555
3566
  "displayId": "0f6f062f-1478-4df2-96a1-c495d037d260",
3556
3567
  "widgetId": "11111111-1111-4111-a111-111111111111"
3568
+ }`
3569
+ },
3570
+ {
3571
+ 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.",
3572
+ 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."`,
3573
+ raw: `{
3574
+ "type": "TABLE_OR_SUBTABLE",
3575
+ "source": {
3576
+ "originResourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
3577
+ "isOriginSubSchema": false
3578
+ },
3579
+ "placement": {
3580
+ "layout": { "x": 0, "y": 0, "w": 12, "h": 8 }
3581
+ },
3582
+ "presentation": { "name": "Invoices" },
3583
+ "view": {
3584
+ "fields": ["contact-name", "invoice-number", "status", "amount"]
3585
+ },
3586
+ "behavior": {
3587
+ "lockedFields": [
3588
+ {
3589
+ "field": { "fieldId": "contact-name" },
3590
+ "conditions": []
3591
+ },
3592
+ {
3593
+ "field": { "fieldId": "status" },
3594
+ "conditions": [
3595
+ {
3596
+ "origin": { "fieldId": "invoice-number" },
3597
+ "comparisonOperator": "IS_EMPTY",
3598
+ "values": []
3599
+ }
3600
+ ],
3601
+ "messageBeforeLock": "Status locks until the invoice number is set.",
3602
+ "messageAfterLock": "Status is locked because the invoice number is missing."
3603
+ }
3604
+ ]
3605
+ }
3606
+ }`,
3607
+ response: `{
3608
+ "displayId": "0f6f062f-1478-4df2-96a1-c495d037d260",
3609
+ "widgetId": "11111111-1111-4111-a111-111111111111"
3557
3610
  }`
3558
3611
  },
3559
3612
  {
@@ -3935,6 +3988,43 @@ var specificExamples = {
3935
3988
  "hideDeleteButton": true,
3936
3989
  "hideFilterButton": true
3937
3990
  }
3991
+ }`
3992
+ },
3993
+ {
3994
+ 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.",
3995
+ 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."`,
3996
+ raw: `{
3997
+ "behavior": {
3998
+ "lockedFields": [
3999
+ {
4000
+ "field": { "fieldId": "contact-name" },
4001
+ "conditions": []
4002
+ },
4003
+ {
4004
+ "field": { "fieldId": "status" },
4005
+ "conditions": [
4006
+ {
4007
+ "origin": { "fieldId": "invoice-number" },
4008
+ "comparisonOperator": "IS_EMPTY",
4009
+ "values": []
4010
+ }
4011
+ ],
4012
+ "messageBeforeLock": "Status locks until the invoice number is set.",
4013
+ "messageAfterLock": "Status is locked because the invoice number is missing."
4014
+ }
4015
+ ]
4016
+ }
4017
+ }`,
4018
+ response: `{
4019
+ "displayId": "0f6f062f-1478-4df2-96a1-c495d037d260",
4020
+ "widgetId": "11111111-1111-4111-a111-111111111111"
4021
+ }`
4022
+ },
4023
+ {
4024
+ description: "Clear the locked-fields configuration.",
4025
+ command: "zinkee --json displays widgets update 0f6f062f-1478-4df2-96a1-c495d037d260 11111111-1111-4111-a111-111111111111 --clear-locked-fields",
4026
+ raw: `{
4027
+ "behavior": { "lockedFields": [] }
3938
4028
  }`
3939
4029
  },
3940
4030
  {
@@ -4884,21 +4974,36 @@ var specificExamples = {
4884
4974
  "name": "Executive Revenue",
4885
4975
  "layoutTemplate": "widget_row_tabs",
4886
4976
  "variableCount": 3,
4887
- "widgetCount": 6
4977
+ "widgetCount": 6,
4978
+ "folder": {
4979
+ "id": "b1a2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
4980
+ "name": "\u{1F4CA} Executive",
4981
+ "isRoot": false
4982
+ }
4888
4983
  },
4889
4984
  {
4890
4985
  "id": "6b7c8d9e-0f12-3456-789a-bcdef0123456",
4891
4986
  "name": "Sales Pipeline",
4892
4987
  "layoutTemplate": "freeform",
4893
4988
  "variableCount": 1,
4894
- "widgetCount": 3
4989
+ "widgetCount": 3,
4990
+ "folder": {
4991
+ "id": "a0b1c2d3-e4f5-4061-8273-8495a6b7c8d9",
4992
+ "name": null,
4993
+ "isRoot": true
4994
+ }
4895
4995
  },
4896
4996
  {
4897
4997
  "id": "ef012345-6789-4abc-8def-0123456789ab",
4898
4998
  "name": "Customer Detail",
4899
4999
  "layoutTemplate": "grid",
4900
5000
  "variableCount": 0,
4901
- "widgetCount": 2
5001
+ "widgetCount": 2,
5002
+ "folder": {
5003
+ "id": "b1a2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
5004
+ "name": "\u{1F4CA} Executive",
5005
+ "isRoot": false
5006
+ }
4902
5007
  }
4903
5008
  ]`
4904
5009
  }
@@ -5030,7 +5135,12 @@ var specificExamples = {
5030
5135
  "targetVariableId": "aaaaaaaa-1111-4111-a111-111111111111",
5031
5136
  "label": "Open customer"
5032
5137
  }
5033
- ]
5138
+ ],
5139
+ "folder": {
5140
+ "id": "b1a2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
5141
+ "name": "\u{1F4CA} Executive",
5142
+ "isRoot": false
5143
+ }
5034
5144
  }`
5035
5145
  }
5036
5146
  ]),
@@ -7533,9 +7643,9 @@ function automationRows(automations) {
7533
7643
  id: automation.id ?? "",
7534
7644
  name: automation.name ?? "",
7535
7645
  status: automation.status ?? "",
7536
- folderId: automation.folderId ?? "",
7537
7646
  triggerType: isJsonObject2(automation.trigger) && typeof automation.trigger.type === "string" ? automation.trigger.type : "",
7538
- actionCount: Array.isArray(automation.actions) ? automation.actions.length : ""
7647
+ actionCount: Array.isArray(automation.actions) ? automation.actions.length : "",
7648
+ ...folderColumns(automation.folder)
7539
7649
  }));
7540
7650
  }
7541
7651
  function actionRows(actions) {
@@ -8057,7 +8167,7 @@ function registerAutomationsCommands(program, options = {}) {
8057
8167
  }
8058
8168
  printTable(
8059
8169
  automationRows(data),
8060
- ["id", "name", "status", "folderId", "triggerType", "actionCount"],
8170
+ ["id", "name", "status", "triggerType", "actionCount", ...FOLDER_TABLE_KEYS],
8061
8171
  stdout
8062
8172
  );
8063
8173
  });
@@ -8907,6 +9017,83 @@ function parseFilterExpression(input) {
8907
9017
  function collectFilters(value, previous = []) {
8908
9018
  return [...previous, parseFilterExpression(value)];
8909
9019
  }
9020
+ function parseLockConditionOption(input) {
9021
+ const trimmed = input.trim();
9022
+ let lockedField;
9023
+ let expressionText;
9024
+ if (trimmed.includes(":") && !trimmed.includes(" ")) {
9025
+ const separatorIndex = trimmed.indexOf(":");
9026
+ lockedField = trimmed.slice(0, separatorIndex).trim();
9027
+ expressionText = trimmed.slice(separatorIndex + 1).trim();
9028
+ } else {
9029
+ const parts = trimmed.split(/\s+/);
9030
+ lockedField = parts[0]?.trim() ?? "";
9031
+ expressionText = parts.slice(1).join(" ").trim();
9032
+ }
9033
+ if (!lockedField || !expressionText) {
9034
+ throw new InvalidArgumentError3(
9035
+ 'Expected "<lockedField>:<field>:<comparator>[:<value>]" (or space-separated), e.g. "status:invoice-number:is_empty".'
9036
+ );
9037
+ }
9038
+ return { lockedField, expression: parseFilterExpression(expressionText) };
9039
+ }
9040
+ function collectLockConditions(value, previous = []) {
9041
+ return [...previous, parseLockConditionOption(value)];
9042
+ }
9043
+ function parseLockMessageOption(input) {
9044
+ const separatorIndex = input.indexOf(":");
9045
+ const lockedField = separatorIndex > 0 ? input.slice(0, separatorIndex).trim() : "";
9046
+ const message = separatorIndex > 0 ? input.slice(separatorIndex + 1).trim() : "";
9047
+ if (!lockedField || !message) {
9048
+ throw new InvalidArgumentError3('Expected "<lockedField>:<message>", e.g. "status:Locked once approved.".');
9049
+ }
9050
+ return { lockedField, message };
9051
+ }
9052
+ function collectLockMessages(value, previous = []) {
9053
+ return [...previous, parseLockMessageOption(value)];
9054
+ }
9055
+ function buildLockedFields(options) {
9056
+ const hasLockFlags = (options.lockField?.length ?? 0) > 0 || (options.lockCondition?.length ?? 0) > 0 || (options.lockMessageBefore?.length ?? 0) > 0 || (options.lockMessageAfter?.length ?? 0) > 0;
9057
+ if (options.clearLockedFields) {
9058
+ if (hasLockFlags) {
9059
+ throw new CliError(
9060
+ "invalid_cli_usage",
9061
+ 'Use either "--clear-locked-fields" or the "--lock-*" flags, not both.'
9062
+ );
9063
+ }
9064
+ return [];
9065
+ }
9066
+ if (!hasLockFlags) {
9067
+ return void 0;
9068
+ }
9069
+ const rules = /* @__PURE__ */ new Map();
9070
+ const ensureRule = (lockedField) => {
9071
+ let rule = rules.get(lockedField);
9072
+ if (!rule) {
9073
+ rule = { conditions: [] };
9074
+ rules.set(lockedField, rule);
9075
+ }
9076
+ return rule;
9077
+ };
9078
+ for (const lockedField of options.lockField ?? []) {
9079
+ ensureRule(lockedField);
9080
+ }
9081
+ for (const { lockedField, expression } of options.lockCondition ?? []) {
9082
+ ensureRule(lockedField).conditions.push(toDisplayFilter(expression));
9083
+ }
9084
+ for (const { lockedField, message } of options.lockMessageBefore ?? []) {
9085
+ ensureRule(lockedField).messageBeforeLock = message;
9086
+ }
9087
+ for (const { lockedField, message } of options.lockMessageAfter ?? []) {
9088
+ ensureRule(lockedField).messageAfterLock = message;
9089
+ }
9090
+ return [...rules.entries()].map(([lockedField, rule]) => ({
9091
+ field: { fieldId: lockedField },
9092
+ conditions: rule.conditions,
9093
+ ...rule.messageBeforeLock !== void 0 ? { messageBeforeLock: rule.messageBeforeLock } : {},
9094
+ ...rule.messageAfterLock !== void 0 ? { messageAfterLock: rule.messageAfterLock } : {}
9095
+ }));
9096
+ }
8910
9097
  function readRawObject2(raw, rawFile) {
8911
9098
  if (raw && rawFile) {
8912
9099
  throw new CliError("invalid_cli_usage", 'Use either "--raw" or "--raw-file", not both.');
@@ -9091,7 +9278,8 @@ function displayRows(displays) {
9091
9278
  name: display.name ?? "",
9092
9279
  layoutTemplate: display.layoutTemplate ?? "",
9093
9280
  variableCount: display.variableCount ?? "",
9094
- widgetCount: display.widgetCount ?? ""
9281
+ widgetCount: display.widgetCount ?? "",
9282
+ ...folderColumns(display.folder)
9095
9283
  }));
9096
9284
  }
9097
9285
  function getDisplaySubresource(value) {
@@ -9237,6 +9425,13 @@ function buildWidgetBody(options) {
9237
9425
  hideSeeButton: options.hideSeeButton
9238
9426
  };
9239
9427
  }
9428
+ const lockedFields = buildLockedFields(options);
9429
+ if (lockedFields !== void 0) {
9430
+ body.behavior = {
9431
+ ...typeof body.behavior === "object" && body.behavior ? body.behavior : {},
9432
+ lockedFields
9433
+ };
9434
+ }
9240
9435
  if (options.calc || options.calcField || options.kpiConfig) {
9241
9436
  body.kpi = {
9242
9437
  ...typeof body.kpi === "object" && body.kpi ? body.kpi : {},
@@ -9334,7 +9529,11 @@ function registerDisplaysCommands(program, options = {}) {
9334
9529
  emitJson4(stdout, "displays list", data);
9335
9530
  return;
9336
9531
  }
9337
- printTable(displayRows(data), ["id", "name", "layoutTemplate", "variableCount", "widgetCount"], stdout);
9532
+ printTable(
9533
+ displayRows(data),
9534
+ ["id", "name", "layoutTemplate", "variableCount", "widgetCount", ...FOLDER_TABLE_KEYS],
9535
+ stdout
9536
+ );
9338
9537
  });
9339
9538
  displays.command("get").description("Get a display").argument("<display>", "display uuid or slug", parseUuidOrSlugSelector3).action(async function action(display) {
9340
9539
  const { api, json } = createDisplaysApi(this, filePath);
@@ -9588,7 +9787,7 @@ function registerDisplaysCommands(program, options = {}) {
9588
9787
  }
9589
9788
  printTable([data], void 0, stdout);
9590
9789
  });
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) {
9790
+ 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
9791
  const { api, json, readOnly } = createDisplaysApi(this, filePath);
9593
9792
  ensureWritable3("displays widgets create", readOnly, "write");
9594
9793
  const data = await api.createWidget(display, buildWidgetBody(commandOptions));
@@ -9598,7 +9797,7 @@ function registerDisplaysCommands(program, options = {}) {
9598
9797
  }
9599
9798
  writeLine4(stdout, `Created widget on display "${display.value}".`);
9600
9799
  });
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) {
9800
+ 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
9801
  const { api, json, readOnly } = createDisplaysApi(this, filePath);
9603
9802
  ensureWritable3("displays widgets update", readOnly, "write");
9604
9803
  const data = await api.updateWidget(display, widgetId, buildWidgetBody(commandOptions));
@@ -11725,9 +11924,10 @@ function emitSchemasTable(stdout, schemas) {
11725
11924
  name: schema.name ?? "",
11726
11925
  slug: schema.slug ?? "",
11727
11926
  auditable: schema.auditable ?? "",
11728
- commentable: schema.commentable ?? ""
11927
+ commentable: schema.commentable ?? "",
11928
+ ...folderColumns(schema.folder)
11729
11929
  })),
11730
- ["id", "name", "slug", "auditable", "commentable"],
11930
+ ["id", "name", "slug", "auditable", "commentable", ...FOLDER_TABLE_KEYS],
11731
11931
  stdout
11732
11932
  );
11733
11933
  }