@automate.ax/catalog 0.74.0 → 0.76.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.
Files changed (52) hide show
  1. package/dist/authoring.d.ts +1 -0
  2. package/dist/authoring.js +1 -0
  3. package/dist/triggers/airtable.js +1 -2
  4. package/dist/triggers/asana.js +1 -2
  5. package/dist/triggers/brevo.js +1 -2
  6. package/dist/triggers/core-dashboard.d.ts +374 -0
  7. package/dist/triggers/core-dashboard.js +202 -0
  8. package/dist/triggers/core-http.d.ts +30 -0
  9. package/dist/triggers/core-http.js +43 -0
  10. package/dist/triggers/core-invocation.d.ts +9 -0
  11. package/dist/triggers/core-invocation.js +15 -0
  12. package/dist/triggers/core-mailhook.d.ts +35 -0
  13. package/dist/triggers/core-mailhook.js +63 -0
  14. package/dist/triggers/core-schedule.d.ts +9 -0
  15. package/dist/triggers/core-schedule.js +17 -0
  16. package/dist/triggers/core.d.ts +15 -426
  17. package/dist/triggers/core.js +16 -346
  18. package/dist/triggers/github.js +4 -5
  19. package/dist/triggers/google.js +4 -5
  20. package/dist/triggers/index.d.ts +20 -20
  21. package/dist/triggers/index.js +2 -1
  22. package/dist/triggers/linear.js +1 -2
  23. package/dist/triggers/microsoft.js +3 -4
  24. package/dist/triggers/name.d.ts +13 -0
  25. package/dist/triggers/name.js +31 -0
  26. package/dist/triggers/resend.js +1 -2
  27. package/dist/triggers/slack.js +3 -4
  28. package/dist/triggers/trello.js +1 -2
  29. package/dist/triggers/vercel.js +5 -6
  30. package/dist/triggers/whatsapp.js +1 -2
  31. package/package.json +118 -5
  32. package/src/authoring.ts +8 -0
  33. package/src/triggers/airtable.ts +1 -2
  34. package/src/triggers/asana.ts +1 -2
  35. package/src/triggers/brevo.ts +1 -2
  36. package/src/triggers/core-dashboard.ts +361 -0
  37. package/src/triggers/core-http.ts +69 -0
  38. package/src/triggers/core-invocation.ts +18 -0
  39. package/src/triggers/core-mailhook.ts +83 -0
  40. package/src/triggers/core-schedule.ts +21 -0
  41. package/src/triggers/core.ts +38 -544
  42. package/src/triggers/github.ts +4 -5
  43. package/src/triggers/google.ts +4 -5
  44. package/src/triggers/index.ts +2 -1
  45. package/src/triggers/linear.ts +1 -2
  46. package/src/triggers/microsoft.ts +3 -4
  47. package/src/triggers/name.ts +37 -0
  48. package/src/triggers/resend.ts +1 -2
  49. package/src/triggers/slack.ts +3 -4
  50. package/src/triggers/trello.ts +1 -2
  51. package/src/triggers/vercel.ts +5 -6
  52. package/src/triggers/whatsapp.ts +1 -2
@@ -1,548 +1,42 @@
1
1
  import type { TriggerDefinition } from "../types"
