zinkee 0.1.12 → 0.1.15
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/AGENTS.md +42 -0
- package/README.md +7 -0
- package/dist/index.js +64 -30
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/api/records.ts +7 -0
- package/src/command-registry.ts +7 -0
- package/src/commands/automations.test.ts +5 -5
- package/src/commands/displays.test.ts +2 -2
- package/src/commands/records.test.ts +58 -0
- package/src/commands/records.ts +19 -0
- package/src/utils/examples.ts +32 -21
- package/src/utils/schema-fields.ts +11 -9
package/AGENTS.md
CHANGED
|
@@ -50,3 +50,45 @@ Use this order when reasoning about behavior:
|
|
|
50
50
|
## Testing
|
|
51
51
|
|
|
52
52
|
Prefer focused command tests and parser/client unit tests.
|
|
53
|
+
|
|
54
|
+
> **Unit tests use `fetchMock` and never hit the real API.** When changing the
|
|
55
|
+
> shape of a payload (enum values, property names, structure), unit tests will
|
|
56
|
+
> still pass even if the real API would reject the request with `400`. For
|
|
57
|
+
> shape-sensitive changes — especially edits to strings in `src/utils/examples.ts`
|
|
58
|
+
> — also run the resulting command against a real workspace and confirm the API
|
|
59
|
+
> accepts it.
|
|
60
|
+
|
|
61
|
+
## Contributing
|
|
62
|
+
|
|
63
|
+
### Branches
|
|
64
|
+
|
|
65
|
+
- `feature/eng-<ticket>-<slug>` for Linear-tracked work
|
|
66
|
+
- `fix/<slug>` / `chore/<slug>` / `docs/<slug>` for untracked work
|
|
67
|
+
- Never push to `main` directly; always open a PR
|
|
68
|
+
|
|
69
|
+
### Commits
|
|
70
|
+
|
|
71
|
+
- Conventional Commits format: `<type>(<scope>): <subject>` (e.g.
|
|
72
|
+
`fix(displays): correct chart-type values in widget examples`)
|
|
73
|
+
- Subject in imperative mood, under ~72 chars, no trailing period
|
|
74
|
+
- Body explains the *why*, not the *what* — the diff already shows what changed
|
|
75
|
+
- Stage files explicitly (`git add <path>`); never `git add -A`
|
|
76
|
+
- Don't add `Co-Authored-By:` trailers; existing history doesn't use them
|
|
77
|
+
|
|
78
|
+
### Before committing
|
|
79
|
+
|
|
80
|
+
1. `npm run typecheck` — must pass
|
|
81
|
+
2. `npm test` — must pass
|
|
82
|
+
3. For changes that affect runtime behaviour or `--example` output, also
|
|
83
|
+
exercise the affected commands against a live workspace (see Testing note
|
|
84
|
+
above).
|
|
85
|
+
|
|
86
|
+
### Versioning
|
|
87
|
+
|
|
88
|
+
- Versioning is patch-only today (`0.1.x`). Bump the patch number unless the
|
|
89
|
+
team decides to move to a different scheme.
|
|
90
|
+
- Every PR that ships user-visible changes (new commands, fixed examples,
|
|
91
|
+
behaviour changes) bumps `package.json` version in the same PR — not in a
|
|
92
|
+
separate "release" PR.
|
|
93
|
+
- Before bumping, fetch `origin/main` to make sure the version you pick isn't
|
|
94
|
+
already taken by another PR that merged ahead of yours.
|
package/README.md
CHANGED
|
@@ -273,10 +273,17 @@ zinkee records update projects <record-uuid> --set status=2
|
|
|
273
273
|
|
|
274
274
|
# Delete
|
|
275
275
|
zinkee records delete projects <record-uuid>
|
|
276
|
+
|
|
277
|
+
# Clear all records from a schema (destructive — irreversible)
|
|
278
|
+
zinkee records clear projects
|
|
276
279
|
```
|
|
277
280
|
|
|
278
281
|
Option values are written as numbers (`--set status=1`) but returned as strings (`"1"`). Number values are stored and returned as strings.
|
|
279
282
|
|
|
283
|
+
`records clear` removes every record from the schema's table. Heritage rules
|
|
284
|
+
(`CASCADE` / `SET NULL`) propagate to child schemas asynchronously through the
|
|
285
|
+
CDC pipeline, so related tables converge eventually. Blocked by `--read-only`.
|
|
286
|
+
|
|
280
287
|
---
|
|
281
288
|
|
|
282
289
|
## Files
|
package/dist/index.js
CHANGED
|
@@ -660,6 +660,13 @@ var commandRegistry = {
|
|
|
660
660
|
supportsRaw: false,
|
|
661
661
|
output: writeOutput
|
|
662
662
|
},
|
|
663
|
+
"records clear": {
|
|
664
|
+
command: "records clear",
|
|
665
|
+
accessLevel: "destructive",
|
|
666
|
+
supportsExample: true,
|
|
667
|
+
supportsRaw: false,
|
|
668
|
+
output: writeOutput
|
|
669
|
+
},
|
|
663
670
|
"comments list": {
|
|
664
671
|
command: "comments list",
|
|
665
672
|
accessLevel: "read",
|
|
@@ -2189,17 +2196,17 @@ var fieldTypeDefinitions = [
|
|
|
2189
2196
|
className: "FormulaField",
|
|
2190
2197
|
aliases: ["formula", "FormulaField"],
|
|
2191
2198
|
description: "Calculated field from a formula.",
|
|
2192
|
-
rawShape:
|
|
2199
|
+
rawShape: '{"type":"FormulaField","slug":"formula-code","label":"Formula Code","config":{"formulaText":"concat(\\"CUST-\\", f1e1d000-0000-0000-0000-000000000005)","uiFormatKind":"none"}}',
|
|
2193
2200
|
examplePayloads: [
|
|
2194
2201
|
{
|
|
2195
2202
|
name: "Formula field (none)",
|
|
2196
2203
|
payload: {
|
|
2197
2204
|
type: "FormulaField",
|
|
2198
|
-
slug: "formula-
|
|
2199
|
-
label: "Formula
|
|
2205
|
+
slug: "formula-code",
|
|
2206
|
+
label: "Formula Code",
|
|
2200
2207
|
required: false,
|
|
2201
2208
|
config: {
|
|
2202
|
-
formulaText:
|
|
2209
|
+
formulaText: 'concat("CUST-", f1e1d000-0000-0000-0000-000000000005)',
|
|
2203
2210
|
uiFormatKind: "none",
|
|
2204
2211
|
status: "ACTIVE",
|
|
2205
2212
|
conditionalFormatting: []
|
|
@@ -2214,7 +2221,7 @@ var fieldTypeDefinitions = [
|
|
|
2214
2221
|
label: "Formula Total",
|
|
2215
2222
|
required: false,
|
|
2216
2223
|
config: {
|
|
2217
|
-
formulaText: "
|
|
2224
|
+
formulaText: "c52efe3f-2825-4c60-a7e3-34dd4c1ce043 * 1.21",
|
|
2218
2225
|
uiFormatKind: "number",
|
|
2219
2226
|
status: "ACTIVE",
|
|
2220
2227
|
numberFormatOptions: {
|
|
@@ -2230,11 +2237,11 @@ var fieldTypeDefinitions = [
|
|
|
2230
2237
|
name: "Formula field (date)",
|
|
2231
2238
|
payload: {
|
|
2232
2239
|
type: "FormulaField",
|
|
2233
|
-
slug: "formula-
|
|
2234
|
-
label: "
|
|
2240
|
+
slug: "formula-period",
|
|
2241
|
+
label: "Formula Period",
|
|
2235
2242
|
required: false,
|
|
2236
2243
|
config: {
|
|
2237
|
-
formulaText:
|
|
2244
|
+
formulaText: 'date_format(d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90, "AAAA-MM")',
|
|
2238
2245
|
uiFormatKind: "date",
|
|
2239
2246
|
status: "ACTIVE",
|
|
2240
2247
|
dateFormatOptions: {
|
|
@@ -2254,7 +2261,7 @@ var fieldTypeDefinitions = [
|
|
|
2254
2261
|
label: "Computed Assignee",
|
|
2255
2262
|
required: false,
|
|
2256
2263
|
config: {
|
|
2257
|
-
formulaText: "
|
|
2264
|
+
formulaText: "a7b8c9d0-e1f2-3a4b-5c6d-7e8f90123456",
|
|
2258
2265
|
uiFormatKind: "member",
|
|
2259
2266
|
status: "ACTIVE",
|
|
2260
2267
|
conditionalFormatting: []
|
|
@@ -2991,11 +2998,11 @@ var specificExamples = {
|
|
|
2991
2998
|
},
|
|
2992
2999
|
{
|
|
2993
3000
|
description: "Patch formula field (formula text).",
|
|
2994
|
-
command: `zinkee --json schemas fields update contacts formula-total --raw '{"type":"FormulaField","config":{"formulaText":"
|
|
3001
|
+
command: `zinkee --json schemas fields update contacts formula-total --raw '{"type":"FormulaField","config":{"formulaText":"c52efe3f-2825-4c60-a7e3-34dd4c1ce043 * 1.10","uiFormatKind":"number","status":"ACTIVE","numberFormatOptions":{"format":"number","decimals":2,"thousandsSeparator":true},"conditionalFormatting":[]}}'`,
|
|
2995
3002
|
raw: `{
|
|
2996
3003
|
"type": "FormulaField",
|
|
2997
3004
|
"config": {
|
|
2998
|
-
"formulaText": "
|
|
3005
|
+
"formulaText": "c52efe3f-2825-4c60-a7e3-34dd4c1ce043 * 1.10",
|
|
2999
3006
|
"uiFormatKind": "number",
|
|
3000
3007
|
"status": "ACTIVE",
|
|
3001
3008
|
"numberFormatOptions": {
|
|
@@ -3906,8 +3913,8 @@ var specificExamples = {
|
|
|
3906
3913
|
}`
|
|
3907
3914
|
},
|
|
3908
3915
|
{
|
|
3909
|
-
description: "Create a
|
|
3910
|
-
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
|
|
3916
|
+
description: "Create a bars CHART widget with a time-serie x-axis and two y-axis series.",
|
|
3917
|
+
command: `zinkee --json displays widgets create 0f6f062f-1478-4df2-96a1-c495d037d260 --type CHART --name "Revenue by month" --origin-resource 2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e --layout '{"x":0,"y":0,"w":8,"h":6}' --chart-type bars --x-axis-field due-date --x-axis-date-format MONTH --x-axis-time-series --y-axis-serie '{"typeCalc":"SUM","fieldCalc":"amount","color":"#4B9CD3","axisType":"PRIMARY"}' --y-axis-serie '{"typeCalc":"COUNT","fieldCalc":"id","color":"#E57373","axisType":"SECONDARY"}' --legend '{"position":"bottom"}'`,
|
|
3911
3918
|
raw: `{
|
|
3912
3919
|
"type": "CHART",
|
|
3913
3920
|
"source": {
|
|
@@ -3919,7 +3926,7 @@ var specificExamples = {
|
|
|
3919
3926
|
},
|
|
3920
3927
|
"presentation": { "name": "Revenue by month" },
|
|
3921
3928
|
"chart": {
|
|
3922
|
-
"chartType": "
|
|
3929
|
+
"chartType": "bars",
|
|
3923
3930
|
"xAxisFieldId": "due-date",
|
|
3924
3931
|
"xAxisDateFormat": "MONTH",
|
|
3925
3932
|
"xAxisAsTimeSerie": true,
|
|
@@ -3928,13 +3935,13 @@ var specificExamples = {
|
|
|
3928
3935
|
"typeCalc": "SUM",
|
|
3929
3936
|
"fieldCalc": "amount",
|
|
3930
3937
|
"color": "#4B9CD3",
|
|
3931
|
-
"axisType": "
|
|
3938
|
+
"axisType": "PRIMARY"
|
|
3932
3939
|
},
|
|
3933
3940
|
{
|
|
3934
3941
|
"typeCalc": "COUNT",
|
|
3935
3942
|
"fieldCalc": "id",
|
|
3936
3943
|
"color": "#E57373",
|
|
3937
|
-
"axisType": "
|
|
3944
|
+
"axisType": "SECONDARY"
|
|
3938
3945
|
}
|
|
3939
3946
|
],
|
|
3940
3947
|
"legend": { "position": "bottom" }
|
|
@@ -4080,11 +4087,11 @@ var specificExamples = {
|
|
|
4080
4087
|
}`
|
|
4081
4088
|
},
|
|
4082
4089
|
{
|
|
4083
|
-
description: "Replace the chart series with
|
|
4084
|
-
command: `zinkee --json displays widgets update 0f6f062f-1478-4df2-96a1-c495d037d260 22222222-2222-4222-a222-222222222222 --chart-type
|
|
4090
|
+
description: "Replace the chart series with weekly lines.",
|
|
4091
|
+
command: `zinkee --json displays widgets update 0f6f062f-1478-4df2-96a1-c495d037d260 22222222-2222-4222-a222-222222222222 --chart-type lines --x-axis-field due-date --x-axis-date-format WEEK --x-axis-time-series --y-axis-serie '{"typeCalc":"SUM","fieldCalc":"amount","color":"#2E7D32","axisType":"PRIMARY"}'`,
|
|
4085
4092
|
raw: `{
|
|
4086
4093
|
"chart": {
|
|
4087
|
-
"chartType": "
|
|
4094
|
+
"chartType": "lines",
|
|
4088
4095
|
"xAxisFieldId": "due-date",
|
|
4089
4096
|
"xAxisDateFormat": "WEEK",
|
|
4090
4097
|
"xAxisAsTimeSerie": true,
|
|
@@ -4093,7 +4100,7 @@ var specificExamples = {
|
|
|
4093
4100
|
"typeCalc": "SUM",
|
|
4094
4101
|
"fieldCalc": "amount",
|
|
4095
4102
|
"color": "#2E7D32",
|
|
4096
|
-
"axisType": "
|
|
4103
|
+
"axisType": "PRIMARY"
|
|
4097
4104
|
}
|
|
4098
4105
|
]
|
|
4099
4106
|
}
|
|
@@ -4421,7 +4428,7 @@ var specificExamples = {
|
|
|
4421
4428
|
"required": false,
|
|
4422
4429
|
"system": false,
|
|
4423
4430
|
"config": {
|
|
4424
|
-
"formulaText": "
|
|
4431
|
+
"formulaText": "c52efe3f-2825-4c60-a7e3-34dd4c1ce043 * 1.21",
|
|
4425
4432
|
"uiFormatKind": "number",
|
|
4426
4433
|
"status": "ACTIVE",
|
|
4427
4434
|
"defaultValue": null,
|
|
@@ -4436,12 +4443,12 @@ var specificExamples = {
|
|
|
4436
4443
|
{
|
|
4437
4444
|
"id": "6d7e8f90-1234-5678-9abc-def012345678",
|
|
4438
4445
|
"type": "FormulaField",
|
|
4439
|
-
"slug": "formula-
|
|
4440
|
-
"label": "
|
|
4446
|
+
"slug": "formula-period",
|
|
4447
|
+
"label": "Formula Period",
|
|
4441
4448
|
"required": false,
|
|
4442
4449
|
"system": false,
|
|
4443
4450
|
"config": {
|
|
4444
|
-
"formulaText": "
|
|
4451
|
+
"formulaText": "date_format(d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90, "AAAA-MM")",
|
|
4445
4452
|
"uiFormatKind": "date",
|
|
4446
4453
|
"status": "ACTIVE",
|
|
4447
4454
|
"defaultValue": null,
|
|
@@ -4723,6 +4730,16 @@ var specificExamples = {
|
|
|
4723
4730
|
response: `{
|
|
4724
4731
|
"recordId": "550e8400-e29b-41d4-a716-446655440000",
|
|
4725
4732
|
"deleted": true
|
|
4733
|
+
}`
|
|
4734
|
+
}
|
|
4735
|
+
]),
|
|
4736
|
+
"records clear": buildCommandExamples([
|
|
4737
|
+
{
|
|
4738
|
+
description: "Delete every record from a schema's table. Heritage rules (CASCADE / SET NULL) propagate to child schemas asynchronously via the CDC pipeline.",
|
|
4739
|
+
command: "zinkee --json records clear contacts",
|
|
4740
|
+
response: `{
|
|
4741
|
+
"schemaId": "2eb8bdcf-6d9c-4fbb-9018-7fa8180f4c5e",
|
|
4742
|
+
"cleared": true
|
|
4726
4743
|
}`
|
|
4727
4744
|
}
|
|
4728
4745
|
]),
|
|
@@ -5804,7 +5821,7 @@ var specificExamples = {
|
|
|
5804
5821
|
},
|
|
5805
5822
|
{
|
|
5806
5823
|
description: "Add a search-records action whose condition pulls its value from the trigger payload using --condition-json.",
|
|
5807
|
-
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":"
|
|
5824
|
+
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":"f1e1d000-0000-0000-0000-000000000005"}}]}'`,
|
|
5808
5825
|
raw: `{
|
|
5809
5826
|
"type": "search_records",
|
|
5810
5827
|
"name": "Find duplicates",
|
|
@@ -5819,7 +5836,7 @@ var specificExamples = {
|
|
|
5819
5836
|
"rawValue": null,
|
|
5820
5837
|
"source": {
|
|
5821
5838
|
"type": "TRIGGER",
|
|
5822
|
-
"id": "
|
|
5839
|
+
"id": "f1e1d000-0000-0000-0000-000000000005"
|
|
5823
5840
|
}
|
|
5824
5841
|
}
|
|
5825
5842
|
]
|
|
@@ -6328,7 +6345,7 @@ async function buildDynamicAutomationExamples(commandName, options = {}) {
|
|
|
6328
6345
|
return buildCommandExamples([
|
|
6329
6346
|
{
|
|
6330
6347
|
description: `Add a create-record action with literal and trigger-based mappings targeting ${schemaField.schemaRef}.`,
|
|
6331
|
-
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":"
|
|
6348
|
+
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":"${schemaField.fieldId}"}}'`,
|
|
6332
6349
|
raw: `{
|
|
6333
6350
|
"type": "create_record",
|
|
6334
6351
|
"name": "Create follow-up order",
|
|
@@ -6343,7 +6360,7 @@ async function buildDynamicAutomationExamples(commandName, options = {}) {
|
|
|
6343
6360
|
"rawValue": null,
|
|
6344
6361
|
"source": {
|
|
6345
6362
|
"type": "TRIGGER",
|
|
6346
|
-
"id": "
|
|
6363
|
+
"id": "${schemaField.fieldId}"
|
|
6347
6364
|
}
|
|
6348
6365
|
}
|
|
6349
6366
|
}
|
|
@@ -6370,7 +6387,7 @@ async function buildDynamicAutomationExamples(commandName, options = {}) {
|
|
|
6370
6387
|
},
|
|
6371
6388
|
{
|
|
6372
6389
|
description: `Add a search-records action with a trigger-based condition on ${schemaField.schemaRef}.`,
|
|
6373
|
-
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":"
|
|
6390
|
+
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":"${schemaField.fieldId}"}}]}'`,
|
|
6374
6391
|
raw: `{
|
|
6375
6392
|
"type": "search_records",
|
|
6376
6393
|
"name": "Find duplicates",
|
|
@@ -6385,7 +6402,7 @@ async function buildDynamicAutomationExamples(commandName, options = {}) {
|
|
|
6385
6402
|
"rawValue": null,
|
|
6386
6403
|
"source": {
|
|
6387
6404
|
"type": "TRIGGER",
|
|
6388
|
-
"id": "
|
|
6405
|
+
"id": "${schemaField.fieldId}"
|
|
6389
6406
|
}
|
|
6390
6407
|
}
|
|
6391
6408
|
]
|
|
@@ -9773,6 +9790,12 @@ var RecordsApi = class {
|
|
|
9773
9790
|
{ method: "DELETE" }
|
|
9774
9791
|
);
|
|
9775
9792
|
}
|
|
9793
|
+
clearRecords(schema) {
|
|
9794
|
+
return this.client.requestJson(
|
|
9795
|
+
`/api/v2/schemas/${selectorValue8(schema)}/records:clear`,
|
|
9796
|
+
{ method: "DELETE" }
|
|
9797
|
+
);
|
|
9798
|
+
}
|
|
9776
9799
|
normalizeQueryInput(query) {
|
|
9777
9800
|
const where = query.where?.map((expression) => ({
|
|
9778
9801
|
field: expression.field,
|
|
@@ -10299,6 +10322,17 @@ function registerRecordsCommands(program, options = {}) {
|
|
|
10299
10322
|
}
|
|
10300
10323
|
writeLine9(stdout, `Deleted record "${record.value}" from schema "${schema.value}".`);
|
|
10301
10324
|
});
|
|
10325
|
+
records.command("clear").description("Delete all records from a schema's table").argument("<schema>", "schema uuid or slug", parseUuidOrSlugSelector7).action(async function action(schema) {
|
|
10326
|
+
const { api, schemasApi, json, readOnly } = createRecordsApi(this, filePath);
|
|
10327
|
+
ensureWritable6("records clear", readOnly, "destructive");
|
|
10328
|
+
const resolvedSchema = await resolveSchemaSelector(schemasApi, schema);
|
|
10329
|
+
const data = await api.clearRecords(resolvedSchema);
|
|
10330
|
+
if (json) {
|
|
10331
|
+
emitJson9(stdout, "records clear", data, filePath);
|
|
10332
|
+
return;
|
|
10333
|
+
}
|
|
10334
|
+
writeLine9(stdout, `Cleared all records from schema "${schema.value}".`);
|
|
10335
|
+
});
|
|
10302
10336
|
}
|
|
10303
10337
|
|
|
10304
10338
|
// src/commands/schemas.ts
|