zinkee 0.1.44 → 0.1.45
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/README.md +4 -0
- package/dist/chunk-MHEVRMDX.js +1230 -0
- package/dist/chunk-MHEVRMDX.js.map +1 -0
- package/{src/utils/examples.ts → dist/examples-E6FFEVBE.js} +856 -1141
- package/dist/examples-E6FFEVBE.js.map +1 -0
- package/dist/index.js +1145 -8456
- package/dist/index.js.map +1 -1
- package/package.json +6 -3
- package/.github/workflows/npm-publish.yml +0 -77
- package/.github/workflows/pr-checks.yml +0 -36
- package/AGENTS.md +0 -110
- package/docs/cli-contract.md +0 -41
- package/docs/npm-release.md +0 -64
- package/docs/superpowers/plans/2026-03-24-zinkee-cli-implementation.md +0 -837
- package/docs/superpowers/plans/2026-03-25-cli-backend-error-contract.md +0 -503
- package/docs/superpowers/plans/2026-03-26-display-freeform-create.md +0 -389
- package/docs/superpowers/specs/2026-03-24-zinkee-cli-backend-blockers.md +0 -172
- package/docs/superpowers/specs/2026-03-24-zinkee-cli-design.md +0 -1576
- package/docs/superpowers/specs/2026-03-24-zinkee-cli-e2e-checklist.md +0 -215
- package/docs/superpowers/specs/2026-03-24-zinkee-cli-e2e-design.md +0 -492
- package/docs/superpowers/specs/2026-03-24-zinkee-cli-e2e-status.md +0 -307
- package/docs/superpowers/specs/2026-07-30-cli-pr-checks-design.md +0 -37
- package/src/api/automations.ts +0 -404
- package/src/api/comments.ts +0 -51
- package/src/api/displays.ts +0 -337
- package/src/api/document-templates.ts +0 -110
- package/src/api/files.ts +0 -50
- package/src/api/formulas.test.ts +0 -65
- package/src/api/formulas.ts +0 -67
- package/src/api/logs.ts +0 -34
- package/src/api/navigation.ts +0 -70
- package/src/api/records.ts +0 -184
- package/src/api/schemas.ts +0 -148
- package/src/api/teamspace.ts +0 -110
- package/src/cli-examples.ts +0 -130
- package/src/cli-runner.ts +0 -95
- package/src/client.test.ts +0 -189
- package/src/client.ts +0 -269
- package/src/command-registry.ts +0 -882
- package/src/commands/automations.test.ts +0 -1030
- package/src/commands/automations.ts +0 -2102
- package/src/commands/comments.test.ts +0 -214
- package/src/commands/comments.ts +0 -303
- package/src/commands/config.test.ts +0 -81
- package/src/commands/config.ts +0 -150
- package/src/commands/displays.test.ts +0 -1105
- package/src/commands/displays.ts +0 -1442
- package/src/commands/document-templates.test.ts +0 -569
- package/src/commands/document-templates.ts +0 -563
- package/src/commands/files.test.ts +0 -284
- package/src/commands/files.ts +0 -280
- package/src/commands/formulas.test.ts +0 -194
- package/src/commands/formulas.ts +0 -243
- package/src/commands/logs.test.ts +0 -123
- package/src/commands/logs.ts +0 -159
- package/src/commands/navigation.test.ts +0 -211
- package/src/commands/navigation.ts +0 -348
- package/src/commands/profiles.test.ts +0 -191
- package/src/commands/profiles.ts +0 -303
- package/src/commands/records.test.ts +0 -860
- package/src/commands/records.ts +0 -883
- package/src/commands/schemas.test.ts +0 -1252
- package/src/commands/schemas.ts +0 -890
- package/src/commands/teamspace.test.ts +0 -229
- package/src/commands/teamspace.ts +0 -546
- package/src/completion/engine.test.ts +0 -138
- package/src/completion/engine.ts +0 -168
- package/src/completion/install.test.ts +0 -179
- package/src/completion/install.ts +0 -260
- package/src/completion/runtime.ts +0 -150
- package/src/completion/scripts.ts +0 -91
- package/src/config.test.ts +0 -362
- package/src/config.ts +0 -294
- package/src/index.test.ts +0 -217
- package/src/index.ts +0 -8
- package/src/parsers/expressions.test.ts +0 -95
- package/src/parsers/expressions.ts +0 -128
- package/src/parsers/kv.test.ts +0 -35
- package/src/parsers/kv.ts +0 -49
- package/src/parsers/selectors.test.ts +0 -23
- package/src/parsers/selectors.ts +0 -29
- package/src/program.ts +0 -64
- package/src/runtime-context.ts +0 -103
- package/src/types.ts +0 -76
- package/src/utils/argv-rewrite.test.ts +0 -149
- package/src/utils/argv-rewrite.ts +0 -269
- package/src/utils/errors.test.ts +0 -85
- package/src/utils/errors.ts +0 -191
- package/src/utils/examples.test.ts +0 -374
- package/src/utils/output.test.ts +0 -65
- package/src/utils/output.ts +0 -154
- package/src/utils/schema-fields.ts +0 -1016
- package/tsconfig.json +0 -20
- package/tsup.config.ts +0 -13
|
@@ -1,1016 +0,0 @@
|
|
|
1
|
-
import type { JsonObject } from "../types.js";
|
|
2
|
-
import { CliError } from "./errors.js";
|
|
3
|
-
|
|
4
|
-
export type SchemaFieldTypeKey =
|
|
5
|
-
| "text"
|
|
6
|
-
| "number"
|
|
7
|
-
| "date"
|
|
8
|
-
| "option"
|
|
9
|
-
| "file"
|
|
10
|
-
| "reference"
|
|
11
|
-
| "formula"
|
|
12
|
-
| "member"
|
|
13
|
-
| "autoincremental"
|
|
14
|
-
| "schedule";
|
|
15
|
-
|
|
16
|
-
export interface SchemaFieldExamplePayload {
|
|
17
|
-
name: string;
|
|
18
|
-
payload: JsonObject;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface SchemaFieldTypeDefinition {
|
|
22
|
-
key: SchemaFieldTypeKey;
|
|
23
|
-
className: string;
|
|
24
|
-
aliases: readonly string[];
|
|
25
|
-
description: string;
|
|
26
|
-
rawShape: string;
|
|
27
|
-
examplePayloads: readonly SchemaFieldExamplePayload[];
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function isJsonObject(value: unknown): value is JsonObject {
|
|
31
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function toJsonObject(value: unknown): JsonObject | undefined {
|
|
35
|
-
return isJsonObject(value) ? value : undefined;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function toStringValue(value: unknown): string | undefined {
|
|
39
|
-
return typeof value === "string" && value.trim().length > 0 ? value : undefined;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function toNumberValue(value: unknown): number | undefined {
|
|
43
|
-
if (typeof value === "number" && Number.isFinite(value)) {
|
|
44
|
-
return value;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (typeof value === "string" && value.trim().length > 0) {
|
|
48
|
-
const parsed = Number(value);
|
|
49
|
-
if (Number.isFinite(parsed)) {
|
|
50
|
-
return parsed;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return undefined;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const fieldTypeDefinitions = [
|
|
58
|
-
{
|
|
59
|
-
key: "text",
|
|
60
|
-
className: "TextField",
|
|
61
|
-
aliases: ["text", "TextField"],
|
|
62
|
-
description: "Plain text field.",
|
|
63
|
-
rawShape:
|
|
64
|
-
'{"type":"TextField","slug":"name","label":"Name","config":{"textType":"NORMAL"}}',
|
|
65
|
-
examplePayloads: [
|
|
66
|
-
{
|
|
67
|
-
name: "Text field (normal)",
|
|
68
|
-
payload: {
|
|
69
|
-
type: "TextField",
|
|
70
|
-
slug: "customer-name",
|
|
71
|
-
label: "Customer Name",
|
|
72
|
-
required: true,
|
|
73
|
-
config: {
|
|
74
|
-
textType: "NORMAL",
|
|
75
|
-
defaultValue: null,
|
|
76
|
-
conditionalFormatting: [],
|
|
77
|
-
},
|
|
78
|
-
},
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
name: "Text field (long)",
|
|
82
|
-
payload: {
|
|
83
|
-
type: "TextField",
|
|
84
|
-
slug: "customer-notes",
|
|
85
|
-
label: "Customer Notes",
|
|
86
|
-
required: false,
|
|
87
|
-
config: {
|
|
88
|
-
textType: "LONG",
|
|
89
|
-
defaultValue: "Add internal notes here...",
|
|
90
|
-
conditionalFormatting: [],
|
|
91
|
-
},
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
],
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
key: "number",
|
|
98
|
-
className: "NumberField",
|
|
99
|
-
aliases: ["number", "NumberField"],
|
|
100
|
-
description: "Numeric field.",
|
|
101
|
-
rawShape:
|
|
102
|
-
'{"type":"NumberField","slug":"quantity","label":"Quantity","config":{"defaultValue":"0","formatOptions":{"format":"number","decimals":0,"thousandsSeparator":false}}}',
|
|
103
|
-
examplePayloads: [
|
|
104
|
-
{
|
|
105
|
-
name: "Number field (plain integer)",
|
|
106
|
-
payload: {
|
|
107
|
-
type: "NumberField",
|
|
108
|
-
slug: "quantity",
|
|
109
|
-
label: "Quantity",
|
|
110
|
-
required: false,
|
|
111
|
-
config: {
|
|
112
|
-
defaultValue: "0",
|
|
113
|
-
formatOptions: {
|
|
114
|
-
format: "number",
|
|
115
|
-
decimals: 0,
|
|
116
|
-
thousandsSeparator: false,
|
|
117
|
-
},
|
|
118
|
-
conditionalFormatting: [],
|
|
119
|
-
},
|
|
120
|
-
},
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
name: "Number field (decimal with thousands)",
|
|
124
|
-
payload: {
|
|
125
|
-
type: "NumberField",
|
|
126
|
-
slug: "weight",
|
|
127
|
-
label: "Weight (kg)",
|
|
128
|
-
required: false,
|
|
129
|
-
config: {
|
|
130
|
-
defaultValue: "0",
|
|
131
|
-
formatOptions: {
|
|
132
|
-
format: "number",
|
|
133
|
-
decimals: 2,
|
|
134
|
-
thousandsSeparator: true,
|
|
135
|
-
negativesInRed: false,
|
|
136
|
-
},
|
|
137
|
-
conditionalFormatting: [],
|
|
138
|
-
},
|
|
139
|
-
},
|
|
140
|
-
},
|
|
141
|
-
{
|
|
142
|
-
name: "Number field (currency € prefix)",
|
|
143
|
-
payload: {
|
|
144
|
-
type: "NumberField",
|
|
145
|
-
slug: "amount-eur",
|
|
146
|
-
label: "Amount (EUR)",
|
|
147
|
-
required: false,
|
|
148
|
-
config: {
|
|
149
|
-
defaultValue: "0",
|
|
150
|
-
formatOptions: {
|
|
151
|
-
format: "currency",
|
|
152
|
-
decimals: 2,
|
|
153
|
-
negativesInRed: true,
|
|
154
|
-
thousandsSeparator: true,
|
|
155
|
-
symbolEnabled: true,
|
|
156
|
-
symbolPosition: "before",
|
|
157
|
-
symbolValue: "€",
|
|
158
|
-
},
|
|
159
|
-
conditionalFormatting: [],
|
|
160
|
-
},
|
|
161
|
-
},
|
|
162
|
-
},
|
|
163
|
-
{
|
|
164
|
-
name: "Number field (currency $ suffix)",
|
|
165
|
-
payload: {
|
|
166
|
-
type: "NumberField",
|
|
167
|
-
slug: "amount-usd",
|
|
168
|
-
label: "Amount (USD)",
|
|
169
|
-
required: false,
|
|
170
|
-
config: {
|
|
171
|
-
defaultValue: "0",
|
|
172
|
-
formatOptions: {
|
|
173
|
-
format: "currency",
|
|
174
|
-
decimals: 2,
|
|
175
|
-
negativesInRed: false,
|
|
176
|
-
thousandsSeparator: true,
|
|
177
|
-
symbolEnabled: true,
|
|
178
|
-
symbolPosition: "right",
|
|
179
|
-
symbolValue: " $",
|
|
180
|
-
},
|
|
181
|
-
conditionalFormatting: [],
|
|
182
|
-
},
|
|
183
|
-
},
|
|
184
|
-
},
|
|
185
|
-
{
|
|
186
|
-
name: "Number field (percentage)",
|
|
187
|
-
payload: {
|
|
188
|
-
type: "NumberField",
|
|
189
|
-
slug: "discount-rate",
|
|
190
|
-
label: "Discount Rate",
|
|
191
|
-
required: false,
|
|
192
|
-
config: {
|
|
193
|
-
defaultValue: "0",
|
|
194
|
-
formatOptions: {
|
|
195
|
-
format: "percentage",
|
|
196
|
-
decimals: 1,
|
|
197
|
-
negativesInRed: true,
|
|
198
|
-
},
|
|
199
|
-
conditionalFormatting: [],
|
|
200
|
-
},
|
|
201
|
-
},
|
|
202
|
-
},
|
|
203
|
-
{
|
|
204
|
-
name: "Number field (duration HH:MM)",
|
|
205
|
-
payload: {
|
|
206
|
-
type: "NumberField",
|
|
207
|
-
slug: "tracked-time",
|
|
208
|
-
label: "Tracked Time",
|
|
209
|
-
required: false,
|
|
210
|
-
config: {
|
|
211
|
-
defaultValue: "0",
|
|
212
|
-
formatOptions: {
|
|
213
|
-
format: "duration",
|
|
214
|
-
durationFormat: "HH:MM",
|
|
215
|
-
},
|
|
216
|
-
conditionalFormatting: [],
|
|
217
|
-
},
|
|
218
|
-
},
|
|
219
|
-
},
|
|
220
|
-
],
|
|
221
|
-
},
|
|
222
|
-
{
|
|
223
|
-
key: "date",
|
|
224
|
-
className: "DateField",
|
|
225
|
-
aliases: ["date", "DateField"],
|
|
226
|
-
description: "Date or datetime field.",
|
|
227
|
-
rawShape:
|
|
228
|
-
'{"type":"DateField","slug":"due-date","label":"Due Date","config":{"formatOptions":{"format":"date","dateFormat":"YYYY-MM-DD","showTime":false}}}',
|
|
229
|
-
examplePayloads: [
|
|
230
|
-
{
|
|
231
|
-
name: "Date field (date only)",
|
|
232
|
-
payload: {
|
|
233
|
-
type: "DateField",
|
|
234
|
-
slug: "birth-date",
|
|
235
|
-
label: "Birth Date",
|
|
236
|
-
required: false,
|
|
237
|
-
config: {
|
|
238
|
-
defaultValue: null,
|
|
239
|
-
formatOptions: {
|
|
240
|
-
format: "date",
|
|
241
|
-
dateFormat: "YYYY-MM-DD",
|
|
242
|
-
showTime: false,
|
|
243
|
-
},
|
|
244
|
-
conditionalFormatting: [],
|
|
245
|
-
},
|
|
246
|
-
},
|
|
247
|
-
},
|
|
248
|
-
{
|
|
249
|
-
name: "Date field (datetime EU)",
|
|
250
|
-
payload: {
|
|
251
|
-
type: "DateField",
|
|
252
|
-
slug: "due-date",
|
|
253
|
-
label: "Due Date",
|
|
254
|
-
required: false,
|
|
255
|
-
config: {
|
|
256
|
-
defaultValue: null,
|
|
257
|
-
formatOptions: {
|
|
258
|
-
format: "datetime",
|
|
259
|
-
dateFormat: "DD/MM/YYYY",
|
|
260
|
-
showTime: true,
|
|
261
|
-
},
|
|
262
|
-
conditionalFormatting: [],
|
|
263
|
-
},
|
|
264
|
-
},
|
|
265
|
-
},
|
|
266
|
-
{
|
|
267
|
-
name: "Date field (datetime US)",
|
|
268
|
-
payload: {
|
|
269
|
-
type: "DateField",
|
|
270
|
-
slug: "appointment-at",
|
|
271
|
-
label: "Appointment",
|
|
272
|
-
required: false,
|
|
273
|
-
config: {
|
|
274
|
-
defaultValue: null,
|
|
275
|
-
formatOptions: {
|
|
276
|
-
format: "datetime",
|
|
277
|
-
dateFormat: "MM/DD/YYYY",
|
|
278
|
-
showTime: true,
|
|
279
|
-
},
|
|
280
|
-
conditionalFormatting: [],
|
|
281
|
-
},
|
|
282
|
-
},
|
|
283
|
-
},
|
|
284
|
-
],
|
|
285
|
-
},
|
|
286
|
-
{
|
|
287
|
-
key: "option",
|
|
288
|
-
className: "OptionField",
|
|
289
|
-
aliases: ["option", "OptionField"],
|
|
290
|
-
description: "Dropdown/select field with options.",
|
|
291
|
-
rawShape:
|
|
292
|
-
'{"type":"OptionField","slug":"status","label":"Status","config":{"options":[{"id":1,"name":"Open","color":"default"},{"id":2,"name":"Closed","color":"success"}]}}',
|
|
293
|
-
examplePayloads: [
|
|
294
|
-
{
|
|
295
|
-
name: "Option field (select dropdown)",
|
|
296
|
-
payload: {
|
|
297
|
-
type: "OptionField",
|
|
298
|
-
slug: "priority",
|
|
299
|
-
label: "Priority",
|
|
300
|
-
required: false,
|
|
301
|
-
config: {
|
|
302
|
-
options: [
|
|
303
|
-
{ id: 1, name: "Low", color: "default" },
|
|
304
|
-
{ id: 2, name: "Medium", color: "warning" },
|
|
305
|
-
{ id: 3, name: "High", color: "danger" },
|
|
306
|
-
],
|
|
307
|
-
defaultValue: 1,
|
|
308
|
-
conditionalFormatting: [],
|
|
309
|
-
buttonConfig: null,
|
|
310
|
-
},
|
|
311
|
-
},
|
|
312
|
-
},
|
|
313
|
-
{
|
|
314
|
-
name: "Option field (button cycle)",
|
|
315
|
-
payload: {
|
|
316
|
-
type: "OptionField",
|
|
317
|
-
slug: "stage",
|
|
318
|
-
label: "Stage",
|
|
319
|
-
required: false,
|
|
320
|
-
config: {
|
|
321
|
-
options: [
|
|
322
|
-
{ id: 1, name: "To Do", color: "default" },
|
|
323
|
-
{ id: 2, name: "Doing", color: "warning" },
|
|
324
|
-
{ id: 3, name: "Done", color: "success" },
|
|
325
|
-
],
|
|
326
|
-
defaultValue: 1,
|
|
327
|
-
conditionalFormatting: [],
|
|
328
|
-
buttonConfig: {
|
|
329
|
-
displayMode: "button",
|
|
330
|
-
buttonBehavior: {
|
|
331
|
-
mode: "cycle",
|
|
332
|
-
cycleOrder: [1, 2, 3],
|
|
333
|
-
requireConfirmation: false,
|
|
334
|
-
lockAfterSelection: false,
|
|
335
|
-
allowReselect: true,
|
|
336
|
-
},
|
|
337
|
-
},
|
|
338
|
-
},
|
|
339
|
-
},
|
|
340
|
-
},
|
|
341
|
-
{
|
|
342
|
-
name: "Option field (button dropdown w/ confirm)",
|
|
343
|
-
payload: {
|
|
344
|
-
type: "OptionField",
|
|
345
|
-
slug: "status",
|
|
346
|
-
label: "Status",
|
|
347
|
-
required: false,
|
|
348
|
-
config: {
|
|
349
|
-
options: [
|
|
350
|
-
{ id: 1, name: "Open", color: "default" },
|
|
351
|
-
{ id: 2, name: "In Progress", color: "warning" },
|
|
352
|
-
{ id: 3, name: "Done", color: "success" },
|
|
353
|
-
],
|
|
354
|
-
defaultValue: 1,
|
|
355
|
-
conditionalFormatting: [],
|
|
356
|
-
buttonConfig: {
|
|
357
|
-
displayMode: "button",
|
|
358
|
-
buttonBehavior: {
|
|
359
|
-
mode: "dropdown",
|
|
360
|
-
requireConfirmation: true,
|
|
361
|
-
confirmationMessage: "Confirm status change",
|
|
362
|
-
useFixedLabel: true,
|
|
363
|
-
buttonLabel: "Set status",
|
|
364
|
-
allowReselect: true,
|
|
365
|
-
},
|
|
366
|
-
},
|
|
367
|
-
},
|
|
368
|
-
},
|
|
369
|
-
},
|
|
370
|
-
],
|
|
371
|
-
},
|
|
372
|
-
{
|
|
373
|
-
key: "file",
|
|
374
|
-
className: "FileField",
|
|
375
|
-
aliases: ["file", "FileField"],
|
|
376
|
-
description: "File attachment field.",
|
|
377
|
-
rawShape:
|
|
378
|
-
'{"type":"FileField","slug":"attachment","label":"Attachment","config":{}}',
|
|
379
|
-
examplePayloads: [
|
|
380
|
-
{
|
|
381
|
-
name: "File field",
|
|
382
|
-
payload: {
|
|
383
|
-
type: "FileField",
|
|
384
|
-
slug: "attachment",
|
|
385
|
-
label: "Attachment",
|
|
386
|
-
required: false,
|
|
387
|
-
config: {},
|
|
388
|
-
},
|
|
389
|
-
},
|
|
390
|
-
],
|
|
391
|
-
},
|
|
392
|
-
{
|
|
393
|
-
key: "reference",
|
|
394
|
-
className: "ReferenceField",
|
|
395
|
-
aliases: ["reference", "ReferenceField"],
|
|
396
|
-
description: "Reference to another schema.",
|
|
397
|
-
rawShape:
|
|
398
|
-
'{"type":"ReferenceField","slug":"company-ref","label":"Company","config":{"targetSchema":"<schema-uuid>","targetDisplayField":"<field-uuid>"}}',
|
|
399
|
-
examplePayloads: [
|
|
400
|
-
{
|
|
401
|
-
name: "Reference field (minimal)",
|
|
402
|
-
payload: {
|
|
403
|
-
type: "ReferenceField",
|
|
404
|
-
slug: "company-ref",
|
|
405
|
-
label: "Company",
|
|
406
|
-
required: false,
|
|
407
|
-
config: {
|
|
408
|
-
targetSchema: "5223cbc8-8c6c-4694-93bc-dd176364df9b",
|
|
409
|
-
targetDisplayField: "c60b8526-5835-4c9f-aecd-9a16c7704a34",
|
|
410
|
-
},
|
|
411
|
-
},
|
|
412
|
-
},
|
|
413
|
-
{
|
|
414
|
-
name: "Reference field (restrict + filter + description)",
|
|
415
|
-
payload: {
|
|
416
|
-
type: "ReferenceField",
|
|
417
|
-
slug: "customer-ref",
|
|
418
|
-
label: "Customer",
|
|
419
|
-
required: false,
|
|
420
|
-
config: {
|
|
421
|
-
targetSchema: "5223cbc8-8c6c-4694-93bc-dd176364df9b",
|
|
422
|
-
targetDisplayField: "c60b8526-5835-4c9f-aecd-9a16c7704a34",
|
|
423
|
-
deleteBehavior: "RESTRICT",
|
|
424
|
-
defaultValue: "CUST-12",
|
|
425
|
-
filterFields: [
|
|
426
|
-
{
|
|
427
|
-
fatherField: "c60b8526-5835-4c9f-aecd-9a16c7704a34",
|
|
428
|
-
currentField: "45c5da96-0dc2-4cc1-ba61-7660a9c6da32",
|
|
429
|
-
comparison: "EQUAL",
|
|
430
|
-
value: null,
|
|
431
|
-
},
|
|
432
|
-
],
|
|
433
|
-
descriptionFields: [
|
|
434
|
-
{
|
|
435
|
-
id: "c52efe3f-2825-4c60-a7e3-34dd4c1ce043",
|
|
436
|
-
fieldType: "NumberField",
|
|
437
|
-
options: null,
|
|
438
|
-
format: "number",
|
|
439
|
-
},
|
|
440
|
-
],
|
|
441
|
-
conditionalFormatting: [],
|
|
442
|
-
},
|
|
443
|
-
},
|
|
444
|
-
},
|
|
445
|
-
],
|
|
446
|
-
},
|
|
447
|
-
{
|
|
448
|
-
key: "formula",
|
|
449
|
-
className: "FormulaField",
|
|
450
|
-
aliases: ["formula", "FormulaField"],
|
|
451
|
-
description: "Calculated field from a formula.",
|
|
452
|
-
rawShape:
|
|
453
|
-
'{"type":"FormulaField","slug":"formula-code","label":"Formula Code","config":{"formulaText":"concat(\\"CUST-\\", f1e1d000-0000-0000-0000-000000000005)","uiFormatKind":"none"}}',
|
|
454
|
-
examplePayloads: [
|
|
455
|
-
{
|
|
456
|
-
name: "Formula field (none)",
|
|
457
|
-
payload: {
|
|
458
|
-
type: "FormulaField",
|
|
459
|
-
slug: "formula-code",
|
|
460
|
-
label: "Formula Code",
|
|
461
|
-
required: false,
|
|
462
|
-
config: {
|
|
463
|
-
formulaText:
|
|
464
|
-
'concat("CUST-", f1e1d000-0000-0000-0000-000000000005)',
|
|
465
|
-
uiFormatKind: "none",
|
|
466
|
-
status: "ACTIVE",
|
|
467
|
-
conditionalFormatting: [],
|
|
468
|
-
},
|
|
469
|
-
},
|
|
470
|
-
},
|
|
471
|
-
{
|
|
472
|
-
name: "Formula field (number)",
|
|
473
|
-
payload: {
|
|
474
|
-
type: "FormulaField",
|
|
475
|
-
slug: "formula-total",
|
|
476
|
-
label: "Formula Total",
|
|
477
|
-
required: false,
|
|
478
|
-
config: {
|
|
479
|
-
formulaText: "c52efe3f-2825-4c60-a7e3-34dd4c1ce043 * 1.21",
|
|
480
|
-
uiFormatKind: "number",
|
|
481
|
-
status: "ACTIVE",
|
|
482
|
-
numberFormatOptions: {
|
|
483
|
-
format: "number",
|
|
484
|
-
decimals: 2,
|
|
485
|
-
thousandsSeparator: true,
|
|
486
|
-
},
|
|
487
|
-
conditionalFormatting: [],
|
|
488
|
-
},
|
|
489
|
-
},
|
|
490
|
-
},
|
|
491
|
-
{
|
|
492
|
-
name: "Formula field (date)",
|
|
493
|
-
payload: {
|
|
494
|
-
type: "FormulaField",
|
|
495
|
-
slug: "formula-period",
|
|
496
|
-
label: "Formula Period",
|
|
497
|
-
required: false,
|
|
498
|
-
config: {
|
|
499
|
-
formulaText:
|
|
500
|
-
'date_format(d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90, "AAAA-MM")',
|
|
501
|
-
uiFormatKind: "date",
|
|
502
|
-
status: "ACTIVE",
|
|
503
|
-
dateFormatOptions: {
|
|
504
|
-
format: "date",
|
|
505
|
-
dateFormat: "DD/MM/YYYY",
|
|
506
|
-
showTime: false,
|
|
507
|
-
},
|
|
508
|
-
conditionalFormatting: [],
|
|
509
|
-
},
|
|
510
|
-
},
|
|
511
|
-
},
|
|
512
|
-
{
|
|
513
|
-
name: "Formula field (member)",
|
|
514
|
-
payload: {
|
|
515
|
-
type: "FormulaField",
|
|
516
|
-
slug: "formula-assignee",
|
|
517
|
-
label: "Computed Assignee",
|
|
518
|
-
required: false,
|
|
519
|
-
config: {
|
|
520
|
-
formulaText: "a7b8c9d0-e1f2-3a4b-5c6d-7e8f90123456",
|
|
521
|
-
uiFormatKind: "member",
|
|
522
|
-
status: "ACTIVE",
|
|
523
|
-
conditionalFormatting: [],
|
|
524
|
-
},
|
|
525
|
-
},
|
|
526
|
-
},
|
|
527
|
-
],
|
|
528
|
-
},
|
|
529
|
-
{
|
|
530
|
-
key: "member",
|
|
531
|
-
className: "MemberField",
|
|
532
|
-
aliases: ["member", "MemberField"],
|
|
533
|
-
description: "Workspace member field.",
|
|
534
|
-
rawShape:
|
|
535
|
-
'{"type":"MemberField","slug":"owner","label":"Owner","config":{"defaultValue":null}}',
|
|
536
|
-
examplePayloads: [
|
|
537
|
-
{
|
|
538
|
-
name: "Member field",
|
|
539
|
-
payload: {
|
|
540
|
-
type: "MemberField",
|
|
541
|
-
slug: "owner",
|
|
542
|
-
label: "Owner",
|
|
543
|
-
required: false,
|
|
544
|
-
config: {
|
|
545
|
-
defaultValue: null,
|
|
546
|
-
conditionalFormatting: [],
|
|
547
|
-
},
|
|
548
|
-
},
|
|
549
|
-
},
|
|
550
|
-
],
|
|
551
|
-
},
|
|
552
|
-
{
|
|
553
|
-
key: "autoincremental",
|
|
554
|
-
className: "AutoIncrementalField",
|
|
555
|
-
aliases: [
|
|
556
|
-
"autoincremental",
|
|
557
|
-
"auto-incremental",
|
|
558
|
-
"auto_incremental",
|
|
559
|
-
"AutoIncrementalField",
|
|
560
|
-
],
|
|
561
|
-
description: "Auto-generated incremental counter.",
|
|
562
|
-
rawShape:
|
|
563
|
-
'{"type":"AutoIncrementalField","slug":"order-number","label":"Order Number","config":{"segmentedByFieldId":null}}',
|
|
564
|
-
examplePayloads: [
|
|
565
|
-
{
|
|
566
|
-
name: "Autoincremental (global counter)",
|
|
567
|
-
payload: {
|
|
568
|
-
type: "AutoIncrementalField",
|
|
569
|
-
slug: "order-number",
|
|
570
|
-
label: "Order Number",
|
|
571
|
-
required: false,
|
|
572
|
-
config: {
|
|
573
|
-
segmentedByFieldId: null,
|
|
574
|
-
conditionalFormatting: [],
|
|
575
|
-
},
|
|
576
|
-
},
|
|
577
|
-
},
|
|
578
|
-
{
|
|
579
|
-
name: "Autoincremental (segmented)",
|
|
580
|
-
payload: {
|
|
581
|
-
type: "AutoIncrementalField",
|
|
582
|
-
slug: "sequence-code",
|
|
583
|
-
label: "Sequence Code",
|
|
584
|
-
required: false,
|
|
585
|
-
config: {
|
|
586
|
-
segmentedByFieldId: "45c5da96-0dc2-4cc1-ba61-7660a9c6da32",
|
|
587
|
-
conditionalFormatting: [],
|
|
588
|
-
},
|
|
589
|
-
},
|
|
590
|
-
},
|
|
591
|
-
],
|
|
592
|
-
},
|
|
593
|
-
{
|
|
594
|
-
key: "schedule",
|
|
595
|
-
className: "ScheduleField",
|
|
596
|
-
aliases: ["schedule", "ScheduleField"],
|
|
597
|
-
description:
|
|
598
|
-
"Recurrence/schedule field bound to a number reference and a date period (frequency: monthly or daily).",
|
|
599
|
-
rawShape:
|
|
600
|
-
'{"type":"ScheduleField","slug":"recurrence","label":"Recurrence","config":{"referenceField":"<number-field-uuid>","beginningPeriodField":"<date-field-uuid>","endingPeriodField":"<date-field-uuid>","frequency":"monthly"}}',
|
|
601
|
-
examplePayloads: [
|
|
602
|
-
{
|
|
603
|
-
name: "Schedule field (monthly)",
|
|
604
|
-
payload: {
|
|
605
|
-
type: "ScheduleField",
|
|
606
|
-
slug: "monthly-recurrence",
|
|
607
|
-
label: "Monthly Recurrence",
|
|
608
|
-
required: false,
|
|
609
|
-
config: {
|
|
610
|
-
referenceField: "c52efe3f-2825-4c60-a7e3-34dd4c1ce043",
|
|
611
|
-
beginningPeriodField: "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
|
|
612
|
-
endingPeriodField: "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
|
|
613
|
-
frequency: "monthly",
|
|
614
|
-
},
|
|
615
|
-
},
|
|
616
|
-
},
|
|
617
|
-
{
|
|
618
|
-
name: "Schedule field (daily)",
|
|
619
|
-
payload: {
|
|
620
|
-
type: "ScheduleField",
|
|
621
|
-
slug: "daily-recurrence",
|
|
622
|
-
label: "Daily Recurrence",
|
|
623
|
-
required: false,
|
|
624
|
-
config: {
|
|
625
|
-
referenceField: "c52efe3f-2825-4c60-a7e3-34dd4c1ce043",
|
|
626
|
-
beginningPeriodField: "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
|
|
627
|
-
endingPeriodField: "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
|
|
628
|
-
frequency: "daily",
|
|
629
|
-
},
|
|
630
|
-
},
|
|
631
|
-
},
|
|
632
|
-
],
|
|
633
|
-
},
|
|
634
|
-
] as const satisfies readonly SchemaFieldTypeDefinition[];
|
|
635
|
-
|
|
636
|
-
const fieldTypeDefinitionByAlias = new Map(
|
|
637
|
-
fieldTypeDefinitions.flatMap((definition) =>
|
|
638
|
-
definition.aliases.map((alias) => [alias.trim().toLowerCase(), definition] as const),
|
|
639
|
-
),
|
|
640
|
-
);
|
|
641
|
-
|
|
642
|
-
const fieldTypeDefinitionByClassName = new Map<string, SchemaFieldTypeDefinition>(
|
|
643
|
-
fieldTypeDefinitions.map((definition) => [definition.className, definition] as const),
|
|
644
|
-
);
|
|
645
|
-
|
|
646
|
-
const optionValidationMessage =
|
|
647
|
-
'Option fields require an "options" array with at least one entry like {"id":1,"name":"Open","color":"default"}.';
|
|
648
|
-
|
|
649
|
-
export function getSchemaFieldTypeDefinitions(): readonly SchemaFieldTypeDefinition[] {
|
|
650
|
-
return fieldTypeDefinitions;
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
export function listSchemaFieldTypes(): readonly SchemaFieldTypeKey[] {
|
|
654
|
-
return fieldTypeDefinitions.map((definition) => definition.key);
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
export function formatSchemaFieldTypes(): string {
|
|
658
|
-
return listSchemaFieldTypes().join(", ");
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
export function resolveSchemaFieldType(
|
|
662
|
-
input: string | undefined,
|
|
663
|
-
): SchemaFieldTypeDefinition | undefined {
|
|
664
|
-
if (!input) {
|
|
665
|
-
return undefined;
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
return fieldTypeDefinitionByAlias.get(input.trim().toLowerCase());
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
export function resolveSchemaFieldTypeByClassName(
|
|
672
|
-
className: string | undefined,
|
|
673
|
-
): SchemaFieldTypeDefinition | undefined {
|
|
674
|
-
if (!className) {
|
|
675
|
-
return undefined;
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
return fieldTypeDefinitionByClassName.get(className);
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
export function normalizeSchemaFieldType(input: string): string {
|
|
682
|
-
const definition = resolveSchemaFieldType(input);
|
|
683
|
-
|
|
684
|
-
if (definition) {
|
|
685
|
-
return definition.className;
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
if (/^[a-z]/.test(input) && !input.endsWith("Field")) {
|
|
689
|
-
return `${input.charAt(0).toUpperCase()}${input.slice(1)}Field`;
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
return input;
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
export function assertSupportedSchemaFieldType(type: string): void {
|
|
696
|
-
if (!resolveSchemaFieldTypeByClassName(type)) {
|
|
697
|
-
throw new CliError(
|
|
698
|
-
"invalid_cli_usage",
|
|
699
|
-
`Unsupported field type "${type}". Valid types: ${formatSchemaFieldTypes()}.`,
|
|
700
|
-
);
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
interface OptionEntry {
|
|
705
|
-
[key: string]: string | number;
|
|
706
|
-
id: number;
|
|
707
|
-
name: string;
|
|
708
|
-
color: string;
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
function normalizeOptionEntries(entries: readonly unknown[]): OptionEntry[] {
|
|
712
|
-
return entries.flatMap((entry) => {
|
|
713
|
-
if (!isJsonObject(entry)) {
|
|
714
|
-
return [];
|
|
715
|
-
}
|
|
716
|
-
|
|
717
|
-
const id = toNumberValue(entry.id);
|
|
718
|
-
const name = toStringValue(entry.name) ?? toStringValue(entry.label);
|
|
719
|
-
const color = toStringValue(entry.color) ?? "default";
|
|
720
|
-
|
|
721
|
-
if (id === undefined || !name) {
|
|
722
|
-
return [];
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
return [{ id, name, color }];
|
|
726
|
-
});
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
function normalizeOptionPayload(input: JsonObject): JsonObject {
|
|
730
|
-
const additionalProperties = toJsonObject(input.additionalProperties) ?? {};
|
|
731
|
-
const config = toJsonObject(input.config);
|
|
732
|
-
const rootOptions = Array.isArray(input.options) ? input.options : undefined;
|
|
733
|
-
const nestedOptions = Array.isArray(additionalProperties.options)
|
|
734
|
-
? additionalProperties.options
|
|
735
|
-
: Array.isArray(config?.options)
|
|
736
|
-
? config.options
|
|
737
|
-
: undefined;
|
|
738
|
-
const optionObjects = normalizeOptionEntries(
|
|
739
|
-
nestedOptions ??
|
|
740
|
-
(Array.isArray(rootOptions) ? rootOptions : []),
|
|
741
|
-
);
|
|
742
|
-
|
|
743
|
-
if (optionObjects.length === 0) {
|
|
744
|
-
throw new CliError("invalid_cli_usage", optionValidationMessage);
|
|
745
|
-
}
|
|
746
|
-
|
|
747
|
-
const { options: _options, additionalProperties: _additionalProperties, ...rest } = input;
|
|
748
|
-
const defaultValue =
|
|
749
|
-
config?.defaultValue ?? input.defaultValue ?? additionalProperties.defaultValue;
|
|
750
|
-
const conditionalFormatting =
|
|
751
|
-
config?.conditionalFormatting ?? additionalProperties.conditionalFormatting;
|
|
752
|
-
const buttonConfig = config?.buttonConfig ?? additionalProperties.buttonConfig;
|
|
753
|
-
|
|
754
|
-
return {
|
|
755
|
-
...rest,
|
|
756
|
-
config: {
|
|
757
|
-
...(config ?? {}),
|
|
758
|
-
options: optionObjects,
|
|
759
|
-
...(defaultValue !== undefined ? { defaultValue } : {}),
|
|
760
|
-
...(conditionalFormatting !== undefined ? { conditionalFormatting } : {}),
|
|
761
|
-
...(buttonConfig !== undefined ? { buttonConfig } : {}),
|
|
762
|
-
},
|
|
763
|
-
};
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
function normalizeReferencePayload(input: JsonObject): JsonObject {
|
|
767
|
-
const additionalProperties = toJsonObject(input.additionalProperties) ?? {};
|
|
768
|
-
const config = toJsonObject(input.config) ?? {};
|
|
769
|
-
const targetSchema =
|
|
770
|
-
config.targetSchema ?? input.targetSchema ?? additionalProperties.targetSchema;
|
|
771
|
-
const targetDisplayField =
|
|
772
|
-
config.targetDisplayField ??
|
|
773
|
-
input.targetDisplayField ??
|
|
774
|
-
additionalProperties.targetDisplayField;
|
|
775
|
-
const deleteBehavior =
|
|
776
|
-
config.deleteBehavior ?? input.deleteBehavior ?? additionalProperties.deleteBehavior;
|
|
777
|
-
const defaultValue =
|
|
778
|
-
config.defaultValue ?? input.defaultValue ?? additionalProperties.defaultValue;
|
|
779
|
-
const filterFields =
|
|
780
|
-
config.filterFields ?? input.filterFields ?? additionalProperties.filterFields;
|
|
781
|
-
const descriptionFields =
|
|
782
|
-
config.descriptionFields ??
|
|
783
|
-
input.descriptionFields ??
|
|
784
|
-
additionalProperties.descriptionFields;
|
|
785
|
-
const conditionalFormatting =
|
|
786
|
-
config.conditionalFormatting ??
|
|
787
|
-
input.conditionalFormatting ??
|
|
788
|
-
additionalProperties.conditionalFormatting;
|
|
789
|
-
|
|
790
|
-
const normalized: JsonObject = {
|
|
791
|
-
...input,
|
|
792
|
-
};
|
|
793
|
-
|
|
794
|
-
normalized.config = {
|
|
795
|
-
...config,
|
|
796
|
-
...(targetSchema !== undefined ? { targetSchema } : {}),
|
|
797
|
-
...(targetDisplayField !== undefined ? { targetDisplayField } : {}),
|
|
798
|
-
...(deleteBehavior !== undefined ? { deleteBehavior } : {}),
|
|
799
|
-
...(defaultValue !== undefined ? { defaultValue } : {}),
|
|
800
|
-
...(filterFields !== undefined ? { filterFields } : {}),
|
|
801
|
-
...(descriptionFields !== undefined ? { descriptionFields } : {}),
|
|
802
|
-
...(conditionalFormatting !== undefined ? { conditionalFormatting } : {}),
|
|
803
|
-
};
|
|
804
|
-
|
|
805
|
-
const normalizedConfig = toJsonObject(normalized.config) ?? {};
|
|
806
|
-
|
|
807
|
-
if (
|
|
808
|
-
!toStringValue(normalizedConfig.targetSchema) ||
|
|
809
|
-
!toStringValue(normalizedConfig.targetDisplayField)
|
|
810
|
-
) {
|
|
811
|
-
const definition = resolveSchemaFieldType("reference")!;
|
|
812
|
-
throw new CliError(
|
|
813
|
-
"invalid_cli_usage",
|
|
814
|
-
`Reference fields require "targetSchema" and "targetDisplayField". Expected raw shape: ${definition.rawShape}`,
|
|
815
|
-
);
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
return normalized;
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
const scheduleAllowedFrequencies = new Set(["monthly", "daily"]);
|
|
822
|
-
|
|
823
|
-
function normalizeSchedulePayload(input: JsonObject): JsonObject {
|
|
824
|
-
const additionalProperties = toJsonObject(input.additionalProperties) ?? {};
|
|
825
|
-
const config = toJsonObject(input.config) ?? {};
|
|
826
|
-
const referenceField =
|
|
827
|
-
config.referenceField ?? input.referenceField ?? additionalProperties.referenceField;
|
|
828
|
-
const beginningPeriodField =
|
|
829
|
-
config.beginningPeriodField ??
|
|
830
|
-
input.beginningPeriodField ??
|
|
831
|
-
additionalProperties.beginningPeriodField;
|
|
832
|
-
const endingPeriodField =
|
|
833
|
-
config.endingPeriodField ??
|
|
834
|
-
input.endingPeriodField ??
|
|
835
|
-
additionalProperties.endingPeriodField;
|
|
836
|
-
const frequency =
|
|
837
|
-
config.frequency ?? input.frequency ?? additionalProperties.frequency;
|
|
838
|
-
|
|
839
|
-
const {
|
|
840
|
-
referenceField: _referenceField,
|
|
841
|
-
beginningPeriodField: _beginningPeriodField,
|
|
842
|
-
endingPeriodField: _endingPeriodField,
|
|
843
|
-
frequency: _frequency,
|
|
844
|
-
additionalProperties: _additionalProperties,
|
|
845
|
-
...rest
|
|
846
|
-
} = input;
|
|
847
|
-
|
|
848
|
-
const normalized: JsonObject = {
|
|
849
|
-
...rest,
|
|
850
|
-
config: {
|
|
851
|
-
...config,
|
|
852
|
-
...(referenceField !== undefined ? { referenceField } : {}),
|
|
853
|
-
...(beginningPeriodField !== undefined ? { beginningPeriodField } : {}),
|
|
854
|
-
...(endingPeriodField !== undefined ? { endingPeriodField } : {}),
|
|
855
|
-
...(frequency !== undefined ? { frequency } : {}),
|
|
856
|
-
},
|
|
857
|
-
};
|
|
858
|
-
|
|
859
|
-
const normalizedConfig = toJsonObject(normalized.config) ?? {};
|
|
860
|
-
const definition = resolveSchemaFieldType("schedule")!;
|
|
861
|
-
|
|
862
|
-
if (
|
|
863
|
-
!toStringValue(normalizedConfig.referenceField) ||
|
|
864
|
-
!toStringValue(normalizedConfig.beginningPeriodField) ||
|
|
865
|
-
!toStringValue(normalizedConfig.endingPeriodField) ||
|
|
866
|
-
!toStringValue(normalizedConfig.frequency)
|
|
867
|
-
) {
|
|
868
|
-
throw new CliError(
|
|
869
|
-
"invalid_cli_usage",
|
|
870
|
-
`Schedule fields require "referenceField", "beginningPeriodField", "endingPeriodField" and "frequency". Expected raw shape: ${definition.rawShape}`,
|
|
871
|
-
);
|
|
872
|
-
}
|
|
873
|
-
|
|
874
|
-
const frequencyValue = toStringValue(normalizedConfig.frequency)!;
|
|
875
|
-
if (!scheduleAllowedFrequencies.has(frequencyValue)) {
|
|
876
|
-
throw new CliError(
|
|
877
|
-
"invalid_cli_usage",
|
|
878
|
-
`Schedule "frequency" must be "monthly" or "daily" (received "${frequencyValue}").`,
|
|
879
|
-
);
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
return normalized;
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
function normalizeFormulaPayload(input: JsonObject): JsonObject {
|
|
886
|
-
const { status: _status, ...rest } = input;
|
|
887
|
-
const rawAdditionalProperties = toJsonObject(input.additionalProperties);
|
|
888
|
-
const rawConfig = toJsonObject(input.config);
|
|
889
|
-
const { status: _additionalStatus, ...additionalProperties } =
|
|
890
|
-
rawAdditionalProperties ?? {};
|
|
891
|
-
const { status: _configStatus, ...config } = rawConfig ?? {};
|
|
892
|
-
const formulaText =
|
|
893
|
-
config.formulaText ??
|
|
894
|
-
rest.formulaText ??
|
|
895
|
-
rest.expression ??
|
|
896
|
-
additionalProperties.formulaText ??
|
|
897
|
-
additionalProperties.expression;
|
|
898
|
-
|
|
899
|
-
const normalized: JsonObject = {
|
|
900
|
-
...rest,
|
|
901
|
-
};
|
|
902
|
-
|
|
903
|
-
normalized.config = {
|
|
904
|
-
...config,
|
|
905
|
-
...(formulaText !== undefined ? { formulaText } : {}),
|
|
906
|
-
...(config.uiFormatKind !== undefined ? { uiFormatKind: config.uiFormatKind } : {}),
|
|
907
|
-
...(config.defaultValue !== undefined ? { defaultValue: config.defaultValue } : {}),
|
|
908
|
-
...(config.numberFormatOptions !== undefined
|
|
909
|
-
? { numberFormatOptions: config.numberFormatOptions }
|
|
910
|
-
: {}),
|
|
911
|
-
...(config.dateFormatOptions !== undefined
|
|
912
|
-
? { dateFormatOptions: config.dateFormatOptions }
|
|
913
|
-
: {}),
|
|
914
|
-
...(config.conditionalFormatting !== undefined
|
|
915
|
-
? { conditionalFormatting: config.conditionalFormatting }
|
|
916
|
-
: {}),
|
|
917
|
-
};
|
|
918
|
-
|
|
919
|
-
const normalizedConfig = toJsonObject(normalized.config) ?? {};
|
|
920
|
-
|
|
921
|
-
if (!toStringValue(normalizedConfig.formulaText)) {
|
|
922
|
-
const definition = resolveSchemaFieldType("formula")!;
|
|
923
|
-
throw new CliError(
|
|
924
|
-
"invalid_cli_usage",
|
|
925
|
-
`Formula fields require "formulaText". Expected raw shape: ${definition.rawShape}`,
|
|
926
|
-
);
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
return normalized;
|
|
930
|
-
}
|
|
931
|
-
|
|
932
|
-
export function normalizeSchemaFieldCreatePayload(input: JsonObject): JsonObject {
|
|
933
|
-
const rawType = toStringValue(input.type);
|
|
934
|
-
const normalizedType = rawType ? normalizeSchemaFieldType(rawType) : undefined;
|
|
935
|
-
const definition = resolveSchemaFieldTypeByClassName(normalizedType);
|
|
936
|
-
|
|
937
|
-
if (!definition) {
|
|
938
|
-
return input;
|
|
939
|
-
}
|
|
940
|
-
|
|
941
|
-
const normalizedWithType: JsonObject = {
|
|
942
|
-
...input,
|
|
943
|
-
type: definition.className,
|
|
944
|
-
};
|
|
945
|
-
|
|
946
|
-
switch (definition.key) {
|
|
947
|
-
case "option":
|
|
948
|
-
return normalizeOptionPayload(normalizedWithType);
|
|
949
|
-
case "reference":
|
|
950
|
-
return normalizeReferencePayload(normalizedWithType);
|
|
951
|
-
case "formula":
|
|
952
|
-
return normalizeFormulaPayload(normalizedWithType);
|
|
953
|
-
case "schedule":
|
|
954
|
-
return normalizeSchedulePayload(normalizedWithType);
|
|
955
|
-
case "autoincremental": {
|
|
956
|
-
const config = toJsonObject(normalizedWithType.config) ?? {};
|
|
957
|
-
const segmentedByFieldId =
|
|
958
|
-
config.segmentedByFieldId ??
|
|
959
|
-
normalizedWithType.segmentedByFieldId ??
|
|
960
|
-
null;
|
|
961
|
-
return {
|
|
962
|
-
...normalizedWithType,
|
|
963
|
-
config: {
|
|
964
|
-
...config,
|
|
965
|
-
segmentedByFieldId,
|
|
966
|
-
...(config.conditionalFormatting !== undefined
|
|
967
|
-
? { conditionalFormatting: config.conditionalFormatting }
|
|
968
|
-
: {}),
|
|
969
|
-
},
|
|
970
|
-
};
|
|
971
|
-
}
|
|
972
|
-
default:
|
|
973
|
-
return normalizedWithType;
|
|
974
|
-
}
|
|
975
|
-
}
|
|
976
|
-
|
|
977
|
-
export function normalizeSchemaFieldUpdatePayload(
|
|
978
|
-
type: string,
|
|
979
|
-
input: JsonObject,
|
|
980
|
-
): JsonObject {
|
|
981
|
-
const definition = resolveSchemaFieldTypeByClassName(type);
|
|
982
|
-
|
|
983
|
-
if (definition?.key === "formula") {
|
|
984
|
-
return normalizeFormulaPayload(input);
|
|
985
|
-
}
|
|
986
|
-
|
|
987
|
-
return input;
|
|
988
|
-
}
|
|
989
|
-
|
|
990
|
-
export function buildSchemaFieldCreateHelpText(): string {
|
|
991
|
-
const sections = fieldTypeDefinitions.map(
|
|
992
|
-
(definition) =>
|
|
993
|
-
` - ${definition.key}: ${definition.description}\n raw: ${definition.rawShape}`,
|
|
994
|
-
);
|
|
995
|
-
|
|
996
|
-
return [
|
|
997
|
-
"",
|
|
998
|
-
"Valid field types:",
|
|
999
|
-
` ${formatSchemaFieldTypes()}`,
|
|
1000
|
-
"",
|
|
1001
|
-
"Raw payload shapes by type:",
|
|
1002
|
-
...sections,
|
|
1003
|
-
"",
|
|
1004
|
-
'Use "zinkee --example schemas fields create --type <type>" to show a concrete example for one type.',
|
|
1005
|
-
].join("\n");
|
|
1006
|
-
}
|
|
1007
|
-
|
|
1008
|
-
export function buildSchemaFieldCreateValidationMessage(type: string): string {
|
|
1009
|
-
const definition = resolveSchemaFieldTypeByClassName(type);
|
|
1010
|
-
|
|
1011
|
-
if (!definition) {
|
|
1012
|
-
return `Invalid payload for field type "${type}". Valid types: ${formatSchemaFieldTypes()}.`;
|
|
1013
|
-
}
|
|
1014
|
-
|
|
1015
|
-
return `Invalid payload for field type "${definition.key}". Expected raw shape: ${definition.rawShape}`;
|
|
1016
|
-
}
|