2
- import * as z from "zod/mini"
3
-
4
- const MAX_EMAIL_LOCAL_PART_BYTES = 64
5
- const EMAIL_SCHEMA = z.email()
6
- const URL_SCHEMA = z.url()
7
- const CRON_PRESENTATION_CONFIG_SCHEMA = z.object({
8
- schedule: z.string(),
9
- timeZone: z.prefault(z.string(), "UTC"),
10
- })
11
- const HTTP_PRESENTATION_CONFIG_SCHEMA = z.object({
12
- scope: z.prefault(z.enum(["trigger", "automation", "project"]), "trigger"),
13
- })
14
- const MAILHOOK_PRESENTATION_CONFIG_SCHEMA = z.object({
15
- scope: z.prefault(z.enum(["trigger", "automation", "project"]), "trigger"),
16
- })
17
- const INVOCATION_PRESENTATION_CONFIG_SCHEMA = z.object({
18
- entrypoint: z.string(),
19
- })
20
- const FIELD_NAME_SCHEMA = z
21
- .string()
22
- .check(z.trim(), z.minLength(1), z.maxLength(100))
23
- const FIELD_LABEL_SCHEMA = z
24
- .string()
25
- .check(z.trim(), z.minLength(1), z.maxLength(255))
26
- const FIELD_DESCRIPTION_SCHEMA = z.string().check(z.maxLength(2_000))
27
- const FIELD_LENGTH_SCHEMA = z.int().check(z.nonnegative())
28
- const DASHBOARD_RUN_FIELD_BASE_SCHEMA = {
29
- description: z.optional(FIELD_DESCRIPTION_SCHEMA),
30
- label: z.optional(FIELD_LABEL_SCHEMA),
31
- name: FIELD_NAME_SCHEMA,
32
- }
33
- const DASHBOARD_RUN_TEXT_FIELD_SCHEMA = z.object({
34
- ...DASHBOARD_RUN_FIELD_BASE_SCHEMA,
35
- defaultValue: z.optional(z.string()),
36
- maxLength: z.optional(FIELD_LENGTH_SCHEMA),
37
- minLength: z.optional(FIELD_LENGTH_SCHEMA),
38
- placeholder: z.optional(z.string()),
39
- required: z.prefault(z.boolean(), true),
40
- type: z.enum(["email", "phone", "text", "textarea", "url"]),
41
- })
42
- const DASHBOARD_RUN_NUMBER_FIELD_SCHEMA = z.object({
43
- ...DASHBOARD_RUN_FIELD_BASE_SCHEMA,
44
- defaultValue: z.optional(z.number()),
45
- max: z.optional(z.number()),
46
- min: z.optional(z.number()),
47
- placeholder: z.optional(z.string()),
48
- required: z.prefault(z.boolean(), true),
49
- step: z.prefault(z.number().check(z.positive()), 1),
50
- type: z.literal("number"),
51
- })
52
- const DASHBOARD_RUN_DATE_FIELD_SCHEMA = z.object({
53
- ...DASHBOARD_RUN_FIELD_BASE_SCHEMA,
54
- defaultValue: z.optional(z.iso.date()),
55
- max: z.optional(z.iso.date()),
56
- min: z.optional(z.iso.date()),
57
- required: z.prefault(z.boolean(), true),
58
- step: z.prefault(z.int().check(z.positive()), 1),
59
- type: z.literal("date"),
60
- })
61
- const DASHBOARD_RUN_DATETIME_FIELD_SCHEMA = z.object({
62
- ...DASHBOARD_RUN_FIELD_BASE_SCHEMA,
63
- defaultValue: z.optional(z.iso.datetime({ local: true })),
64
- max: z.optional(z.iso.datetime({ local: true })),
65
- min: z.optional(z.iso.datetime({ local: true })),
66
- required: z.prefault(z.boolean(), true),
67
- step: z.prefault(z.number().check(z.positive()), 60),
68
- type: z.literal("datetime"),
69
- })
70
- const DASHBOARD_RUN_CHOICE_FIELD_SCHEMA = {
71
- ...DASHBOARD_RUN_FIELD_BASE_SCHEMA,
72
- defaultValue: z.optional(FIELD_NAME_SCHEMA),
73
- options: z
74
- .array(
75
- z.object({
76
- label: FIELD_LABEL_SCHEMA,
77
- value: FIELD_NAME_SCHEMA,
78
- }),
79
- )
80
- .check(z.minLength(1)),
81
- placeholder: z.optional(z.string()),
82
- required: z.prefault(z.boolean(), true),
83
- }
84
- const DASHBOARD_RUN_SELECT_FIELD_SCHEMA = z.object({
85
- ...DASHBOARD_RUN_CHOICE_FIELD_SCHEMA,
86
- type: z.literal("select"),
87
- })
88
- const DASHBOARD_RUN_RADIO_FIELD_SCHEMA = z.object({
89
- ...DASHBOARD_RUN_CHOICE_FIELD_SCHEMA,
90
- type: z.literal("radio"),
91
- })
92
- const DASHBOARD_RUN_MULTI_SELECT_FIELD_SCHEMA = z.object({
93
- ...DASHBOARD_RUN_FIELD_BASE_SCHEMA,
94
- defaultValue: z.optional(z.array(FIELD_NAME_SCHEMA)),
95
- options: z
96
- .array(
97
- z.object({
98
- label: FIELD_LABEL_SCHEMA,
99
- value: FIELD_NAME_SCHEMA,
100
- }),
101
- )
102
- .check(z.minLength(1)),
103
- placeholder: z.optional(z.string()),
104
- required: z.prefault(z.boolean(), true),
105
- type: z.literal("multi-select"),
106
- })
107
- const DASHBOARD_RUN_CHECKBOX_FIELD_SCHEMA = z.object({
108
- ...DASHBOARD_RUN_FIELD_BASE_SCHEMA,
109
- defaultValue: z.prefault(z.boolean(), false),
110
- required: z.prefault(z.boolean(), false),
111
- type: z.literal("checkbox"),
112
- })
113
- const DASHBOARD_RUN_FIELD_SCHEMA = z.pipe(
114
- z.discriminatedUnion("type", [
115
- DASHBOARD_RUN_TEXT_FIELD_SCHEMA,
116
- DASHBOARD_RUN_NUMBER_FIELD_SCHEMA,
117
- DASHBOARD_RUN_DATE_FIELD_SCHEMA,
118
- DASHBOARD_RUN_DATETIME_FIELD_SCHEMA,
119
- DASHBOARD_RUN_SELECT_FIELD_SCHEMA,
120
- DASHBOARD_RUN_RADIO_FIELD_SCHEMA,
121
- DASHBOARD_RUN_MULTI_SELECT_FIELD_SCHEMA,
122
- DASHBOARD_RUN_CHECKBOX_FIELD_SCHEMA,
123
- ]),
124
- z.transform((field) => ({
125
- ...field,
126
- label:
127
- field.label ??
128
- `${sentenceCase(field.name)}${field.type === "checkbox" ? "?" : ""}`,
129
- })),
130
- )
131
- const DASHBOARD_RUN_FIELDS_SCHEMA = z.array(DASHBOARD_RUN_FIELD_SCHEMA).check(
132
- z.refine(
133
- (fields) =>
134
- new Set(fields.map((field) => field.name)).size === fields.length,
135
- "Dashboard run field names must be unique.",
136
- ),
137
- z.refine(
138
- (fields) => fields.every(isDashboardRunFieldDefaultValid),
139
- "Dashboard run field defaults must satisfy their field constraints.",
140
- ),
141
- )
142
-
143
- export const DASHBOARD_RUN_CONFIG_SCHEMA = z.object({
144
- description: z.optional(FIELD_DESCRIPTION_SCHEMA),
145
- fields: z.prefault(DASHBOARD_RUN_FIELDS_SCHEMA, []),
146
- submitLabel: z.prefault(
147
- z.string().check(z.trim(), z.minLength(1), z.maxLength(100)),
148
- "Run",
149
- ),
150
- title: z.string().check(z.trim(), z.minLength(1), z.maxLength(255)),
151
- })
2
+ import { dashboardRunTriggerDefinition } from "./core-dashboard"
3
+ import { httpRequestTriggerDefinition } from "./core-http"
4
+ import { automationInvokedTriggerDefinition } from "./core-invocation"
5
+ import { mailhookEmailReceivedTriggerDefinition } from "./core-mailhook"
6
+ import { cronTickTriggerDefinition } from "./core-schedule"
7
+
8
+ export {
9
+ DASHBOARD_RUN_CONFIG_SCHEMA,
10
+ dashboardRunTriggerDefinition,
11
+ getDashboardRunEndpoint,
12
+ getDashboardRunEndpointKey,
13
+ type DashboardRunConfig,
14
+ type DashboardRunEndpointOptions,
15
+ type DashboardRunField,
16
+ } from "./core-dashboard"
17
+ export {
18
+ getHttpTriggerEndpoint,
19
+ getHttpTriggerEndpointKey,
20
+ httpRequestTriggerDefinition,
21
+ type HttpTriggerEndpointOptions,
22
+ type HttpTriggerScope,
23
+ } from "./core-http"
24
+ export { automationInvokedTriggerDefinition } from "./core-invocation"
25
+ export {
26
+ getMailhookAddress,
27
+ getMailhookAddressKey,
28
+ mailhookEmailReceivedTriggerDefinition,
29
+ PLATFORM_EMAIL_DOMAIN,
30
+ type MailhookAddressOptions,
31
+ type MailhookScope,
32
+ } from "./core-mailhook"
33
+ export { cronTickTriggerDefinition } from "./core-schedule"
34
+ export { sentenceCase } from "./name"
152
35
 
