@automate.ax/catalog 0.153.2 → 0.154.0

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.
@@ -1,240 +1,10 @@
1
1
  import type { TriggerDefinition } from "../types"
2
- import { sentenceCase } from "./name"
3
2
  import * as z from "zod/mini"
4
-
5
- const EMAIL_SCHEMA = z.email()
6
- const URL_SCHEMA = z.url()
7
- const DATE_SCHEMA = z.iso.date()
8
- const DATETIME_SCHEMA = z.iso.datetime({ local: true })
9
- const FIELD_NAME_SCHEMA = z
10
- .string()
11
- .check(z.trim(), z.minLength(1), z.maxLength(100))
12
- const FIELD_LABEL_SCHEMA = z
13
- .string()
14
- .check(z.trim(), z.minLength(1), z.maxLength(255))
15
- const FIELD_DESCRIPTION_SCHEMA = z.string().check(z.maxLength(2_000))
16
- const FIELD_LENGTH_SCHEMA = z.int().check(z.nonnegative())
17
- const DASHBOARD_RUN_FIELD_BASE_SCHEMA = {
18
- description: z.optional(FIELD_DESCRIPTION_SCHEMA),
19
- label: z.optional(FIELD_LABEL_SCHEMA),
20
- name: FIELD_NAME_SCHEMA,
21
- }
22
- const DASHBOARD_RUN_TEXT_FIELD_SCHEMA = z.object({
23
- ...DASHBOARD_RUN_FIELD_BASE_SCHEMA,
24
- defaultValue: z.optional(z.string()),
25
- maxLength: z.optional(FIELD_LENGTH_SCHEMA),
26
- minLength: z.optional(FIELD_LENGTH_SCHEMA),
27
- placeholder: z.optional(z.string()),
28
- required: z.prefault(z.boolean(), true),
29
- type: z.enum(["email", "phone", "text", "textarea", "url"]),
30
- })
31
- const DASHBOARD_RUN_NUMBER_FIELD_SCHEMA = z.object({
32
- ...DASHBOARD_RUN_FIELD_BASE_SCHEMA,
33
- defaultValue: z.optional(z.number()),
34
- max: z.optional(z.number()),
35
- min: z.optional(z.number()),
36
- placeholder: z.optional(z.string()),
37
- required: z.prefault(z.boolean(), true),
38
- step: z.prefault(z.number().check(z.positive()), 1),
39
- type: z.literal("number"),
40
- })
41
- const DASHBOARD_RUN_DATE_FIELD_SCHEMA = z.object({
42
- ...DASHBOARD_RUN_FIELD_BASE_SCHEMA,
43
- defaultValue: z.optional(z.iso.date()),
44
- max: z.optional(z.iso.date()),
45
- min: z.optional(z.iso.date()),
46
- required: z.prefault(z.boolean(), true),
47
- step: z.prefault(z.int().check(z.positive()), 1),
48
- type: z.literal("date"),
49
- })
50
- const DASHBOARD_RUN_DATETIME_FIELD_SCHEMA = z.object({
51
- ...DASHBOARD_RUN_FIELD_BASE_SCHEMA,
52
- defaultValue: z.optional(z.iso.datetime({ local: true })),
53
- max: z.optional(z.iso.datetime({ local: true })),
54
- min: z.optional(z.iso.datetime({ local: true })),
55
- required: z.prefault(z.boolean(), true),
56
- step: z.prefault(z.number().check(z.positive()), 60),
57
- type: z.literal("datetime"),
58
- })
59
- const DASHBOARD_RUN_CHOICE_FIELD_SCHEMA = {
60
- ...DASHBOARD_RUN_FIELD_BASE_SCHEMA,
61
- defaultValue: z.optional(FIELD_NAME_SCHEMA),
62
- options: z
63
- .array(
64
- z.object({
65
- label: FIELD_LABEL_SCHEMA,
66
- value: FIELD_NAME_SCHEMA,
67
- }),
68
- )
69
- .check(z.minLength(1)),
70
- placeholder: z.optional(z.string()),
71
- required: z.prefault(z.boolean(), true),
72
- }
73
- const DASHBOARD_RUN_SELECT_FIELD_SCHEMA = z.object({
74
- ...DASHBOARD_RUN_CHOICE_FIELD_SCHEMA,
75
- type: z.literal("select"),
76
- })
77
- const DASHBOARD_RUN_RADIO_FIELD_SCHEMA = z.object({
78
- ...DASHBOARD_RUN_CHOICE_FIELD_SCHEMA,
79
- type: z.literal("radio"),
80
- })
81
- const DASHBOARD_RUN_MULTI_SELECT_FIELD_SCHEMA = z.object({
82
- ...DASHBOARD_RUN_FIELD_BASE_SCHEMA,
83
- defaultValue: z.optional(z.array(FIELD_NAME_SCHEMA)),
84
- options: z
85
- .array(
86
- z.object({
87
- label: FIELD_LABEL_SCHEMA,
88
- value: FIELD_NAME_SCHEMA,
89
- }),
90
- )
91
- .check(z.minLength(1)),
92
- placeholder: z.optional(z.string()),
93
- required: z.prefault(z.boolean(), true),
94
- type: z.literal("multi-select"),
95
- })
96
- const DASHBOARD_RUN_CHECKBOX_FIELD_SCHEMA = z.object({
97
- ...DASHBOARD_RUN_FIELD_BASE_SCHEMA,
98
- defaultValue: z.prefault(z.boolean(), false),
99
- required: z.prefault(z.boolean(), false),
100
- type: z.literal("checkbox"),
101
- })
102
- const DASHBOARD_RUN_FIELD_SCHEMA = z.pipe(
103
- z.discriminatedUnion("type", [
104
- DASHBOARD_RUN_TEXT_FIELD_SCHEMA,
105
- DASHBOARD_RUN_NUMBER_FIELD_SCHEMA,
106
- DASHBOARD_RUN_DATE_FIELD_SCHEMA,
107
- DASHBOARD_RUN_DATETIME_FIELD_SCHEMA,
108
- DASHBOARD_RUN_SELECT_FIELD_SCHEMA,
109
- DASHBOARD_RUN_RADIO_FIELD_SCHEMA,
110
- DASHBOARD_RUN_MULTI_SELECT_FIELD_SCHEMA,
111
- DASHBOARD_RUN_CHECKBOX_FIELD_SCHEMA,
112
- ]),
113
- z.transform((field) => ({
114
- ...field,
115
- label:
116
- field.label ??
117
- `${sentenceCase(field.name)}${field.type === "checkbox" ? "?" : ""}`,
118
- })),
119
- )
120
- export const DASHBOARD_RUN_FIELDS_SCHEMA = z
121
- .array(DASHBOARD_RUN_FIELD_SCHEMA)
122
- .check(
123
- z.refine(
124
- (fields) =>
125
- new Set(fields.map((field) => field.name)).size === fields.length,
126
- "Dashboard run field names must be unique.",
127
- ),
128
- z.refine(
129
- (fields) => fields.every(isDashboardRunFieldDefaultValid),
130
- "Dashboard run field defaults must satisfy their field constraints.",
131
- ),
132
- )
133
-
134
- export type DashboardRunFieldValue =
135
- | boolean
136
- | number
137
- | string
138
- | readonly string[]
139
- | null
140
-
141
- /**
142
- * Returns the configured fallback for a field without an assigned value.
143
- *
144
- * @param field - Field whose fallback should be resolved.
145
- */
146
- export function getDashboardRunFieldDefaultValue(field: DashboardRunField) {
147
- if (field.defaultValue !== undefined) return field.defaultValue
148
- if (field.type === "checkbox") return false
149
- if (field.type === "multi-select") return []
150
- if (field.type === "number")
151
- return field.required === false ? null : undefined
152
- return field.required === false ? "" : undefined
153
- }
154
-
155
- /**
156
- * Checks one decoded value against a dashboard field declaration.
157
- *
158
- * @param field - Field declaration whose constraints apply.
159
- * @param value - Decoded value to validate.
160
- */
161
- export function isDashboardRunFieldValueValid(
162
- field: DashboardRunField,
163
- value: unknown,
164
- ) {
165
- if (field.type === "checkbox") {
166
- return typeof value === "boolean" && (field.required === false || value)
167
- }
168
- if (field.type === "multi-select") {
169
- return (
170
- Array.isArray(value) &&
171
- (field.required === false || value.length > 0) &&
172
- value.every(
173
- (entry) =>
174
- typeof entry === "string" &&
175
- field.options.some((option) => option.value === entry),
176
- )
177
- )
178
- }
179
- if (field.type === "number") {
180
- if (value === null) return field.required === false
181
- return (
182
- typeof value === "number" &&
183
- Number.isFinite(value) &&
184
- (field.min === undefined || value >= field.min) &&
185
- (field.max === undefined || value <= field.max) &&
186
- !isDashboardRunStepMismatch(
187
- value,
188
- field.min ?? field.defaultValue ?? 0,
189
- field.step ?? 1,
190
- )
191
- )
192
- }
193
- if (typeof value !== "string") return false
194
- if (field.type === "radio" || field.type === "select") {
195
- return (
196
- (field.required === false && value === "") ||
197
- field.options.some((option) => option.value === value)
198
- )
199
- }
200
- if (field.type === "date" || field.type === "datetime") {
201
- if (field.required === false && value === "") return true
202
- const parsed = parseDashboardRunDateValue(field.type, value)
203
- return (
204
- (field.type === "date" ? DATE_SCHEMA : DATETIME_SCHEMA).safeParse(value)
205
- .success &&
206
- Number.isFinite(parsed) &&
207
- (field.min === undefined ||
208
- parsed >= parseDashboardRunDateValue(field.type, field.min)) &&
209
- (field.max === undefined ||
210
- parsed <= parseDashboardRunDateValue(field.type, field.max)) &&
211
- !isDashboardRunStepMismatch(
212
- parsed,
213
- parseDashboardRunDateValue(
214
- field.type,
215
- field.min ??
216
- field.defaultValue ??
217
- (field.type === "date" ? "1970-01-01" : "1970-01-01T00:00"),
218
- ),
219
- (field.step ?? (field.type === "date" ? 1 : 60)) *
220
- (field.type === "date" ? 86_400_000 : 1_000),
221
- )
222
- )
223
- }
224
-
225
- const normalized = value.trim()
226
- return (
227
- (normalized.length > 0 || field.required === false) &&
228
- (field.minLength === undefined || normalized.length >= field.minLength) &&
229
- (field.maxLength === undefined || normalized.length <= field.maxLength) &&
230
- (field.type !== "email" || EMAIL_SCHEMA.safeParse(normalized).success) &&
231
- (field.type !== "url" || URL_SCHEMA.safeParse(normalized).success)
232
- )
233
- }
3
+ import { FORM_FIELDS_SCHEMA, type FormField } from "../form-fields"
234
4
 
