zinkee 0.1.4 → 0.1.7

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
@@ -674,6 +674,13 @@ var commandRegistry = {
674
674
  supportsRaw: true,
675
675
  output: writeOutput
676
676
  },
677
+ "logs list": {
678
+ command: "logs list",
679
+ accessLevel: "read",
680
+ supportsExample: true,
681
+ supportsRaw: false,
682
+ output: readOutput
683
+ },
677
684
  "teamspace folders list": {
678
685
  command: "teamspace folders list",
679
686
  accessLevel: "read",
@@ -1976,7 +1983,8 @@ function buildCommandExample(example) {
1976
1983
  return {
1977
1984
  command: example.command,
1978
1985
  description: example.description,
1979
- raw: example.raw
1986
+ raw: example.raw,
1987
+ response: example.response
1980
1988
  };
1981
1989
  }
1982
1990
  function buildCommandExamples(examples) {
@@ -1984,339 +1992,3061 @@ function buildCommandExamples(examples) {
1984
1992
  }
1985
1993
  var SAMPLE_UUID = "550e8400-e29b-41d4-a716-446655440001";
1986
1994
  var specificExamples = {
1987
- "records query": buildCommandExamples([
1995
+ "profiles list": buildCommandExamples([
1988
1996
  {
1989
- description: "Query records with filters, sort and pagination",
1990
- command: 'zinkee --json records query contacts --select id,name --where "status eq active" --sort createdAt:desc --limit 20 --offset 0'
1997
+ description: "List all local profiles. The CLI always redacts the apiKey to ******** plus the last 4 chars.",
1998
+ command: "zinkee --json profiles list",
1999
+ response: `[
2000
+ {
2001
+ "name": "prod",
2002
+ "isDefault": true,
2003
+ "apiKey": "********cdef",
2004
+ "baseUrl": "https://api.zinkee.com"
2005
+ },
2006
+ {
2007
+ "name": "local",
2008
+ "isDefault": false,
2009
+ "apiKey": "********4321",
2010
+ "baseUrl": "http://localhost:8088"
2011
+ }
2012
+ ]`
1991
2013
  }
1992
2014
  ]),
1993
- "records create": buildCommandExamples([
2015
+ "profiles get": buildCommandExamples([
1994
2016
  {
1995
- description: "Create a record with simple and structured values",
1996
- command: `zinkee --json records create contacts --set name=Ana --set-json meta='{"tier":"gold"}'`
2017
+ description: "Show one profile by name.",
2018
+ command: "zinkee --json profiles get prod",
2019
+ response: `{
2020
+ "name": "prod",
2021
+ "isDefault": true,
2022
+ "apiKey": "********cdef",
2023
+ "baseUrl": "https://api.zinkee.com"
2024
+ }`
1997
2025
  }
1998
2026
  ]),
1999
- "files download": buildCommandExamples([
2027
+ "profiles use": buildCommandExamples([
2000
2028
  {
2001
- description: "Download a file to disk in JSON mode",
2002
- command: `zinkee --json files download ${SAMPLE_UUID} --output ./download.bin`
2029
+ description: "Set a profile as the default one used when --profile is not passed.",
2030
+ command: "zinkee --json profiles use local",
2031
+ response: `{
2032
+ "profile": "local",
2033
+ "defaultProfile": "local"
2034
+ }`
2003
2035
  }
2004
2036
  ]),
2005
- "navigation resources move": buildCommandExamples([
2037
+ "profiles add": buildCommandExamples([
2006
2038
  {
2007
- description: "Move a resource into a navigation folder by exact folder name",
2008
- command: `zinkee --json navigation resources move ${SAMPLE_UUID} --type schema --to Finance`
2039
+ description: "Add a new profile with an explicit base URL. Becomes the default if no other profile existed.",
2040
+ command: "zinkee --json profiles add prod --api-key sk-prod-9f3a2c1b-1234567890abcdef --base-url https://api.zinkee.com",
2041
+ response: `{
2042
+ "name": "prod",
2043
+ "isDefault": true,
2044
+ "apiKey": "********cdef",
2045
+ "baseUrl": "https://api.zinkee.com"
2046
+ }`
2047
+ },
2048
+ {
2049
+ description: "Add a profile without --base-url (the runtime falls back to the production URL at call time).",
2050
+ command: "zinkee --json profiles add staging --api-key sk-staging-7777aaaa-bbbbccccddddeeee",
2051
+ response: `{
2052
+ "name": "staging",
2053
+ "isDefault": false,
2054
+ "apiKey": "********eeee"
2055
+ }`
2009
2056
  }
2010
2057
  ]),
2011
- "teamspace resources publish": buildCommandExamples([
2058
+ "profiles update": buildCommandExamples([
2059
+ {
2060
+ description: "Rotate just the API key of an existing profile.",
2061
+ command: "zinkee --json profiles update prod --api-key sk-prod-0000new0-fedcba0987654321",
2062
+ response: `{
2063
+ "name": "prod",
2064
+ "isDefault": true,
2065
+ "apiKey": "********4321",
2066
+ "baseUrl": "https://api.zinkee.com"
2067
+ }`
2068
+ },
2012
2069
  {
2013
- description: "Publish a resource into a teamspace folder",
2014
- command: `zinkee --json teamspace resources publish ${SAMPLE_UUID} --to "Customer Success"`
2070
+ description: "Point an existing profile at a different base URL (useful when moving envs).",
2071
+ command: "zinkee --json profiles update local --base-url http://localhost:9090",
2072
+ response: `{
2073
+ "name": "local",
2074
+ "isDefault": false,
2075
+ "apiKey": "********4321",
2076
+ "baseUrl": "http://localhost:9090"
2077
+ }`
2015
2078
  }
2016
2079
  ]),
2017
- "displays widgets create": buildCommandExamples([
2080
+ "profiles remove": buildCommandExamples([
2018
2081
  {
2019
- description: "Create a chart widget through the generic --type path",
2020
- command: 'zinkee --json displays widgets create display-1 --type chart --name "Revenue" --chart-type bar'
2082
+ description: "Remove a profile. If it was the default, defaultProfile becomes null and you should set a new one with profiles use.",
2083
+ command: "zinkee --json profiles remove staging",
2084
+ response: `{
2085
+ "profile": "staging",
2086
+ "defaultProfile": "prod"
2087
+ }`
2021
2088
  }
2022
2089
  ]),
2023
- "automations create": buildCommandExamples([
2090
+ "config path": buildCommandExamples([
2024
2091
  {
2025
- description: "Create a scheduled automation with a six-field cron expression. This is the safest first example because it does not depend on workspace schemas.",
2026
- command: 'zinkee --json automations create --name "Nightly invoice sync" --trigger-type scheduled --cron "0 15 10 * * 1"',
2027
- raw: `{
2028
- "name": "Nightly invoice sync",
2029
- "trigger": {
2030
- "type": "scheduled",
2031
- "config": {
2032
- "cronExpression": "0 15 10 * * 1"
2092
+ description: "Print the path of the config file the CLI is reading right now.",
2093
+ command: "zinkee --json config path",
2094
+ response: `{
2095
+ "path": "/home/guillermo/.config/zinkee/config.json"
2096
+ }`
2097
+ }
2098
+ ]),
2099
+ "config show": buildCommandExamples([
2100
+ {
2101
+ description: "Dump the whole config with secrets redacted. Same ******** + last 4 chars mask that profiles list uses.",
2102
+ command: "zinkee --json config show",
2103
+ response: `{
2104
+ "defaultProfile": "prod",
2105
+ "profiles": {
2106
+ "prod": {
2107
+ "apiKey": "********cdef",
2108
+ "baseUrl": "https://api.zinkee.com"
2109
+ },
2110
+ "local": {
2111
+ "apiKey": "********4321",
2112
+ "baseUrl": "http://localhost:8088"
2033
2113
  }
2034
2114
  }
2035
2115
  }`
2036
- },
2116
+ }
2117
+ ]),
2118
+ "config validate": buildCommandExamples([
2037
2119
  {
2038
- description: "Create a record-created automation using a real schema slug or UUID. Replace 'leads' with a schema from 'zinkee --json schemas list'.",
2039
- command: 'zinkee --json automations create --name "Lead welcome" --trigger-type record_created --trigger-schema leads',
2040
- raw: `{
2041
- "name": "Lead welcome",
2042
- "trigger": {
2043
- "type": "record_created",
2044
- "config": {
2045
- "schemaId": "leads"
2120
+ description: "Validate that the local config resolves a profile. Useful as a CI gate before running other commands.",
2121
+ command: "zinkee --json config validate",
2122
+ response: `{
2123
+ "valid": true,
2124
+ "profile": "prod"
2125
+ }`
2046
2126
  }
2127
+ ]),
2128
+ "schemas create": buildCommandExamples([
2129
+ {
2130
+ description: "Create an auditable and commentable schema from flags.",
2131
+ command: 'zinkee --json schemas create --name "Codex Demo" --slug codex-demo --auditable --commentable',
2132
+ raw: `{
2133
+ "name": "Codex Demo",
2134
+ "slug": "codex-demo",
2135
+ "auditable": true,
2136
+ "commentable": true
2137
+ }`,
2138
+ response: `{
2139
+ "schemaId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
2140
+ "slug": "codex-demo",
2141
+ "folder": {
2142
+ "id": "00000000-0000-0000-0000-000000000000",
2143
+ "name": "root",
2144
+ "isRoot": true
2047
2145
  }
2048
2146
  }`
2049
2147
  },
2050
2148
  {
2051
- description: "Create a record-changed automation using real schema and field slugs or UUIDs. Replace 'orders' and 'status' with values from your workspace.",
2052
- command: 'zinkee --json automations create --name "Order status sync" --trigger-type record_changed --trigger-schema orders --trigger-field status',
2149
+ description: "Minimal create with just name and slug.",
2150
+ command: "zinkee --json schemas create --name Leads --slug leads",
2053
2151
  raw: `{
2054
- "name": "Order status sync",
2055
- "trigger": {
2056
- "type": "record_changed",
2057
- "config": {
2058
- "schemaId": "orders",
2059
- "fieldIds": ["status"]
2060
- }
2061
- }
2152
+ "name": "Leads",
2153
+ "slug": "leads"
2154
+ }`
2155
+ },
2156
+ {
2157
+ description: "Create an auditable schema inside an existing navigation folder (folder id can be a UUID or the exact folder name).",
2158
+ command: "zinkee --json schemas create --name Tasks --slug tasks --auditable --folder 7f4e7c25-d8b2-4c1a-9f3e-6a7b5c8d9e1f",
2159
+ raw: `{
2160
+ "name": "Tasks",
2161
+ "slug": "tasks",
2162
+ "auditable": true,
2163
+ "commentable": false,
2164
+ "folderId": "7f4e7c25-d8b2-4c1a-9f3e-6a7b5c8d9e1f"
2062
2165
  }`
2063
2166
  }
2064
2167
  ]),
2065
- "automations update": buildCommandExamples([
2168
+ "schemas update": buildCommandExamples([
2066
2169
  {
2067
- description: "Patch automation metadata using the backend set/unset contract",
2068
- command: `zinkee --json automations update automation-1 --raw '{"set":{"description":"Updated by CLI docs"},"unset":["folderId"]}'`,
2170
+ description: "Rename a schema and change its slug.",
2171
+ command: 'zinkee --json schemas update contacts --name "Customer Contacts" --slug customer-contacts',
2069
2172
  raw: `{
2070
2173
  "set": {
2071
- "description": "Updated by CLI docs"
2174
+ "name": "Customer Contacts",
2175
+ "slug": "customer-contacts"
2176
+ }
2177
+ }`,
2178
+ response: `{
2179
+ "id": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
2180
+ "name": "Customer Contacts",
2181
+ "slug": "customer-contacts",
2182
+ "folder": {
2183
+ "id": "7f4e7c25-d8b2-4c1a-9f3e-6a7b5c8d9e1f",
2184
+ "name": "Customers",
2185
+ "isRoot": false
2072
2186
  },
2073
- "unset": ["folderId"]
2187
+ "auditable": true,
2188
+ "commentable": true,
2189
+ "fields": []
2190
+ }`
2191
+ },
2192
+ {
2193
+ description: "Enable the audit log on a schema.",
2194
+ command: "zinkee --json schemas update contacts --auditable true",
2195
+ raw: `{
2196
+ "set": {
2197
+ "auditable": true
2198
+ }
2199
+ }`
2200
+ },
2201
+ {
2202
+ description: "Toggle commentable off.",
2203
+ command: "zinkee --json schemas update contacts --commentable false",
2204
+ raw: `{
2205
+ "set": {
2206
+ "commentable": false
2207
+ }
2074
2208
  }`
2075
2209
  }
2076
2210
  ]),
2077
- "automations trigger set": buildCommandExamples([
2211
+ "schemas fields update": buildCommandExamples([
2078
2212
  {
2079
- description: "Replace the trigger with a scheduled trigger",
2080
- command: 'zinkee --json automations trigger set automation-1 --trigger-type scheduled --cron "0 0 9 * * *"',
2213
+ description: "Rename a field label and drop the required flag.",
2214
+ command: 'zinkee --json schemas fields update contacts contact-name --label "Customer Full Name" --required false',
2081
2215
  raw: `{
2082
- "type": "scheduled",
2083
- "config": {
2084
- "cronExpression": "0 0 9 * * *"
2085
- }
2216
+ "set": {
2217
+ "label": "Customer Full Name",
2218
+ "required": false
2219
+ }
2220
+ }`,
2221
+ response: `{
2222
+ "schemaId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
2223
+ "fieldId": "c60b8526-5835-4c9f-aecd-9a16c7704a34",
2224
+ "slug": "customer-full-name"
2086
2225
  }`
2087
2226
  },
2088
2227
  {
2089
- description: "Replace the trigger with a record-changed trigger and a literal condition",
2090
- command: "zinkee --json automations trigger set automation-1 --trigger-type record_changed --trigger-schema orders --trigger-field status --condition status:eq:approved",
2228
+ description: "Make a field required.",
2229
+ command: "zinkee --json schemas fields update contacts status --required true",
2091
2230
  raw: `{
2092
- "type": "record_changed",
2093
- "config": {
2094
- "schemaId": "orders",
2095
- "fieldIds": ["status"],
2096
- "conditions": [
2097
- {
2098
- "field": "status",
2099
- "comparator": "eq",
2100
- "values": [
2101
- {
2102
- "rawValue": "approved",
2103
- "source": null
2104
- }
2105
- ]
2106
- }
2107
- ]
2231
+ "set": {
2232
+ "required": true
2108
2233
  }
2109
2234
  }`
2110
2235
  },
2111
2236
  {
2112
- description: "Replace the trigger with a webhook trigger using an existing webhook endpoint id",
2113
- command: "zinkee --json automations trigger set automation-1 --trigger-type webhook --webhook-endpoint-id 550e8400-e29b-41d4-a716-446655440001",
2237
+ description: "Patch the format options of a number field through a raw set payload (no dedicated flag exists for nested config paths).",
2238
+ command: `zinkee --json schemas fields update contacts amount --raw '{"set":{"config":{"formatOptions":{"format":"percent","decimals":1}}}}'`,
2114
2239
  raw: `{
2115
- "type": "webhook",
2116
- "config": {
2117
- "webhookEndpointId": "550e8400-e29b-41d4-a716-446655440001"
2240
+ "set": {
2241
+ "config": {
2242
+ "formatOptions": {
2243
+ "format": "percent",
2244
+ "decimals": 1
2245
+ }
2246
+ }
2118
2247
  }
2119
2248
  }`
2120
2249
  }
2121
2250
  ]),
2122
- "automations actions add": buildCommandExamples([
2251
+ "records query": buildCommandExamples([
2123
2252
  {
2124
- description: "Add a create-record action with literal and trigger-based field mappings",
2125
- command: `zinkee --json automations actions add automation-1 --type create_record --name "Create follow-up" --target-schema followups --map status=pending --map-json owner='{"rawValue":null,"source":{"type":"TRIGGER","id":"payload_value"}}'`,
2253
+ description: "Lookup a single record by id.",
2254
+ command: 'zinkee --json records query contacts --select id,contact-name --where "id eq 550e8400-e29b-41d4-a716-446655440000" --sort id:desc --limit 10',
2126
2255
  raw: `{
2127
- "type": "create_record",
2128
- "name": "Create follow-up",
2129
- "config": {
2130
- "targetSchemaId": "followups",
2131
- "fieldMapping": {
2132
- "status": {
2133
- "rawValue": "pending",
2134
- "source": null
2135
- },
2136
- "owner": {
2137
- "rawValue": null,
2138
- "source": {
2139
- "type": "TRIGGER",
2140
- "id": "payload_value"
2141
- }
2256
+ "select": ["id", "contact-name"],
2257
+ "where": [
2258
+ { "field": "id", "op": "eq", "value": "550e8400-e29b-41d4-a716-446655440000" }
2259
+ ],
2260
+ "sort": [
2261
+ { "field": "id", "direction": "DESC" }
2262
+ ],
2263
+ "page": { "offset": 0, "size": 10 }
2264
+ }`,
2265
+ response: `{
2266
+ "records": [
2267
+ {
2268
+ "recordId": "550e8400-e29b-41d4-a716-446655440000",
2269
+ "values": {
2270
+ "contact-name": "Ada Lovelace",
2271
+ "status": 2,
2272
+ "amount": 1250.50
2142
2273
  }
2143
2274
  }
2275
+ ],
2276
+ "page": {
2277
+ "offset": 0,
2278
+ "limit": 25,
2279
+ "total": 1,
2280
+ "count": 1,
2281
+ "hasMore": false
2144
2282
  }
2145
2283
  }`
2146
2284
  },
2147
2285
  {
2148
- description: "Add a search-records action with a trigger-based condition",
2149
- command: `zinkee --json automations actions add automation-1 --type search_records --name "Find duplicates" --target-schema followups --condition-json '{"field":"email","comparator":"eq","values":[{"rawValue":null,"source":{"type":"TRIGGER","id":"payload_value"}}]}'`,
2286
+ description: "Filter by multiple conditions and sort by amount then name.",
2287
+ command: `zinkee --json records query contacts --select id,contact-name,status,amount --where "status in 1,2" --where "amount gte 500" --sort amount:desc --sort contact-name:asc --limit 25`,
2150
2288
  raw: `{
2151
- "type": "search_records",
2152
- "name": "Find duplicates",
2153
- "config": {
2154
- "targetSchemaId": "followups",
2155
- "conditions": [
2156
- {
2157
- "field": "email",
2158
- "comparator": "eq",
2159
- "values": [
2160
- {
2161
- "rawValue": null,
2162
- "source": {
2163
- "type": "TRIGGER",
2164
- "id": "payload_value"
2165
- }
2166
- }
2167
- ]
2168
- }
2169
- ]
2170
- }
2289
+ "select": ["id", "contact-name", "status", "amount"],
2290
+ "where": [
2291
+ { "field": "status", "op": "in", "value": [1, 2] },
2292
+ { "field": "amount", "op": "gte", "value": 500 }
2293
+ ],
2294
+ "sort": [
2295
+ { "field": "amount", "direction": "DESC" },
2296
+ { "field": "contact-name", "direction": "ASC" }
2297
+ ],
2298
+ "page": { "offset": 0, "size": 25 }
2171
2299
  }`
2172
2300
  },
2173
2301
  {
2174
- description: "Add an HTTP request action through the generic --type path",
2175
- command: "zinkee --json automations actions add automation-1 --type http_request --name Notify --method POST --url https://example.com/hook --content-type application/json",
2302
+ description: "Text contains search.",
2303
+ command: 'zinkee --json records query contacts --select id,contact-name,contact-email --where "contact-name contains Lovelace" --limit 50',
2176
2304
  raw: `{
2177
- "type": "http_request",
2178
- "name": "Notify",
2179
- "config": {
2180
- "method": "POST",
2181
- "url": "https://example.com/hook",
2182
- "contentType": "application/json"
2183
- }
2305
+ "select": ["id", "contact-name", "contact-email"],
2306
+ "where": [
2307
+ { "field": "contact-name", "op": "contains", "value": "Lovelace" }
2308
+ ],
2309
+ "page": { "offset": 0, "size": 50 }
2184
2310
  }`
2185
2311
  },
2186
2312
  {
2187
- description: "Add an execute-plugin action with structured plugin arguments. Replace 'clone-budget' with an active id from 'zinkee --json automations plugins list'.",
2188
- command: `zinkee --json automations actions add automation-1 --type execute_plugin --name "Run plugin" --plugin clone-budget --arg mode=safe --arg-json payload='{"dryRun":true}'`,
2313
+ description: "Records with a non-empty due-date inside a date range.",
2314
+ command: 'zinkee --json records query contacts --where "due-date is_not_empty" --where "due-date lte 2026-12-31T23:59:59Z" --sort due-date:asc',
2189
2315
  raw: `{
2190
- "type": "execute_plugin",
2191
- "name": "Run plugin",
2192
- "config": {
2193
- "pluginId": "clone-budget",
2194
- "pluginArgs": {
2195
- "mode": "safe",
2196
- "payload": {
2197
- "dryRun": true
2198
- }
2199
- }
2200
- }
2316
+ "where": [
2317
+ { "field": "due-date", "op": "is_not_empty" },
2318
+ { "field": "due-date", "op": "lte", "value": "2026-12-31T23:59:59Z" }
2319
+ ],
2320
+ "sort": [
2321
+ { "field": "due-date", "direction": "ASC" }
2322
+ ]
2323
+ }`
2324
+ },
2325
+ {
2326
+ description: "Records whose status is not equal to a value.",
2327
+ command: 'zinkee --json records query contacts --where "status neq 0"',
2328
+ raw: `{
2329
+ "where": [
2330
+ { "field": "status", "op": "neq", "value": 0 }
2331
+ ]
2332
+ }`
2333
+ },
2334
+ {
2335
+ description: "Records with an amount greater than a threshold.",
2336
+ command: 'zinkee --json records query contacts --where "amount gt 1000"',
2337
+ raw: `{
2338
+ "where": [
2339
+ { "field": "amount", "op": "gt", "value": 1000 }
2340
+ ]
2341
+ }`
2342
+ },
2343
+ {
2344
+ description: "Records with an amount less than a threshold.",
2345
+ command: 'zinkee --json records query contacts --where "amount lt 100"',
2346
+ raw: `{
2347
+ "where": [
2348
+ { "field": "amount", "op": "lt", "value": 100 }
2349
+ ]
2350
+ }`
2351
+ },
2352
+ {
2353
+ description: "Records whose due-date is empty.",
2354
+ command: 'zinkee --json records query contacts --where "due-date is_empty"',
2355
+ raw: `{
2356
+ "where": [
2357
+ { "field": "due-date", "op": "is_empty" }
2358
+ ]
2359
+ }`
2360
+ },
2361
+ {
2362
+ description: "Records whose contact-email is not empty.",
2363
+ command: 'zinkee --json records query contacts --where "contact-email is_not_empty"',
2364
+ raw: `{
2365
+ "where": [
2366
+ { "field": "contact-email", "op": "is_not_empty" }
2367
+ ]
2201
2368
  }`
2202
2369
  }
2203
2370
  ]),
2204
- "automations actions update": buildCommandExamples([
2371
+ "records create": buildCommandExamples([
2205
2372
  {
2206
- description: "Update a record action using the trigger record without sending conditions",
2207
- command: 'zinkee --json automations actions update automation-1 action-1 --type update_record --name "Update trigger record" --target-schema followups --map status=ready --use-trigger-record',
2373
+ description: "Minimal create using just two plain string fields.",
2374
+ command: `zinkee --json records create contacts --set contact-name="Ada Lovelace" --set contact-email=ada@example.com`,
2208
2375
  raw: `{
2209
- "type": "update_record",
2210
- "name": "Update trigger record",
2211
- "config": {
2212
- "targetSchemaId": "followups",
2213
- "fieldMapping": {
2214
- "status": {
2215
- "rawValue": "ready",
2216
- "source": null
2217
- }
2376
+ "values": {
2377
+ "contact-name": "Ada Lovelace",
2378
+ "contact-email": "ada@example.com"
2379
+ }
2380
+ }`,
2381
+ response: `{
2382
+ "recordId": "550e8400-e29b-41d4-a716-446655440000",
2383
+ "values": {
2384
+ "contact-name": "Ada Lovelace",
2385
+ "contact-email": "ada@example.com"
2386
+ }
2387
+ }`
2218
2388
  },
2219
- "useTriggerRecord": true
2389
+ {
2390
+ description: "Create a record mixing text, option, number, date and reference fields. Structured values go through --set-json.",
2391
+ command: `zinkee --json records create contacts --set contact-name="Grace Hopper" --set contact-email=grace@example.com --set-json status=2 --set-json amount=1999.99 --set due-date=2026-06-01T09:00:00Z --set customer-ref=8ad602a1-f6e3-43f6-9ab2-f1c5afc99621 --set owner=6c8a3e0d-4e5f-4a1b-9c2d-3e4f5a6b7c8d`,
2392
+ raw: `{
2393
+ "values": {
2394
+ "contact-name": "Grace Hopper",
2395
+ "contact-email": "grace@example.com",
2396
+ "status": 2,
2397
+ "amount": 1999.99,
2398
+ "due-date": "2026-06-01T09:00:00Z",
2399
+ "customer-ref": "8ad602a1-f6e3-43f6-9ab2-f1c5afc99621",
2400
+ "owner": "6c8a3e0d-4e5f-4a1b-9c2d-3e4f5a6b7c8d"
2220
2401
  }
2221
2402
  }`
2222
2403
  }
2223
2404
  ]),
2224
- "automations flow set": buildCommandExamples([
2405
+ "records update": buildCommandExamples([
2225
2406
  {
2226
- description: "Set flow entry actions and transitions",
2227
- command: "zinkee --json automations flow set automation-1 --entry action-1 --transition action-1:action-2",
2407
+ description: "Set one field and unset another.",
2408
+ command: 'zinkee --json records update contacts 550e8400-e29b-41d4-a716-446655440000 --set contact-name="Ada Lovelace Updated" --unset contact-email',
2228
2409
  raw: `{
2229
- "entryActionIds": ["action-1"],
2230
- "transitions": [
2410
+ "set": {
2411
+ "contact-name": "Ada Lovelace Updated"
2412
+ },
2413
+ "unset": ["contact-email"]
2414
+ }`,
2415
+ response: `{
2416
+ "recordId": "550e8400-e29b-41d4-a716-446655440000",
2417
+ "values": {
2418
+ "contact-name": "Ada Lovelace Updated",
2419
+ "status": 2,
2420
+ "amount": 1250.50,
2421
+ "due-date": "2026-05-15T12:00:00Z",
2422
+ "owner": "6c8a3e0d-4e5f-4a1b-9c2d-3e4f5a6b7c8d"
2423
+ }
2424
+ }`
2425
+ },
2231
2426
  {
2232
- "fromActionId": "action-1",
2233
- "toActionId": "action-2"
2234
- }
2235
- ]
2427
+ description: "Patch multiple typed values at once.",
2428
+ command: "zinkee --json records update contacts 550e8400-e29b-41d4-a716-446655440000 --set-json status=3 --set-json amount=2500.00 --set due-date=2026-07-01T09:00:00Z --set owner=6c8a3e0d-4e5f-4a1b-9c2d-3e4f5a6b7c8d",
2429
+ raw: `{
2430
+ "set": {
2431
+ "status": 3,
2432
+ "amount": 2500.00,
2433
+ "due-date": "2026-07-01T09:00:00Z",
2434
+ "owner": "6c8a3e0d-4e5f-4a1b-9c2d-3e4f5a6b7c8d"
2435
+ }
2436
+ }`
2437
+ },
2438
+ {
2439
+ description: "Unset only (clear fields).",
2440
+ command: "zinkee --json records update contacts 550e8400-e29b-41d4-a716-446655440000 --unset contact-email --unset due-date",
2441
+ raw: `{
2442
+ "unset": ["contact-email", "due-date"]
2236
2443
  }`
2237
2444
  }
2238
2445
  ]),
2239
- "automations webhook set": buildCommandExamples([
2446
+ "comments create": buildCommandExamples([
2240
2447
  {
2241
- description: "Configure webhook ingestion paths and field mappings for a webhook automation. This config is separate from the webhook trigger itself.",
2242
- command: `zinkee --json automations webhook set automation-1 --active --idempotency-key-path "$.id" --event-type-path "$.type" --allowed-event-type frontend.demo.created --field-mapping '{"variable":"external_id","jsonPath":"$.data.id"}'`,
2448
+ description: "Plain text comment on a record (uses --text).",
2449
+ command: `zinkee --json comments create contacts 550e8400-e29b-41d4-a716-446655440000 --text "This record needs review."`,
2243
2450
  raw: `{
2244
- "active": true,
2245
- "idempotencyKeyJsonPath": "$.id",
2246
- "eventTypeJsonPath": "$.type",
2247
- "allowedEventTypes": ["frontend.demo.created"],
2248
- "fieldMappings": [
2451
+ "content": [
2249
2452
  {
2250
- "variable": "external_id",
2251
- "jsonPath": "$.data.id"
2453
+ "type": "TEXT",
2454
+ "value": "This record needs review."
2252
2455
  }
2253
2456
  ]
2457
+ }`,
2458
+ response: `{
2459
+ "id": "cd8e3b2a-1f5c-4e9a-8b7d-0a2b3c4d5e6f",
2460
+ "recordId": "550e8400-e29b-41d4-a716-446655440000",
2461
+ "createdAt": "2026-04-22T10:15:00Z",
2462
+ "createdBy": "developer@zinkee.com",
2463
+ "content": [
2464
+ { "type": "TEXT", "value": "This record needs review." }
2465
+ ]
2254
2466
  }`
2255
- }
2256
- ]),
2257
- "automations connections create": buildCommandExamples([
2467
+ },
2258
2468
  {
2259
- description: "Create a stored workspace connection for HTTP request actions",
2260
- command: `zinkee --json automations connections create --name "ERP API Key" --type api_key --scope workspace --config '{"headerName":"Authorization"}' --secret apiKey=super-secret --active`,
2469
+ description: "Comment with an inline member mention. Mentions only go through --raw today because --text is plain text.",
2470
+ command: `zinkee --json comments create contacts 550e8400-e29b-41d4-a716-446655440000 --raw '{"content":[{"type":"TEXT","value":"Assigning to "},{"type":"MENTION","value":"9f8e7d6c-5b4a-3c2d-1e0f-a1b2c3d4e5f6"},{"type":"TEXT","value":" for follow up."}]}'`,
2261
2471
  raw: `{
2262
- "name": "ERP API Key",
2263
- "type": "api_key",
2264
- "scope": "workspace",
2265
- "config": {
2266
- "headerName": "Authorization"
2267
- },
2268
- "secret": {
2269
- "apiKey": "super-secret"
2270
- },
2271
- "active": true
2472
+ "content": [
2473
+ { "type": "TEXT", "value": "Assigning to " },
2474
+ { "type": "MENTION", "value": "9f8e7d6c-5b4a-3c2d-1e0f-a1b2c3d4e5f6" },
2475
+ { "type": "TEXT", "value": " for follow up." }
2476
+ ]
2272
2477
  }`
2273
2478
  }
2274
2479
  ]),
2275
- "automations connections update": buildCommandExamples([
2480
+ "files download": buildCommandExamples([
2276
2481
  {
2277
- description: "Patch an existing stored connection",
2278
- command: `zinkee --json automations connections update connection-1 --raw '{"set":{"name":"ERP API Key Updated","config":{"headerName":"Authorization"}}}'`,
2279
- raw: `{
2280
- "set": {
2281
- "name": "ERP API Key Updated",
2282
- "config": {
2283
- "headerName": "Authorization"
2482
+ description: "Download a file to disk (the CLI writes the raw bytes to the --output path; the JSON mode only emits a success envelope).",
2483
+ command: `zinkee --json files download ${SAMPLE_UUID} --output ./download.bin`
2284
2484
  }
2285
- }
2485
+ ]),
2486
+ "files upload": buildCommandExamples([
2487
+ {
2488
+ description: "Upload a local file. The CLI sends the multipart form and the backend returns the generated file id to reference from record FileField values.",
2489
+ command: "zinkee --json files upload ./report.pdf",
2490
+ response: `{
2491
+ "id": "d290f1ee-6c54-4b01-90e6-d701748f0851"
2286
2492
  }`
2287
2493
  }
2288
- ])
2289
- };
2290
- function fallbackExamples(commandName) {
2494
+ ]),
2495
+ "files delete": buildCommandExamples([
2496
+ {
2497
+ description: "Delete a file from workspace storage. Records that still reference the file id keep the stale pointer until updated separately.",
2498
+ command: `zinkee --json files delete ${SAMPLE_UUID}`,
2499
+ response: `{
2500
+ "id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
2501
+ "deleted": true
2502
+ }`
2503
+ }
2504
+ ]),
2505
+ "navigation folders create": buildCommandExamples([
2506
+ {
2507
+ description: "Create a folder with a display order and custom properties.",
2508
+ command: `zinkee --json navigation folders create --name Finance --order 20 --props '{"color":"green"}'`,
2509
+ raw: `{
2510
+ "name": "Finance",
2511
+ "order": 20,
2512
+ "additionalProperties": {
2513
+ "color": "green"
2514
+ }
2515
+ }`,
2516
+ response: `{
2517
+ "folderId": "c5d6e7f8-9012-3456-789a-bcdef0123456",
2518
+ "name": "Finance"
2519
+ }`
2520
+ },
2521
+ {
2522
+ description: "Minimal create with just a name.",
2523
+ command: "zinkee --json navigation folders create --name Archive",
2524
+ raw: `{
2525
+ "name": "Archive"
2526
+ }`
2527
+ },
2528
+ {
2529
+ description: "Create a folder with color and icon metadata.",
2530
+ command: `zinkee --json navigation folders create --name Reports --order 5 --props '{"color":"teal","icon":"chart-line"}'`,
2531
+ raw: `{
2532
+ "name": "Reports",
2533
+ "order": 5,
2534
+ "additionalProperties": {
2535
+ "color": "teal",
2536
+ "icon": "chart-line"
2537
+ }
2538
+ }`
2539
+ }
2540
+ ]),
2541
+ "navigation folders update": buildCommandExamples([
2542
+ {
2543
+ description: "Rename the folder, change its order, and rewrite its additionalProperties.",
2544
+ command: `zinkee --json navigation folders update Finance --name "Finance Ops" --order 30 --props '{"color":"teal"}'`,
2545
+ raw: `{
2546
+ "name": "Finance Ops",
2547
+ "order": 30,
2548
+ "additionalProperties": {
2549
+ "color": "teal"
2550
+ }
2551
+ }`,
2552
+ response: `{
2553
+ "folderId": "84a0fca4-37ef-4c83-a8ed-9ef67ad9324a",
2554
+ "name": "Finance Ops"
2555
+ }`
2556
+ },
2557
+ {
2558
+ description: "Rename only.",
2559
+ command: 'zinkee --json navigation folders update Finance --name "Finance (legacy)"',
2560
+ raw: `{
2561
+ "name": "Finance (legacy)"
2562
+ }`
2563
+ },
2564
+ {
2565
+ description: "Change only the display order.",
2566
+ command: "zinkee --json navigation folders update Finance --order 1",
2567
+ raw: `{
2568
+ "order": 1
2569
+ }`
2570
+ },
2571
+ {
2572
+ description: "Replace only additionalProperties.",
2573
+ command: `zinkee --json navigation folders update Finance --props '{"color":"red","icon":"archive"}'`,
2574
+ raw: `{
2575
+ "additionalProperties": {
2576
+ "color": "red",
2577
+ "icon": "archive"
2578
+ }
2579
+ }`
2580
+ }
2581
+ ]),
2582
+ "navigation resources move": buildCommandExamples([
2583
+ {
2584
+ description: "Move a schema into a navigation folder.",
2585
+ command: "zinkee --json navigation resources move 2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e --type SCHEMA --to Sales",
2586
+ raw: `{
2587
+ "resourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
2588
+ "resourceType": "SCHEMA",
2589
+ "targetFolderId": "84a0fca4-37ef-4c83-a8ed-9ef67ad9324a"
2590
+ }`,
2591
+ response: `{
2592
+ "resourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
2593
+ "targetFolderId": "84a0fca4-37ef-4c83-a8ed-9ef67ad9324a"
2594
+ }`
2595
+ },
2596
+ {
2597
+ description: "Move a workflow.",
2598
+ command: "zinkee --json navigation resources move 3f8a2c1b-9d4e-4a5b-8c6d-7e8f90123456 --type WORKFLOW --to Operations",
2599
+ raw: `{
2600
+ "resourceId": "3f8a2c1b-9d4e-4a5b-8c6d-7e8f90123456",
2601
+ "resourceType": "WORKFLOW",
2602
+ "targetFolderId": "b8c9d0e1-f2a3-4b5c-6d7e-8f9012345678"
2603
+ }`
2604
+ },
2605
+ {
2606
+ description: "Move a display.",
2607
+ command: "zinkee --json navigation resources move 0f6f062f-1478-4df2-96a1-c495d037d260 --type DISPLAY --to Operations",
2608
+ raw: `{
2609
+ "resourceId": "0f6f062f-1478-4df2-96a1-c495d037d260",
2610
+ "resourceType": "DISPLAY",
2611
+ "targetFolderId": "b8c9d0e1-f2a3-4b5c-6d7e-8f9012345678"
2612
+ }`
2613
+ },
2614
+ {
2615
+ description: "Move a resource back to the root folder (root is always UUID 00000000-0000-0000-0000-000000000000).",
2616
+ command: "zinkee --json navigation resources move 5223cbc8-8c6c-4694-93bc-dd176364df9b --type SCHEMA --to 00000000-0000-0000-0000-000000000000",
2617
+ raw: `{
2618
+ "resourceId": "5223cbc8-8c6c-4694-93bc-dd176364df9b",
2619
+ "resourceType": "SCHEMA",
2620
+ "targetFolderId": "00000000-0000-0000-0000-000000000000"
2621
+ }`
2622
+ },
2623
+ {
2624
+ description: "Move a schedule resource.",
2625
+ command: "zinkee --json navigation resources move a1b2c3d4-e5f6-7890-1234-567890abcdef --type SCHEDULE --to Operations",
2626
+ raw: `{
2627
+ "resourceId": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
2628
+ "resourceType": "SCHEDULE",
2629
+ "targetFolderId": "b8c9d0e1-f2a3-4b5c-6d7e-8f9012345678"
2630
+ }`
2631
+ }
2632
+ ]),
2633
+ "teamspace folders create": buildCommandExamples([
2634
+ {
2635
+ description: "Create a teamspace folder with order and icon metadata.",
2636
+ command: `zinkee --json teamspace folders create --name "Customer Success" --order 10 --props '{"icon":"folder-users"}'`,
2637
+ raw: `{
2638
+ "name": "Customer Success",
2639
+ "order": 10,
2640
+ "additionalProperties": {
2641
+ "icon": "folder-users"
2642
+ }
2643
+ }`,
2644
+ response: `{
2645
+ "id": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
2646
+ "name": "Customer Success",
2647
+ "order": 10,
2648
+ "isRoot": false,
2649
+ "resourceCount": 0,
2650
+ "resources": [],
2651
+ "additionalProperties": {
2652
+ "icon": "folder-users"
2653
+ }
2654
+ }`
2655
+ },
2656
+ {
2657
+ description: "Minimal create.",
2658
+ command: "zinkee --json teamspace folders create --name Shared",
2659
+ raw: `{
2660
+ "name": "Shared"
2661
+ }`
2662
+ },
2663
+ {
2664
+ description: "Prominent folder with icon and color.",
2665
+ command: `zinkee --json teamspace folders create --name Executive --order 1 --props '{"icon":"crown","color":"gold"}'`,
2666
+ raw: `{
2667
+ "name": "Executive",
2668
+ "order": 1,
2669
+ "additionalProperties": {
2670
+ "icon": "crown",
2671
+ "color": "gold"
2672
+ }
2673
+ }`
2674
+ }
2675
+ ]),
2676
+ "teamspace folders update": buildCommandExamples([
2677
+ {
2678
+ description: "Rename, reorder and update properties in one call.",
2679
+ command: `zinkee --json teamspace folders update "Customer Success" --name "Shared KPIs" --order 5 --props '{"icon":"chart-bar"}'`,
2680
+ raw: `{
2681
+ "name": "Shared KPIs",
2682
+ "order": 5,
2683
+ "additionalProperties": {
2684
+ "icon": "chart-bar"
2685
+ }
2686
+ }`,
2687
+ response: `{
2688
+ "id": "f45a251d-3ea0-4b41-bfe8-c0f44c8ad54a",
2689
+ "name": "Shared KPIs",
2690
+ "order": 5,
2691
+ "isRoot": false,
2692
+ "resourceCount": 1,
2693
+ "resources": [
2694
+ {
2695
+ "id": "0f6f062f-1478-4df2-96a1-c495d037d260",
2696
+ "name": "Executive Revenue",
2697
+ "type": "DISPLAY"
2698
+ }
2699
+ ],
2700
+ "additionalProperties": {
2701
+ "icon": "chart-bar"
2702
+ }
2703
+ }`
2704
+ },
2705
+ {
2706
+ description: "Rename only.",
2707
+ command: 'zinkee --json teamspace folders update "Customer Success" --name "Shared Analytics"',
2708
+ raw: `{
2709
+ "name": "Shared Analytics"
2710
+ }`
2711
+ },
2712
+ {
2713
+ description: "Reorder only.",
2714
+ command: 'zinkee --json teamspace folders update "Customer Success" --order 2',
2715
+ raw: `{
2716
+ "order": 2
2717
+ }`
2718
+ },
2719
+ {
2720
+ description: "Update only the icon metadata.",
2721
+ command: `zinkee --json teamspace folders update "Customer Success" --props '{"icon":"chart-line"}'`,
2722
+ raw: `{
2723
+ "additionalProperties": {
2724
+ "icon": "chart-line"
2725
+ }
2726
+ }`
2727
+ }
2728
+ ]),
2729
+ "teamspace resources publish": buildCommandExamples([
2730
+ {
2731
+ description: "Publish a schema by slug into a teamspace folder.",
2732
+ command: 'zinkee --json teamspace resources publish customer-records --to "Shared Dashboards"',
2733
+ raw: `{
2734
+ "resourceId": "customer-records",
2735
+ "targetFolderId": "f45a251d-3ea0-4b41-bfe8-c0f44c8ad54a"
2736
+ }`,
2737
+ response: `{
2738
+ "resourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
2739
+ "targetFolder": {
2740
+ "id": "f45a251d-3ea0-4b41-bfe8-c0f44c8ad54a",
2741
+ "name": "Shared Dashboards",
2742
+ "isRoot": false
2743
+ },
2744
+ "previousFolder": null
2745
+ }`
2746
+ },
2747
+ {
2748
+ description: "Publish a schema by UUID.",
2749
+ command: 'zinkee --json teamspace resources publish 2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e --to "Shared Dashboards"',
2750
+ raw: `{
2751
+ "resourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
2752
+ "targetFolderId": "f45a251d-3ea0-4b41-bfe8-c0f44c8ad54a"
2753
+ }`
2754
+ },
2755
+ {
2756
+ description: "Publish a display.",
2757
+ command: 'zinkee --json teamspace resources publish 0f6f062f-1478-4df2-96a1-c495d037d260 --to "Shared Dashboards"',
2758
+ raw: `{
2759
+ "resourceId": "0f6f062f-1478-4df2-96a1-c495d037d260",
2760
+ "targetFolderId": "f45a251d-3ea0-4b41-bfe8-c0f44c8ad54a"
2761
+ }`
2762
+ },
2763
+ {
2764
+ description: "Publish directly at the teamspace root (root folder UUID is always 00000000-0000-0000-0000-000000000000).",
2765
+ command: "zinkee --json teamspace resources publish customer-records --to 00000000-0000-0000-0000-000000000000",
2766
+ raw: `{
2767
+ "resourceId": "customer-records",
2768
+ "targetFolderId": "00000000-0000-0000-0000-000000000000"
2769
+ }`
2770
+ }
2771
+ ]),
2772
+ "teamspace resources unpublish": buildCommandExamples([
2773
+ {
2774
+ description: "Unpublish a schema by slug.",
2775
+ command: "zinkee --json teamspace resources unpublish customer-records",
2776
+ raw: `{
2777
+ "resourceId": "customer-records"
2778
+ }`,
2779
+ response: `{
2780
+ "resourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
2781
+ "removedFromFolder": {
2782
+ "id": "f45a251d-3ea0-4b41-bfe8-c0f44c8ad54a",
2783
+ "name": "Shared Dashboards",
2784
+ "isRoot": false
2785
+ }
2786
+ }`
2787
+ },
2788
+ {
2789
+ description: "Unpublish a schema by UUID.",
2790
+ command: "zinkee --json teamspace resources unpublish 2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
2791
+ raw: `{
2792
+ "resourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e"
2793
+ }`
2794
+ },
2795
+ {
2796
+ description: "Unpublish a display.",
2797
+ command: "zinkee --json teamspace resources unpublish 0f6f062f-1478-4df2-96a1-c495d037d260",
2798
+ raw: `{
2799
+ "resourceId": "0f6f062f-1478-4df2-96a1-c495d037d260"
2800
+ }`
2801
+ }
2802
+ ]),
2803
+ "displays create": buildCommandExamples([
2804
+ {
2805
+ description: "Create a freeform display with an initial widget layout. Freeform layouts travel through --freeform-layouts.",
2806
+ command: `zinkee --json displays create --name "Control Proyecto Freeform" --template freeform --freeform-layouts '{"lg":[{"i":"widget-1","x":0,"y":0,"w":6,"h":5}]}'`,
2807
+ raw: `{
2808
+ "name": "Control Proyecto Freeform",
2809
+ "layout": {
2810
+ "template": "freeform",
2811
+ "freeformLayouts": {
2812
+ "lg": [
2813
+ { "i": "widget-1", "x": 0, "y": 0, "w": 6, "h": 5 }
2814
+ ]
2815
+ }
2816
+ }
2817
+ }`,
2818
+ response: `{
2819
+ "displayId": "0f6f062f-1478-4df2-96a1-c495d037d260"
2820
+ }`
2821
+ },
2822
+ {
2823
+ description: "Create a tabbed display using the widget_row_tabs template.",
2824
+ command: 'zinkee --json displays create --name "Executive Revenue" --template widget_row_tabs',
2825
+ raw: `{
2826
+ "name": "Executive Revenue",
2827
+ "layout": {
2828
+ "template": "widget_row_tabs"
2829
+ }
2830
+ }`
2831
+ },
2832
+ {
2833
+ description: "Create a grid display.",
2834
+ command: 'zinkee --json displays create --name "Customer Detail" --template grid',
2835
+ raw: `{
2836
+ "name": "Customer Detail",
2837
+ "layout": {
2838
+ "template": "grid"
2839
+ }
2840
+ }`
2841
+ }
2842
+ ]),
2843
+ "displays tabs create": buildCommandExamples([
2844
+ {
2845
+ description: "Create a horizontal tab.",
2846
+ command: "zinkee --json displays tabs create 0f6f062f-1478-4df2-96a1-c495d037d260 --name Overview --orientation horizontal",
2847
+ raw: `{
2848
+ "name": "Overview",
2849
+ "orientation": "horizontal"
2850
+ }`,
2851
+ response: `{
2852
+ "displayId": "0f6f062f-1478-4df2-96a1-c495d037d260",
2853
+ "tabId": "tab-overview"
2854
+ }`
2855
+ },
2856
+ {
2857
+ description: "Create a vertical tab.",
2858
+ command: "zinkee --json displays tabs create 0f6f062f-1478-4df2-96a1-c495d037d260 --name Details --orientation vertical",
2859
+ raw: `{
2860
+ "name": "Details",
2861
+ "orientation": "vertical"
2862
+ }`
2863
+ }
2864
+ ]),
2865
+ "displays tabs update": buildCommandExamples([
2866
+ {
2867
+ description: "Rename a tab.",
2868
+ command: 'zinkee --json displays tabs update 0f6f062f-1478-4df2-96a1-c495d037d260 tab-main --name "Overview (renamed)"',
2869
+ raw: `{
2870
+ "name": "Overview (renamed)"
2871
+ }`,
2872
+ response: `{
2873
+ "displayId": "0f6f062f-1478-4df2-96a1-c495d037d260",
2874
+ "tabId": "tab-main"
2875
+ }`
2876
+ },
2877
+ {
2878
+ description: "Change orientation only.",
2879
+ command: "zinkee --json displays tabs update 0f6f062f-1478-4df2-96a1-c495d037d260 tab-main --orientation vertical",
2880
+ raw: `{
2881
+ "orientation": "vertical"
2882
+ }`
2883
+ },
2884
+ {
2885
+ description: "Rename and reorient at once.",
2886
+ command: "zinkee --json displays tabs update 0f6f062f-1478-4df2-96a1-c495d037d260 tab-main --name Details --orientation vertical",
2887
+ raw: `{
2888
+ "name": "Details",
2889
+ "orientation": "vertical"
2890
+ }`
2891
+ }
2892
+ ]),
2893
+ "displays variables create": buildCommandExamples([
2894
+ {
2895
+ description: "Create a single-select REFERENCE variable bound to a (schema, field) pair. schemaId and fieldId accept slugs or UUIDs.",
2896
+ command: 'zinkee --json displays variables create 0f6f062f-1478-4df2-96a1-c495d037d260 --type REFERENCE --name Customer --source-schema contacts --source-field contact-name --default ""',
2897
+ raw: `{
2898
+ "type": "REFERENCE",
2899
+ "name": "Customer",
2900
+ "source": {
2901
+ "schemaId": "contacts",
2902
+ "fieldId": "contact-name"
2903
+ },
2904
+ "defaultValue": "",
2905
+ "allowMultiple": false,
2906
+ "staticVariable": false,
2907
+ "filters": []
2908
+ }`,
2909
+ response: `{
2910
+ "displayId": "0f6f062f-1478-4df2-96a1-c495d037d260",
2911
+ "variableId": "aaaaaaaa-1111-4111-a111-111111111111"
2912
+ }`
2913
+ },
2914
+ {
2915
+ description: "Create a multi-select REFERENCE variable with a filter. Complex filters go via --raw because --filter only accepts raw expressions.",
2916
+ command: `zinkee --json displays variables create 0f6f062f-1478-4df2-96a1-c495d037d260 --raw '{"type":"REFERENCE","name":"Active customers","source":{"schemaId":"contacts","fieldId":"contact-name"},"defaultValues":[],"allowMultiple":true,"staticVariable":false,"filters":[{"origin":{"schemaId":"contacts","fieldId":"status"},"comparisonOperator":"ANY_OF","values":["1","2"]}]}'`,
2917
+ raw: `{
2918
+ "type": "REFERENCE",
2919
+ "name": "Active customers",
2920
+ "source": {
2921
+ "schemaId": "contacts",
2922
+ "fieldId": "contact-name"
2923
+ },
2924
+ "defaultValues": [],
2925
+ "allowMultiple": true,
2926
+ "staticVariable": false,
2927
+ "filters": [
2928
+ {
2929
+ "origin": {
2930
+ "schemaId": "contacts",
2931
+ "fieldId": "status"
2932
+ },
2933
+ "comparisonOperator": "ANY_OF",
2934
+ "values": ["1", "2"]
2935
+ }
2936
+ ]
2937
+ }`
2938
+ },
2939
+ {
2940
+ description: "Create a MEMBER variable with a default user id.",
2941
+ command: "zinkee --json displays variables create 0f6f062f-1478-4df2-96a1-c495d037d260 --type MEMBER --name Owner --default 6c8a3e0d-4e5f-4a1b-9c2d-3e4f5a6b7c8d",
2942
+ raw: `{
2943
+ "type": "MEMBER",
2944
+ "name": "Owner",
2945
+ "defaultValue": "6c8a3e0d-4e5f-4a1b-9c2d-3e4f5a6b7c8d",
2946
+ "allowMultiple": false,
2947
+ "staticVariable": false
2948
+ }`
2949
+ },
2950
+ {
2951
+ description: "Create a DATE variable using a dynamic period (thisMonth).",
2952
+ command: "zinkee --json displays variables create 0f6f062f-1478-4df2-96a1-c495d037d260 --type DATE --name Period --date-mode dynamic --date-dynamic-option thisMonth",
2953
+ raw: `{
2954
+ "type": "DATE",
2955
+ "name": "Period",
2956
+ "date": {
2957
+ "mode": "dynamic",
2958
+ "dynamicOption": "thisMonth"
2959
+ }
2960
+ }`
2961
+ },
2962
+ {
2963
+ description: "Create a DATE variable with a specific date.",
2964
+ command: "zinkee --json displays variables create 0f6f062f-1478-4df2-96a1-c495d037d260 --type DATE --name Cutoff --date-mode specific --date-specific 2026-04-22",
2965
+ raw: `{
2966
+ "type": "DATE",
2967
+ "name": "Cutoff",
2968
+ "date": {
2969
+ "mode": "specific",
2970
+ "specificDate": "2026-04-22"
2971
+ }
2972
+ }`
2973
+ },
2974
+ {
2975
+ description: "Create a DATE variable with a custom range.",
2976
+ command: "zinkee --json displays variables create 0f6f062f-1478-4df2-96a1-c495d037d260 --type DATE --name Quarter --date-mode range --date-range-start 2026-04-01 --date-range-end 2026-06-30",
2977
+ raw: `{
2978
+ "type": "DATE",
2979
+ "name": "Quarter",
2980
+ "date": {
2981
+ "mode": "range",
2982
+ "rangeStart": "2026-04-01",
2983
+ "rangeEnd": "2026-06-30"
2984
+ }
2985
+ }`
2986
+ }
2987
+ ]),
2988
+ "displays variables update": buildCommandExamples([
2989
+ {
2990
+ description: "Rename the variable and make it static (defaults must be cleared with a raw patch because the CLI has no --default-values [] shortcut).",
2991
+ command: `zinkee --json displays variables update 0f6f062f-1478-4df2-96a1-c495d037d260 aaaaaaaa-1111-4111-a111-111111111111 --raw '{"name":"Proyecto principal","staticVariable":true,"defaultValues":[]}'`,
2992
+ raw: `{
2993
+ "name": "Proyecto principal",
2994
+ "staticVariable": true,
2995
+ "defaultValues": []
2996
+ }`,
2997
+ response: `{
2998
+ "displayId": "0f6f062f-1478-4df2-96a1-c495d037d260",
2999
+ "variableId": "aaaaaaaa-1111-4111-a111-111111111111"
3000
+ }`
3001
+ },
3002
+ {
3003
+ description: "Replace the reference filters of the variable.",
3004
+ command: `zinkee --json displays variables update 0f6f062f-1478-4df2-96a1-c495d037d260 aaaaaaaa-1111-4111-a111-111111111111 --raw '{"filters":[{"origin":{"schemaId":"contacts","fieldId":"status"},"comparisonOperator":"ANY_OF","values":["2","3"]}]}'`,
3005
+ raw: `{
3006
+ "filters": [
3007
+ {
3008
+ "origin": {
3009
+ "schemaId": "contacts",
3010
+ "fieldId": "status"
3011
+ },
3012
+ "comparisonOperator": "ANY_OF",
3013
+ "values": ["2", "3"]
3014
+ }
3015
+ ]
3016
+ }`
3017
+ },
3018
+ {
3019
+ description: "Switch a variable to multi-select.",
3020
+ command: `zinkee --json displays variables update 0f6f062f-1478-4df2-96a1-c495d037d260 aaaaaaaa-1111-4111-a111-111111111111 --allow-multiple --raw '{"defaultValues":[]}'`,
3021
+ raw: `{
3022
+ "allowMultiple": true,
3023
+ "defaultValues": []
3024
+ }`
3025
+ },
3026
+ {
3027
+ description: "Change a DATE variable to use lastWeek.",
3028
+ command: "zinkee --json displays variables update 0f6f062f-1478-4df2-96a1-c495d037d260 bbbbbbbb-2222-4222-a222-222222222222 --date-mode dynamic --date-dynamic-option lastWeek",
3029
+ raw: `{
3030
+ "date": {
3031
+ "mode": "dynamic",
3032
+ "dynamicOption": "lastWeek"
3033
+ }
3034
+ }`
3035
+ }
3036
+ ]),
3037
+ "displays widgets create": buildCommandExamples([
3038
+ {
3039
+ description: "Create a TABLE widget (CLI normalises --type table to TABLE_OR_SUBTABLE).",
3040
+ command: `zinkee --json displays widgets create 0f6f062f-1478-4df2-96a1-c495d037d260 --type table --name Customers --origin-resource 2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e --layout '{"x":0,"y":0,"w":12,"h":8}' --field id --field contact-name --field status --sort '{"fieldId":"id","direction":"DESC"}'`,
3041
+ raw: `{
3042
+ "type": "TABLE_OR_SUBTABLE",
3043
+ "source": {
3044
+ "originResourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
3045
+ "isOriginSubSchema": false
3046
+ },
3047
+ "placement": {
3048
+ "layout": { "x": 0, "y": 0, "w": 12, "h": 8 }
3049
+ },
3050
+ "presentation": {
3051
+ "name": "Customers"
3052
+ },
3053
+ "query": {
3054
+ "sorts": [
3055
+ { "fieldId": "id", "direction": "DESC" }
3056
+ ]
3057
+ },
3058
+ "view": {
3059
+ "fields": ["id", "contact-name", "status"]
3060
+ }
3061
+ }`,
3062
+ response: `{
3063
+ "displayId": "0f6f062f-1478-4df2-96a1-c495d037d260",
3064
+ "widgetId": "11111111-1111-4111-a111-111111111111"
3065
+ }`
3066
+ },
3067
+ {
3068
+ description: "Create a DETAIL widget on a tab. The rich placement is easier via --raw.",
3069
+ command: `zinkee --json displays widgets create 0f6f062f-1478-4df2-96a1-c495d037d260 --raw '{"type":"DETAIL","source":{"originResourceId":"2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e","isOriginSubSchema":false},"placement":{"tabId":"tab-detail","layout":{"x":0,"y":0,"w":6,"h":10}},"presentation":{"name":"Customer detail"},"behavior":{"readOnly":true},"view":{"fields":["contact-name","contact-email","status","amount"]}}'`,
3070
+ raw: `{
3071
+ "type": "DETAIL",
3072
+ "source": {
3073
+ "originResourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
3074
+ "isOriginSubSchema": false
3075
+ },
3076
+ "placement": {
3077
+ "tabId": "tab-detail",
3078
+ "layout": { "x": 0, "y": 0, "w": 6, "h": 10 }
3079
+ },
3080
+ "presentation": { "name": "Customer detail" },
3081
+ "behavior": { "readOnly": true },
3082
+ "view": {
3083
+ "fields": ["contact-name", "contact-email", "status", "amount"]
3084
+ }
3085
+ }`
3086
+ },
3087
+ {
3088
+ description: "Create a KPI widget computing SUM(amount).",
3089
+ command: `zinkee --json displays widgets create 0f6f062f-1478-4df2-96a1-c495d037d260 --type KPI --name "Total revenue" --origin-resource 2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e --layout '{"x":0,"y":0,"w":3,"h":3}' --calc SUM --calc-field amount --kpi-config '{"format":"currency","decimals":2}'`,
3090
+ raw: `{
3091
+ "type": "KPI",
3092
+ "source": {
3093
+ "originResourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
3094
+ "isOriginSubSchema": false
3095
+ },
3096
+ "placement": {
3097
+ "layout": { "x": 0, "y": 0, "w": 3, "h": 3 }
3098
+ },
3099
+ "presentation": { "name": "Total revenue" },
3100
+ "kpi": {
3101
+ "typeCalc": "SUM",
3102
+ "fieldCalc": "amount",
3103
+ "config": { "format": "currency", "decimals": 2 }
3104
+ }
3105
+ }`
3106
+ },
3107
+ {
3108
+ description: "Create a bar CHART widget with a time-serie x-axis and two y-axis series.",
3109
+ 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 bar --x-axis-field due-date --x-axis-date-format MONTH --x-axis-time-series --y-axis-serie '{"typeCalc":"SUM","fieldCalc":"amount","color":"#4B9CD3","axisType":"BAR"}' --y-axis-serie '{"typeCalc":"COUNT","fieldCalc":"id","color":"#E57373","axisType":"LINE"}' --legend '{"position":"bottom"}'`,
3110
+ raw: `{
3111
+ "type": "CHART",
3112
+ "source": {
3113
+ "originResourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
3114
+ "isOriginSubSchema": false
3115
+ },
3116
+ "placement": {
3117
+ "layout": { "x": 0, "y": 0, "w": 8, "h": 6 }
3118
+ },
3119
+ "presentation": { "name": "Revenue by month" },
3120
+ "chart": {
3121
+ "chartType": "bar",
3122
+ "xAxisFieldId": "due-date",
3123
+ "xAxisDateFormat": "MONTH",
3124
+ "xAxisAsTimeSerie": true,
3125
+ "yAxisSeries": [
3126
+ {
3127
+ "typeCalc": "SUM",
3128
+ "fieldCalc": "amount",
3129
+ "color": "#4B9CD3",
3130
+ "axisType": "BAR"
3131
+ },
3132
+ {
3133
+ "typeCalc": "COUNT",
3134
+ "fieldCalc": "id",
3135
+ "color": "#E57373",
3136
+ "axisType": "LINE"
3137
+ }
3138
+ ],
3139
+ "legend": { "position": "bottom" }
3140
+ }
3141
+ }`
3142
+ },
3143
+ {
3144
+ description: "Create a TIMELINE widget.",
3145
+ command: `zinkee --json displays widgets create 0f6f062f-1478-4df2-96a1-c495d037d260 --type TIMELINE --name "Customer schedule" --origin-resource 2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e --layout '{"x":0,"y":0,"w":12,"h":6}' --field contact-name --field due-date`,
3146
+ raw: `{
3147
+ "type": "TIMELINE",
3148
+ "source": {
3149
+ "originResourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
3150
+ "isOriginSubSchema": false
3151
+ },
3152
+ "placement": {
3153
+ "layout": { "x": 0, "y": 0, "w": 12, "h": 6 }
3154
+ },
3155
+ "presentation": { "name": "Customer schedule" },
3156
+ "view": {
3157
+ "fields": ["contact-name", "due-date"]
3158
+ }
3159
+ }`
3160
+ },
3161
+ {
3162
+ description: "Create a KANBAN widget with a status filter and groupsExpanded config (rich query/view requires --raw).",
3163
+ command: `zinkee --json displays widgets create 0f6f062f-1478-4df2-96a1-c495d037d260 --raw '{"type":"KANBAN","source":{"originResourceId":"2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e","isOriginSubSchema":false},"placement":{"layout":{"x":0,"y":0,"w":12,"h":8}},"presentation":{"name":"Status board"},"query":{"filters":[{"origin":{"schemaId":"contacts","fieldId":"status"},"comparisonOperator":"ANY_OF","values":["1","2","3"]}]},"view":{"fields":["contact-name","status","amount"],"groupsExpanded":{"1":true,"2":true,"3":false}}}'`,
3164
+ raw: `{
3165
+ "type": "KANBAN",
3166
+ "source": {
3167
+ "originResourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
3168
+ "isOriginSubSchema": false
3169
+ },
3170
+ "placement": {
3171
+ "layout": { "x": 0, "y": 0, "w": 12, "h": 8 }
3172
+ },
3173
+ "presentation": { "name": "Status board" },
3174
+ "query": {
3175
+ "filters": [
3176
+ {
3177
+ "origin": {
3178
+ "schemaId": "contacts",
3179
+ "fieldId": "status"
3180
+ },
3181
+ "comparisonOperator": "ANY_OF",
3182
+ "values": ["1", "2", "3"]
3183
+ }
3184
+ ]
3185
+ },
3186
+ "view": {
3187
+ "fields": ["contact-name", "status", "amount"],
3188
+ "groupsExpanded": { "1": true, "2": true, "3": false }
3189
+ }
3190
+ }`
3191
+ },
3192
+ {
3193
+ description: "Create a HIERARCHY widget rooted on a parent field.",
3194
+ command: `zinkee --json displays widgets create 0f6f062f-1478-4df2-96a1-c495d037d260 --raw '{"type":"HIERARCHY","source":{"originResourceId":"2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e","isOriginSubSchema":false},"placement":{"layout":{"x":0,"y":0,"w":12,"h":6}},"presentation":{"name":"Org tree"},"view":{"fields":["contact-name","status"],"hierarchyConfig":{"parentFieldId":"contact-name"}}}'`,
3195
+ raw: `{
3196
+ "type": "HIERARCHY",
3197
+ "source": {
3198
+ "originResourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
3199
+ "isOriginSubSchema": false
3200
+ },
3201
+ "placement": {
3202
+ "layout": { "x": 0, "y": 0, "w": 12, "h": 6 }
3203
+ },
3204
+ "presentation": { "name": "Org tree" },
3205
+ "view": {
3206
+ "fields": ["contact-name", "status"],
3207
+ "hierarchyConfig": {
3208
+ "parentFieldId": "contact-name"
3209
+ }
3210
+ }
3211
+ }`
3212
+ }
3213
+ ]),
3214
+ "displays widgets update": buildCommandExamples([
3215
+ {
3216
+ description: "Move placement, update view columns, rename the widget and lock it.",
3217
+ command: `zinkee --json displays widgets update 0f6f062f-1478-4df2-96a1-c495d037d260 11111111-1111-4111-a111-111111111111 --layout '{"x":1,"y":2,"w":8,"h":4}' --field id --field contact-name --field status --name "Revenue Updated" --widget-read-only`,
3218
+ raw: `{
3219
+ "placement": {
3220
+ "layout": { "x": 1, "y": 2, "w": 8, "h": 4 }
3221
+ },
3222
+ "view": {
3223
+ "fields": ["id", "contact-name", "status"]
3224
+ },
3225
+ "presentation": { "name": "Revenue Updated" },
3226
+ "behavior": { "readOnly": true }
3227
+ }`,
3228
+ response: `{
3229
+ "displayId": "0f6f062f-1478-4df2-96a1-c495d037d260",
3230
+ "widgetId": "11111111-1111-4111-a111-111111111111"
3231
+ }`
3232
+ },
3233
+ {
3234
+ description: "Add query filters that match the full comparisonOperator contract (requires --raw because --filter only accepts free-form expressions).",
3235
+ 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"]}]}}'`,
3236
+ raw: `{
3237
+ "query": {
3238
+ "filters": [
3239
+ {
3240
+ "origin": {
3241
+ "schemaId": "contacts",
3242
+ "fieldId": "status"
3243
+ },
3244
+ "comparisonOperator": "EQUAL",
3245
+ "values": ["2"]
3246
+ },
3247
+ {
3248
+ "origin": {
3249
+ "schemaId": "contacts",
3250
+ "fieldId": "amount"
3251
+ },
3252
+ "comparisonOperator": "GREATER_OR_EQUAL",
3253
+ "values": ["500"]
3254
+ }
3255
+ ]
3256
+ }
3257
+ }`
3258
+ },
3259
+ {
3260
+ description: "Hide the add, delete and filter buttons.",
3261
+ command: "zinkee --json displays widgets update 0f6f062f-1478-4df2-96a1-c495d037d260 11111111-1111-4111-a111-111111111111 --hide-add-button --hide-delete-button --hide-filter-button",
3262
+ raw: `{
3263
+ "behavior": {
3264
+ "hideAddButton": true,
3265
+ "hideDeleteButton": true,
3266
+ "hideFilterButton": true
3267
+ }
3268
+ }`
3269
+ },
3270
+ {
3271
+ description: "Update the KPI aggregation to AVG with one-decimal format.",
3272
+ command: `zinkee --json displays widgets update 0f6f062f-1478-4df2-96a1-c495d037d260 33333333-3333-4333-a333-333333333333 --calc AVG --calc-field amount --kpi-config '{"format":"number","decimals":1}'`,
3273
+ raw: `{
3274
+ "kpi": {
3275
+ "typeCalc": "AVG",
3276
+ "fieldCalc": "amount",
3277
+ "config": { "format": "number", "decimals": 1 }
3278
+ }
3279
+ }`
3280
+ },
3281
+ {
3282
+ description: "Replace the chart series with a weekly line.",
3283
+ command: `zinkee --json displays widgets update 0f6f062f-1478-4df2-96a1-c495d037d260 22222222-2222-4222-a222-222222222222 --chart-type line --x-axis-field due-date --x-axis-date-format WEEK --x-axis-time-series --y-axis-serie '{"typeCalc":"SUM","fieldCalc":"amount","color":"#2E7D32","axisType":"LINE"}'`,
3284
+ raw: `{
3285
+ "chart": {
3286
+ "chartType": "line",
3287
+ "xAxisFieldId": "due-date",
3288
+ "xAxisDateFormat": "WEEK",
3289
+ "xAxisAsTimeSerie": true,
3290
+ "yAxisSeries": [
3291
+ {
3292
+ "typeCalc": "SUM",
3293
+ "fieldCalc": "amount",
3294
+ "color": "#2E7D32",
3295
+ "axisType": "LINE"
3296
+ }
3297
+ ]
3298
+ }
3299
+ }`
3300
+ },
3301
+ {
3302
+ description: "Rewrite the widget bindings (requires --raw because the CLI has no --binding flag).",
3303
+ command: `zinkee --json displays widgets update 0f6f062f-1478-4df2-96a1-c495d037d260 11111111-1111-4111-a111-111111111111 --raw '{"bindings":{"variableMap":{"aaaaaaaa-1111-4111-a111-111111111111":"contact-name","cccccccc-3333-4333-a333-333333333333":"owner"}}}'`,
3304
+ raw: `{
3305
+ "bindings": {
3306
+ "variableMap": {
3307
+ "aaaaaaaa-1111-4111-a111-111111111111": "contact-name",
3308
+ "cccccccc-3333-4333-a333-333333333333": "owner"
3309
+ }
3310
+ }
3311
+ }`
3312
+ }
3313
+ ]),
3314
+ "displays navigation-targets create": buildCommandExamples([
3315
+ {
3316
+ description: "Create a navigation target with a visible label.",
3317
+ command: 'zinkee --json displays navigation-targets create 0f6f062f-1478-4df2-96a1-c495d037d260 --source-widget 11111111-1111-4111-a111-111111111111 --target-display ef012345-6789-4abc-8def-0123456789ab --target-variable aaaaaaaa-1111-4111-a111-111111111111 --label "Open customer"',
3318
+ raw: `{
3319
+ "sourceWidgetId": "11111111-1111-4111-a111-111111111111",
3320
+ "targetDisplayId": "ef012345-6789-4abc-8def-0123456789ab",
3321
+ "targetVariableId": "aaaaaaaa-1111-4111-a111-111111111111",
3322
+ "label": "Open customer"
3323
+ }`,
3324
+ response: `{
3325
+ "displayId": "0f6f062f-1478-4df2-96a1-c495d037d260",
3326
+ "navigationTargetId": "nav-target-customer"
3327
+ }`
3328
+ },
3329
+ {
3330
+ description: "Create a navigation target without a label (uses the target display name).",
3331
+ command: "zinkee --json displays navigation-targets create 0f6f062f-1478-4df2-96a1-c495d037d260 --source-widget 22222222-2222-4222-a222-222222222222 --target-display ef012345-6789-4abc-8def-0123456789ab --target-variable aaaaaaaa-1111-4111-a111-111111111111",
3332
+ raw: `{
3333
+ "sourceWidgetId": "22222222-2222-4222-a222-222222222222",
3334
+ "targetDisplayId": "ef012345-6789-4abc-8def-0123456789ab",
3335
+ "targetVariableId": "aaaaaaaa-1111-4111-a111-111111111111"
3336
+ }`
3337
+ }
3338
+ ]),
3339
+ "displays navigation-targets update": buildCommandExamples([
3340
+ {
3341
+ description: "Change just the label.",
3342
+ command: 'zinkee --json displays navigation-targets update 0f6f062f-1478-4df2-96a1-c495d037d260 nav-target-customer --label "Go to customer"',
3343
+ raw: `{
3344
+ "label": "Go to customer"
3345
+ }`,
3346
+ response: `{
3347
+ "displayId": "0f6f062f-1478-4df2-96a1-c495d037d260",
3348
+ "navigationTargetId": "nav-target-customer"
3349
+ }`
3350
+ },
3351
+ {
3352
+ description: "Redirect the target to another display/variable pair.",
3353
+ command: "zinkee --json displays navigation-targets update 0f6f062f-1478-4df2-96a1-c495d037d260 nav-target-customer --target-display 6b7c8d9e-0f12-3456-789a-bcdef0123456 --target-variable bbbbbbbb-2222-4222-a222-222222222222",
3354
+ raw: `{
3355
+ "targetDisplayId": "6b7c8d9e-0f12-3456-789a-bcdef0123456",
3356
+ "targetVariableId": "bbbbbbbb-2222-4222-a222-222222222222"
3357
+ }`
3358
+ },
3359
+ {
3360
+ description: "Change the source widget.",
3361
+ command: "zinkee --json displays navigation-targets update 0f6f062f-1478-4df2-96a1-c495d037d260 nav-target-customer --source-widget 44444444-4444-4444-a444-444444444444",
3362
+ raw: `{
3363
+ "sourceWidgetId": "44444444-4444-4444-a444-444444444444"
3364
+ }`
3365
+ }
3366
+ ]),
3367
+ "displays cross-widget-filter set": buildCommandExamples([
3368
+ {
3369
+ description: "Link one source widget/field to several target widgets through the same field.",
3370
+ command: "zinkee --json displays cross-widget-filter set 0f6f062f-1478-4df2-96a1-c495d037d260 --source-widget 11111111-1111-4111-a111-111111111111 --source-field c60b8526-5835-4c9f-aecd-9a16c7704a34 --target 22222222-2222-4222-a222-222222222222:c60b8526-5835-4c9f-aecd-9a16c7704a34 --target 33333333-3333-4333-a333-333333333333:c60b8526-5835-4c9f-aecd-9a16c7704a34",
3371
+ raw: `{
3372
+ "source": {
3373
+ "widgetId": "11111111-1111-4111-a111-111111111111",
3374
+ "fieldId": "c60b8526-5835-4c9f-aecd-9a16c7704a34"
3375
+ },
3376
+ "targets": [
3377
+ {
3378
+ "widgetId": "22222222-2222-4222-a222-222222222222",
3379
+ "fieldId": "c60b8526-5835-4c9f-aecd-9a16c7704a34"
3380
+ },
3381
+ {
3382
+ "widgetId": "33333333-3333-4333-a333-333333333333",
3383
+ "fieldId": "c60b8526-5835-4c9f-aecd-9a16c7704a34"
3384
+ }
3385
+ ]
3386
+ }`
3387
+ },
3388
+ {
3389
+ description: "Filter one target widget by the status field of the source.",
3390
+ command: "zinkee --json displays cross-widget-filter set 0f6f062f-1478-4df2-96a1-c495d037d260 --source-widget 11111111-1111-4111-a111-111111111111 --source-field a8f1d7e3-2b5c-4d9e-8a1b-3c4d5e6f7890 --target 66666666-6666-4666-a666-666666666666:a8f1d7e3-2b5c-4d9e-8a1b-3c4d5e6f7890",
3391
+ raw: `{
3392
+ "source": {
3393
+ "widgetId": "11111111-1111-4111-a111-111111111111",
3394
+ "fieldId": "a8f1d7e3-2b5c-4d9e-8a1b-3c4d5e6f7890"
3395
+ },
3396
+ "targets": [
3397
+ {
3398
+ "widgetId": "66666666-6666-4666-a666-666666666666",
3399
+ "fieldId": "a8f1d7e3-2b5c-4d9e-8a1b-3c4d5e6f7890"
3400
+ }
3401
+ ]
3402
+ }`
3403
+ }
3404
+ ]),
3405
+ "schemas list": buildCommandExamples([
3406
+ {
3407
+ description: "List schemas in the workspace with folder and field counts.",
3408
+ command: "zinkee --json schemas list",
3409
+ response: `[
3410
+ {
3411
+ "id": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
3412
+ "name": "Contacts",
3413
+ "slug": "contacts",
3414
+ "folder": {
3415
+ "id": "7f4e7c25-d8b2-4c1a-9f3e-6a7b5c8d9e1f",
3416
+ "name": "Customers",
3417
+ "isRoot": false
3418
+ },
3419
+ "auditable": false,
3420
+ "commentable": false,
3421
+ "fieldCount": 11
3422
+ },
3423
+ {
3424
+ "id": "5223cbc8-8c6c-4694-93bc-dd176364df9b",
3425
+ "name": "Orders",
3426
+ "slug": "orders",
3427
+ "folder": {
3428
+ "id": "00000000-0000-0000-0000-000000000000",
3429
+ "name": "root",
3430
+ "isRoot": true
3431
+ },
3432
+ "auditable": true,
3433
+ "commentable": true,
3434
+ "fieldCount": 7
3435
+ }
3436
+ ]`
3437
+ }
3438
+ ]),
3439
+ "schemas get": buildCommandExamples([
3440
+ {
3441
+ description: "Get a schema with all its fields.",
3442
+ command: "zinkee --json schemas get contacts",
3443
+ response: `{
3444
+ "id": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
3445
+ "name": "Contacts",
3446
+ "slug": "contacts",
3447
+ "folder": {
3448
+ "id": "7f4e7c25-d8b2-4c1a-9f3e-6a7b5c8d9e1f",
3449
+ "name": "Customers",
3450
+ "isRoot": false
3451
+ },
3452
+ "auditable": true,
3453
+ "commentable": true,
3454
+ "fields": [
3455
+ {
3456
+ "id": "c60b8526-5835-4c9f-aecd-9a16c7704a34",
3457
+ "type": "TextField",
3458
+ "slug": "contact-name",
3459
+ "label": "Customer Name",
3460
+ "required": true,
3461
+ "system": false,
3462
+ "config": {
3463
+ "textType": "LONG",
3464
+ "defaultValue": "Unknown",
3465
+ "conditionalFormatting": []
3466
+ }
3467
+ },
3468
+ {
3469
+ "id": "a8f1d7e3-2b5c-4d9e-8a1b-3c4d5e6f7890",
3470
+ "type": "OptionField",
3471
+ "slug": "status",
3472
+ "label": "Status",
3473
+ "required": false,
3474
+ "system": false,
3475
+ "config": {
3476
+ "options": [
3477
+ { "id": 1, "name": "Open", "color": "default" },
3478
+ { "id": 2, "name": "In Progress", "color": "warning" },
3479
+ { "id": 3, "name": "Done", "color": "success" }
3480
+ ],
3481
+ "defaultValue": 1,
3482
+ "conditionalFormatting": [],
3483
+ "buttonConfig": null
3484
+ }
3485
+ },
3486
+ {
3487
+ "id": "c52efe3f-2825-4c60-a7e3-34dd4c1ce043",
3488
+ "type": "NumberField",
3489
+ "slug": "amount",
3490
+ "label": "Amount",
3491
+ "required": false,
3492
+ "system": false,
3493
+ "config": {
3494
+ "defaultValue": "0",
3495
+ "formatOptions": {
3496
+ "format": "currency",
3497
+ "decimals": 2,
3498
+ "negativesInRed": true,
3499
+ "thousandsSeparator": true,
3500
+ "symbolEnabled": true,
3501
+ "symbolPosition": "before",
3502
+ "symbolValue": "\u20AC"
3503
+ },
3504
+ "conditionalFormatting": []
3505
+ }
3506
+ },
3507
+ {
3508
+ "id": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
3509
+ "type": "DateField",
3510
+ "slug": "due-date",
3511
+ "label": "Due Date",
3512
+ "required": false,
3513
+ "system": false,
3514
+ "config": {
3515
+ "defaultValue": null,
3516
+ "formatOptions": {
3517
+ "format": "datetime",
3518
+ "dateFormat": "DD/MM/YYYY",
3519
+ "showTime": true
3520
+ },
3521
+ "conditionalFormatting": []
3522
+ }
3523
+ },
3524
+ {
3525
+ "id": "a7b8c9d0-e1f2-3a4b-5c6d-7e8f90123456",
3526
+ "type": "MemberField",
3527
+ "slug": "owner",
3528
+ "label": "Owner",
3529
+ "required": false,
3530
+ "system": false,
3531
+ "config": {
3532
+ "defaultValue": null,
3533
+ "conditionalFormatting": []
3534
+ }
3535
+ }
3536
+ ]
3537
+ }`
3538
+ }
3539
+ ]),
3540
+ "schemas delete": buildCommandExamples([
3541
+ {
3542
+ description: "Delete a schema (also removes it from navigation folders).",
3543
+ command: "zinkee --json schemas delete contacts",
3544
+ response: `{
3545
+ "schemaId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
3546
+ "deleted": true
3547
+ }`
3548
+ }
3549
+ ]),
3550
+ "schemas fields list": buildCommandExamples([
3551
+ {
3552
+ description: "List the fields of a schema (fields are inlined in the schema resource).",
3553
+ command: "zinkee --json schemas fields list contacts",
3554
+ response: `[
3555
+ {
3556
+ "id": "c60b8526-5835-4c9f-aecd-9a16c7704a34",
3557
+ "type": "TextField",
3558
+ "slug": "contact-name",
3559
+ "label": "Customer Name",
3560
+ "required": true,
3561
+ "system": false,
3562
+ "config": {
3563
+ "textType": "LONG",
3564
+ "defaultValue": "Unknown",
3565
+ "conditionalFormatting": []
3566
+ }
3567
+ },
3568
+ {
3569
+ "id": "a8f1d7e3-2b5c-4d9e-8a1b-3c4d5e6f7890",
3570
+ "type": "OptionField",
3571
+ "slug": "status",
3572
+ "label": "Status",
3573
+ "required": false,
3574
+ "system": false,
3575
+ "config": {
3576
+ "options": [
3577
+ { "id": 1, "name": "Open", "color": "default" },
3578
+ { "id": 2, "name": "In Progress", "color": "warning" },
3579
+ { "id": 3, "name": "Done", "color": "success" }
3580
+ ],
3581
+ "defaultValue": 1,
3582
+ "conditionalFormatting": [],
3583
+ "buttonConfig": null
3584
+ }
3585
+ }
3586
+ ]`
3587
+ }
3588
+ ]),
3589
+ "schemas fields get": buildCommandExamples([
3590
+ {
3591
+ description: "Get a schema field (returns the full typed field contract).",
3592
+ command: "zinkee --json schemas fields get contacts status",
3593
+ response: `{
3594
+ "id": "a8f1d7e3-2b5c-4d9e-8a1b-3c4d5e6f7890",
3595
+ "type": "OptionField",
3596
+ "slug": "status",
3597
+ "label": "Status",
3598
+ "required": false,
3599
+ "system": false,
3600
+ "config": {
3601
+ "options": [
3602
+ { "id": 1, "name": "Open", "color": "default" },
3603
+ { "id": 2, "name": "In Progress", "color": "warning" },
3604
+ { "id": 3, "name": "Done", "color": "success" }
3605
+ ],
3606
+ "defaultValue": 1,
3607
+ "conditionalFormatting": [],
3608
+ "buttonConfig": {
3609
+ "displayMode": "button",
3610
+ "buttonBehavior": {
3611
+ "mode": "cycle",
3612
+ "cycleOrder": [1, 2, 3],
3613
+ "requireConfirmation": false,
3614
+ "lockAfterSelection": false,
3615
+ "useFixedLabel": false,
3616
+ "allowReselect": true
3617
+ }
3618
+ }
3619
+ }
3620
+ }`
3621
+ }
3622
+ ]),
3623
+ "schemas fields delete": buildCommandExamples([
3624
+ {
3625
+ description: "Delete a schema field.",
3626
+ command: "zinkee --json schemas fields delete contacts status",
3627
+ response: `{
3628
+ "schemaId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
3629
+ "fieldId": "a8f1d7e3-2b5c-4d9e-8a1b-3c4d5e6f7890",
3630
+ "slug": "status"
3631
+ }`
3632
+ }
3633
+ ]),
3634
+ "records list": buildCommandExamples([
3635
+ {
3636
+ description: "List records with default pagination.",
3637
+ command: "zinkee --json records list contacts",
3638
+ response: `{
3639
+ "records": [
3640
+ {
3641
+ "recordId": "550e8400-e29b-41d4-a716-446655440000",
3642
+ "values": {
3643
+ "contact-name": "Ada Lovelace",
3644
+ "contact-email": "ada@example.com",
3645
+ "status": 2,
3646
+ "amount": 1250.50,
3647
+ "due-date": "2026-05-15T12:00:00Z",
3648
+ "owner": "6c8a3e0d-4e5f-4a1b-9c2d-3e4f5a6b7c8d"
3649
+ }
3650
+ },
3651
+ {
3652
+ "recordId": "7c9a4b31-e85d-42f7-8b6a-123456789abc",
3653
+ "values": {
3654
+ "contact-name": "Alan Turing",
3655
+ "contact-email": "alan@example.com",
3656
+ "status": 1,
3657
+ "amount": 890.00
3658
+ }
3659
+ }
3660
+ ],
3661
+ "page": {
3662
+ "offset": 0,
3663
+ "limit": 50,
3664
+ "total": 2,
3665
+ "count": 2,
3666
+ "hasMore": false
3667
+ }
3668
+ }`
3669
+ },
3670
+ {
3671
+ description: "Paginate further into the result set.",
3672
+ command: "zinkee --json records list contacts --limit 50 --offset 100"
3673
+ }
3674
+ ]),
3675
+ "records get": buildCommandExamples([
3676
+ {
3677
+ description: "Get one record by id (values are keyed by field slug).",
3678
+ command: `zinkee --json records get contacts ${SAMPLE_UUID}`,
3679
+ response: `{
3680
+ "recordId": "550e8400-e29b-41d4-a716-446655440000",
3681
+ "values": {
3682
+ "contact-name": "Ada Lovelace",
3683
+ "contact-email": "ada@example.com",
3684
+ "status": 2,
3685
+ "amount": 1250.50,
3686
+ "due-date": "2026-05-15T12:00:00Z",
3687
+ "owner": "6c8a3e0d-4e5f-4a1b-9c2d-3e4f5a6b7c8d"
3688
+ }
3689
+ }`
3690
+ }
3691
+ ]),
3692
+ "records delete": buildCommandExamples([
3693
+ {
3694
+ description: "Delete a record.",
3695
+ command: `zinkee --json records delete contacts ${SAMPLE_UUID}`,
3696
+ response: `{
3697
+ "recordId": "550e8400-e29b-41d4-a716-446655440000",
3698
+ "deleted": true
3699
+ }`
3700
+ }
3701
+ ]),
3702
+ "comments list": buildCommandExamples([
3703
+ {
3704
+ description: "List comments on a record (content is an array of TEXT/MENTION items).",
3705
+ command: `zinkee --json comments list contacts ${SAMPLE_UUID}`,
3706
+ response: `[
3707
+ {
3708
+ "id": "cd8e3b2a-1f5c-4e9a-8b7d-0a2b3c4d5e6f",
3709
+ "recordId": "550e8400-e29b-41d4-a716-446655440000",
3710
+ "createdAt": "2026-04-22T10:15:00Z",
3711
+ "createdBy": "developer@zinkee.com",
3712
+ "content": [
3713
+ { "type": "TEXT", "value": "This record needs review." }
3714
+ ]
3715
+ },
3716
+ {
3717
+ "id": "a1b2c3d4-5e6f-7890-abcd-ef1234567890",
3718
+ "recordId": "550e8400-e29b-41d4-a716-446655440000",
3719
+ "createdAt": "2026-04-22T11:30:00Z",
3720
+ "createdBy": "developer@zinkee.com",
3721
+ "content": [
3722
+ { "type": "TEXT", "value": "Assigning to " },
3723
+ { "type": "MENTION", "value": "9f8e7d6c-5b4a-3c2d-1e0f-a1b2c3d4e5f6" },
3724
+ { "type": "TEXT", "value": " for follow up." }
3725
+ ]
3726
+ }
3727
+ ]`
3728
+ }
3729
+ ]),
3730
+ "logs list": buildCommandExamples([
3731
+ {
3732
+ description: "List the change history for a record (CREATE entry plus UPDATE entries with before/after values per field).",
3733
+ command: `zinkee --json logs list contacts ${SAMPLE_UUID}`,
3734
+ response: `[
3735
+ {
3736
+ "recordId": "550e8400-e29b-41d4-a716-446655440000",
3737
+ "timestamp": "2026-04-22T10:00:00Z",
3738
+ "changeField": "",
3739
+ "change": {
3740
+ "beforeValue": null,
3741
+ "afterValue": null,
3742
+ "author": "developer@zinkee.com",
3743
+ "operation": "CREATE"
3744
+ }
3745
+ },
3746
+ {
3747
+ "recordId": "550e8400-e29b-41d4-a716-446655440000",
3748
+ "timestamp": "2026-04-22T10:15:00Z",
3749
+ "changeField": "status",
3750
+ "change": {
3751
+ "beforeValue": "1",
3752
+ "afterValue": "2",
3753
+ "author": "developer@zinkee.com",
3754
+ "operation": "UPDATE"
3755
+ }
3756
+ },
3757
+ {
3758
+ "recordId": "550e8400-e29b-41d4-a716-446655440000",
3759
+ "timestamp": "2026-04-22T10:20:00Z",
3760
+ "changeField": "amount",
3761
+ "change": {
3762
+ "beforeValue": "1000.00",
3763
+ "afterValue": "1250.50",
3764
+ "author": "developer@zinkee.com",
3765
+ "operation": "UPDATE"
3766
+ }
3767
+ }
3768
+ ]`
3769
+ }
3770
+ ]),
3771
+ "navigation folders list": buildCommandExamples([
3772
+ {
3773
+ description: "List navigation folders with embedded resources, sorted by order.",
3774
+ command: "zinkee --json navigation folders list",
3775
+ response: `[
3776
+ {
3777
+ "id": "84a0fca4-37ef-4c83-a8ed-9ef67ad9324a",
3778
+ "order": 1,
3779
+ "name": "Sales",
3780
+ "resources": [
3781
+ {
3782
+ "id": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
3783
+ "name": "Contacts",
3784
+ "type": "SCHEMA",
3785
+ "isInSpace": false,
3786
+ "additionalProperties": {}
3787
+ },
3788
+ {
3789
+ "id": "5223cbc8-8c6c-4694-93bc-dd176364df9b",
3790
+ "name": "Orders",
3791
+ "type": "SCHEMA",
3792
+ "isInSpace": true,
3793
+ "additionalProperties": {}
3794
+ }
3795
+ ],
3796
+ "additionalProperties": {
3797
+ "color": "blue"
3798
+ }
3799
+ },
3800
+ {
3801
+ "id": "b8c9d0e1-f2a3-4b5c-6d7e-8f9012345678",
3802
+ "order": 2,
3803
+ "name": "Operations",
3804
+ "resources": [
3805
+ {
3806
+ "id": "3f8a2c1b-9d4e-4a5b-8c6d-7e8f90123456",
3807
+ "name": "Quote approval",
3808
+ "type": "WORKFLOW",
3809
+ "isInSpace": false,
3810
+ "additionalProperties": {}
3811
+ },
3812
+ {
3813
+ "id": "0f6f062f-1478-4df2-96a1-c495d037d260",
3814
+ "name": "Executive Revenue",
3815
+ "type": "DISPLAY",
3816
+ "isInSpace": true,
3817
+ "additionalProperties": {
3818
+ "pinned": true
3819
+ }
3820
+ }
3821
+ ],
3822
+ "additionalProperties": {
3823
+ "color": "purple"
3824
+ }
3825
+ },
3826
+ {
3827
+ "id": "00000000-0000-0000-0000-000000000000",
3828
+ "order": 99,
3829
+ "name": "root",
3830
+ "resources": [],
3831
+ "additionalProperties": {}
3832
+ }
3833
+ ]`
3834
+ }
3835
+ ]),
3836
+ "navigation folders get": buildCommandExamples([
3837
+ {
3838
+ description: "Get a navigation folder by exact name or UUID.",
3839
+ command: "zinkee --json navigation folders get Finance"
3840
+ }
3841
+ ]),
3842
+ "navigation folders delete": buildCommandExamples([
3843
+ {
3844
+ description: "Delete a navigation folder by exact name or UUID.",
3845
+ command: "zinkee --json navigation folders delete Finance",
3846
+ response: `{
3847
+ "folderId": "84a0fca4-37ef-4c83-a8ed-9ef67ad9324a",
3848
+ "name": "Finance Ops"
3849
+ }`
3850
+ }
3851
+ ]),
3852
+ "teamspace folders list": buildCommandExamples([
3853
+ {
3854
+ description: "List teamspace folders.",
3855
+ command: "zinkee --json teamspace folders list"
3856
+ },
3857
+ {
3858
+ description: "List teamspace folders with their published resources.",
3859
+ command: "zinkee --json teamspace folders list --include-resources",
3860
+ response: `[
3861
+ {
3862
+ "id": "f45a251d-3ea0-4b41-bfe8-c0f44c8ad54a",
3863
+ "name": "Shared Dashboards",
3864
+ "order": 1,
3865
+ "isRoot": false,
3866
+ "resourceCount": 1,
3867
+ "resources": [
3868
+ {
3869
+ "id": "0f6f062f-1478-4df2-96a1-c495d037d260",
3870
+ "name": "Executive Revenue",
3871
+ "type": "DISPLAY"
3872
+ }
3873
+ ],
3874
+ "additionalProperties": {}
3875
+ }
3876
+ ]`
3877
+ }
3878
+ ]),
3879
+ "teamspace folders get": buildCommandExamples([
3880
+ {
3881
+ description: "Get a teamspace folder by exact name or UUID.",
3882
+ command: 'zinkee --json teamspace folders get "Shared Dashboards"'
3883
+ }
3884
+ ]),
3885
+ "teamspace folders delete": buildCommandExamples([
3886
+ {
3887
+ description: "Delete a teamspace folder. Its resources are moved to the returned target folder (root by default).",
3888
+ command: 'zinkee --json teamspace folders delete "Customer Success"',
3889
+ response: `{
3890
+ "folderId": "f45a251d-3ea0-4b41-bfe8-c0f44c8ad54a",
3891
+ "movedResourceCount": 3,
3892
+ "targetFolder": {
3893
+ "id": "00000000-0000-0000-0000-000000000000",
3894
+ "name": "root",
3895
+ "isRoot": true
3896
+ }
3897
+ }`
3898
+ }
3899
+ ]),
3900
+ "files storage": buildCommandExamples([
3901
+ {
3902
+ description: "Get the storage quota and current usage (bytes).",
3903
+ command: "zinkee --json files storage",
3904
+ response: `{
3905
+ "maxSize": 10737418240,
3906
+ "usedSize": 2147483648
3907
+ }`
3908
+ }
3909
+ ]),
3910
+ "displays list": buildCommandExamples([
3911
+ {
3912
+ description: "List displays in the workspace with variable and widget counts.",
3913
+ command: "zinkee --json displays list",
3914
+ response: `[
3915
+ {
3916
+ "id": "0f6f062f-1478-4df2-96a1-c495d037d260",
3917
+ "name": "Executive Revenue",
3918
+ "layoutTemplate": "widget_row_tabs",
3919
+ "variableCount": 3,
3920
+ "widgetCount": 6
3921
+ },
3922
+ {
3923
+ "id": "6b7c8d9e-0f12-3456-789a-bcdef0123456",
3924
+ "name": "Sales Pipeline",
3925
+ "layoutTemplate": "freeform",
3926
+ "variableCount": 1,
3927
+ "widgetCount": 3
3928
+ },
3929
+ {
3930
+ "id": "ef012345-6789-4abc-8def-0123456789ab",
3931
+ "name": "Customer Detail",
3932
+ "layoutTemplate": "grid",
3933
+ "variableCount": 0,
3934
+ "widgetCount": 2
3935
+ }
3936
+ ]`
3937
+ }
3938
+ ]),
3939
+ "displays get": buildCommandExamples([
3940
+ {
3941
+ description: "Get a display with its layout (tabs/freeformLayouts/slots), variables, widgets, cross-widget filter and navigation targets.",
3942
+ command: "zinkee --json displays get 0f6f062f-1478-4df2-96a1-c495d037d260",
3943
+ response: `{
3944
+ "id": "0f6f062f-1478-4df2-96a1-c495d037d260",
3945
+ "name": "Executive Revenue",
3946
+ "layout": {
3947
+ "template": "widget_row_tabs",
3948
+ "freeformLayouts": null,
3949
+ "slots": null,
3950
+ "tabs": [
3951
+ {
3952
+ "id": "tab-main",
3953
+ "name": "Overview",
3954
+ "orientation": "horizontal",
3955
+ "widgetIds": [
3956
+ "11111111-1111-4111-a111-111111111111",
3957
+ "22222222-2222-4222-a222-222222222222",
3958
+ "33333333-3333-4333-a333-333333333333"
3959
+ ]
3960
+ },
3961
+ {
3962
+ "id": "tab-detail",
3963
+ "name": "Detail",
3964
+ "orientation": "horizontal",
3965
+ "widgetIds": [
3966
+ "44444444-4444-4444-a444-444444444444",
3967
+ "55555555-5555-4555-a555-555555555555",
3968
+ "66666666-6666-4666-a666-666666666666"
3969
+ ]
3970
+ }
3971
+ ]
3972
+ },
3973
+ "variables": [
3974
+ {
3975
+ "id": "aaaaaaaa-1111-4111-a111-111111111111",
3976
+ "type": "REFERENCE",
3977
+ "name": "Customer",
3978
+ "source": {
3979
+ "schemaId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
3980
+ "fieldId": "c60b8526-5835-4c9f-aecd-9a16c7704a34"
3981
+ },
3982
+ "defaultValue": "",
3983
+ "allowMultiple": false,
3984
+ "staticVariable": false,
3985
+ "filters": []
3986
+ },
3987
+ {
3988
+ "id": "bbbbbbbb-2222-4222-a222-222222222222",
3989
+ "type": "DATE",
3990
+ "name": "Period",
3991
+ "date": {
3992
+ "mode": "dynamic",
3993
+ "dynamicOption": "thisMonth"
3994
+ }
3995
+ },
3996
+ {
3997
+ "id": "cccccccc-3333-4333-a333-333333333333",
3998
+ "type": "MEMBER",
3999
+ "name": "Owner",
4000
+ "defaultValue": "6c8a3e0d-4e5f-4a1b-9c2d-3e4f5a6b7c8d",
4001
+ "allowMultiple": false,
4002
+ "staticVariable": false
4003
+ }
4004
+ ],
4005
+ "widgets": [
4006
+ {
4007
+ "id": "11111111-1111-4111-a111-111111111111",
4008
+ "type": "TABLE_OR_SUBTABLE",
4009
+ "source": {
4010
+ "originResourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
4011
+ "isOriginSubSchema": false
4012
+ },
4013
+ "placement": {
4014
+ "layout": { "x": 0, "y": 0, "w": 12, "h": 8 }
4015
+ },
4016
+ "presentation": {
4017
+ "name": "Customers",
4018
+ "description": "All customers",
4019
+ "icon": "users",
4020
+ "color": "blue"
4021
+ },
4022
+ "bindings": {
4023
+ "variableMap": {
4024
+ "aaaaaaaa-1111-4111-a111-111111111111": "c60b8526-5835-4c9f-aecd-9a16c7704a34"
4025
+ }
4026
+ },
4027
+ "query": {
4028
+ "filters": [],
4029
+ "sorts": [
4030
+ { "fieldId": "c60b8526-5835-4c9f-aecd-9a16c7704a34", "direction": "ASC" }
4031
+ ]
4032
+ },
4033
+ "behavior": {
4034
+ "readOnly": false,
4035
+ "hideAddButton": false,
4036
+ "hideDeleteButton": false
4037
+ },
4038
+ "view": {
4039
+ "fields": ["id", "contact-name", "status", "amount"],
4040
+ "columnSize": { "contact-name": 240 }
4041
+ }
4042
+ }
4043
+ ],
4044
+ "crossWidgetFilter": {
4045
+ "source": {
4046
+ "widgetId": "11111111-1111-4111-a111-111111111111",
4047
+ "fieldId": "c60b8526-5835-4c9f-aecd-9a16c7704a34"
4048
+ },
4049
+ "targets": [
4050
+ {
4051
+ "widgetId": "22222222-2222-4222-a222-222222222222",
4052
+ "fieldId": "c60b8526-5835-4c9f-aecd-9a16c7704a34"
4053
+ }
4054
+ ]
4055
+ },
4056
+ "navigationTargets": [
4057
+ {
4058
+ "id": "nav-target-customer",
4059
+ "sourceWidgetId": "11111111-1111-4111-a111-111111111111",
4060
+ "targetDisplayId": "ef012345-6789-4abc-8def-0123456789ab",
4061
+ "targetVariableId": "aaaaaaaa-1111-4111-a111-111111111111",
4062
+ "label": "Open customer"
4063
+ }
4064
+ ]
4065
+ }`
4066
+ }
4067
+ ]),
4068
+ "displays update": buildCommandExamples([
4069
+ {
4070
+ description: "Rename a display (patch of top-level metadata only).",
4071
+ command: 'zinkee --json displays update 0f6f062f-1478-4df2-96a1-c495d037d260 --name "Pipeline overview (renamed)"',
4072
+ raw: `{
4073
+ "name": "Pipeline overview (renamed)"
4074
+ }`,
4075
+ response: `{
4076
+ "displayId": "0f6f062f-1478-4df2-96a1-c495d037d260"
4077
+ }`
4078
+ }
4079
+ ]),
4080
+ "displays delete": buildCommandExamples([
4081
+ {
4082
+ description: "Delete a display.",
4083
+ command: "zinkee --json displays delete 0f6f062f-1478-4df2-96a1-c495d037d260"
4084
+ }
4085
+ ]),
4086
+ "displays layout get": buildCommandExamples([
4087
+ {
4088
+ description: "Get the layout block of a display (template + tabs/freeformLayouts/slots).",
4089
+ command: "zinkee --json displays layout get 0f6f062f-1478-4df2-96a1-c495d037d260"
4090
+ }
4091
+ ]),
4092
+ "displays layout update": buildCommandExamples([
4093
+ {
4094
+ description: "Replace the freeform layout of a display.",
4095
+ command: `zinkee --json displays layout update 0f6f062f-1478-4df2-96a1-c495d037d260 --template freeform --freeform-layouts '{"lg":[{"i":"widget-1","x":0,"y":0,"w":6,"h":5}]}'`
4096
+ }
4097
+ ]),
4098
+ "displays tabs list": buildCommandExamples([
4099
+ {
4100
+ description: "List the tabs of a display (only meaningful when the layout template uses tabs).",
4101
+ command: "zinkee --json displays tabs list 0f6f062f-1478-4df2-96a1-c495d037d260"
4102
+ }
4103
+ ]),
4104
+ "displays tabs delete": buildCommandExamples([
4105
+ {
4106
+ description: "Delete a tab by id.",
4107
+ command: "zinkee --json displays tabs delete 0f6f062f-1478-4df2-96a1-c495d037d260 tab-main",
4108
+ response: `{
4109
+ "displayId": "0f6f062f-1478-4df2-96a1-c495d037d260",
4110
+ "tabId": "tab-main"
4111
+ }`
4112
+ }
4113
+ ]),
4114
+ "displays variables list": buildCommandExamples([
4115
+ {
4116
+ description: "List the variables of a display.",
4117
+ command: "zinkee --json displays variables list 0f6f062f-1478-4df2-96a1-c495d037d260"
4118
+ }
4119
+ ]),
4120
+ "displays variables get": buildCommandExamples([
4121
+ {
4122
+ description: "Get one variable by id.",
4123
+ command: "zinkee --json displays variables get 0f6f062f-1478-4df2-96a1-c495d037d260 aaaaaaaa-1111-4111-a111-111111111111"
4124
+ }
4125
+ ]),
4126
+ "displays variables delete": buildCommandExamples([
4127
+ {
4128
+ description: "Delete a variable.",
4129
+ command: "zinkee --json displays variables delete 0f6f062f-1478-4df2-96a1-c495d037d260 aaaaaaaa-1111-4111-a111-111111111111",
4130
+ response: `{
4131
+ "displayId": "0f6f062f-1478-4df2-96a1-c495d037d260",
4132
+ "variableId": "aaaaaaaa-1111-4111-a111-111111111111"
4133
+ }`
4134
+ }
4135
+ ]),
4136
+ "displays widgets list": buildCommandExamples([
4137
+ {
4138
+ description: "List the widgets of a display.",
4139
+ command: "zinkee --json displays widgets list 0f6f062f-1478-4df2-96a1-c495d037d260"
4140
+ }
4141
+ ]),
4142
+ "displays widgets get": buildCommandExamples([
4143
+ {
4144
+ description: "Get one widget (returns the canonical typed widget contract).",
4145
+ command: "zinkee --json displays widgets get 0f6f062f-1478-4df2-96a1-c495d037d260 11111111-1111-4111-a111-111111111111",
4146
+ response: `{
4147
+ "id": "11111111-1111-4111-a111-111111111111",
4148
+ "type": "TABLE_OR_SUBTABLE",
4149
+ "source": {
4150
+ "originResourceId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
4151
+ "isOriginSubSchema": false
4152
+ },
4153
+ "placement": {
4154
+ "layout": { "x": 0, "y": 0, "w": 12, "h": 8 }
4155
+ },
4156
+ "presentation": {
4157
+ "name": "Customers",
4158
+ "description": "All customers",
4159
+ "icon": "users",
4160
+ "color": "blue"
4161
+ },
4162
+ "bindings": {
4163
+ "variableMap": {
4164
+ "aaaaaaaa-1111-4111-a111-111111111111": "c60b8526-5835-4c9f-aecd-9a16c7704a34"
4165
+ }
4166
+ },
4167
+ "query": {
4168
+ "filters": [],
4169
+ "sorts": [
4170
+ { "fieldId": "c60b8526-5835-4c9f-aecd-9a16c7704a34", "direction": "ASC" }
4171
+ ]
4172
+ },
4173
+ "behavior": {
4174
+ "readOnly": false,
4175
+ "hideAddButton": false,
4176
+ "hideDeleteButton": false
4177
+ },
4178
+ "view": {
4179
+ "fields": ["id", "contact-name", "status", "amount"],
4180
+ "columnSize": { "contact-name": 240 }
4181
+ }
4182
+ }`
4183
+ }
4184
+ ]),
4185
+ "displays widgets delete": buildCommandExamples([
4186
+ {
4187
+ description: "Delete a widget.",
4188
+ command: "zinkee --json displays widgets delete 0f6f062f-1478-4df2-96a1-c495d037d260 11111111-1111-4111-a111-111111111111",
4189
+ response: `{
4190
+ "displayId": "0f6f062f-1478-4df2-96a1-c495d037d260",
4191
+ "widgetId": "11111111-1111-4111-a111-111111111111"
4192
+ }`
4193
+ }
4194
+ ]),
4195
+ "displays navigation-targets list": buildCommandExamples([
4196
+ {
4197
+ description: "List navigation targets for a display.",
4198
+ command: "zinkee --json displays navigation-targets list 0f6f062f-1478-4df2-96a1-c495d037d260"
4199
+ }
4200
+ ]),
4201
+ "displays navigation-targets delete": buildCommandExamples([
4202
+ {
4203
+ description: "Delete a navigation target.",
4204
+ command: "zinkee --json displays navigation-targets delete 0f6f062f-1478-4df2-96a1-c495d037d260 nav-target-customer",
4205
+ response: `{
4206
+ "displayId": "0f6f062f-1478-4df2-96a1-c495d037d260",
4207
+ "navigationTargetId": "nav-target-customer"
4208
+ }`
4209
+ }
4210
+ ]),
4211
+ "displays cross-widget-filter get": buildCommandExamples([
4212
+ {
4213
+ description: "Get the cross-widget filter of a display (can be null if none is set).",
4214
+ command: "zinkee --json displays cross-widget-filter get 0f6f062f-1478-4df2-96a1-c495d037d260"
4215
+ }
4216
+ ]),
4217
+ "displays cross-widget-filter delete": buildCommandExamples([
4218
+ {
4219
+ description: "Delete the cross-widget filter of a display.",
4220
+ command: "zinkee --json displays cross-widget-filter delete 0f6f062f-1478-4df2-96a1-c495d037d260"
4221
+ }
4222
+ ]),
4223
+ "automations list": buildCommandExamples([
4224
+ {
4225
+ description: "List automations with summaries.",
4226
+ command: "zinkee --json automations list",
4227
+ response: `[
4228
+ {
4229
+ "id": "d2df2478-2513-4ecb-a2aa-2cea8c3d614a",
4230
+ "name": "Codex Trigger Demo 1774278580",
4231
+ "description": "Demo compleja no-webhook para revisar en frontend.",
4232
+ "status": "active",
4233
+ "folder": {
4234
+ "id": "cdfc14e3-3169-4ffb-8d9b-b11858a9240f",
4235
+ "name": "Codex Frontend Demo",
4236
+ "isRoot": false
4237
+ },
4238
+ "triggerType": "record_changed",
4239
+ "actionTypes": ["create_record", "http_request", "execute_plugin", "send_message"]
4240
+ }
4241
+ ]`
4242
+ },
4243
+ {
4244
+ description: "Filter automations by folder, status, and trigger type.",
4245
+ command: 'zinkee --json automations list --folder "Codex Frontend Demo" --status active --trigger-type record_changed'
4246
+ }
4247
+ ]),
4248
+ "automations get": buildCommandExamples([
4249
+ {
4250
+ description: "Get the full automation document, including trigger, actions and flow.",
4251
+ command: "zinkee --json automations get automation-1",
4252
+ response: `{
4253
+ "id": "d2df2478-2513-4ecb-a2aa-2cea8c3d614a",
4254
+ "name": "Codex Trigger Demo 1774278580",
4255
+ "description": "Demo compleja no-webhook para revisar en frontend.",
4256
+ "status": "active",
4257
+ "folder": {
4258
+ "id": "cdfc14e3-3169-4ffb-8d9b-b11858a9240f",
4259
+ "name": "Codex Frontend Demo",
4260
+ "isRoot": false
4261
+ },
4262
+ "trigger": {
4263
+ "type": "record_changed",
4264
+ "config": {
4265
+ "schemaId": "68d2c7be-4392-42de-b5ae-625ad79cfc3c",
4266
+ "fieldIds": ["4dd04e57-2a01-4c49-8728-9cb288bffb8d"],
4267
+ "conditions": [
4268
+ {
4269
+ "field": "4dd04e57-2a01-4c49-8728-9cb288bffb8d",
4270
+ "comparator": "ine",
4271
+ "values": [{"rawValue": "", "source": null}]
4272
+ }
4273
+ ]
4274
+ }
4275
+ },
4276
+ "actions": [
4277
+ {
4278
+ "id": "a657c49a-8ca1-4ec1-af86-d0dac4fc49b2",
4279
+ "type": "create_record",
4280
+ "name": "Create follow-up order",
4281
+ "config": {
4282
+ "targetSchemaId": "68d2c7be-4392-42de-b5ae-625ad79cfc3c",
4283
+ "fieldMapping": {
4284
+ "34250412-f016-44c0-9f88-37dd1ddb4b13": {
4285
+ "rawValue": "Created by automation",
4286
+ "source": null
4287
+ }
4288
+ }
4289
+ }
4290
+ },
4291
+ {
4292
+ "id": "784d0971-bd8f-4b05-87eb-3392d1570273",
4293
+ "type": "http_request",
4294
+ "name": "Notify ERP",
4295
+ "config": {
4296
+ "method": "POST",
4297
+ "url": "https://example.com/integrations/order-status",
4298
+ "headers": {"X-Demo": "codex"},
4299
+ "body": "{\\"event\\":\\"order.status.changed\\"}",
4300
+ "contentType": "application/json",
4301
+ "timeoutMs": 5000,
4302
+ "variables": {},
4303
+ "authMode": "STORED",
4304
+ "connectionId": "4fc20b5c-9353-4991-b68e-1027cb674ed4"
4305
+ }
4306
+ },
4307
+ {
4308
+ "id": "dae13307-057f-4c39-817c-4d2dd5898421",
4309
+ "type": "execute_plugin",
4310
+ "name": "Run billing plugin",
4311
+ "config": {
4312
+ "pluginId": "demo-plugin",
4313
+ "pluginArgs": {
4314
+ "mode": "safe"
4315
+ }
4316
+ }
4317
+ }
4318
+ ],
4319
+ "flow": {
4320
+ "entryActionIds": ["a657c49a-8ca1-4ec1-af86-d0dac4fc49b2"],
4321
+ "transitions": [
4322
+ {
4323
+ "fromActionId": "a657c49a-8ca1-4ec1-af86-d0dac4fc49b2",
4324
+ "toActionId": "784d0971-bd8f-4b05-87eb-3392d1570273"
4325
+ },
4326
+ {
4327
+ "fromActionId": "784d0971-bd8f-4b05-87eb-3392d1570273",
4328
+ "toActionId": "dae13307-057f-4c39-817c-4d2dd5898421"
4329
+ }
4330
+ ]
4331
+ }
4332
+ }`
4333
+ }
4334
+ ]),
4335
+ "automations delete": buildCommandExamples([
4336
+ {
4337
+ description: "Delete an automation. The response mirrors the mutation shape.",
4338
+ command: "zinkee --json automations delete automation-1",
4339
+ response: `{
4340
+ "automationId": "d2df2478-2513-4ecb-a2aa-2cea8c3d614a",
4341
+ "webhookEndpoint": null
4342
+ }`
4343
+ }
4344
+ ]),
4345
+ "automations activate": buildCommandExamples([
4346
+ {
4347
+ description: "Activate an automation (transitions it to status=active).",
4348
+ command: "zinkee --json automations activate automation-1",
4349
+ response: `{
4350
+ "automationId": "d2df2478-2513-4ecb-a2aa-2cea8c3d614a",
4351
+ "webhookEndpoint": null
4352
+ }`
4353
+ }
4354
+ ]),
4355
+ "automations deactivate": buildCommandExamples([
4356
+ {
4357
+ description: "Deactivate an automation (transitions it to status=inactive).",
4358
+ command: "zinkee --json automations deactivate automation-1",
4359
+ response: `{
4360
+ "automationId": "d2df2478-2513-4ecb-a2aa-2cea8c3d614a",
4361
+ "webhookEndpoint": null
4362
+ }`
4363
+ }
4364
+ ]),
4365
+ "automations folders list": buildCommandExamples([
4366
+ {
4367
+ description: "List flat automation folders (non-root plus the root bucket).",
4368
+ command: "zinkee --json automations folders list",
4369
+ response: `[
4370
+ {
4371
+ "id": "cdfc14e3-3169-4ffb-8d9b-b11858a9240f",
4372
+ "name": "Codex Frontend Demo",
4373
+ "isRoot": false,
4374
+ "automationCount": 2
4375
+ },
4376
+ {
4377
+ "id": "8b22282b-3db3-4dd7-87f7-b29365dcf3f6",
4378
+ "name": null,
4379
+ "isRoot": true,
4380
+ "automationCount": 3
4381
+ }
4382
+ ]`
4383
+ }
4384
+ ]),
4385
+ "automations folders delete": buildCommandExamples([
4386
+ {
4387
+ description: "Delete a non-root automation folder by exact name.",
4388
+ command: 'zinkee --json automations folders delete "Codex Frontend Demo"',
4389
+ response: `{
4390
+ "id": "cdfc14e3-3169-4ffb-8d9b-b11858a9240f",
4391
+ "name": "Codex Frontend Demo",
4392
+ "isRoot": false,
4393
+ "automationCount": 0
4394
+ }`
4395
+ }
4396
+ ]),
4397
+ "automations trigger get": buildCommandExamples([
4398
+ {
4399
+ description: "Get the trigger subresource. Response shape depends on trigger type; here the scheduled variant.",
4400
+ command: "zinkee --json automations trigger get automation-1",
4401
+ response: `{
4402
+ "type": "scheduled",
4403
+ "config": {
4404
+ "cronExpression": "0 15 10 * * 1"
4405
+ }
4406
+ }`
4407
+ }
4408
+ ]),
4409
+ "automations webhook get": buildCommandExamples([
4410
+ {
4411
+ description: "Get the webhook endpoint companion resource (only exists when the trigger is a webhook).",
4412
+ command: "zinkee --json automations webhook get automation-1",
4413
+ response: `{
4414
+ "endpointId": "b3cb4283-97ab-4d94-9e6f-82d0ee5cee24",
4415
+ "automationId": "d2df2478-2513-4ecb-a2aa-2cea8c3d614a",
4416
+ "endpointUrl": "https://hooks.zinkee.com/webhooks/b3cb4283-97ab-4d94-9e6f-82d0ee5cee24",
4417
+ "active": true,
4418
+ "idempotencyKeyJsonPath": "$.id",
4419
+ "eventTypeJsonPath": "$.type",
4420
+ "allowedEventTypes": ["frontend.demo.created"],
4421
+ "fieldMappings": [
4422
+ {
4423
+ "variable": "external_id",
4424
+ "jsonPath": "$.data.id"
4425
+ }
4426
+ ]
4427
+ }`
4428
+ }
4429
+ ]),
4430
+ "automations webhook delete": buildCommandExamples([
4431
+ {
4432
+ description: "Delete the webhook endpoint companion resource (returns no body).",
4433
+ command: "zinkee --json automations webhook delete automation-1"
4434
+ }
4435
+ ]),
4436
+ "automations actions list": buildCommandExamples([
4437
+ {
4438
+ description: "List the ordered actions of an automation.",
4439
+ command: "zinkee --json automations actions list automation-1",
4440
+ response: `[
4441
+ {
4442
+ "id": "a657c49a-8ca1-4ec1-af86-d0dac4fc49b2",
4443
+ "type": "create_record",
4444
+ "name": "Create follow-up order",
4445
+ "config": {
4446
+ "targetSchemaId": "68d2c7be-4392-42de-b5ae-625ad79cfc3c",
4447
+ "fieldMapping": {
4448
+ "34250412-f016-44c0-9f88-37dd1ddb4b13": {
4449
+ "rawValue": "Created by automation",
4450
+ "source": null
4451
+ }
4452
+ }
4453
+ }
4454
+ },
4455
+ {
4456
+ "id": "784d0971-bd8f-4b05-87eb-3392d1570273",
4457
+ "type": "http_request",
4458
+ "name": "Notify ERP",
4459
+ "config": {
4460
+ "method": "POST",
4461
+ "url": "https://example.com/integrations/order-status",
4462
+ "headers": {"X-Demo": "codex"},
4463
+ "body": "{\\"event\\":\\"order.status.changed\\"}",
4464
+ "contentType": "application/json",
4465
+ "timeoutMs": 5000,
4466
+ "variables": {},
4467
+ "authMode": "STORED",
4468
+ "connectionId": "4fc20b5c-9353-4991-b68e-1027cb674ed4"
4469
+ }
4470
+ },
4471
+ {
4472
+ "id": "dae13307-057f-4c39-817c-4d2dd5898421",
4473
+ "type": "execute_plugin",
4474
+ "name": "Run billing plugin",
4475
+ "config": {
4476
+ "pluginId": "demo-plugin",
4477
+ "pluginArgs": {"mode": "safe"}
4478
+ }
4479
+ }
4480
+ ]`
4481
+ }
4482
+ ]),
4483
+ "automations actions delete": buildCommandExamples([
4484
+ {
4485
+ description: "Delete one action from an automation.",
4486
+ command: "zinkee --json automations actions delete automation-1 action-1",
4487
+ response: `{
4488
+ "automationId": "d2df2478-2513-4ecb-a2aa-2cea8c3d614a",
4489
+ "webhookEndpoint": null
4490
+ }`
4491
+ }
4492
+ ]),
4493
+ "automations flow get": buildCommandExamples([
4494
+ {
4495
+ description: "Get the flow subresource (entry actions and transitions).",
4496
+ command: "zinkee --json automations flow get automation-1",
4497
+ response: `{
4498
+ "entryActionIds": ["a657c49a-8ca1-4ec1-af86-d0dac4fc49b2"],
4499
+ "transitions": [
4500
+ {
4501
+ "fromActionId": "a657c49a-8ca1-4ec1-af86-d0dac4fc49b2",
4502
+ "toActionId": "784d0971-bd8f-4b05-87eb-3392d1570273"
4503
+ },
4504
+ {
4505
+ "fromActionId": "784d0971-bd8f-4b05-87eb-3392d1570273",
4506
+ "toActionId": "dae13307-057f-4c39-817c-4d2dd5898421"
4507
+ }
4508
+ ]
4509
+ }`
4510
+ }
4511
+ ]),
4512
+ "automations plugins list": buildCommandExamples([
4513
+ {
4514
+ description: "List active workspace plugins available for execute_plugin actions.",
4515
+ command: "zinkee --json automations plugins list",
4516
+ response: `[
4517
+ {
4518
+ "id": "demo-plugin",
4519
+ "name": "Demo Plugin",
4520
+ "active": true,
4521
+ "description": "Example plugin for automations",
4522
+ "properties": {
4523
+ "version": "1.0"
4524
+ }
4525
+ }
4526
+ ]`
4527
+ }
4528
+ ]),
4529
+ "automations plugins get": buildCommandExamples([
4530
+ {
4531
+ description: "Get one plugin by id.",
4532
+ command: "zinkee --json automations plugins get demo-plugin",
4533
+ response: `{
4534
+ "id": "demo-plugin",
4535
+ "name": "Demo Plugin",
4536
+ "active": true,
4537
+ "description": "Example plugin for automations",
4538
+ "properties": {
4539
+ "version": "1.0"
4540
+ }
4541
+ }`
4542
+ }
4543
+ ]),
4544
+ "automations connections list": buildCommandExamples([
4545
+ {
4546
+ description: "List stored workspace connections (secrets are never returned).",
4547
+ command: "zinkee --json automations connections list",
4548
+ response: `[
4549
+ {
4550
+ "id": "4fc20b5c-9353-4991-b68e-1027cb674ed4",
4551
+ "name": "ERP API Key",
4552
+ "type": "api_key",
4553
+ "scope": "workspace",
4554
+ "active": true,
4555
+ "config": {
4556
+ "headerName": "Authorization"
4557
+ }
4558
+ }
4559
+ ]`
4560
+ }
4561
+ ]),
4562
+ "automations connections get": buildCommandExamples([
4563
+ {
4564
+ description: "Get one stored connection by id.",
4565
+ command: "zinkee --json automations connections get connection-1",
4566
+ response: `{
4567
+ "id": "4fc20b5c-9353-4991-b68e-1027cb674ed4",
4568
+ "name": "ERP API Key",
4569
+ "type": "api_key",
4570
+ "scope": "workspace",
4571
+ "ownerMemberId": "6c8a3e0d-7b1f-4c98-a2e9-8b9a2e3f5b14",
4572
+ "active": true,
4573
+ "config": {
4574
+ "headerName": "Authorization"
4575
+ },
4576
+ "createdAt": "2026-04-21T09:00:00Z",
4577
+ "updatedAt": "2026-04-21T09:00:00Z",
4578
+ "createdBy": "developer@zinkee.com",
4579
+ "updatedBy": "developer@zinkee.com"
4580
+ }`
4581
+ }
4582
+ ]),
4583
+ "automations connections delete": buildCommandExamples([
4584
+ {
4585
+ description: "Delete one stored connection (returns no body).",
4586
+ command: "zinkee --json automations connections delete connection-1"
4587
+ }
4588
+ ]),
4589
+ "automations create": buildCommandExamples([
4590
+ {
4591
+ description: "Create a scheduled automation with description and target folder. Safe first example because it does not depend on workspace schemas.",
4592
+ command: 'zinkee --json automations create --name "Nightly invoice sync" --description "Runs every Monday morning" --folder cdfc14e3-3169-4ffb-8d9b-b11858a9240f --trigger-type scheduled --cron "0 15 10 * * 1"',
4593
+ raw: `{
4594
+ "name": "Nightly invoice sync",
4595
+ "description": "Runs every Monday morning",
4596
+ "folderId": "cdfc14e3-3169-4ffb-8d9b-b11858a9240f",
4597
+ "trigger": {
4598
+ "type": "scheduled",
4599
+ "config": {
4600
+ "cronExpression": "0 15 10 * * 1"
4601
+ }
4602
+ }
4603
+ }`,
4604
+ response: `{
4605
+ "automationId": "d2df2478-2513-4ecb-a2aa-2cea8c3d614a",
4606
+ "webhookEndpoint": null
4607
+ }`
4608
+ },
4609
+ {
4610
+ description: "Create a record-created automation with an 'is not empty' condition. Replace 'leads' and 'status' with real schema/field slugs or UUIDs.",
4611
+ command: `zinkee --json automations create --name "Lead welcome" --trigger-type record_created --trigger-schema leads --condition-json '{"field":"status","comparator":"ine","values":[{"rawValue":"","source":null}]}'`,
4612
+ raw: `{
4613
+ "name": "Lead welcome",
4614
+ "trigger": {
4615
+ "type": "record_created",
4616
+ "config": {
4617
+ "schemaId": "leads",
4618
+ "conditions": [
4619
+ {
4620
+ "field": "status",
4621
+ "comparator": "ine",
4622
+ "values": [{"rawValue": "", "source": null}]
4623
+ }
4624
+ ]
4625
+ }
4626
+ }
4627
+ }`
4628
+ },
4629
+ {
4630
+ description: "Create a record-changed automation watching a single field, with an 'is not empty' condition. Replace 'orders' and 'status' with values from your workspace.",
4631
+ command: `zinkee --json automations create --name "Order status sync" --trigger-type record_changed --trigger-schema orders --trigger-field status --condition-json '{"field":"status","comparator":"ine","values":[{"rawValue":"","source":null}]}'`,
4632
+ raw: `{
4633
+ "name": "Order status sync",
4634
+ "trigger": {
4635
+ "type": "record_changed",
4636
+ "config": {
4637
+ "schemaId": "orders",
4638
+ "fieldIds": ["status"],
4639
+ "conditions": [
4640
+ {
4641
+ "field": "status",
4642
+ "comparator": "ine",
4643
+ "values": [{"rawValue": "", "source": null}]
4644
+ }
4645
+ ]
4646
+ }
4647
+ }
4648
+ }`
4649
+ }
4650
+ ]),
4651
+ "automations update": buildCommandExamples([
4652
+ {
4653
+ description: "Update automation description and move it to a folder. Supported patch paths: name, description, folderId.",
4654
+ command: 'zinkee --json automations update automation-1 --description "Updated by an agent" --folder cdfc14e3-3169-4ffb-8d9b-b11858a9240f',
4655
+ raw: `{
4656
+ "set": {
4657
+ "description": "Updated by an agent",
4658
+ "folderId": "cdfc14e3-3169-4ffb-8d9b-b11858a9240f"
4659
+ }
4660
+ }`
4661
+ },
4662
+ {
4663
+ description: "Clear the folder assignment by combining an explicit unset through the raw payload.",
4664
+ command: `zinkee --json automations update automation-1 --raw '{"unset":["folderId"]}'`,
4665
+ raw: `{
4666
+ "unset": ["folderId"]
4667
+ }`
4668
+ }
4669
+ ]),
4670
+ "automations trigger set": buildCommandExamples([
4671
+ {
4672
+ description: "Replace the trigger with a scheduled (cron) trigger.",
4673
+ command: 'zinkee --json automations trigger set automation-1 --trigger-type scheduled --cron "0 15 10 * * 1"',
4674
+ raw: `{
4675
+ "type": "scheduled",
4676
+ "config": {
4677
+ "cronExpression": "0 15 10 * * 1"
4678
+ }
4679
+ }`
4680
+ },
4681
+ {
4682
+ description: "Replace the trigger with a record-created trigger plus an 'is not empty' condition. Agents should provide at least one meaningful condition.",
4683
+ command: `zinkee --json automations trigger set automation-1 --trigger-type record_created --trigger-schema orders --condition-json '{"field":"status","comparator":"ine","values":[{"rawValue":"","source":null}]}'`,
4684
+ raw: `{
4685
+ "type": "record_created",
4686
+ "config": {
4687
+ "schemaId": "orders",
4688
+ "conditions": [
4689
+ {
4690
+ "field": "status",
4691
+ "comparator": "ine",
4692
+ "values": [{"rawValue": "", "source": null}]
4693
+ }
4694
+ ]
4695
+ }
4696
+ }`
4697
+ },
4698
+ {
4699
+ description: "Replace the trigger with a record-changed trigger watching one field, with an 'is not empty' condition on that field.",
4700
+ command: `zinkee --json automations trigger set automation-1 --trigger-type record_changed --trigger-schema orders --trigger-field status --condition-json '{"field":"status","comparator":"ine","values":[{"rawValue":"","source":null}]}'`,
4701
+ raw: `{
4702
+ "type": "record_changed",
4703
+ "config": {
4704
+ "schemaId": "orders",
4705
+ "fieldIds": ["status"],
4706
+ "conditions": [
4707
+ {
4708
+ "field": "status",
4709
+ "comparator": "ine",
4710
+ "values": [{"rawValue": "", "source": null}]
4711
+ }
4712
+ ]
4713
+ }
4714
+ }`
4715
+ },
4716
+ {
4717
+ description: "Replace the trigger with a webhook trigger that reuses an existing webhook endpoint id.",
4718
+ command: "zinkee --json automations trigger set automation-1 --trigger-type webhook --webhook-endpoint-id b3cb4283-97ab-4d94-9e6f-82d0ee5cee24",
4719
+ raw: `{
4720
+ "type": "webhook",
4721
+ "config": {
4722
+ "webhookEndpointId": "b3cb4283-97ab-4d94-9e6f-82d0ee5cee24"
4723
+ }
4724
+ }`
4725
+ }
4726
+ ]),
4727
+ "automations actions add": buildCommandExamples([
4728
+ {
4729
+ description: "Add a create-record action with two literal field mappings. Populate visible fieldMapping entries so the frontend form is complete.",
4730
+ command: 'zinkee --json automations actions add automation-1 --type create_record --name "Create follow-up order" --target-schema followups --map status=pending --map description="Created by automation"',
4731
+ raw: `{
4732
+ "type": "create_record",
4733
+ "name": "Create follow-up order",
4734
+ "config": {
4735
+ "targetSchemaId": "followups",
4736
+ "fieldMapping": {
4737
+ "status": {
4738
+ "rawValue": "pending",
4739
+ "source": null
4740
+ },
4741
+ "description": {
4742
+ "rawValue": "Created by automation",
4743
+ "source": null
4744
+ }
4745
+ }
4746
+ }
4747
+ }`
4748
+ },
4749
+ {
4750
+ description: "Add an update-record action that targets the trigger record. Pair --use-trigger-record with --map to rewrite fields on the record that fired the automation.",
4751
+ command: 'zinkee --json automations actions add automation-1 --type update_record --name "Mark order as processed" --target-schema orders --use-trigger-record --map status=processed',
4752
+ raw: `{
4753
+ "type": "update_record",
4754
+ "name": "Mark order as processed",
4755
+ "config": {
4756
+ "targetSchemaId": "orders",
4757
+ "fieldMapping": {
4758
+ "status": {
4759
+ "rawValue": "processed",
4760
+ "source": null
4761
+ }
4762
+ },
4763
+ "useTriggerRecord": true
4764
+ }
4765
+ }`
4766
+ },
4767
+ {
4768
+ description: "Add a search-records action scoped to a target schema.",
4769
+ command: 'zinkee --json automations actions add automation-1 --type search_records --name "Find related invoices" --target-schema orders',
4770
+ raw: `{
4771
+ "type": "search_records",
4772
+ "name": "Find related invoices",
4773
+ "config": {
4774
+ "targetSchemaId": "orders"
4775
+ }
4776
+ }`
4777
+ },
4778
+ {
4779
+ description: "Add a search-records action whose condition pulls its value from the trigger payload using --condition-json.",
4780
+ command: `zinkee --json automations actions add automation-1 --type search_records --name "Find duplicates" --target-schema followups --condition-json '{"field":"email","comparator":"eq","values":[{"rawValue":null,"source":{"type":"TRIGGER","id":"payload_value"}}]}'`,
4781
+ raw: `{
4782
+ "type": "search_records",
4783
+ "name": "Find duplicates",
4784
+ "config": {
4785
+ "targetSchemaId": "followups",
4786
+ "conditions": [
4787
+ {
4788
+ "field": "email",
4789
+ "comparator": "eq",
4790
+ "values": [
4791
+ {
4792
+ "rawValue": null,
4793
+ "source": {
4794
+ "type": "TRIGGER",
4795
+ "id": "payload_value"
4796
+ }
4797
+ }
4798
+ ]
4799
+ }
4800
+ ]
4801
+ }
4802
+ }`
4803
+ },
4804
+ {
4805
+ description: "Add an HTTP request action using a stored workspace connection for authentication.",
4806
+ command: 'zinkee --json automations actions add automation-1 --type http_request --name "Notify external ERP" --method POST --url https://example.com/integrations/order-status --header X-Demo=codex --content-type application/json --timeout-ms 5000 --auth-mode STORED --connection connection-1',
4807
+ raw: `{
4808
+ "type": "http_request",
4809
+ "name": "Notify external ERP",
4810
+ "config": {
4811
+ "method": "POST",
4812
+ "url": "https://example.com/integrations/order-status",
4813
+ "headers": {
4814
+ "X-Demo": "codex"
4815
+ },
4816
+ "contentType": "application/json",
4817
+ "timeoutMs": 5000,
4818
+ "authMode": "STORED",
4819
+ "connectionId": "connection-1"
4820
+ }
4821
+ }`
4822
+ },
4823
+ {
4824
+ description: "Add an execute-plugin action with structured plugin arguments. Replace 'demo-plugin' with an active id from 'zinkee --json automations plugins list'.",
4825
+ command: `zinkee --json automations actions add automation-1 --type execute_plugin --name "Run billing plugin" --plugin demo-plugin --arg mode=safe --arg-json steps='["one","two"]'`,
4826
+ raw: `{
4827
+ "type": "execute_plugin",
4828
+ "name": "Run billing plugin",
4829
+ "config": {
4830
+ "pluginId": "demo-plugin",
4831
+ "pluginArgs": {
4832
+ "mode": "safe",
4833
+ "steps": ["one", "two"]
4834
+ }
4835
+ }
4836
+ }`
4837
+ }
4838
+ ]),
4839
+ "automations actions update": buildCommandExamples([
4840
+ {
4841
+ description: "Replace an update-record action so it targets the trigger record. Conditions are stripped automatically when --use-trigger-record is provided.",
4842
+ command: 'zinkee --json automations actions update automation-1 action-1 --type update_record --name "Update trigger record" --target-schema followups --map status=ready --use-trigger-record',
4843
+ raw: `{
4844
+ "type": "update_record",
4845
+ "name": "Update trigger record",
4846
+ "config": {
4847
+ "targetSchemaId": "followups",
4848
+ "fieldMapping": {
4849
+ "status": {
4850
+ "rawValue": "ready",
4851
+ "source": null
4852
+ }
4853
+ },
4854
+ "useTriggerRecord": true
4855
+ }
4856
+ }`,
4857
+ response: `{
4858
+ "id": "a657c49a-8ca1-4ec1-af86-d0dac4fc49b2",
4859
+ "type": "create_record",
4860
+ "name": "Create follow-up order",
4861
+ "config": {
4862
+ "targetSchemaId": "68d2c7be-4392-42de-b5ae-625ad79cfc3c",
4863
+ "fieldMapping": {
4864
+ "34250412-f016-44c0-9f88-37dd1ddb4b13": {
4865
+ "rawValue": "Updated by an agent",
4866
+ "source": null
4867
+ }
4868
+ }
4869
+ }
4870
+ }`
4871
+ },
4872
+ {
4873
+ description: "Replace an HTTP request action, keeping it authenticated through a stored connection.",
4874
+ command: 'zinkee --json automations actions update automation-1 action-1 --type http_request --name "Notify external ERP" --method POST --url https://example.com/integrations/order-status --content-type application/json --timeout-ms 5000 --auth-mode STORED --connection connection-1',
4875
+ raw: `{
4876
+ "type": "http_request",
4877
+ "name": "Notify external ERP",
4878
+ "config": {
4879
+ "method": "POST",
4880
+ "url": "https://example.com/integrations/order-status",
4881
+ "contentType": "application/json",
4882
+ "timeoutMs": 5000,
4883
+ "authMode": "STORED",
4884
+ "connectionId": "connection-1"
4885
+ }
4886
+ }`
4887
+ }
4888
+ ]),
4889
+ "automations flow set": buildCommandExamples([
4890
+ {
4891
+ description: "Set one entry action and chain two transitions (action-1 \u2192 action-2 \u2192 action-3).",
4892
+ command: "zinkee --json automations flow set automation-1 --entry action-1 --transition action-1:action-2 --transition action-2:action-3",
4893
+ raw: `{
4894
+ "entryActionIds": ["action-1"],
4895
+ "transitions": [
4896
+ {
4897
+ "fromActionId": "action-1",
4898
+ "toActionId": "action-2"
4899
+ },
4900
+ {
4901
+ "fromActionId": "action-2",
4902
+ "toActionId": "action-3"
4903
+ }
4904
+ ]
4905
+ }`
4906
+ }
4907
+ ]),
4908
+ "automations webhook set": buildCommandExamples([
4909
+ {
4910
+ description: "Create or update the webhook endpoint companion resource with idempotency key, event type filter, and a field mapping. This config is separate from the webhook trigger itself.",
4911
+ command: `zinkee --json automations webhook set automation-1 --idempotency-key-path "$.id" --event-type-path "$.type" --allowed-event-type frontend.demo.created --field-mapping '{"variable":"external_id","jsonPath":"$.data.id"}' --active`,
4912
+ raw: `{
4913
+ "active": true,
4914
+ "idempotencyKeyJsonPath": "$.id",
4915
+ "eventTypeJsonPath": "$.type",
4916
+ "allowedEventTypes": ["frontend.demo.created"],
4917
+ "fieldMappings": [
4918
+ {
4919
+ "variable": "external_id",
4920
+ "jsonPath": "$.data.id"
4921
+ }
4922
+ ]
4923
+ }`,
4924
+ response: `{
4925
+ "endpointId": "b3cb4283-97ab-4d94-9e6f-82d0ee5cee24",
4926
+ "automationId": "d2df2478-2513-4ecb-a2aa-2cea8c3d614a",
4927
+ "endpointUrl": "https://hooks.zinkee.com/webhooks/b3cb4283-97ab-4d94-9e6f-82d0ee5cee24",
4928
+ "active": true,
4929
+ "idempotencyKeyJsonPath": "$.id",
4930
+ "eventTypeJsonPath": "$.type",
4931
+ "allowedEventTypes": ["frontend.demo.created"],
4932
+ "fieldMappings": [
4933
+ {
4934
+ "variable": "external_id",
4935
+ "jsonPath": "$.data.id"
4936
+ }
4937
+ ]
4938
+ }`
4939
+ }
4940
+ ]),
4941
+ "automations connections create": buildCommandExamples([
4942
+ {
4943
+ description: "Create a stored workspace connection for http_request actions. Secret values are write-only and never returned on read.",
4944
+ command: `zinkee --json automations connections create --name "ERP API Key" --type api_key --scope workspace --config '{"headerName":"Authorization"}' --secret apiKey=super-secret --active`,
4945
+ raw: `{
4946
+ "name": "ERP API Key",
4947
+ "type": "api_key",
4948
+ "scope": "workspace",
4949
+ "config": {
4950
+ "headerName": "Authorization"
4951
+ },
4952
+ "secret": {
4953
+ "apiKey": "super-secret"
4954
+ },
4955
+ "active": true
4956
+ }`,
4957
+ response: `{
4958
+ "id": "4fc20b5c-9353-4991-b68e-1027cb674ed4",
4959
+ "name": "ERP API Key",
4960
+ "type": "api_key",
4961
+ "scope": "workspace",
4962
+ "ownerMemberId": "6c8a3e0d-7b1f-4c98-a2e9-8b9a2e3f5b14",
4963
+ "active": true,
4964
+ "config": {
4965
+ "headerName": "Authorization"
4966
+ },
4967
+ "createdAt": "2026-04-21T09:00:00Z",
4968
+ "updatedAt": "2026-04-21T09:00:00Z",
4969
+ "createdBy": "developer@zinkee.com",
4970
+ "updatedBy": "developer@zinkee.com"
4971
+ }`
4972
+ }
4973
+ ]),
4974
+ "automations connections update": buildCommandExamples([
4975
+ {
4976
+ description: "Patch an existing stored connection. Use set.secret only when rotating secrets.",
4977
+ command: `zinkee --json automations connections update connection-1 --raw '{"set":{"name":"ERP API Key Updated","config":{"headerName":"Authorization"}}}'`,
4978
+ raw: `{
4979
+ "set": {
4980
+ "name": "ERP API Key Updated",
4981
+ "config": {
4982
+ "headerName": "Authorization"
4983
+ }
4984
+ }
4985
+ }`,
4986
+ response: `{
4987
+ "id": "4fc20b5c-9353-4991-b68e-1027cb674ed4",
4988
+ "name": "ERP API Key Updated",
4989
+ "type": "api_key",
4990
+ "scope": "workspace",
4991
+ "ownerMemberId": "6c8a3e0d-7b1f-4c98-a2e9-8b9a2e3f5b14",
4992
+ "active": true,
4993
+ "config": {
4994
+ "headerName": "Authorization"
4995
+ },
4996
+ "createdAt": "2026-04-21T09:00:00Z",
4997
+ "updatedAt": "2026-04-21T10:15:00Z",
4998
+ "createdBy": "developer@zinkee.com",
4999
+ "updatedBy": "developer@zinkee.com"
5000
+ }`
5001
+ }
5002
+ ]),
5003
+ "automations folders create": buildCommandExamples([
5004
+ {
5005
+ description: "Create one flat automation folder.",
5006
+ command: 'zinkee --json automations folders create --name "Codex Frontend Demo"',
5007
+ raw: `{
5008
+ "name": "Codex Frontend Demo"
5009
+ }`,
5010
+ response: `{
5011
+ "id": "cdfc14e3-3169-4ffb-8d9b-b11858a9240f",
5012
+ "name": "Codex Frontend Demo",
5013
+ "isRoot": false,
5014
+ "automationCount": 0
5015
+ }`
5016
+ }
5017
+ ]),
5018
+ "automations folders update": buildCommandExamples([
5019
+ {
5020
+ description: "Rename a non-root automation folder. The folder argument accepts a UUID or an exact name.",
5021
+ command: 'zinkee --json automations folders update "Codex Frontend Demo" --name "Codex Frontend Demo Updated"',
5022
+ raw: `{
5023
+ "name": "Codex Frontend Demo Updated"
5024
+ }`,
5025
+ response: `{
5026
+ "id": "cdfc14e3-3169-4ffb-8d9b-b11858a9240f",
5027
+ "name": "Codex Frontend Demo Updated",
5028
+ "isRoot": false,
5029
+ "automationCount": 2
5030
+ }`
5031
+ }
5032
+ ]),
5033
+ "automations folders move": buildCommandExamples([
5034
+ {
5035
+ description: "Move one automation into a target folder by exact folder name.",
5036
+ command: 'zinkee --json automations folders move automation-1 --to "Codex Frontend Demo"',
5037
+ raw: `{
5038
+ "automationId": "automation-1"
5039
+ }`,
5040
+ response: `{
5041
+ "id": "cdfc14e3-3169-4ffb-8d9b-b11858a9240f",
5042
+ "name": "Codex Frontend Demo",
5043
+ "isRoot": false
5044
+ }`
5045
+ }
5046
+ ])
5047
+ };
5048
+ function fallbackExamples(commandName) {
2291
5049
  switch (commandName) {
2292
- case "profiles list":
2293
- return [{ description: "List configured profiles", command: "zinkee profiles list" }];
2294
- case "profiles get":
2295
- return [{ description: "Show a profile", command: "zinkee profiles get prod" }];
2296
- case "profiles add":
2297
- return [{ description: "Add a profile", command: "zinkee profiles add local --api-key token --base-url http://localhost:8088" }];
2298
- case "config validate":
2299
- return [{ description: "Validate config", command: "zinkee --json config validate" }];
2300
- case "schemas list":
2301
- return [{ description: "List schemas", command: "zinkee --json schemas list" }];
2302
- case "schemas create":
2303
- return [{ description: "Create a schema", command: "zinkee --json schemas create --name Contacts --slug contacts --auditable --commentable" }];
2304
- case "comments create":
2305
- return [{ description: "Create a text comment", command: `zinkee --json comments create contacts ${SAMPLE_UUID} --text "Hello world"` }];
2306
- case "navigation folders create":
2307
- return [{ description: "Create a navigation folder", command: "zinkee --json navigation folders create --name Finance --order 10" }];
2308
- case "teamspace folders list":
2309
- return [{ description: "List teamspace folders with resources", command: "zinkee --json teamspace folders list --include-resources" }];
2310
- case "displays create":
2311
- return [
2312
- { description: "Create a display", command: "zinkee --json displays create --name Pipeline --template widget_row_tabs" },
2313
- {
2314
- description: "Create a freeform display with responsive layout data",
2315
- command: `zinkee --json displays create --name "Control Proyecto Freeform" --template freeform --freeform-layouts '{"lg":[{"i":"widget-1","x":0,"y":0,"w":6,"h":5}]}'`
2316
- }
2317
- ];
2318
- case "automations list":
2319
- return [{ description: "List automations", command: "zinkee --json automations list" }];
2320
5050
  default:
2321
5051
  return [];
2322
5052
  }
@@ -2461,31 +5191,49 @@ async function buildDynamicAutomationExamples(commandName, options = {}) {
2461
5191
  "cronExpression": "0 15 10 * * 1"
2462
5192
  }
2463
5193
  }
5194
+ }`,
5195
+ response: `{
5196
+ "automationId": "d2df2478-2513-4ecb-a2aa-2cea8c3d614a",
5197
+ "webhookEndpoint": null
2464
5198
  }`
2465
5199
  },
2466
5200
  {
2467
- description: `Create a record-created automation using a real schema reference from this workspace (${schemaField.schemaRef}).`,
2468
- command: `zinkee --json automations create --name "Record created demo" --trigger-type record_created --trigger-schema ${schemaField.schemaRef}`,
5201
+ description: `Create a record-created automation using a real schema reference from this workspace (${schemaField.schemaRef}), with an 'is not empty' condition on ${schemaField.fieldRef}.`,
5202
+ command: `zinkee --json automations create --name "Record created demo" --trigger-type record_created --trigger-schema ${schemaField.schemaRef} --condition-json '{"field":"${schemaField.fieldRef}","comparator":"ine","values":[{"rawValue":"","source":null}]}'`,
2469
5203
  raw: `{
2470
5204
  "name": "Record created demo",
2471
5205
  "trigger": {
2472
5206
  "type": "record_created",
2473
5207
  "config": {
2474
- "schemaId": "${schemaField.schemaRef}"
5208
+ "schemaId": "${schemaField.schemaRef}",
5209
+ "conditions": [
5210
+ {
5211
+ "field": "${schemaField.fieldRef}",
5212
+ "comparator": "ine",
5213
+ "values": [{"rawValue": "", "source": null}]
5214
+ }
5215
+ ]
2475
5216
  }
2476
5217
  }
2477
5218
  }`
2478
5219
  },
2479
5220
  {
2480
- description: `Create a record-changed automation using a real schema and field reference from this workspace (${schemaField.schemaRef} / ${schemaField.fieldRef}).`,
2481
- command: `zinkee --json automations create --name "Record changed demo" --trigger-type record_changed --trigger-schema ${schemaField.schemaRef} --trigger-field ${schemaField.fieldRef}`,
5221
+ description: `Create a record-changed automation watching ${schemaField.fieldRef} on ${schemaField.schemaRef}, with an 'is not empty' condition on that field.`,
5222
+ command: `zinkee --json automations create --name "Record changed demo" --trigger-type record_changed --trigger-schema ${schemaField.schemaRef} --trigger-field ${schemaField.fieldRef} --condition-json '{"field":"${schemaField.fieldRef}","comparator":"ine","values":[{"rawValue":"","source":null}]}'`,
2482
5223
  raw: `{
2483
5224
  "name": "Record changed demo",
2484
5225
  "trigger": {
2485
5226
  "type": "record_changed",
2486
5227
  "config": {
2487
5228
  "schemaId": "${schemaField.schemaRef}",
2488
- "fieldIds": ["${schemaField.fieldRef}"]
5229
+ "fieldIds": ["${schemaField.fieldRef}"],
5230
+ "conditions": [
5231
+ {
5232
+ "field": "${schemaField.fieldRef}",
5233
+ "comparator": "ine",
5234
+ "values": [{"rawValue": "", "source": null}]
5235
+ }
5236
+ ]
2489
5237
  }
2490
5238
  }
2491
5239
  }`
@@ -2498,17 +5246,34 @@ async function buildDynamicAutomationExamples(commandName, options = {}) {
2498
5246
  return buildCommandExamples([
2499
5247
  {
2500
5248
  description: "Replace the trigger with a scheduled trigger on a real automation from this workspace.",
2501
- command: `zinkee --json automations trigger set ${automationId} --trigger-type scheduled --cron "0 0 9 * * *"`,
5249
+ command: `zinkee --json automations trigger set ${automationId} --trigger-type scheduled --cron "0 15 10 * * 1"`,
2502
5250
  raw: `{
2503
5251
  "type": "scheduled",
2504
5252
  "config": {
2505
- "cronExpression": "0 0 9 * * *"
5253
+ "cronExpression": "0 15 10 * * 1"
5254
+ }
5255
+ }`
5256
+ },
5257
+ {
5258
+ description: `Replace the trigger with a record-created trigger on ${schemaField.schemaRef}, with an 'is not empty' condition on ${schemaField.fieldRef}.`,
5259
+ command: `zinkee --json automations trigger set ${automationId} --trigger-type record_created --trigger-schema ${schemaField.schemaRef} --condition-json '{"field":"${schemaField.fieldRef}","comparator":"ine","values":[{"rawValue":"","source":null}]}'`,
5260
+ raw: `{
5261
+ "type": "record_created",
5262
+ "config": {
5263
+ "schemaId": "${schemaField.schemaRef}",
5264
+ "conditions": [
5265
+ {
5266
+ "field": "${schemaField.fieldRef}",
5267
+ "comparator": "ine",
5268
+ "values": [{"rawValue": "", "source": null}]
5269
+ }
5270
+ ]
2506
5271
  }
2507
5272
  }`
2508
5273
  },
2509
5274
  {
2510
- description: `Replace the trigger with a record-changed trigger using a real schema and field (${schemaField.schemaRef} / ${schemaField.fieldRef}).`,
2511
- command: `zinkee --json automations trigger set ${automationId} --trigger-type record_changed --trigger-schema ${schemaField.schemaRef} --trigger-field ${schemaField.fieldRef} --condition ${schemaField.fieldRef}:eq:approved`,
5275
+ description: `Replace the trigger with a record-changed trigger watching ${schemaField.fieldRef} on ${schemaField.schemaRef}.`,
5276
+ command: `zinkee --json automations trigger set ${automationId} --trigger-type record_changed --trigger-schema ${schemaField.schemaRef} --trigger-field ${schemaField.fieldRef} --condition-json '{"field":"${schemaField.fieldRef}","comparator":"ine","values":[{"rawValue":"","source":null}]}'`,
2512
5277
  raw: `{
2513
5278
  "type": "record_changed",
2514
5279
  "config": {
@@ -2517,13 +5282,8 @@ async function buildDynamicAutomationExamples(commandName, options = {}) {
2517
5282
  "conditions": [
2518
5283
  {
2519
5284
  "field": "${schemaField.fieldRef}",
2520
- "comparator": "eq",
2521
- "values": [
2522
- {
2523
- "rawValue": "approved",
2524
- "source": null
2525
- }
2526
- ]
5285
+ "comparator": "ine",
5286
+ "values": [{"rawValue": "", "source": null}]
2527
5287
  }
2528
5288
  ]
2529
5289
  }
@@ -2536,11 +5296,11 @@ async function buildDynamicAutomationExamples(commandName, options = {}) {
2536
5296
  }
2537
5297
  return buildCommandExamples([
2538
5298
  {
2539
- description: "Add a create-record action with literal and trigger-based mappings from this workspace.",
2540
- command: `zinkee --json automations actions add ${automationId} --type create_record --name "Create follow-up" --target-schema ${schemaField.schemaRef} --map ${schemaField.fieldRef}=pending --map-json owner='{"rawValue":null,"source":{"type":"TRIGGER","id":"payload_value"}}'`,
5299
+ description: `Add a create-record action with literal and trigger-based mappings targeting ${schemaField.schemaRef}.`,
5300
+ command: `zinkee --json automations actions add ${automationId} --type create_record --name "Create follow-up order" --target-schema ${schemaField.schemaRef} --map ${schemaField.fieldRef}=pending --map-json owner='{"rawValue":null,"source":{"type":"TRIGGER","id":"payload_value"}}'`,
2541
5301
  raw: `{
2542
5302
  "type": "create_record",
2543
- "name": "Create follow-up",
5303
+ "name": "Create follow-up order",
2544
5304
  "config": {
2545
5305
  "targetSchemaId": "${schemaField.schemaRef}",
2546
5306
  "fieldMapping": {
@@ -2560,7 +5320,25 @@ async function buildDynamicAutomationExamples(commandName, options = {}) {
2560
5320
  }`
2561
5321
  },
2562
5322
  {
2563
- description: "Add a search-records action with a trigger-based condition from this workspace.",
5323
+ description: `Add an update-record action that targets the trigger record on ${schemaField.schemaRef}.`,
5324
+ command: `zinkee --json automations actions add ${automationId} --type update_record --name "Mark record as processed" --target-schema ${schemaField.schemaRef} --use-trigger-record --map ${schemaField.fieldRef}=processed`,
5325
+ raw: `{
5326
+ "type": "update_record",
5327
+ "name": "Mark record as processed",
5328
+ "config": {
5329
+ "targetSchemaId": "${schemaField.schemaRef}",
5330
+ "fieldMapping": {
5331
+ "${schemaField.fieldRef}": {
5332
+ "rawValue": "processed",
5333
+ "source": null
5334
+ }
5335
+ },
5336
+ "useTriggerRecord": true
5337
+ }
5338
+ }`
5339
+ },
5340
+ {
5341
+ description: `Add a search-records action with a trigger-based condition on ${schemaField.schemaRef}.`,
2564
5342
  command: `zinkee --json automations actions add ${automationId} --type search_records --name "Find duplicates" --target-schema ${schemaField.schemaRef} --condition-json '{"field":"${schemaField.fieldRef}","comparator":"eq","values":[{"rawValue":null,"source":{"type":"TRIGGER","id":"payload_value"}}]}'`,
2565
5343
  raw: `{
2566
5344
  "type": "search_records",
@@ -2584,34 +5362,54 @@ async function buildDynamicAutomationExamples(commandName, options = {}) {
2584
5362
  ]
2585
5363
  }
2586
5364
  }`
2587
- },
2588
- {
2589
- description: "Add an HTTP request action through the generic --type path.",
2590
- command: `zinkee --json automations actions add ${automationId} --type http_request --name Notify --method POST --url https://example.com/hook --content-type application/json`,
2591
- raw: `{
5365
+ },
5366
+ ...connectionId ? buildCommandExamples([
5367
+ {
5368
+ description: `Add an HTTP request action authenticated through a stored connection (${connectionId}).`,
5369
+ command: `zinkee --json automations actions add ${automationId} --type http_request --name "Notify external ERP" --method POST --url https://example.com/integrations/order-status --header X-Demo=codex --content-type application/json --timeout-ms 5000 --auth-mode STORED --connection ${connectionId}`,
5370
+ raw: `{
5371
+ "type": "http_request",
5372
+ "name": "Notify external ERP",
5373
+ "config": {
5374
+ "method": "POST",
5375
+ "url": "https://example.com/integrations/order-status",
5376
+ "headers": {
5377
+ "X-Demo": "codex"
5378
+ },
5379
+ "contentType": "application/json",
5380
+ "timeoutMs": 5000,
5381
+ "authMode": "STORED",
5382
+ "connectionId": "${connectionId}"
5383
+ }
5384
+ }`
5385
+ }
5386
+ ]) : buildCommandExamples([
5387
+ {
5388
+ description: "Add an HTTP request action through the generic --type path.",
5389
+ command: `zinkee --json automations actions add ${automationId} --type http_request --name "Notify external ERP" --method POST --url https://example.com/integrations/order-status --content-type application/json`,
5390
+ raw: `{
2592
5391
  "type": "http_request",
2593
- "name": "Notify",
5392
+ "name": "Notify external ERP",
2594
5393
  "config": {
2595
5394
  "method": "POST",
2596
- "url": "https://example.com/hook",
5395
+ "url": "https://example.com/integrations/order-status",
2597
5396
  "contentType": "application/json"
2598
5397
  }
2599
5398
  }`
2600
- },
5399
+ }
5400
+ ]),
2601
5401
  ...pluginId ? buildCommandExamples([
2602
5402
  {
2603
5403
  description: `Add an execute-plugin action using an active plugin from this workspace (${pluginId}).`,
2604
- command: `zinkee --json automations actions add ${automationId} --type execute_plugin --name "Run plugin" --plugin ${pluginId} --arg mode=safe --arg-json payload='{"dryRun":true}'`,
5404
+ command: `zinkee --json automations actions add ${automationId} --type execute_plugin --name "Run billing plugin" --plugin ${pluginId} --arg mode=safe --arg-json steps='["one","two"]'`,
2605
5405
  raw: `{
2606
5406
  "type": "execute_plugin",
2607
- "name": "Run plugin",
5407
+ "name": "Run billing plugin",
2608
5408
  "config": {
2609
5409
  "pluginId": "${pluginId}",
2610
5410
  "pluginArgs": {
2611
5411
  "mode": "safe",
2612
- "payload": {
2613
- "dryRun": true
2614
- }
5412
+ "steps": ["one", "two"]
2615
5413
  }
2616
5414
  }
2617
5415
  }`
@@ -2639,6 +5437,21 @@ async function buildDynamicAutomationExamples(commandName, options = {}) {
2639
5437
  },
2640
5438
  "useTriggerRecord": true
2641
5439
  }
5440
+ }`,
5441
+ response: `{
5442
+ "id": "${automationWithAction.actionId}",
5443
+ "type": "update_record",
5444
+ "name": "Update trigger record",
5445
+ "config": {
5446
+ "targetSchemaId": "${schemaField.schemaRef}",
5447
+ "fieldMapping": {
5448
+ "${schemaField.fieldRef}": {
5449
+ "rawValue": "ready",
5450
+ "source": null
5451
+ }
5452
+ },
5453
+ "useTriggerRecord": true
5454
+ }
2642
5455
  }`
2643
5456
  }
2644
5457
  ]);
@@ -2672,6 +5485,21 @@ async function buildDynamicAutomationExamples(commandName, options = {}) {
2672
5485
  "apiKey": "super-secret"
2673
5486
  },
2674
5487
  "active": true
5488
+ }`,
5489
+ response: `{
5490
+ "id": "4fc20b5c-9353-4991-b68e-1027cb674ed4",
5491
+ "name": "ERP API Key",
5492
+ "type": "api_key",
5493
+ "scope": "workspace",
5494
+ "ownerMemberId": "6c8a3e0d-7b1f-4c98-a2e9-8b9a2e3f5b14",
5495
+ "active": true,
5496
+ "config": {
5497
+ "headerName": "Authorization"
5498
+ },
5499
+ "createdAt": "2026-04-21T09:00:00Z",
5500
+ "updatedAt": "2026-04-21T09:00:00Z",
5501
+ "createdBy": "developer@zinkee.com",
5502
+ "updatedBy": "developer@zinkee.com"
2675
5503
  }`
2676
5504
  }
2677
5505
  ]);
@@ -2690,6 +5518,21 @@ async function buildDynamicAutomationExamples(commandName, options = {}) {
2690
5518
  "headerName": "Authorization"
2691
5519
  }
2692
5520
  }
5521
+ }`,
5522
+ response: `{
5523
+ "id": "${connectionId}",
5524
+ "name": "ERP API Key Updated",
5525
+ "type": "api_key",
5526
+ "scope": "workspace",
5527
+ "ownerMemberId": "6c8a3e0d-7b1f-4c98-a2e9-8b9a2e3f5b14",
5528
+ "active": true,
5529
+ "config": {
5530
+ "headerName": "Authorization"
5531
+ },
5532
+ "createdAt": "2026-04-21T09:00:00Z",
5533
+ "updatedAt": "2026-04-21T10:15:00Z",
5534
+ "createdBy": "developer@zinkee.com",
5535
+ "updatedBy": "developer@zinkee.com"
2693
5536
  }`
2694
5537
  }
2695
5538
  ]);
@@ -2807,6 +5650,13 @@ ${index + 1}. ${example.description}
2807
5650
  writer.write(" Equivalent JSON payload:\n");
2808
5651
  for (const line of example.raw.split("\n")) {
2809
5652
  writer.write(` ${line}
5653
+ `);
5654
+ }
5655
+ }
5656
+ if (example.response) {
5657
+ writer.write(" Example response:\n");
5658
+ for (const line of example.response.split("\n")) {
5659
+ writer.write(` ${line}
2810
5660
  `);
2811
5661
  }
2812
5662
  }
@@ -2815,7 +5665,7 @@ ${index + 1}. ${example.description}
2815
5665
 
2816
5666
  // src/program.ts
2817
5667
  import { createRequire } from "module";
2818
- import { Command as Command9 } from "commander";
5668
+ import { Command as Command10 } from "commander";
2819
5669
 
2820
5670
  // src/commands/config.ts
2821
5671
  function getCommandIo(stdout) {
@@ -5308,9 +8158,117 @@ function registerFilesCommands(program, options = {}) {
5308
8158
  });
5309
8159
  }
5310
8160
 
8161
+ // src/commands/logs.ts
8162
+ import { InvalidArgumentError as InvalidArgumentError5 } from "commander";
8163
+
8164
+ // src/api/logs.ts
8165
+ function selectorValue6(selector2) {
8166
+ return selector2.value;
8167
+ }
8168
+ var LogsApi = class {
8169
+ constructor(client) {
8170
+ this.client = client;
8171
+ }
8172
+ listLogs(schema, recordId) {
8173
+ return this.client.getJson(
8174
+ `/api/v2/schemas/${selectorValue6(schema)}/records/${recordId}/logs`
8175
+ );
8176
+ }
8177
+ };
8178
+
8179
+ // src/commands/logs.ts
8180
+ function getCommandIo6(stdout) {
8181
+ return stdout ?? process.stdout;
8182
+ }
8183
+ function writeLine6(stdout, value) {
8184
+ stdout.write(`${value}
8185
+ `);
8186
+ }
8187
+ function getGlobalOptions6(command) {
8188
+ return command.optsWithGlobals();
8189
+ }
8190
+ function emitJson6(stdout, commandName, data, ..._extra) {
8191
+ writeLine6(
8192
+ stdout,
8193
+ JSON.stringify(buildJsonSuccess(data, { command: commandName }))
8194
+ );
8195
+ }
8196
+ function toConfigurationError6(filePath, error) {
8197
+ if (error instanceof CliError) {
8198
+ throw error;
8199
+ }
8200
+ if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
8201
+ throw new CliError("configuration_error", `Config file not found at ${filePath}.`);
8202
+ }
8203
+ if (error instanceof Error) {
8204
+ throw new CliError("configuration_error", error.message);
8205
+ }
8206
+ throw error;
8207
+ }
8208
+ function createLogsApi(command, filePath) {
8209
+ try {
8210
+ const config = readRuntimeConfig(filePath);
8211
+ const runtime = resolveRuntimeContext(config, getGlobalOptions6(command));
8212
+ if (!runtime.baseUrl) {
8213
+ throw new CliError(
8214
+ "configuration_error",
8215
+ `Resolved profile "${runtime.profile}" is missing a base URL.`
8216
+ );
8217
+ }
8218
+ return {
8219
+ api: new LogsApi(
8220
+ new ApiClient({
8221
+ baseUrl: runtime.baseUrl,
8222
+ apiKey: runtime.apiKey
8223
+ })
8224
+ ),
8225
+ json: runtime.json
8226
+ };
8227
+ } catch (error) {
8228
+ toConfigurationError6(filePath, error);
8229
+ }
8230
+ }
8231
+ function parseUuidOrSlugSelector5(input) {
8232
+ try {
8233
+ return normalizeUuidOrSlug(input);
8234
+ } catch (error) {
8235
+ const message = error instanceof Error ? error.message : "Invalid selector.";
8236
+ throw new InvalidArgumentError5(message);
8237
+ }
8238
+ }
8239
+ function isJsonObject4(value) {
8240
+ return typeof value === "object" && value !== null && !Array.isArray(value);
8241
+ }
8242
+ function toTableRows3(data) {
8243
+ if (Array.isArray(data)) {
8244
+ return data.map((entry) => isJsonObject4(entry) ? entry : { value: entry });
8245
+ }
8246
+ if (isJsonObject4(data)) {
8247
+ return [data];
8248
+ }
8249
+ return [{ value: data }];
8250
+ }
8251
+ function emitTable3(stdout, data) {
8252
+ printTable(toTableRows3(data), void 0, stdout);
8253
+ }
8254
+ function registerLogsCommands(program, options = {}) {
8255
+ const filePath = options.configPath ?? defaultConfigPath;
8256
+ const stdout = getCommandIo6(options.stdout);
8257
+ const logs = program.command("logs").description("Inspect record change logs");
8258
+ logs.command("list").description("List change logs for a record").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector5).argument("<record>", "record uuid or slug", parseUuidOrSlugSelector5).action(async function action(schema, record) {
8259
+ const { api, json } = createLogsApi(this, filePath);
8260
+ const data = await api.listLogs(schema, record.value);
8261
+ if (json) {
8262
+ emitJson6(stdout, "logs list", data, filePath);
8263
+ return;
8264
+ }
8265
+ emitTable3(stdout, data);
8266
+ });
8267
+ }
8268
+
5311
8269
  // src/commands/navigation.ts
5312
8270
  import { readFileSync as readFileSync6 } from "fs";
5313
- import { InvalidArgumentError as InvalidArgumentError5 } from "commander";
8271
+ import { InvalidArgumentError as InvalidArgumentError6 } from "commander";
5314
8272
 
5315
8273
  // src/api/navigation.ts
5316
8274
  function jsonOptions5(body, method) {
@@ -5322,7 +8280,7 @@ function jsonOptions5(body, method) {
5322
8280
  body: JSON.stringify(body)
5323
8281
  };
5324
8282
  }
5325
- function selectorValue6(selector2) {
8283
+ function selectorValue7(selector2) {
5326
8284
  return selector2.value;
5327
8285
  }
5328
8286
  var NavigationApi = class {
@@ -5340,13 +8298,13 @@ var NavigationApi = class {
5340
8298
  }
5341
8299
  updateFolder(folder, body) {
5342
8300
  return this.client.requestJson(
5343
- `/api/v2/navigation/folders/${selectorValue6(folder)}`,
8301
+ `/api/v2/navigation/folders/${selectorValue7(folder)}`,
5344
8302
  jsonOptions5(body, "PATCH")
5345
8303
  );
5346
8304
  }
5347
8305
  deleteFolder(folder) {
5348
8306
  return this.client.requestJson(
5349
- `/api/v2/navigation/folders/${selectorValue6(folder)}`,
8307
+ `/api/v2/navigation/folders/${selectorValue7(folder)}`,
5350
8308
  { method: "DELETE" }
5351
8309
  );
5352
8310
  }
@@ -5359,20 +8317,20 @@ var NavigationApi = class {
5359
8317
  };
5360
8318
 
5361
8319
  // src/commands/navigation.ts
5362
- function getCommandIo6(stdout) {
8320
+ function getCommandIo7(stdout) {
5363
8321
  return stdout ?? process.stdout;
5364
8322
  }
5365
- function writeLine6(stdout, value) {
8323
+ function writeLine7(stdout, value) {
5366
8324
  stdout.write(`${value}
5367
8325
  `);
5368
8326
  }
5369
- function getGlobalOptions6(command) {
8327
+ function getGlobalOptions7(command) {
5370
8328
  return command.optsWithGlobals();
5371
8329
  }
5372
- function emitJson6(stdout, commandName, data, configPath) {
5373
- writeLine6(stdout, JSON.stringify(buildJsonSuccess(data, { command: commandName, configPath })));
8330
+ function emitJson7(stdout, commandName, data, configPath) {
8331
+ writeLine7(stdout, JSON.stringify(buildJsonSuccess(data, { command: commandName, configPath })));
5374
8332
  }
5375
- function toConfigurationError6(filePath, error) {
8333
+ function toConfigurationError7(filePath, error) {
5376
8334
  if (error instanceof CliError) {
5377
8335
  throw error;
5378
8336
  }
@@ -5387,7 +8345,7 @@ function toConfigurationError6(filePath, error) {
5387
8345
  function createNavigationApi(command, filePath) {
5388
8346
  try {
5389
8347
  const config = readRuntimeConfig(filePath);
5390
- const runtime = resolveRuntimeContext(config, getGlobalOptions6(command));
8348
+ const runtime = resolveRuntimeContext(config, getGlobalOptions7(command));
5391
8349
  if (!runtime.baseUrl) {
5392
8350
  throw new CliError("configuration_error", `Resolved profile "${runtime.profile}" is missing a base URL.`);
5393
8351
  }
@@ -5402,7 +8360,7 @@ function createNavigationApi(command, filePath) {
5402
8360
  readOnly: runtime.readOnly
5403
8361
  };
5404
8362
  } catch (error) {
5405
- toConfigurationError6(filePath, error);
8363
+ toConfigurationError7(filePath, error);
5406
8364
  }
5407
8365
  }
5408
8366
  function ensureWritable5(commandName, readOnly, mode) {
@@ -5414,12 +8372,12 @@ function ensureWritable5(commandName, readOnly, mode) {
5414
8372
  );
5415
8373
  }
5416
8374
  }
5417
- function parseUuidOrSlugSelector5(input) {
8375
+ function parseUuidOrSlugSelector6(input) {
5418
8376
  try {
5419
8377
  return normalizeUuidOrSlug(input);
5420
8378
  } catch (error) {
5421
8379
  const message = error instanceof Error ? error.message : "Invalid selector.";
5422
- throw new InvalidArgumentError5(message);
8380
+ throw new InvalidArgumentError6(message);
5423
8381
  }
5424
8382
  }
5425
8383
  function parseInteger(value, flagName) {
@@ -5498,24 +8456,24 @@ function folderRows2(folders) {
5498
8456
  }
5499
8457
  function registerNavigationCommands(program, options = {}) {
5500
8458
  const filePath = options.configPath ?? defaultConfigPath;
5501
- const stdout = getCommandIo6(options.stdout);
8459
+ const stdout = getCommandIo7(options.stdout);
5502
8460
  const navigation = program.command("navigation").description("Manage workspace navigation");
5503
8461
  const folders = navigation.command("folders").description("Manage navigation folders");
5504
8462
  folders.command("list").description("List navigation folders").action(async function action() {
5505
8463
  const { api, json } = createNavigationApi(this, filePath);
5506
8464
  const data = await api.listFolders();
5507
8465
  if (json) {
5508
- emitJson6(stdout, "navigation folders list", data, filePath);
8466
+ emitJson7(stdout, "navigation folders list", data, filePath);
5509
8467
  return;
5510
8468
  }
5511
8469
  printTable(folderRows2(data), ["id", "order", "name", "resourceCount"], stdout);
5512
8470
  });
5513
- folders.command("get").description("Get a navigation folder by UUID or exact name").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector5).action(async function action(folder) {
8471
+ folders.command("get").description("Get a navigation folder by UUID or exact name").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector6).action(async function action(folder) {
5514
8472
  const { api, json } = createNavigationApi(this, filePath);
5515
8473
  const data = await api.listFolders();
5516
8474
  const resolved = resolveFolder2(data, folder);
5517
8475
  if (json) {
5518
- emitJson6(stdout, "navigation folders get", resolved, filePath);
8476
+ emitJson7(stdout, "navigation folders get", resolved, filePath);
5519
8477
  return;
5520
8478
  }
5521
8479
  printTable(folderRows2([resolved]), ["id", "order", "name", "resourceCount"], stdout);
@@ -5525,12 +8483,12 @@ function registerNavigationCommands(program, options = {}) {
5525
8483
  ensureWritable5("navigation folders create", readOnly, "write");
5526
8484
  const data = await api.createFolder(buildFolderBody(commandOptions));
5527
8485
  if (json) {
5528
- emitJson6(stdout, "navigation folders create", data, filePath);
8486
+ emitJson7(stdout, "navigation folders create", data, filePath);
5529
8487
  return;
5530
8488
  }
5531
- writeLine6(stdout, `Created navigation folder "${String(data.name ?? commandOptions.name)}".`);
8489
+ writeLine7(stdout, `Created navigation folder "${String(data.name ?? commandOptions.name)}".`);
5532
8490
  });
5533
- folders.command("update").description("Update a navigation folder").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector5).option("--name <name>", "folder name").option("--order <n>", "folder order").option("--props <json>", "folder additionalProperties JSON").option("--props-file <path>", "folder additionalProperties JSON file").action(async function action(folder, commandOptions) {
8491
+ folders.command("update").description("Update a navigation folder").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector6).option("--name <name>", "folder name").option("--order <n>", "folder order").option("--props <json>", "folder additionalProperties JSON").option("--props-file <path>", "folder additionalProperties JSON file").action(async function action(folder, commandOptions) {
5534
8492
  const { api, json, readOnly } = createNavigationApi(this, filePath);
5535
8493
  ensureWritable5("navigation folders update", readOnly, "write");
5536
8494
  const allFolders = await api.listFolders();
@@ -5541,54 +8499,54 @@ function registerNavigationCommands(program, options = {}) {
5541
8499
  }
5542
8500
  const data = await api.updateFolder({ kind: "uuid", value: resolved.id }, body);
5543
8501
  if (json) {
5544
- emitJson6(stdout, "navigation folders update", data, filePath);
8502
+ emitJson7(stdout, "navigation folders update", data, filePath);
5545
8503
  return;
5546
8504
  }
5547
- writeLine6(stdout, `Updated navigation folder "${String(data.name ?? resolved.name ?? resolved.id)}".`);
8505
+ writeLine7(stdout, `Updated navigation folder "${String(data.name ?? resolved.name ?? resolved.id)}".`);
5548
8506
  });
5549
- folders.command("delete").description("Delete a navigation folder").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector5).action(async function action(folder) {
8507
+ folders.command("delete").description("Delete a navigation folder").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector6).action(async function action(folder) {
5550
8508
  const { api, json, readOnly } = createNavigationApi(this, filePath);
5551
8509
  ensureWritable5("navigation folders delete", readOnly, "destructive");
5552
8510
  const allFolders = await api.listFolders();
5553
8511
  const resolved = resolveFolder2(allFolders, folder);
5554
8512
  const data = await api.deleteFolder({ kind: "uuid", value: resolved.id });
5555
8513
  if (json) {
5556
- emitJson6(stdout, "navigation folders delete", data, filePath);
8514
+ emitJson7(stdout, "navigation folders delete", data, filePath);
5557
8515
  return;
5558
8516
  }
5559
- writeLine6(stdout, `Deleted navigation folder "${resolved.name ?? resolved.id}".`);
8517
+ writeLine7(stdout, `Deleted navigation folder "${resolved.name ?? resolved.id}".`);
5560
8518
  });
5561
8519
  navigation.command("resources").description("Manage navigation resources").command("move").description("Move a resource into a folder").argument("<resource>", "resource UUID").requiredOption("--type <type>", "resource type").requiredOption("--to <folder>", "target folder UUID or exact name").action(async function action(resourceId, commandOptions) {
5562
8520
  const { api, json, readOnly } = createNavigationApi(this, filePath);
5563
8521
  ensureWritable5("navigation resources move", readOnly, "write");
5564
8522
  const allFolders = await api.listFolders();
5565
- const resolved = resolveFolder2(allFolders, parseUuidOrSlugSelector5(commandOptions.to));
8523
+ const resolved = resolveFolder2(allFolders, parseUuidOrSlugSelector6(commandOptions.to));
5566
8524
  const data = await api.moveResource({
5567
8525
  resourceId,
5568
8526
  resourceType: commandOptions.type.toUpperCase(),
5569
8527
  targetFolderId: resolved.id
5570
8528
  });
5571
8529
  if (json) {
5572
- emitJson6(stdout, "navigation resources move", data, filePath);
8530
+ emitJson7(stdout, "navigation resources move", data, filePath);
5573
8531
  return;
5574
8532
  }
5575
- writeLine6(stdout, `Moved resource "${resourceId}" to "${resolved.name ?? resolved.id}".`);
8533
+ writeLine7(stdout, `Moved resource "${resourceId}" to "${resolved.name ?? resolved.id}".`);
5576
8534
  });
5577
8535
  }
5578
8536
 
5579
8537
  // src/commands/profiles.ts
5580
- function getCommandIo7(stdout) {
8538
+ function getCommandIo8(stdout) {
5581
8539
  return stdout ?? process.stdout;
5582
8540
  }
5583
- function writeLine7(stdout, value) {
8541
+ function writeLine8(stdout, value) {
5584
8542
  stdout.write(`${value}
5585
8543
  `);
5586
8544
  }
5587
- function getGlobalOptions7(command) {
8545
+ function getGlobalOptions8(command) {
5588
8546
  return command.optsWithGlobals();
5589
8547
  }
5590
- function emitJson7(stdout, commandName, data, configPath) {
5591
- writeLine7(
8548
+ function emitJson8(stdout, commandName, data, configPath) {
8549
+ writeLine8(
5592
8550
  stdout,
5593
8551
  JSON.stringify(buildJsonSuccess(data, { command: commandName, configPath }))
5594
8552
  );
@@ -5631,15 +8589,15 @@ function emitProfilesTable(stdout, data) {
5631
8589
  }
5632
8590
  function registerProfilesCommands(program, options = {}) {
5633
8591
  const filePath = options.configPath ?? defaultConfigPath;
5634
- const stdout = getCommandIo7(options.stdout);
8592
+ const stdout = getCommandIo8(options.stdout);
5635
8593
  const profiles = program.command("profiles").description("Manage local CLI profiles");
5636
8594
  profiles.command("list").description("List configured profiles").action(function action() {
5637
8595
  const config = readRequiredConfig(filePath);
5638
8596
  const data = Object.entries(config.profiles).map(
5639
8597
  ([name, profile]) => toDisplayProfile(name, profile, config.defaultProfile)
5640
8598
  );
5641
- if (getGlobalOptions7(this).json) {
5642
- emitJson7(stdout, "profiles list", data, filePath);
8599
+ if (getGlobalOptions8(this).json) {
8600
+ emitJson8(stdout, "profiles list", data, filePath);
5643
8601
  return;
5644
8602
  }
5645
8603
  emitProfilesTable(stdout, data);
@@ -5648,8 +8606,8 @@ function registerProfilesCommands(program, options = {}) {
5648
8606
  const config = readRequiredConfig(filePath);
5649
8607
  const profile = getRequiredProfile(config, profileName);
5650
8608
  const data = toDisplayProfile(profileName, profile, config.defaultProfile);
5651
- if (getGlobalOptions7(this).json) {
5652
- emitJson7(stdout, "profiles get", data, filePath);
8609
+ if (getGlobalOptions8(this).json) {
8610
+ emitJson8(stdout, "profiles get", data, filePath);
5653
8611
  return;
5654
8612
  }
5655
8613
  emitProfilesTable(stdout, [data]);
@@ -5663,11 +8621,11 @@ function registerProfilesCommands(program, options = {}) {
5663
8621
  profile: profileName,
5664
8622
  defaultProfile: nextConfig.defaultProfile
5665
8623
  };
5666
- if (getGlobalOptions7(this).json) {
5667
- emitJson7(stdout, "profiles use", data, filePath);
8624
+ if (getGlobalOptions8(this).json) {
8625
+ emitJson8(stdout, "profiles use", data, filePath);
5668
8626
  return;
5669
8627
  }
5670
- writeLine7(stdout, `Using profile "${profileName}".`);
8628
+ writeLine8(stdout, `Using profile "${profileName}".`);
5671
8629
  });
5672
8630
  profiles.command("add").description("Add a profile to the local config").argument("<profile>", "profile name").requiredOption("--api-key <token>", "API key").option("--base-url <url>", "base URL").action(function action(profileName, commandOptions) {
5673
8631
  const config = loadConfigForAdd(filePath);
@@ -5690,11 +8648,11 @@ function registerProfilesCommands(program, options = {}) {
5690
8648
  nextConfig.profiles[profileName] ?? {},
5691
8649
  nextConfig.defaultProfile
5692
8650
  );
5693
- if (getGlobalOptions7(this).json) {
5694
- emitJson7(stdout, "profiles add", data, filePath);
8651
+ if (getGlobalOptions8(this).json) {
8652
+ emitJson8(stdout, "profiles add", data, filePath);
5695
8653
  return;
5696
8654
  }
5697
- writeLine7(stdout, `Added profile "${profileName}".`);
8655
+ writeLine8(stdout, `Added profile "${profileName}".`);
5698
8656
  });
5699
8657
  profiles.command("update").description("Update an existing profile").argument("<profile>", "profile name").option("--api-key <token>", "API key").option("--base-url <url>", "base URL").action(function action(profileName, commandOptions) {
5700
8658
  if (commandOptions.apiKey === void 0 && commandOptions.baseUrl === void 0) {
@@ -5715,11 +8673,11 @@ function registerProfilesCommands(program, options = {}) {
5715
8673
  nextConfig.profiles[profileName] ?? {},
5716
8674
  nextConfig.defaultProfile
5717
8675
  );
5718
- if (getGlobalOptions7(this).json) {
5719
- emitJson7(stdout, "profiles update", data, filePath);
8676
+ if (getGlobalOptions8(this).json) {
8677
+ emitJson8(stdout, "profiles update", data, filePath);
5720
8678
  return;
5721
8679
  }
5722
- writeLine7(stdout, `Updated profile "${profileName}".`);
8680
+ writeLine8(stdout, `Updated profile "${profileName}".`);
5723
8681
  });
5724
8682
  profiles.command("remove").description("Remove a profile from the local config").argument("<profile>", "profile name").action(function action(profileName) {
5725
8683
  const config = readRequiredConfig(filePath);
@@ -5730,17 +8688,17 @@ function registerProfilesCommands(program, options = {}) {
5730
8688
  profile: profileName,
5731
8689
  defaultProfile: nextConfig.defaultProfile
5732
8690
  };
5733
- if (getGlobalOptions7(this).json) {
5734
- emitJson7(stdout, "profiles remove", data, filePath);
8691
+ if (getGlobalOptions8(this).json) {
8692
+ emitJson8(stdout, "profiles remove", data, filePath);
5735
8693
  return;
5736
8694
  }
5737
- writeLine7(stdout, `Removed profile "${profileName}".`);
8695
+ writeLine8(stdout, `Removed profile "${profileName}".`);
5738
8696
  });
5739
8697
  }
5740
8698
 
5741
8699
  // src/commands/records.ts
5742
8700
  import { readFileSync as readFileSync7 } from "fs";
5743
- import { InvalidArgumentError as InvalidArgumentError6 } from "commander";
8701
+ import { InvalidArgumentError as InvalidArgumentError7 } from "commander";
5744
8702
 
5745
8703
  // src/api/records.ts
5746
8704
  function jsonOptions6(body, method) {
@@ -5752,7 +8710,7 @@ function jsonOptions6(body, method) {
5752
8710
  body: JSON.stringify(body)
5753
8711
  };
5754
8712
  }
5755
- function selectorValue7(selector2) {
8713
+ function selectorValue8(selector2) {
5756
8714
  return selector2.value;
5757
8715
  }
5758
8716
  var RecordsApi = class {
@@ -5767,7 +8725,7 @@ var RecordsApi = class {
5767
8725
  if (query.offset !== void 0) {
5768
8726
  params.set("offset", String(query.offset));
5769
8727
  }
5770
- const path = `/api/v2/schemas/${selectorValue7(schema)}/records`;
8728
+ const path = `/api/v2/schemas/${selectorValue8(schema)}/records`;
5771
8729
  const queryString = params.toString();
5772
8730
  return this.client.getJson(
5773
8731
  queryString ? `${path}?${queryString}` : path
@@ -5776,30 +8734,30 @@ var RecordsApi = class {
5776
8734
  queryRecords(schema, query) {
5777
8735
  const body = this.normalizeQueryInput(query);
5778
8736
  return this.client.requestJson(
5779
- `/api/v2/schemas/${selectorValue7(schema)}/records:query`,
8737
+ `/api/v2/schemas/${selectorValue8(schema)}/records:query`,
5780
8738
  jsonOptions6(body, "POST")
5781
8739
  );
5782
8740
  }
5783
8741
  getRecord(schema, record) {
5784
8742
  return this.client.getJson(
5785
- `/api/v2/schemas/${selectorValue7(schema)}/records/${selectorValue7(record)}`
8743
+ `/api/v2/schemas/${selectorValue8(schema)}/records/${selectorValue8(record)}`
5786
8744
  );
5787
8745
  }
5788
8746
  createRecord(schema, input) {
5789
8747
  return this.client.requestJson(
5790
- `/api/v2/schemas/${selectorValue7(schema)}/records`,
8748
+ `/api/v2/schemas/${selectorValue8(schema)}/records`,
5791
8749
  jsonOptions6(input, "POST")
5792
8750
  );
5793
8751
  }
5794
8752
  updateRecord(schema, record, input) {
5795
8753
  return this.client.requestJson(
5796
- `/api/v2/schemas/${selectorValue7(schema)}/records/${selectorValue7(record)}`,
8754
+ `/api/v2/schemas/${selectorValue8(schema)}/records/${selectorValue8(record)}`,
5797
8755
  jsonOptions6(input, "PATCH")
5798
8756
  );
5799
8757
  }
5800
8758
  deleteRecord(schema, record) {
5801
8759
  return this.client.requestJson(
5802
- `/api/v2/schemas/${selectorValue7(schema)}/records/${selectorValue7(record)}`,
8760
+ `/api/v2/schemas/${selectorValue8(schema)}/records/${selectorValue8(record)}`,
5803
8761
  { method: "DELETE" }
5804
8762
  );
5805
8763
  }
@@ -5834,11 +8792,17 @@ var RecordsApi = class {
5834
8792
  // src/parsers/expressions.ts
5835
8793
  var supportedComparators = /* @__PURE__ */ new Set([
5836
8794
  "eq",
5837
- "contains",
8795
+ "neq",
5838
8796
  "gt",
5839
- "is-null",
5840
- "in"
8797
+ "gte",
8798
+ "lt",
8799
+ "lte",
8800
+ "contains",
8801
+ "in",
8802
+ "is_empty",
8803
+ "is_not_empty"
5841
8804
  ]);
8805
+ var noValueComparators = /* @__PURE__ */ new Set(["is_empty", "is_not_empty"]);
5842
8806
  function parseColonExpression(input) {
5843
8807
  const parts = input.split(":");
5844
8808
  if (parts.length < 2) {
@@ -5870,7 +8834,7 @@ function parseSpaceExpression(input) {
5870
8834
  return [field.trim(), comparator.trim(), parts.slice(2).join(" ").trim()];
5871
8835
  }
5872
8836
  function normalizeValue(comparator, rawValue) {
5873
- if (comparator === "is-null") {
8837
+ if (noValueComparators.has(comparator)) {
5874
8838
  if (rawValue.length > 0) {
5875
8839
  throw new Error(`Comparator "${comparator}" does not accept a value.`);
5876
8840
  }
@@ -5906,23 +8870,23 @@ function parseExpression(input) {
5906
8870
  }
5907
8871
 
5908
8872
  // src/commands/records.ts
5909
- function getCommandIo8(stdout) {
8873
+ function getCommandIo9(stdout) {
5910
8874
  return stdout ?? process.stdout;
5911
8875
  }
5912
- function writeLine8(stdout, value) {
8876
+ function writeLine9(stdout, value) {
5913
8877
  stdout.write(`${value}
5914
8878
  `);
5915
8879
  }
5916
- function getGlobalOptions8(command) {
8880
+ function getGlobalOptions9(command) {
5917
8881
  return command.optsWithGlobals();
5918
8882
  }
5919
- function emitJson8(stdout, commandName, data, configPath, meta = {}) {
5920
- writeLine8(
8883
+ function emitJson9(stdout, commandName, data, configPath, meta = {}) {
8884
+ writeLine9(
5921
8885
  stdout,
5922
8886
  JSON.stringify(buildJsonSuccess(data, { command: commandName, configPath, ...meta }))
5923
8887
  );
5924
8888
  }
5925
- function toConfigurationError7(filePath, error) {
8889
+ function toConfigurationError8(filePath, error) {
5926
8890
  if (error instanceof CliError) {
5927
8891
  throw error;
5928
8892
  }
@@ -5937,7 +8901,7 @@ function toConfigurationError7(filePath, error) {
5937
8901
  function createRecordsApi(command, filePath) {
5938
8902
  try {
5939
8903
  const config = readRuntimeConfig(filePath);
5940
- const runtime = resolveRuntimeContext(config, getGlobalOptions8(command));
8904
+ const runtime = resolveRuntimeContext(config, getGlobalOptions9(command));
5941
8905
  if (!runtime.baseUrl) {
5942
8906
  throw new CliError(
5943
8907
  "configuration_error",
@@ -5956,7 +8920,7 @@ function createRecordsApi(command, filePath) {
5956
8920
  readOnly: runtime.readOnly
5957
8921
  };
5958
8922
  } catch (error) {
5959
- toConfigurationError7(filePath, error);
8923
+ toConfigurationError8(filePath, error);
5960
8924
  }
5961
8925
  }
5962
8926
  function ensureWritable6(commandName, readOnly, commandMode) {
@@ -5971,24 +8935,24 @@ function ensureWritable6(commandName, readOnly, commandMode) {
5971
8935
  );
5972
8936
  }
5973
8937
  }
5974
- function parseUuidOrSlugSelector6(input) {
8938
+ function parseUuidOrSlugSelector7(input) {
5975
8939
  try {
5976
8940
  return normalizeUuidOrSlug(input);
5977
8941
  } catch (error) {
5978
8942
  const message = error instanceof Error ? error.message : "Invalid selector.";
5979
- throw new InvalidArgumentError6(message);
8943
+ throw new InvalidArgumentError7(message);
5980
8944
  }
5981
8945
  }
5982
8946
  function parseNonNegativeInteger2(input) {
5983
8947
  if (!/^\d+$/.test(input.trim())) {
5984
- throw new InvalidArgumentError6(`Expected a non-negative integer, received "${input}".`);
8948
+ throw new InvalidArgumentError7(`Expected a non-negative integer, received "${input}".`);
5985
8949
  }
5986
8950
  return Number(input);
5987
8951
  }
5988
8952
  function parseCommaSeparatedValues(input, label) {
5989
8953
  const values = input.split(",").map((value) => value.trim()).filter(Boolean);
5990
8954
  if (values.length === 0) {
5991
- throw new InvalidArgumentError6(`Expected ${label} to contain at least one value.`);
8955
+ throw new InvalidArgumentError7(`Expected ${label} to contain at least one value.`);
5992
8956
  }
5993
8957
  return values;
5994
8958
  }
@@ -5997,7 +8961,7 @@ function parseExpressionValue(input) {
5997
8961
  return parseExpression(input);
5998
8962
  } catch (error) {
5999
8963
  const message = error instanceof Error ? error.message : "Invalid expression.";
6000
- throw new InvalidArgumentError6(message);
8964
+ throw new InvalidArgumentError7(message);
6001
8965
  }
6002
8966
  }
6003
8967
  function parseKeyValueAssignment(input) {
@@ -6005,7 +8969,7 @@ function parseKeyValueAssignment(input) {
6005
8969
  return parseKeyValue(input);
6006
8970
  } catch (error) {
6007
8971
  const message = error instanceof Error ? error.message : "Invalid assignment.";
6008
- throw new InvalidArgumentError6(message);
8972
+ throw new InvalidArgumentError7(message);
6009
8973
  }
6010
8974
  }
6011
8975
  function parseJsonKeyValueAssignment(input) {
@@ -6013,7 +8977,7 @@ function parseJsonKeyValueAssignment(input) {
6013
8977
  return parseJsonAssignment(input);
6014
8978
  } catch (error) {
6015
8979
  const message = error instanceof Error ? error.message : "Invalid JSON assignment.";
6016
- throw new InvalidArgumentError6(message);
8980
+ throw new InvalidArgumentError7(message);
6017
8981
  }
6018
8982
  }
6019
8983
  function collectStringValues(value, previous = []) {
@@ -6031,7 +8995,7 @@ function collectKeyValueAssignments(value, previous = []) {
6031
8995
  function collectJsonAssignments(value, previous = []) {
6032
8996
  return [...previous, parseJsonKeyValueAssignment(value)];
6033
8997
  }
6034
- function isJsonObject4(value) {
8998
+ function isJsonObject5(value) {
6035
8999
  return typeof value === "object" && value !== null && !Array.isArray(value);
6036
9000
  }
6037
9001
  function parseRawJsonObject2(input, sourceLabel) {
@@ -6045,7 +9009,7 @@ function parseRawJsonObject2(input, sourceLabel) {
6045
9009
  `Failed to parse JSON from ${sourceLabel}: ${message}`
6046
9010
  );
6047
9011
  }
6048
- if (!isJsonObject4(parsed)) {
9012
+ if (!isJsonObject5(parsed)) {
6049
9013
  throw new CliError(
6050
9014
  "invalid_cli_usage",
6051
9015
  `Expected ${sourceLabel} to contain a JSON object.`
@@ -6139,7 +9103,7 @@ function readRawSetPayload2(raw) {
6139
9103
  if (setValue === void 0) {
6140
9104
  return {};
6141
9105
  }
6142
- if (!isJsonObject4(setValue)) {
9106
+ if (!isJsonObject5(setValue)) {
6143
9107
  throw new CliError(
6144
9108
  "invalid_cli_usage",
6145
9109
  'Expected raw update payload field "set" to be a JSON object.'
@@ -6192,17 +9156,17 @@ function buildRecordUpdateInput(options) {
6192
9156
  }
6193
9157
  return input;
6194
9158
  }
6195
- function toTableRows3(data) {
9159
+ function toTableRows4(data) {
6196
9160
  if (Array.isArray(data)) {
6197
- return data.map((entry) => isJsonObject4(entry) ? entry : { value: entry });
9161
+ return data.map((entry) => isJsonObject5(entry) ? entry : { value: entry });
6198
9162
  }
6199
- if (isJsonObject4(data)) {
9163
+ if (isJsonObject5(data)) {
6200
9164
  return [data];
6201
9165
  }
6202
9166
  return [{ value: data }];
6203
9167
  }
6204
- function emitTable3(stdout, data) {
6205
- printTable(toTableRows3(data), void 0, stdout);
9168
+ function emitTable4(stdout, data) {
9169
+ printTable(toTableRows4(data), void 0, stdout);
6206
9170
  }
6207
9171
  function getQueryRecords(result) {
6208
9172
  return Array.isArray(result.records) ? result.records : [];
@@ -6226,9 +9190,9 @@ async function resolveSchemaSelector(api, selector2) {
6226
9190
  }
6227
9191
  function registerRecordsCommands(program, options = {}) {
6228
9192
  const filePath = options.configPath ?? defaultConfigPath;
6229
- const stdout = getCommandIo8(options.stdout);
9193
+ const stdout = getCommandIo9(options.stdout);
6230
9194
  const records = program.command("records").description("Manage schema records");
6231
- records.command("list").description("List records for a schema with simple pagination").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector6).option("--limit <number>", "limit results", parseNonNegativeInteger2).option("--offset <number>", "offset results", parseNonNegativeInteger2).action(async function action(schema, commandOptions) {
9195
+ records.command("list").description("List records for a schema with simple pagination").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector7).option("--limit <number>", "limit results", parseNonNegativeInteger2).option("--offset <number>", "offset results", parseNonNegativeInteger2).action(async function action(schema, commandOptions) {
6232
9196
  const { api, schemasApi, json } = createRecordsApi(this, filePath);
6233
9197
  const resolvedSchema = await resolveSchemaSelector(schemasApi, schema);
6234
9198
  const data = await api.listRecords(
@@ -6237,7 +9201,7 @@ function registerRecordsCommands(program, options = {}) {
6237
9201
  );
6238
9202
  const recordsData = getQueryRecords(data);
6239
9203
  if (json) {
6240
- emitJson8(
9204
+ emitJson9(
6241
9205
  stdout,
6242
9206
  "records list",
6243
9207
  recordsData,
@@ -6246,9 +9210,9 @@ function registerRecordsCommands(program, options = {}) {
6246
9210
  );
6247
9211
  return;
6248
9212
  }
6249
- emitTable3(stdout, recordsData);
9213
+ emitTable4(stdout, recordsData);
6250
9214
  });
6251
- records.command("query").description("Query records for a schema").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector6).option("--select <fields>", "comma-separated field selection", (value) => parseCommaSeparatedValues(value, "--select")).option("--where <expression>", "where expression", collectWhereExpressions, []).option("--sort <field:direction>", "sort field(s)", collectSortValues, []).option("--limit <number>", "limit results", parseNonNegativeInteger2).option("--offset <number>", "offset results", parseNonNegativeInteger2).option("--raw <json>", "raw JSON object payload").option("--raw-file <path>", "path to a raw JSON object payload").action(async function action(schema, commandOptions) {
9215
+ records.command("query").description("Query records for a schema").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector7).option("--select <fields>", "comma-separated field selection", (value) => parseCommaSeparatedValues(value, "--select")).option("--where <expression>", "where expression", collectWhereExpressions, []).option("--sort <field:direction>", "sort field(s)", collectSortValues, []).option("--limit <number>", "limit results", parseNonNegativeInteger2).option("--offset <number>", "offset results", parseNonNegativeInteger2).option("--raw <json>", "raw JSON object payload").option("--raw-file <path>", "path to a raw JSON object payload").action(async function action(schema, commandOptions) {
6252
9216
  const { api, schemasApi, json } = createRecordsApi(this, filePath);
6253
9217
  const resolvedSchema = await resolveSchemaSelector(schemasApi, schema);
6254
9218
  const data = await api.queryRecords(
@@ -6257,7 +9221,7 @@ function registerRecordsCommands(program, options = {}) {
6257
9221
  );
6258
9222
  const recordsData = getQueryRecords(data);
6259
9223
  if (json) {
6260
- emitJson8(
9224
+ emitJson9(
6261
9225
  stdout,
6262
9226
  "records query",
6263
9227
  recordsData,
@@ -6266,19 +9230,19 @@ function registerRecordsCommands(program, options = {}) {
6266
9230
  );
6267
9231
  return;
6268
9232
  }
6269
- emitTable3(stdout, recordsData);
9233
+ emitTable4(stdout, recordsData);
6270
9234
  });
6271
- records.command("get").description("Get a record by UUID or slug").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector6).argument("<record>", "record uuid or slug", parseUuidOrSlugSelector6).action(async function action(schema, record) {
9235
+ records.command("get").description("Get a record by UUID or slug").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector7).argument("<record>", "record uuid or slug", parseUuidOrSlugSelector7).action(async function action(schema, record) {
6272
9236
  const { api, schemasApi, json } = createRecordsApi(this, filePath);
6273
9237
  const resolvedSchema = await resolveSchemaSelector(schemasApi, schema);
6274
9238
  const data = await api.getRecord(resolvedSchema, record);
6275
9239
  if (json) {
6276
- emitJson8(stdout, "records get", data, filePath);
9240
+ emitJson9(stdout, "records get", data, filePath);
6277
9241
  return;
6278
9242
  }
6279
- emitTable3(stdout, data);
9243
+ emitTable4(stdout, data);
6280
9244
  });
6281
- records.command("create").description("Create a record").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector6).option("--set <field=value>", "set a string field", collectKeyValueAssignments, []).option("--set-json <field=json>", "set a structured field", collectJsonAssignments, []).option("--raw <json>", "raw JSON object payload").option("--raw-file <path>", "path to a raw JSON object payload").action(async function action(schema, commandOptions) {
9245
+ records.command("create").description("Create a record").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector7).option("--set <field=value>", "set a string field", collectKeyValueAssignments, []).option("--set-json <field=json>", "set a structured field", collectJsonAssignments, []).option("--raw <json>", "raw JSON object payload").option("--raw-file <path>", "path to a raw JSON object payload").action(async function action(schema, commandOptions) {
6282
9246
  const { api, schemasApi, json, readOnly } = createRecordsApi(this, filePath);
6283
9247
  ensureWritable6("records create", readOnly, "write");
6284
9248
  const resolvedSchema = await resolveSchemaSelector(schemasApi, schema);
@@ -6287,12 +9251,12 @@ function registerRecordsCommands(program, options = {}) {
6287
9251
  buildRecordCreateInput(commandOptions)
6288
9252
  );
6289
9253
  if (json) {
6290
- emitJson8(stdout, "records create", data, filePath);
9254
+ emitJson9(stdout, "records create", data, filePath);
6291
9255
  return;
6292
9256
  }
6293
- writeLine8(stdout, `Created record "${getRecordIdentifier(data)}".`);
9257
+ writeLine9(stdout, `Created record "${getRecordIdentifier(data)}".`);
6294
9258
  });
6295
- records.command("update").description("Update a record").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector6).argument("<record>", "record uuid or slug", parseUuidOrSlugSelector6).option("--set <field=value>", "set a string field", collectKeyValueAssignments, []).option("--set-json <field=json>", "set a structured field", collectJsonAssignments, []).option("--unset <field>", "unset a field", collectStringValues, []).option("--raw <json>", "raw JSON object payload").option("--raw-file <path>", "path to a raw JSON object payload").action(async function action(schema, record, commandOptions) {
9259
+ records.command("update").description("Update a record").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector7).argument("<record>", "record uuid or slug", parseUuidOrSlugSelector7).option("--set <field=value>", "set a string field", collectKeyValueAssignments, []).option("--set-json <field=json>", "set a structured field", collectJsonAssignments, []).option("--unset <field>", "unset a field", collectStringValues, []).option("--raw <json>", "raw JSON object payload").option("--raw-file <path>", "path to a raw JSON object payload").action(async function action(schema, record, commandOptions) {
6296
9260
  const { api, schemasApi, json, readOnly } = createRecordsApi(this, filePath);
6297
9261
  ensureWritable6("records update", readOnly, "write");
6298
9262
  const resolvedSchema = await resolveSchemaSelector(schemasApi, schema);
@@ -6302,12 +9266,12 @@ function registerRecordsCommands(program, options = {}) {
6302
9266
  buildRecordUpdateInput(commandOptions)
6303
9267
  );
6304
9268
  if (json) {
6305
- emitJson8(stdout, "records update", data, filePath);
9269
+ emitJson9(stdout, "records update", data, filePath);
6306
9270
  return;
6307
9271
  }
6308
- writeLine8(stdout, `Updated record "${getRecordIdentifier(data)}".`);
9272
+ writeLine9(stdout, `Updated record "${getRecordIdentifier(data)}".`);
6309
9273
  });
6310
- records.command("delete").description("Delete a record").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector6).argument("<record>", "record uuid or slug", parseUuidOrSlugSelector6).action(async function action(schema, record) {
9274
+ records.command("delete").description("Delete a record").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector7).argument("<record>", "record uuid or slug", parseUuidOrSlugSelector7).action(async function action(schema, record) {
6311
9275
  const { api, schemasApi, json, readOnly } = createRecordsApi(this, filePath);
6312
9276
  ensureWritable6("records delete", readOnly, "destructive");
6313
9277
  const resolvedSchema = await resolveSchemaSelector(schemasApi, schema);
@@ -6318,33 +9282,33 @@ function registerRecordsCommands(program, options = {}) {
6318
9282
  deleted: true
6319
9283
  };
6320
9284
  if (json) {
6321
- emitJson8(stdout, "records delete", data, filePath);
9285
+ emitJson9(stdout, "records delete", data, filePath);
6322
9286
  return;
6323
9287
  }
6324
- writeLine8(stdout, `Deleted record "${record.value}" from schema "${schema.value}".`);
9288
+ writeLine9(stdout, `Deleted record "${record.value}" from schema "${schema.value}".`);
6325
9289
  });
6326
9290
  }
6327
9291
 
6328
9292
  // src/commands/schemas.ts
6329
9293
  import { readFileSync as readFileSync8 } from "fs";
6330
- import { InvalidArgumentError as InvalidArgumentError7 } from "commander";
6331
- function getCommandIo9(stdout) {
9294
+ import { InvalidArgumentError as InvalidArgumentError8 } from "commander";
9295
+ function getCommandIo10(stdout) {
6332
9296
  return stdout ?? process.stdout;
6333
9297
  }
6334
- function writeLine9(stdout, value) {
9298
+ function writeLine10(stdout, value) {
6335
9299
  stdout.write(`${value}
6336
9300
  `);
6337
9301
  }
6338
- function getGlobalOptions9(command) {
9302
+ function getGlobalOptions10(command) {
6339
9303
  return command.optsWithGlobals();
6340
9304
  }
6341
- function emitJson9(stdout, commandName, data, configPath) {
6342
- writeLine9(
9305
+ function emitJson10(stdout, commandName, data, configPath) {
9306
+ writeLine10(
6343
9307
  stdout,
6344
9308
  JSON.stringify(buildJsonSuccess(data, { command: commandName, configPath }))
6345
9309
  );
6346
9310
  }
6347
- function toConfigurationError8(filePath, error) {
9311
+ function toConfigurationError9(filePath, error) {
6348
9312
  if (error instanceof CliError) {
6349
9313
  throw error;
6350
9314
  }
@@ -6359,7 +9323,7 @@ function toConfigurationError8(filePath, error) {
6359
9323
  function createSchemasApi(command, filePath) {
6360
9324
  try {
6361
9325
  const config = readRuntimeConfig(filePath);
6362
- const runtime = resolveRuntimeContext(config, getGlobalOptions9(command));
9326
+ const runtime = resolveRuntimeContext(config, getGlobalOptions10(command));
6363
9327
  if (!runtime.baseUrl) {
6364
9328
  throw new CliError(
6365
9329
  "configuration_error",
@@ -6378,7 +9342,7 @@ function createSchemasApi(command, filePath) {
6378
9342
  readOnly: runtime.readOnly
6379
9343
  };
6380
9344
  } catch (error) {
6381
- toConfigurationError8(filePath, error);
9345
+ toConfigurationError9(filePath, error);
6382
9346
  }
6383
9347
  }
6384
9348
  function ensureWritable7(commandName, readOnly, commandMode) {
@@ -6393,12 +9357,12 @@ function ensureWritable7(commandName, readOnly, commandMode) {
6393
9357
  );
6394
9358
  }
6395
9359
  }
6396
- function parseUuidOrSlugSelector7(input) {
9360
+ function parseUuidOrSlugSelector8(input) {
6397
9361
  try {
6398
9362
  return normalizeUuidOrSlug(input);
6399
9363
  } catch (error) {
6400
9364
  const message = error instanceof Error ? error.message : "Invalid selector.";
6401
- throw new InvalidArgumentError7(message);
9365
+ throw new InvalidArgumentError8(message);
6402
9366
  }
6403
9367
  }
6404
9368
  function parseBooleanFlag(input) {
@@ -6409,9 +9373,9 @@ function parseBooleanFlag(input) {
6409
9373
  if (["false", "0", "no", "n", "off"].includes(normalized)) {
6410
9374
  return false;
6411
9375
  }
6412
- throw new InvalidArgumentError7(`Expected a boolean value, received "${input}".`);
9376
+ throw new InvalidArgumentError8(`Expected a boolean value, received "${input}".`);
6413
9377
  }
6414
- function isJsonObject5(value) {
9378
+ function isJsonObject6(value) {
6415
9379
  return typeof value === "object" && value !== null && !Array.isArray(value);
6416
9380
  }
6417
9381
  function parseRawJsonObject3(input, sourceLabel) {
@@ -6425,7 +9389,7 @@ function parseRawJsonObject3(input, sourceLabel) {
6425
9389
  `Failed to parse JSON from ${sourceLabel}: ${message}`
6426
9390
  );
6427
9391
  }
6428
- if (!isJsonObject5(parsed)) {
9392
+ if (!isJsonObject6(parsed)) {
6429
9393
  throw new CliError(
6430
9394
  "invalid_cli_usage",
6431
9395
  `Expected ${sourceLabel} to contain a JSON object.`
@@ -6528,7 +9492,7 @@ function buildFieldCreateInput(options) {
6528
9492
  if (options.required !== void 0) {
6529
9493
  input.required = options.required;
6530
9494
  }
6531
- if ("config" in input && isJsonObject5(input.config) && isEmptyObject5(input.config)) {
9495
+ if ("config" in input && isJsonObject6(input.config) && isEmptyObject5(input.config)) {
6532
9496
  delete input.config;
6533
9497
  }
6534
9498
  return input;
@@ -6605,23 +9569,23 @@ function isEmptyObject5(value) {
6605
9569
  }
6606
9570
  function registerSchemasCommands(program, options = {}) {
6607
9571
  const filePath = options.configPath ?? defaultConfigPath;
6608
- const stdout = getCommandIo9(options.stdout);
9572
+ const stdout = getCommandIo10(options.stdout);
6609
9573
  const schemas = program.command("schemas").description("Manage schemas and schema fields");
6610
9574
  schemas.command("list").description("List schemas").action(async function action() {
6611
9575
  const { api, json } = createSchemasApi(this, filePath);
6612
9576
  const data = await api.listSchemas();
6613
9577
  if (json) {
6614
- emitJson9(stdout, "schemas list", data, filePath);
9578
+ emitJson10(stdout, "schemas list", data, filePath);
6615
9579
  return;
6616
9580
  }
6617
9581
  emitSchemasTable(stdout, data);
6618
9582
  });
6619
- schemas.command("get").description("Get a schema by UUID or slug").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector7).action(async function action(schema) {
9583
+ schemas.command("get").description("Get a schema by UUID or slug").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector8).action(async function action(schema) {
6620
9584
  const { api, json } = createSchemasApi(this, filePath);
6621
9585
  const resolvedSchema = await resolveSchemaSelector2(api, schema);
6622
9586
  const data = await api.getSchema(resolvedSchema);
6623
9587
  if (json) {
6624
- emitJson9(stdout, "schemas get", data, filePath);
9588
+ emitJson10(stdout, "schemas get", data, filePath);
6625
9589
  return;
6626
9590
  }
6627
9591
  emitSchemasTable(stdout, [data]);
@@ -6637,12 +9601,12 @@ function registerSchemasCommands(program, options = {}) {
6637
9601
  };
6638
9602
  const data = await api.createSchema(input);
6639
9603
  if (json) {
6640
- emitJson9(stdout, "schemas create", data, filePath);
9604
+ emitJson10(stdout, "schemas create", data, filePath);
6641
9605
  return;
6642
9606
  }
6643
- writeLine9(stdout, `Created schema "${data.slug ?? commandOptions.slug}".`);
9607
+ writeLine10(stdout, `Created schema "${data.slug ?? commandOptions.slug}".`);
6644
9608
  });
6645
- schemas.command("update").description("Update a schema").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector7).option("--name <name>", "schema name").option("--slug <slug>", "schema slug").option("--auditable <bool>", "auditable flag", parseBooleanFlag).option("--commentable <bool>", "commentable flag", parseBooleanFlag).action(async function action(schema, commandOptions) {
9609
+ schemas.command("update").description("Update a schema").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector8).option("--name <name>", "schema name").option("--slug <slug>", "schema slug").option("--auditable <bool>", "auditable flag", parseBooleanFlag).option("--commentable <bool>", "commentable flag", parseBooleanFlag).action(async function action(schema, commandOptions) {
6646
9610
  const { api, json, readOnly } = createSchemasApi(this, filePath);
6647
9611
  ensureWritable7("schemas update", readOnly, "write");
6648
9612
  const resolvedSchema = await resolveSchemaSelector2(api, schema);
@@ -6655,12 +9619,12 @@ function registerSchemasCommands(program, options = {}) {
6655
9619
  }
6656
9620
  const data = await api.updateSchema(resolvedSchema, input);
6657
9621
  if (json) {
6658
- emitJson9(stdout, "schemas update", data, filePath);
9622
+ emitJson10(stdout, "schemas update", data, filePath);
6659
9623
  return;
6660
9624
  }
6661
- writeLine9(stdout, `Updated schema "${data.slug ?? schema.value}".`);
9625
+ writeLine10(stdout, `Updated schema "${data.slug ?? schema.value}".`);
6662
9626
  });
6663
- schemas.command("delete").description("Delete a schema").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector7).action(async function action(schema) {
9627
+ schemas.command("delete").description("Delete a schema").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector8).action(async function action(schema) {
6664
9628
  const { api, json, readOnly } = createSchemasApi(this, filePath);
6665
9629
  ensureWritable7("schemas delete", readOnly, "destructive");
6666
9630
  const resolvedSchema = await resolveSchemaSelector2(api, schema);
@@ -6670,34 +9634,34 @@ function registerSchemasCommands(program, options = {}) {
6670
9634
  deleted: true
6671
9635
  };
6672
9636
  if (json) {
6673
- emitJson9(stdout, "schemas delete", data, filePath);
9637
+ emitJson10(stdout, "schemas delete", data, filePath);
6674
9638
  return;
6675
9639
  }
6676
- writeLine9(stdout, `Deleted schema "${schema.value}".`);
9640
+ writeLine10(stdout, `Deleted schema "${schema.value}".`);
6677
9641
  });
6678
9642
  const fields = schemas.command("fields").description("Manage schema fields");
6679
- fields.command("list").description("List fields for a schema").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector7).action(async function action(schema) {
9643
+ fields.command("list").description("List fields for a schema").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector8).action(async function action(schema) {
6680
9644
  const { api, json } = createSchemasApi(this, filePath);
6681
9645
  const resolvedSchema = await resolveSchemaSelector2(api, schema);
6682
9646
  const data = await api.listFields(resolvedSchema);
6683
9647
  if (json) {
6684
- emitJson9(stdout, "schemas fields list", data, filePath);
9648
+ emitJson10(stdout, "schemas fields list", data, filePath);
6685
9649
  return;
6686
9650
  }
6687
9651
  emitFieldsTable(stdout, data);
6688
9652
  });
6689
- fields.command("get").description("Get a field by UUID or slug").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector7).argument("<field>", "field uuid or slug", parseUuidOrSlugSelector7).action(async function action(schema, field) {
9653
+ fields.command("get").description("Get a field by UUID or slug").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector8).argument("<field>", "field uuid or slug", parseUuidOrSlugSelector8).action(async function action(schema, field) {
6690
9654
  const { api, json } = createSchemasApi(this, filePath);
6691
9655
  const resolvedSchema = await resolveSchemaSelector2(api, schema);
6692
9656
  const resolvedField = await resolveFieldSelector(api, resolvedSchema, field);
6693
9657
  const data = await api.getField(resolvedSchema, resolvedField);
6694
9658
  if (json) {
6695
- emitJson9(stdout, "schemas fields get", data, filePath);
9659
+ emitJson10(stdout, "schemas fields get", data, filePath);
6696
9660
  return;
6697
9661
  }
6698
9662
  emitFieldsTable(stdout, [data]);
6699
9663
  });
6700
- fields.command("create").description(`Create a field in a schema.${buildSchemaFieldCreateHelpText()}`).argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector7).option("--type <type>", `field type (${formatSchemaFieldTypes()})`).option("--slug <slug>", "field slug").option("--label <label>", "field label").option("--required <bool>", "required flag", parseBooleanFlag).option("--raw <json>", "raw JSON object payload (see type-specific shapes in --help)").option("--raw-file <path>", "path to a raw JSON object payload").action(async function action(schema, commandOptions) {
9664
+ fields.command("create").description(`Create a field in a schema.${buildSchemaFieldCreateHelpText()}`).argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector8).option("--type <type>", `field type (${formatSchemaFieldTypes()})`).option("--slug <slug>", "field slug").option("--label <label>", "field label").option("--required <bool>", "required flag", parseBooleanFlag).option("--raw <json>", "raw JSON object payload (see type-specific shapes in --help)").option("--raw-file <path>", "path to a raw JSON object payload").action(async function action(schema, commandOptions) {
6701
9665
  const { api, json, readOnly } = createSchemasApi(this, filePath);
6702
9666
  ensureWritable7("schemas fields create", readOnly, "write");
6703
9667
  const input = buildFieldCreateInput(commandOptions);
@@ -6709,12 +9673,12 @@ function registerSchemasCommands(program, options = {}) {
6709
9673
  toFieldCreateError(error, input);
6710
9674
  }
6711
9675
  if (json) {
6712
- emitJson9(stdout, "schemas fields create", data, filePath);
9676
+ emitJson10(stdout, "schemas fields create", data, filePath);
6713
9677
  return;
6714
9678
  }
6715
- writeLine9(stdout, `Created field "${data.slug ?? commandOptions.slug}".`);
9679
+ writeLine10(stdout, `Created field "${data.slug ?? commandOptions.slug}".`);
6716
9680
  });
6717
- fields.command("update").description("Update a field in a schema").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector7).argument("<field>", "field uuid or slug", parseUuidOrSlugSelector7).option("--label <label>", "field label").option("--required <bool>", "required flag", parseBooleanFlag).option("--raw <json>", "raw JSON object payload").option("--raw-file <path>", "path to a raw JSON object payload").action(async function action(schema, field, commandOptions) {
9681
+ fields.command("update").description("Update a field in a schema").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector8).argument("<field>", "field uuid or slug", parseUuidOrSlugSelector8).option("--label <label>", "field label").option("--required <bool>", "required flag", parseBooleanFlag).option("--raw <json>", "raw JSON object payload").option("--raw-file <path>", "path to a raw JSON object payload").action(async function action(schema, field, commandOptions) {
6718
9682
  const { api, json, readOnly } = createSchemasApi(this, filePath);
6719
9683
  ensureWritable7("schemas fields update", readOnly, "write");
6720
9684
  const resolvedSchema = await resolveSchemaSelector2(api, schema);
@@ -6733,12 +9697,12 @@ function registerSchemasCommands(program, options = {}) {
6733
9697
  }
6734
9698
  const data = await api.updateField(resolvedSchema, resolvedField, input);
6735
9699
  if (json) {
6736
- emitJson9(stdout, "schemas fields update", data, filePath);
9700
+ emitJson10(stdout, "schemas fields update", data, filePath);
6737
9701
  return;
6738
9702
  }
6739
- writeLine9(stdout, `Updated field "${data.slug ?? field.value}".`);
9703
+ writeLine10(stdout, `Updated field "${data.slug ?? field.value}".`);
6740
9704
  });
6741
- fields.command("delete").description("Delete a field from a schema").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector7).argument("<field>", "field uuid or slug", parseUuidOrSlugSelector7).action(async function action(schema, field) {
9705
+ fields.command("delete").description("Delete a field from a schema").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector8).argument("<field>", "field uuid or slug", parseUuidOrSlugSelector8).action(async function action(schema, field) {
6742
9706
  const { api, json, readOnly } = createSchemasApi(this, filePath);
6743
9707
  ensureWritable7("schemas fields delete", readOnly, "destructive");
6744
9708
  const resolvedSchema = await resolveSchemaSelector2(api, schema);
@@ -6750,16 +9714,16 @@ function registerSchemasCommands(program, options = {}) {
6750
9714
  deleted: true
6751
9715
  };
6752
9716
  if (json) {
6753
- emitJson9(stdout, "schemas fields delete", data, filePath);
9717
+ emitJson10(stdout, "schemas fields delete", data, filePath);
6754
9718
  return;
6755
9719
  }
6756
- writeLine9(stdout, `Deleted field "${field.value}" from schema "${schema.value}".`);
9720
+ writeLine10(stdout, `Deleted field "${field.value}" from schema "${schema.value}".`);
6757
9721
  });
6758
9722
  }
6759
9723
 
6760
9724
  // src/commands/teamspace.ts
6761
9725
  import { readFileSync as readFileSync9 } from "fs";
6762
- import { InvalidArgumentError as InvalidArgumentError8 } from "commander";
9726
+ import { InvalidArgumentError as InvalidArgumentError9 } from "commander";
6763
9727
 
6764
9728
  // src/api/teamspace.ts
6765
9729
  function jsonOptions7(body, method) {
@@ -6771,7 +9735,7 @@ function jsonOptions7(body, method) {
6771
9735
  body: JSON.stringify(body)
6772
9736
  };
6773
9737
  }
6774
- function selectorValue8(selector2) {
9738
+ function selectorValue9(selector2) {
6775
9739
  return selector2.value;
6776
9740
  }
6777
9741
  var TeamspaceApi = class {
@@ -6797,13 +9761,13 @@ var TeamspaceApi = class {
6797
9761
  }
6798
9762
  updateFolder(folder, input) {
6799
9763
  return this.client.requestJson(
6800
- `/api/v2/teamspaces/folders/${selectorValue8(folder)}`,
9764
+ `/api/v2/teamspaces/folders/${selectorValue9(folder)}`,
6801
9765
  jsonOptions7(input, "PATCH")
6802
9766
  );
6803
9767
  }
6804
9768
  deleteFolder(folder) {
6805
9769
  return this.client.requestJson(
6806
- `/api/v2/teamspaces/folders/${selectorValue8(folder)}`,
9770
+ `/api/v2/teamspaces/folders/${selectorValue9(folder)}`,
6807
9771
  { method: "DELETE" }
6808
9772
  );
6809
9773
  }
@@ -6822,23 +9786,23 @@ var TeamspaceApi = class {
6822
9786
  };
6823
9787
 
6824
9788
  // src/commands/teamspace.ts
6825
- function getCommandIo10(stdout) {
9789
+ function getCommandIo11(stdout) {
6826
9790
  return stdout ?? process.stdout;
6827
9791
  }
6828
- function writeLine10(stdout, value) {
9792
+ function writeLine11(stdout, value) {
6829
9793
  stdout.write(`${value}
6830
9794
  `);
6831
9795
  }
6832
- function getGlobalOptions10(command) {
9796
+ function getGlobalOptions11(command) {
6833
9797
  return command.optsWithGlobals();
6834
9798
  }
6835
- function emitJson10(stdout, commandName, data, configPath) {
6836
- writeLine10(
9799
+ function emitJson11(stdout, commandName, data, configPath) {
9800
+ writeLine11(
6837
9801
  stdout,
6838
9802
  JSON.stringify(buildJsonSuccess(data, { command: commandName, configPath }))
6839
9803
  );
6840
9804
  }
6841
- function toConfigurationError9(filePath, error) {
9805
+ function toConfigurationError10(filePath, error) {
6842
9806
  if (error instanceof CliError) {
6843
9807
  throw error;
6844
9808
  }
@@ -6853,7 +9817,7 @@ function toConfigurationError9(filePath, error) {
6853
9817
  function createTeamspaceApi(command, filePath) {
6854
9818
  try {
6855
9819
  const config = readRuntimeConfig(filePath);
6856
- const runtime = resolveRuntimeContext(config, getGlobalOptions10(command));
9820
+ const runtime = resolveRuntimeContext(config, getGlobalOptions11(command));
6857
9821
  if (!runtime.baseUrl) {
6858
9822
  throw new CliError(
6859
9823
  "configuration_error",
@@ -6871,7 +9835,7 @@ function createTeamspaceApi(command, filePath) {
6871
9835
  readOnly: runtime.readOnly
6872
9836
  };
6873
9837
  } catch (error) {
6874
- toConfigurationError9(filePath, error);
9838
+ toConfigurationError10(filePath, error);
6875
9839
  }
6876
9840
  }
6877
9841
  function ensureWritable8(commandName, readOnly, commandMode) {
@@ -6886,21 +9850,21 @@ function ensureWritable8(commandName, readOnly, commandMode) {
6886
9850
  );
6887
9851
  }
6888
9852
  }
6889
- function parseUuidOrSlugSelector8(input) {
9853
+ function parseUuidOrSlugSelector9(input) {
6890
9854
  try {
6891
9855
  return normalizeUuidOrSlug(input);
6892
9856
  } catch (error) {
6893
9857
  const message = error instanceof Error ? error.message : "Invalid selector.";
6894
- throw new InvalidArgumentError8(message);
9858
+ throw new InvalidArgumentError9(message);
6895
9859
  }
6896
9860
  }
6897
9861
  function parseNonNegativeInteger3(input) {
6898
9862
  if (!/^\d+$/.test(input.trim())) {
6899
- throw new InvalidArgumentError8(`Expected a non-negative integer, received "${input}".`);
9863
+ throw new InvalidArgumentError9(`Expected a non-negative integer, received "${input}".`);
6900
9864
  }
6901
9865
  return Number(input);
6902
9866
  }
6903
- function isJsonObject6(value) {
9867
+ function isJsonObject7(value) {
6904
9868
  return typeof value === "object" && value !== null && !Array.isArray(value);
6905
9869
  }
6906
9870
  function parseRawJsonObject4(input, sourceLabel) {
@@ -6914,7 +9878,7 @@ function parseRawJsonObject4(input, sourceLabel) {
6914
9878
  `Failed to parse JSON from ${sourceLabel}: ${message}`
6915
9879
  );
6916
9880
  }
6917
- if (!isJsonObject6(parsed)) {
9881
+ if (!isJsonObject7(parsed)) {
6918
9882
  throw new CliError(
6919
9883
  "invalid_cli_usage",
6920
9884
  `Expected ${sourceLabel} to contain a JSON object.`
@@ -6986,17 +9950,17 @@ function buildFolderUpdateInput(options) {
6986
9950
  }
6987
9951
  return input;
6988
9952
  }
6989
- function toTableRows4(data) {
9953
+ function toTableRows5(data) {
6990
9954
  if (Array.isArray(data)) {
6991
- return data.map((entry) => isJsonObject6(entry) ? entry : { value: entry });
9955
+ return data.map((entry) => isJsonObject7(entry) ? entry : { value: entry });
6992
9956
  }
6993
- if (isJsonObject6(data)) {
9957
+ if (isJsonObject7(data)) {
6994
9958
  return [data];
6995
9959
  }
6996
9960
  return [{ value: data }];
6997
9961
  }
6998
- function emitTable4(stdout, data) {
6999
- printTable(toTableRows4(data), void 0, stdout);
9962
+ function emitTable5(stdout, data) {
9963
+ printTable(toTableRows5(data), void 0, stdout);
7000
9964
  }
7001
9965
  function getFolderIdentifier(folder) {
7002
9966
  return typeof folder.id === "string" ? folder.id : typeof folder.name === "string" ? folder.name : "unknown";
@@ -7052,63 +10016,63 @@ async function resolveFolderSelector2(api, selector2) {
7052
10016
  }
7053
10017
  function registerTeamspaceCommands(program, options = {}) {
7054
10018
  const filePath = options.configPath ?? defaultConfigPath;
7055
- const stdout = getCommandIo10(options.stdout);
10019
+ const stdout = getCommandIo11(options.stdout);
7056
10020
  const teamspace = program.command("teamspace").description("Manage teamspace folders and resources");
7057
10021
  const folders = teamspace.command("folders").description("Manage teamspace folders");
7058
10022
  folders.command("list").description("List teamspace folders").option("--include-resources", "include nested resources").action(async function action(commandOptions) {
7059
10023
  const { api, json } = createTeamspaceApi(this, filePath);
7060
10024
  const data = await api.listFolders(Boolean(commandOptions.includeResources));
7061
10025
  if (json) {
7062
- emitJson10(stdout, "teamspace folders list", data, filePath);
10026
+ emitJson11(stdout, "teamspace folders list", data, filePath);
7063
10027
  return;
7064
10028
  }
7065
- emitTable4(stdout, data);
10029
+ emitTable5(stdout, data);
7066
10030
  });
7067
- folders.command("get").description("Get a teamspace folder by exact name or UUID").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector8).option("--include-resources", "include nested resources").action(async function action(folder, commandOptions) {
10031
+ folders.command("get").description("Get a teamspace folder by exact name or UUID").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector9).option("--include-resources", "include nested resources").action(async function action(folder, commandOptions) {
7068
10032
  const { api, json } = createTeamspaceApi(this, filePath);
7069
10033
  const resolvedFolder = await resolveFolderSelector2(api, folder);
7070
10034
  const allFolders = await api.listFolders(Boolean(commandOptions.includeResources));
7071
10035
  const data = findFolderEntity(allFolders, resolvedFolder);
7072
10036
  if (json) {
7073
- emitJson10(stdout, "teamspace folders get", data, filePath);
10037
+ emitJson11(stdout, "teamspace folders get", data, filePath);
7074
10038
  return;
7075
10039
  }
7076
- emitTable4(stdout, data);
10040
+ emitTable5(stdout, data);
7077
10041
  });
7078
10042
  folders.command("create").description("Create a teamspace folder").requiredOption("--name <name>", "folder name").option("--order <n>", "folder order", parseNonNegativeInteger3).option("--props <json>", "folder properties payload").option("--props-file <path>", "path to a folder properties JSON payload").action(async function action(commandOptions) {
7079
10043
  const { api, json, readOnly } = createTeamspaceApi(this, filePath);
7080
10044
  ensureWritable8("teamspace folders create", readOnly, "write");
7081
10045
  const data = await api.createFolder(buildFolderCreateInput(commandOptions));
7082
10046
  if (json) {
7083
- emitJson10(stdout, "teamspace folders create", data, filePath);
10047
+ emitJson11(stdout, "teamspace folders create", data, filePath);
7084
10048
  return;
7085
10049
  }
7086
- writeLine10(stdout, `Created folder "${getFolderIdentifier(data)}".`);
10050
+ writeLine11(stdout, `Created folder "${getFolderIdentifier(data)}".`);
7087
10051
  });
7088
- folders.command("update").description("Update a teamspace folder").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector8).option("--name <name>", "folder name").option("--order <n>", "folder order", parseNonNegativeInteger3).option("--props <json>", "folder properties payload").option("--props-file <path>", "path to a folder properties JSON payload").action(async function action(folder, commandOptions) {
10052
+ folders.command("update").description("Update a teamspace folder").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector9).option("--name <name>", "folder name").option("--order <n>", "folder order", parseNonNegativeInteger3).option("--props <json>", "folder properties payload").option("--props-file <path>", "path to a folder properties JSON payload").action(async function action(folder, commandOptions) {
7089
10053
  const { api, json, readOnly } = createTeamspaceApi(this, filePath);
7090
10054
  ensureWritable8("teamspace folders update", readOnly, "write");
7091
10055
  const resolvedFolder = await resolveFolderSelector2(api, folder);
7092
10056
  const data = await api.updateFolder(resolvedFolder, buildFolderUpdateInput(commandOptions));
7093
10057
  if (json) {
7094
- emitJson10(stdout, "teamspace folders update", data, filePath);
10058
+ emitJson11(stdout, "teamspace folders update", data, filePath);
7095
10059
  return;
7096
10060
  }
7097
- writeLine10(stdout, `Updated folder "${getFolderIdentifier(data)}".`);
10061
+ writeLine11(stdout, `Updated folder "${getFolderIdentifier(data)}".`);
7098
10062
  });
7099
- folders.command("delete").description("Delete a teamspace folder").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector8).action(async function action(folder) {
10063
+ folders.command("delete").description("Delete a teamspace folder").argument("<folder>", "folder UUID or exact name", parseUuidOrSlugSelector9).action(async function action(folder) {
7100
10064
  const { api, json, readOnly } = createTeamspaceApi(this, filePath);
7101
10065
  ensureWritable8("teamspace folders delete", readOnly, "destructive");
7102
10066
  const resolvedFolder = await resolveFolderSelector2(api, folder);
7103
10067
  const data = await api.deleteFolder(resolvedFolder);
7104
10068
  if (json) {
7105
- emitJson10(stdout, "teamspace folders delete", data, filePath);
10069
+ emitJson11(stdout, "teamspace folders delete", data, filePath);
7106
10070
  return;
7107
10071
  }
7108
- writeLine10(stdout, `Deleted folder "${resolvedFolder.value}".`);
10072
+ writeLine11(stdout, `Deleted folder "${resolvedFolder.value}".`);
7109
10073
  });
7110
10074
  const resources = teamspace.command("resources").description("Manage teamspace resources");
7111
- resources.command("publish").description("Publish a resource to a teamspace folder").argument("<resource>", "resource UUID or exact name", parseUuidOrSlugSelector8).requiredOption("--to <folder>", "target folder", parseUuidOrSlugSelector8).action(async function action(resource, commandOptions) {
10075
+ resources.command("publish").description("Publish a resource to a teamspace folder").argument("<resource>", "resource UUID or exact name", parseUuidOrSlugSelector9).requiredOption("--to <folder>", "target folder", parseUuidOrSlugSelector9).action(async function action(resource, commandOptions) {
7112
10076
  const { api, json, readOnly } = createTeamspaceApi(this, filePath);
7113
10077
  ensureWritable8("teamspace resources publish", readOnly, "write");
7114
10078
  const folder = await resolveFolderSelector2(api, commandOptions.to);
@@ -7117,20 +10081,20 @@ function registerTeamspaceCommands(program, options = {}) {
7117
10081
  targetFolderId: folder.value
7118
10082
  });
7119
10083
  if (json) {
7120
- emitJson10(stdout, "teamspace resources publish", data, filePath);
10084
+ emitJson11(stdout, "teamspace resources publish", data, filePath);
7121
10085
  return;
7122
10086
  }
7123
- writeLine10(stdout, `Published resource "${resource.value}" to folder "${folder.value}".`);
10087
+ writeLine11(stdout, `Published resource "${resource.value}" to folder "${folder.value}".`);
7124
10088
  });
7125
- resources.command("unpublish").description("Unpublish a resource from teamspace").argument("<resource>", "resource UUID or exact name", parseUuidOrSlugSelector8).action(async function action(resource) {
10089
+ resources.command("unpublish").description("Unpublish a resource from teamspace").argument("<resource>", "resource UUID or exact name", parseUuidOrSlugSelector9).action(async function action(resource) {
7126
10090
  const { api, json, readOnly } = createTeamspaceApi(this, filePath);
7127
10091
  ensureWritable8("teamspace resources unpublish", readOnly, "write");
7128
10092
  const data = await api.unpublishResource(resource.value);
7129
10093
  if (json) {
7130
- emitJson10(stdout, "teamspace resources unpublish", data, filePath);
10094
+ emitJson11(stdout, "teamspace resources unpublish", data, filePath);
7131
10095
  return;
7132
10096
  }
7133
- writeLine10(stdout, `Unpublished resource "${resource.value}".`);
10097
+ writeLine11(stdout, `Unpublished resource "${resource.value}".`);
7134
10098
  });
7135
10099
  }
7136
10100
 
@@ -7138,7 +10102,7 @@ function registerTeamspaceCommands(program, options = {}) {
7138
10102
  var require2 = createRequire(import.meta.url);
7139
10103
  var { version } = require2("../package.json");
7140
10104
  function buildProgram(options = {}) {
7141
- const program = new Command9();
10105
+ const program = new Command10();
7142
10106
  program.name("zinkee").description("CLI for Zinkee API v2").version(version).enablePositionalOptions().showHelpAfterError().option("--profile <name>", "select a profile from config").option("--base-url <url>", "override the configured base URL").option("--api-key <token>", "override the configured API key").option("--read-only", "run in read-only mode").option("--example", "show examples for a command").option("--json", "emit JSON output");
7143
10107
  registerProfilesCommands(program, options);
7144
10108
  registerAutomationsCommands(program, options);
@@ -7149,6 +10113,7 @@ function buildProgram(options = {}) {
7149
10113
  registerSchemasCommands(program, options);
7150
10114
  registerRecordsCommands(program, options);
7151
10115
  registerCommentsCommands(program, options);
10116
+ registerLogsCommands(program, options);
7152
10117
  registerTeamspaceCommands(program, options);
7153
10118
  return program;
7154
10119
  }