153
36
  export const coreTriggerDefinitions = {
154
- automationInvoked: {
155
- getDetails: ({ config }) => [
156
- {
157
- label: "Entrypoint",
158
- value: INVOCATION_PRESENTATION_CONFIG_SCHEMA.parse(config).entrypoint,
159
- },
160
- ],
161
- icon: "automation",
162
- name: "Invocation",
163
- type: "automation.invoked",
164
- },
165
- cronTick: {
166
- getDetails: ({ config }) => {
167
- const parsedConfig = CRON_PRESENTATION_CONFIG_SCHEMA.parse(config)
168
-
169
- return [
170
- { label: "Schedule", value: parsedConfig.schedule },
171
- { label: "Time zone", value: parsedConfig.timeZone },
172
- ]
173
- },
174
- icon: "schedule",
175
- name: "Cron schedule",
176
- type: "cron.tick",
177
- },
178
- httpRequest: {
179
- getPrimary: ({
180
- appOrigin,
181
- automationId,
182
- config,
183
- hookSlot,
184
- projectId,
185
- scopePath,
186
- }) => ({
187
- copyable: true,
188
- value: getHttpTriggerEndpoint({
189
- appOrigin,
190
- automationId,
191
- hookSlot,
192
- projectId,
193
- scope: HTTP_PRESENTATION_CONFIG_SCHEMA.parse(config).scope,
194
- scopePath,
195
- }),
196
- }),
197
- icon: "webhook",
198
- name: "HTTP request",
199
- type: "http.request",
200
- },
201
- mailhookEmailReceived: {
202
- getPrimary: ({ automationId, config, hookSlot, projectId, scopePath }) => ({
203
- copyable: true,
204
- value: getMailhookAddress({
205
- automationId,
206
- hookSlot,
207
- projectId,
208
- scope: MAILHOOK_PRESENTATION_CONFIG_SCHEMA.parse(config).scope,
209
- scopePath,
210
- }),
211
- }),
212
- icon: "webhook",
213
- name: "Mailhook",
214
- type: "mailhook.email.received",
215
- },
216
- dashboardRun: {
217
- getDetails: ({ config }) => [
218
- {
219
- label: "Run form",
220
- value: DASHBOARD_RUN_CONFIG_SCHEMA.parse(config).title,
221
- },
222
- ],
223
- icon: "automation",
224
- name: "Dashboard run",
225
- type: "dashboard.run",
226
- },
37
+ automationInvoked: automationInvokedTriggerDefinition,
38
+ cronTick: cronTickTriggerDefinition,
39
+ dashboardRun: dashboardRunTriggerDefinition,
40
+ httpRequest: httpRequestTriggerDefinition,
41
+ mailhookEmailReceived: mailhookEmailReceivedTriggerDefinition,
227
42
  } as const satisfies Record<string, TriggerDefinition>