235
5
  export const DASHBOARD_RUN_CONFIG_SCHEMA = z.object({
236
- description: z.optional(FIELD_DESCRIPTION_SCHEMA),
237
- fields: z.prefault(DASHBOARD_RUN_FIELDS_SCHEMA, []),
6
+ description: z.optional(z.string().check(z.maxLength(2_000))),
7
+ fields: z.prefault(FORM_FIELDS_SCHEMA, []),
238
8
  submitLabel: z.prefault(
239
9
  z.string().check(z.trim(), z.minLength(1), z.maxLength(100)),
240
10
  "Run",
@@ -254,86 +24,8 @@ export const dashboardRunTriggerDefinition = {
254
24
  type: "dashboard.run",
255
25
  } as const satisfies TriggerDefinition
256
26
 
257
- interface DashboardRunFieldBase {
258
- /** Supporting text shown below the field. */
259
- description?: string
260
-
261
- /** Visible field label. Inferred from `name` when omitted. */
262
- label?: string
263
-
264
- /** Property name used in submitted trigger data. */
265
- name: string
266
-
267
- /** Whether the form must contain a value. Defaults to true. */
268
- required?: boolean
269
- }
270
-
271
- export type DashboardRunField =
272
- | (DashboardRunFieldBase & {
273
- defaultValue?: string
274
- maxLength?: number
275
- minLength?: number
276
- placeholder?: string
277
- type: "email" | "phone" | "text" | "textarea" | "url"
278
- })
279
- | (DashboardRunFieldBase & {
280
- defaultValue?: number
281
- max?: number
282
- min?: number
283
- placeholder?: string
284
-
285
- /** Increment used by the number input. Defaults to 1. */
286
- step?: number
287
- type: "number"
288
- })
289
- | (DashboardRunFieldBase & {
290
- /** Initial local date in `YYYY-MM-DD` format. */
291
- defaultValue?: string
292
- max?: string
293
- min?: string
294
-
295
- /** Allowed increment in days. Defaults to 1. */
296
- step?: number
297
- type: "date"
298
- })
299
- | (DashboardRunFieldBase & {
300
- /** Initial local date and time in `YYYY-MM-DDTHH:mm` format. */
301
- defaultValue?: string
302
- max?: string
303
- min?: string
304
-
305
- /** Allowed increment in seconds. Defaults to 60. */
306
- step?: number
307
- type: "datetime"
308
- })
309
- | (DashboardRunFieldBase & {
310
- defaultValue?: string
311
- options: readonly { label: string; value: string }[]
312
- placeholder?: string
313
- type: "select"
314
- })
315
- | (DashboardRunFieldBase & {
316
- defaultValue?: string
317
- options: readonly { label: string; value: string }[]
318
- type: "radio"
319
- })
320
- | (DashboardRunFieldBase & {
321
- defaultValue?: readonly string[]
322
- options: readonly { label: string; value: string }[]
323
- placeholder?: string
324
- type: "multi-select"
325
- })
326
- | (DashboardRunFieldBase & {
327
- /** Initial checked state. Defaults to false. */
328
- defaultValue?: boolean
329
-
330
- /** Whether the checkbox must be checked. Defaults to false. */
331
- required?: boolean
332
- type: "checkbox"
333
- })
334
-
335
27
  export interface DashboardRunConfig<
336
- TFields extends readonly DashboardRunField[] = readonly DashboardRunField[],
28
+ TFields extends readonly FormField[] = readonly FormField[],
337
29
  > {
338
30
  /** Supporting text shown below the form title. */
339
31
  description?: string
@@ -381,86 +73,3 @@ export function getDashboardRunEndpointKey(
381
73
  options.hookSlot,
382
74
  ].join(".")}`
383
75
  }
384
-
385
- /**
386
- * Checks a configured default against the same constraints as submitted data.
387
- *
388
- * @param field - Field definition to validate.
389
- */
390
- function isDashboardRunFieldDefaultValid(field: DashboardRunField) {
391
- if (field.type === "checkbox" || field.defaultValue === undefined) return true
392
-
393
- if (field.type === "multi-select") {
394
- if (field.required !== false && field.defaultValue.length === 0)
395
- return false
396
- return field.defaultValue.every((value) =>
397
- field.options.some((option) => option.value === value),
398
- )
399
- }
400
-
401
- if (field.type === "radio" || field.type === "select") {
402
- return field.options.some((option) => option.value === field.defaultValue)
403
- }
404
-
405
- if (field.type === "number") {
406
- return (
407
- (field.min === undefined || field.defaultValue >= field.min) &&
408
- (field.max === undefined || field.defaultValue <= field.max) &&
409
- !isDashboardRunStepMismatch(
410
- field.defaultValue,
411
- field.min ?? field.defaultValue,
412
- field.step ?? 1,
413
- )
414
- )
415
- }
416
-
417
- if (field.type === "date" || field.type === "datetime") {
418
- const defaultValue = parseDashboardRunDateValue(
419
- field.type,
420
- field.defaultValue,
421
- )
422
- return (
423
- (field.min === undefined ||
424
- defaultValue >= parseDashboardRunDateValue(field.type, field.min)) &&
425
- (field.max === undefined ||
426
- defaultValue <= parseDashboardRunDateValue(field.type, field.max)) &&
427
- !isDashboardRunStepMismatch(
428
- defaultValue,
429
- parseDashboardRunDateValue(field.type, field.min ?? field.defaultValue),
430
- (field.step ?? (field.type === "date" ? 1 : 60)) *
431
- (field.type === "date" ? 86_400_000 : 1_000),
432
- )
433
- )
434
- }
435
-
436
- const defaultValue = field.defaultValue.trim()
437
- return (
438
- (defaultValue.length > 0 || field.required === false) &&
439
- (field.minLength === undefined || defaultValue.length >= field.minLength) &&
440
- (field.maxLength === undefined || defaultValue.length <= field.maxLength) &&
441
- (field.type !== "email" || EMAIL_SCHEMA.safeParse(defaultValue).success) &&
442
- (field.type !== "url" || URL_SCHEMA.safeParse(defaultValue).success)
443
- )
444
- }
445
-
446
- /**
447
- * Checks whether a value falls outside an allowed step interval.
448
- *
449
- * @param value - Configured default value.
450
- * @param base - Value from which step intervals begin.
451
- * @param step - Allowed interval size.
452
- */
453
- function isDashboardRunStepMismatch(value: number, base: number, step: number) {
454
- const intervals = (value - base) / step
455
- return Math.abs(intervals - Math.round(intervals)) > 1e-9
456
- }
457
-
458
- /**
459
- * Converts a validated local date or date-time string to a UTC number.
460
- *
461
- * @param type - Temporal field type.
462
- * @param value - Local ISO value to convert.
463
- */
464
- function parseDashboardRunDateValue(type: "date" | "datetime", value: string) {
465
- return Date.parse(type === "date" ? `${value}T00:00:00Z` : `${value}Z`)
466
- }
@@ -7,16 +7,11 @@ import { cronTickTriggerDefinition } from "./core-schedule"
7
7
 
8
8
  export {
9
9
  DASHBOARD_RUN_CONFIG_SCHEMA,
10
- DASHBOARD_RUN_FIELDS_SCHEMA,
11
10
  dashboardRunTriggerDefinition,
12
11
  getDashboardRunEndpoint,
13
12
  getDashboardRunEndpointKey,
14
- getDashboardRunFieldDefaultValue,
15
- isDashboardRunFieldValueValid,
16
13
  type DashboardRunConfig,
17
14
  type DashboardRunEndpointOptions,
18
- type DashboardRunField,
19
- type DashboardRunFieldValue,
20
15
  } from "./core-dashboard"
21
16
  export {
22
17
  getHttpTriggerEndpoint,
@@ -51,13 +51,8 @@ export {
51
51
  getMailhookAddressKey,
52
52
  PLATFORM_EMAIL_DOMAIN,
53
53
  DASHBOARD_RUN_CONFIG_SCHEMA,
54
- DASHBOARD_RUN_FIELDS_SCHEMA,
55
- getDashboardRunFieldDefaultValue,
56
- isDashboardRunFieldValueValid,
57
54
  type DashboardRunConfig,
58
55
  type DashboardRunEndpointOptions,
59
- type DashboardRunField,
60
- type DashboardRunFieldValue,
61
56
  type HttpTriggerEndpointOptions,
62
57
  type HttpTriggerScope,
63
58
  type MailhookAddressOptions,