228
-
229
- interface DashboardRunFieldBase {
230
- /** Supporting text shown below the field. */
231
- description?: string
232
-
233
- /** Visible field label. Inferred from `name` when omitted. */
234
- label?: string
235
-
236
- /** Property name used in submitted trigger data. */
237
- name: string
238
-
239
- /** Whether the form must contain a value. Defaults to true. */
240
- required?: boolean
241
- }
242
-
243
- export type DashboardRunField =
244
- | (DashboardRunFieldBase & {
245
- defaultValue?: string
246
- maxLength?: number
247
- minLength?: number
248
- placeholder?: string
249
- type: "email" | "phone" | "text" | "textarea" | "url"
250
- })
251
- | (DashboardRunFieldBase & {
252
- defaultValue?: number
253
- max?: number
254
- min?: number
255
- placeholder?: string
256
-
257
- /** Increment used by the number input. Defaults to 1. */
258
- step?: number
259
- type: "number"
260
- })
261
- | (DashboardRunFieldBase & {
262
- /** Initial local date in `YYYY-MM-DD` format. */
263
- defaultValue?: string
264
- max?: string
265
- min?: string
266
-
267
- /** Allowed increment in days. Defaults to 1. */
268
- step?: number
269
- type: "date"
270
- })
271
- | (DashboardRunFieldBase & {
272
- /** Initial local date and time in `YYYY-MM-DDTHH:mm` format. */
273
- defaultValue?: string
274
- max?: string
275
- min?: string
276
-
277
- /** Allowed increment in seconds. Defaults to 60. */
278
- step?: number
279
- type: "datetime"
280
- })
281
- | (DashboardRunFieldBase & {
282
- defaultValue?: string
283
- options: readonly { label: string; value: string }[]
284
- placeholder?: string
285
- type: "select"
286
- })
287
- | (DashboardRunFieldBase & {
288
- defaultValue?: string
289
- options: readonly { label: string; value: string }[]
290
- type: "radio"
291
- })
292
- | (DashboardRunFieldBase & {
293
- defaultValue?: readonly string[]
294
- options: readonly { label: string; value: string }[]
295
- placeholder?: string
296
- type: "multi-select"
297
- })
298
- | (DashboardRunFieldBase & {
299
- /** Initial checked state. Defaults to false. */
300
- defaultValue?: boolean
301
-
302
- /** Whether the checkbox must be checked. Defaults to false. */
303
- required?: boolean
304
- type: "checkbox"
305
- })
306
-
307
- export interface DashboardRunConfig<
308
- TFields extends readonly DashboardRunField[] = readonly DashboardRunField[],
309
- > {
310
- /** Supporting text shown below the form title. */
311
- description?: string
312
-
313
- /** Ordered fields. Omit to run immediately. */
314
- fields?: TFields
315
-
316
- /** Submit button text. Defaults to "Run". */
317
- submitLabel?: string
318
-
319
- /** Form heading. */
320
- title: string
321
- }
322
-
323
- export interface DashboardRunEndpointOptions {
324
- appOrigin: string
325
- automationId: string
326
- hookSlot: number
327
- scopePath?: readonly number[]
328
- }
329
-
330
- export type HttpTriggerScope = "trigger" | "automation" | "project"
331
- export type MailhookScope = HttpTriggerScope
332
-
333
- export const PLATFORM_EMAIL_DOMAIN = "automations.automate.ax"
334
-
335
- export interface HttpTriggerEndpointOptions {
336
- appOrigin: string
337
- automationId: string
338
- hookSlot: number
339
- projectId: string
340
- scope: HttpTriggerScope
341
- scopePath?: readonly number[]
342
- }
343
-
344
- export interface MailhookAddressOptions {
345
- automationId: string
346
- hookSlot: number
347
- plusPath?: string
348
- projectId: string
349
- scope: MailhookScope
350
- scopePath?: readonly number[]
351
- }
352
-
353
- /**
354
- * Returns the public URL for one deployed HTTP trigger.
355
- *
356
- * @param options - Public origin and trigger identity.
357
- */
358
- export function getHttpTriggerEndpoint(options: HttpTriggerEndpointOptions) {
359
- return new URL(
360
- `/x/${getHttpTriggerEndpointKey(options)}/`,
361
- options.appOrigin,
362
- ).toString()
363
- }
364
-
365
- /**
366
- * Returns the durable endpoint identity for one configured HTTP scope.
367
- *
368
- * @param options - Trigger and owning resource identity.
369
- */
370
- export function getHttpTriggerEndpointKey(
371
- options: Omit<HttpTriggerEndpointOptions, "appOrigin">,
372
- ) {
373
- if (options.scope === "project") return options.projectId
374
- if (options.scope === "automation") return options.automationId
375
- return `${options.automationId}:${[
376
- ...(options.scopePath ?? []),
377
- options.hookSlot,
378
- ].join(".")}`
379
- }
380
-
381
- /**
382
- * Returns the unique inbound address for one deployed mailhook.
383
- *
384
- * Add `+suffix` before the `@` to carry a routing value into the event.
385
- *
386
- * @param options - Mailhook identity and sharing scope.
387
- * @throws When the generated local part exceeds the email size limit.
388
- */
389
- export function getMailhookAddress(options: MailhookAddressOptions) {
390
- const localPart = `${getMailhookAddressKey(options)}${options.plusPath ? `+${options.plusPath}` : ""}`
391
- if (new TextEncoder().encode(localPart).length > MAX_EMAIL_LOCAL_PART_BYTES) {
392
- throw new RangeError("Mailhook address local part exceeds 64 bytes.")
393
- }
394
-
395
- return EMAIL_SCHEMA.parse(`${localPart}@${PLATFORM_EMAIL_DOMAIN}`)
396
- }
397
-
398
- /**
399
- * Returns the local-part router key for one configured mailhook scope.
400
- *
401
- * @param options - Mailhook identity and sharing scope.
402
- */
403
- export function getMailhookAddressKey(options: MailhookAddressOptions) {
404
- if (options.scope === "project") return `p${typeIdSuffix(options.projectId)}`
405
- if (options.scope === "automation") {
406
- return `a${typeIdSuffix(options.automationId)}`
407
- }
408
-
409
- return `a${typeIdSuffix(options.automationId)}.${[
410
- ...(options.scopePath ?? []),
411
- options.hookSlot,
412
- ]
413
- .map((segment) => segment.toString(36))
414
- .join(".")}`
415
- }
416
-
417
- /**
418
- * Returns the organization-authenticated submission endpoint for one dashboard
419
- * run.
420
- *
421
- * @param options - Public origin and trigger identity.
422
- */
423
- export function getDashboardRunEndpoint(options: DashboardRunEndpointOptions) {
424
- return new URL(
425
- `/api/dashboard-runs/${getDashboardRunEndpointKey(options)}`,
426
- options.appOrigin,
427
- ).toString()
428
- }
429
-
430
- /**
431
- * Returns the durable endpoint identity for one dashboard run trigger.
432
- *
433
- * @param options - Trigger and owning automation identity.
434
- */
435
- export function getDashboardRunEndpointKey(
436
- options: Omit<DashboardRunEndpointOptions, "appOrigin">,
437
- ) {
438
- return `${options.automationId}:${[
439
- ...(options.scopePath ?? []),
440
- options.hookSlot,
441
- ].join(".")}`
442
- }
443
-
444
- /**
445
- * Checks a configured default against the same constraints as submitted data.
446
- *
447
- * @param field - Field definition to validate.
448
- */
449
- function isDashboardRunFieldDefaultValid(field: DashboardRunField) {
450
- if (field.type === "checkbox" || field.defaultValue === undefined) return true
451
-
452
- if (field.type === "multi-select") {
453
- if (field.required !== false && field.defaultValue.length === 0)
454
- return false
455
- return field.defaultValue.every((value) =>
456
- field.options.some((option) => option.value === value),
457
- )
458
- }
459
-
460
- if (field.type === "radio" || field.type === "select") {
461
- return field.options.some((option) => option.value === field.defaultValue)
462
- }
463
-
464
- if (field.type === "number") {
465
- return (
466
- (field.min === undefined || field.defaultValue >= field.min) &&
467
- (field.max === undefined || field.defaultValue <= field.max) &&
468
- !isDashboardRunStepMismatch(
469
- field.defaultValue,
470
- field.min ?? field.defaultValue,
471
- field.step ?? 1,
472
- )
473
- )
474
- }
475
-
476
- if (field.type === "date" || field.type === "datetime") {
477
- const defaultValue = parseDashboardRunDateValue(
478
- field.type,
479
- field.defaultValue,
480
- )
481
- return (
482
- (field.min === undefined ||
483
- defaultValue >= parseDashboardRunDateValue(field.type, field.min)) &&
484
- (field.max === undefined ||
485
- defaultValue <= parseDashboardRunDateValue(field.type, field.max)) &&
486
- !isDashboardRunStepMismatch(
487
- defaultValue,
488
- parseDashboardRunDateValue(field.type, field.min ?? field.defaultValue),
489
- (field.step ?? (field.type === "date" ? 1 : 60)) *
490
- (field.type === "date" ? 86_400_000 : 1_000),
491
- )
492
- )
493
- }
494
-
495
- const defaultValue = field.defaultValue.trim()
496
- return (
497
- (defaultValue.length > 0 || field.required === false) &&
498
- (field.minLength === undefined || defaultValue.length >= field.minLength) &&
499
- (field.maxLength === undefined || defaultValue.length <= field.maxLength) &&
500
- (field.type !== "email" || EMAIL_SCHEMA.safeParse(defaultValue).success) &&
501
- (field.type !== "url" || URL_SCHEMA.safeParse(defaultValue).success)
502
- )
503
- }
504
-
505
- /**
506
- * Checks whether a value falls outside an allowed step interval.
507
- *
508
- * @param value - Configured default value.
509
- * @param base - Value from which step intervals begin.
510
- * @param step - Allowed interval size.
511
- */
512
- function isDashboardRunStepMismatch(value: number, base: number, step: number) {
513
- const intervals = (value - base) / step
514
- return Math.abs(intervals - Math.round(intervals)) > 1e-9
515
- }
516
-
517
- /**
518
- * Converts a validated local date or date-time string to a UTC number.
519
- *
520
- * @param type - Temporal field type.
521
- * @param value - Local ISO value to convert.
522
- */
523
- function parseDashboardRunDateValue(type: "date" | "datetime", value: string) {
524
- return Date.parse(type === "date" ? `${value}T00:00:00Z` : `${value}Z`)
525
- }
526
-
527
- /**
528
- * Converts a stable identifier to a sentence-cased display name.
529
- *
530
- * @param value - Stable identifier to format.
531
- */
532
- export function sentenceCase(value: string) {
533
- const words = value
534
- .replaceAll(/([a-z\d])([A-Z])/g, "$1 $2")
535
- .replaceAll(/[._-]+/g, " ")
536
- .toLowerCase()
537
-
538
- return words.charAt(0).toUpperCase() + words.slice(1)
539
- }
540
-
541
- /**
542
- * Removes the redundant TypeID prefix from an address router.
543
- *
544
- * @param id - Project or automation TypeID.
545
- */
546
- function typeIdSuffix(id: string) {
547
- return id.includes("_") ? id.slice(id.indexOf("_") + 1) : id
548
- }
@@ -1,4 +1,3 @@
1
- import { githubService } from "../catalog"
2
1
  import type { IntegrationAccountRequirement, TriggerDefinition } from "../types"
3
2
 
4
3
  const GITHUB_ISSUES_ACCOUNT = {
@@ -7,7 +6,7 @@ const GITHUB_ISSUES_ACCOUNT = {
7
6
  requiredScopes: ["issues:read"],
8
7
  },
9
8
  ],
10
- serviceId: githubService.id,
9
+ serviceId: "github",
11
10
  } as const satisfies IntegrationAccountRequirement
12
11
 
13
12
  const GITHUB_PULL_REQUESTS_ACCOUNT = {
@@ -16,7 +15,7 @@ const GITHUB_PULL_REQUESTS_ACCOUNT = {
16
15
  requiredScopes: ["pull_requests:read"],
17
16
  },
18
17
  ],
19
- serviceId: githubService.id,
18
+ serviceId: "github",
20
19
  } as const satisfies IntegrationAccountRequirement
21
20
 
22
21
  const GITHUB_CONTENTS_ACCOUNT = {
@@ -25,7 +24,7 @@ const GITHUB_CONTENTS_ACCOUNT = {
25
24
  requiredScopes: ["contents:read"],
26
25
  },
27
26
  ],
28
- serviceId: githubService.id,
27
+ serviceId: "github",
29
28
  } as const satisfies IntegrationAccountRequirement
30
29
 
31
30
  const GITHUB_ACTIONS_ACCOUNT = {
@@ -34,7 +33,7 @@ const GITHUB_ACTIONS_ACCOUNT = {
34
33
  requiredScopes: ["actions:read"],
35
34
  },
36
35
  ],
37
- serviceId: githubService.id,
36
+ serviceId: "github",
38
37
  } as const satisfies IntegrationAccountRequirement
39
38
 
40
39
  export const githubTriggerDefinitions = {
@@ -1,4 +1,3 @@
1
- import { googleService } from "../catalog"
2
1
  import type { IntegrationAccountRequirement, TriggerDefinition } from "../types"
3
2
 
4
3
  const GMAIL_ACCOUNT = {
@@ -16,7 +15,7 @@ const GMAIL_ACCOUNT = {
16
15
  ],
17
16
  },
18
17
  ],
19
- serviceId: googleService.id,
18
+ serviceId: "google",
20
19
  } as const satisfies IntegrationAccountRequirement
21
20
 
22
21
  const GOOGLE_CALENDAR_ACCOUNT = {
@@ -36,7 +35,7 @@ const GOOGLE_CALENDAR_ACCOUNT = {
36
35
  ],
37
36
  },
38
37
  ],
39
- serviceId: googleService.id,
38
+ serviceId: "google",
40
39
  } as const satisfies IntegrationAccountRequirement
41
40
 
42
41
  const GOOGLE_FORMS_ACCOUNT = {
@@ -56,7 +55,7 @@ const GOOGLE_FORMS_ACCOUNT = {
56
55
  ],
57
56
  },
58
57
  ],
59
- serviceId: googleService.id,
58
+ serviceId: "google",
60
59
  } as const satisfies IntegrationAccountRequirement
61
60
 
62
61
  const GOOGLE_FORM_RESPONSES_ACCOUNT = {
@@ -99,7 +98,7 @@ const GOOGLE_FORM_RESPONSES_ACCOUNT = {
99
98
  ],
100
99
  },
101
100
  ],
102
- serviceId: googleService.id,
101
+ serviceId: "google",
103
102
  } as const satisfies IntegrationAccountRequirement
104
103
 
105
104
  export const googleTriggerDefinitions = {
@@ -1,7 +1,7 @@
1
1
  import { airtableTriggerDefinitions } from "./airtable"
2
2
  import { asanaTriggerDefinitions } from "./asana"
3
3
  import { brevoTriggerDefinitions } from "./brevo"
4
- import { coreTriggerDefinitions, sentenceCase } from "./core"
4
+ import { coreTriggerDefinitions } from "./core"
5
5
  import { githubTriggerDefinitions } from "./github"
6
6
  import { googleTriggerDefinitions } from "./google"
7
7
  import { linearTriggerDefinitions } from "./linear"
@@ -11,6 +11,7 @@ import { slackTriggerDefinitions } from "./slack"
11
11
  import { trelloTriggerDefinitions } from "./trello"
12
12
  import { vercelTriggerDefinitions } from "./vercel"
13
13
  import { whatsappTriggerDefinitions } from "./whatsapp"
14
+ import { sentenceCase } from "./name"
14
15
  import { getIntegrationService } from "../catalog"
15
16
  import type {
16
17
  TriggerDefinition,
@@ -1,4 +1,3 @@
1
- import { linearService } from "../catalog"
2
1
  import type { IntegrationAccountRequirement, TriggerDefinition } from "../types"
3
2
 
4
3
  const LINEAR_ACCOUNT = {
@@ -7,7 +6,7 @@ const LINEAR_ACCOUNT = {
7
6
  requiredScopes: ["read"],
8
7
  },
9
8
  ],
10
- serviceId: linearService.id,
9
+ serviceId: "linear",
11
10
  } as const satisfies IntegrationAccountRequirement
12
11
 
13
12
  export const linearTriggerDefinitions = {