@automate.ax/catalog 0.62.1 → 0.64.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.
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export { airtableService, anthropicService, apolloService, asanaService, brevoService, cerebrasService, cloudflareService, cohereService, deepinfraService, deepseekService, firecrawlService, fireworksService, getIntegrationService, githubService, googleGenaiService, googleService, groqService, huggingfaceService, integrationCatalog, linearService, microsoftService, millionverifierService, mistralService, openaiService, openrouterService, perplexityService, postgresService, resendService, scrapflyService, slackService, tidycalService, togetheraiService, trelloService, vercelAiGatewayService, vercelService, whatsappService, xaiService, type IntegrationServiceId, } from "./catalog.js";
2
2
  export { defineIntegrationCatalog, defineIntegrationService, integrationScope, type IntegrationAccountConnectionOption, type IntegrationAccountRequirement, type IntegrationConnectionDefinition, type IntegrationFormField, type IntegrationScopeRequirement, type IntegrationServiceDefinition, type ScopeRequirementGroup, type TriggerDefinition, type TriggerPresentation, type TriggerPresentationContext, type TriggerPresentationDetail, type TriggerScopePresentation, type TriggerPresentationValue, } from "./types.js";
3
- export { getHttpTriggerEndpoint, getHttpTriggerEndpointKey, getTriggerDefinition, getTriggerName, getTriggerPresentation, isTriggerVisible, triggerCatalog, triggerDefinitions, type HttpTriggerEndpointOptions, type HttpTriggerScope, type TriggerType, } from "./triggers/index.js";
3
+ export { getDashboardRunEndpoint, getDashboardRunEndpointKey, getHttpTriggerEndpoint, getHttpTriggerEndpointKey, getMailhookAddress, getMailhookAddressKey, DASHBOARD_RUN_CONFIG_SCHEMA, getTriggerDefinition, getTriggerName, getTriggerPresentation, isTriggerVisible, PLATFORM_EMAIL_DOMAIN, triggerCatalog, triggerDefinitions, type DashboardRunConfig, type DashboardRunEndpointOptions, type DashboardRunField, type HttpTriggerEndpointOptions, type HttpTriggerScope, type MailhookAddressOptions, type MailhookScope, type TriggerType, } from "./triggers/index.js";
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
1
  export { airtableService, anthropicService, apolloService, asanaService, brevoService, cerebrasService, cloudflareService, cohereService, deepinfraService, deepseekService, firecrawlService, fireworksService, getIntegrationService, githubService, googleGenaiService, googleService, groqService, huggingfaceService, integrationCatalog, linearService, microsoftService, millionverifierService, mistralService, openaiService, openrouterService, perplexityService, postgresService, resendService, scrapflyService, slackService, tidycalService, togetheraiService, trelloService, vercelAiGatewayService, vercelService, whatsappService, xaiService, } from "./catalog.js";
2
2
  export { defineIntegrationCatalog, defineIntegrationService, integrationScope, } from "./types.js";
3
- export { getHttpTriggerEndpoint, getHttpTriggerEndpointKey, getTriggerDefinition, getTriggerName, getTriggerPresentation, isTriggerVisible, triggerCatalog, triggerDefinitions, } from "./triggers/index.js";
3
+ export { getDashboardRunEndpoint, getDashboardRunEndpointKey, getHttpTriggerEndpoint, getHttpTriggerEndpointKey, getMailhookAddress, getMailhookAddressKey, DASHBOARD_RUN_CONFIG_SCHEMA, getTriggerDefinition, getTriggerName, getTriggerPresentation, isTriggerVisible, PLATFORM_EMAIL_DOMAIN, triggerCatalog, triggerDefinitions, } from "./triggers/index.js";
@@ -1,3 +1,47 @@
1
+ import * as z from "zod/mini";
2
+ export declare const DASHBOARD_RUN_CONFIG_SCHEMA: z.ZodMiniObject<{
3
+ description: z.ZodMiniOptional<z.ZodMiniString<string>>;
4
+ fields: z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniDiscriminatedUnion<[z.ZodMiniObject<{
5
+ maxLength: z.ZodMiniOptional<z.ZodMiniNumberFormat>;
6
+ minLength: z.ZodMiniOptional<z.ZodMiniNumberFormat>;
7
+ placeholder: z.ZodMiniOptional<z.ZodMiniString<string>>;
8
+ type: z.ZodMiniEnum<{
9
+ email: "email";
10
+ text: "text";
11
+ url: "url";
12
+ textarea: "textarea";
13
+ }>;
14
+ description: z.ZodMiniOptional<z.ZodMiniString<string>>;
15
+ label: z.ZodMiniString<string>;
16
+ required: z.ZodMiniPrefault<z.ZodMiniBoolean<boolean>>;
17
+ }, z.core.$strip>, z.ZodMiniObject<{
18
+ max: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
19
+ min: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
20
+ placeholder: z.ZodMiniOptional<z.ZodMiniString<string>>;
21
+ step: z.ZodMiniPrefault<z.ZodMiniNumber<number>>;
22
+ type: z.ZodMiniLiteral<"number">;
23
+ description: z.ZodMiniOptional<z.ZodMiniString<string>>;
24
+ label: z.ZodMiniString<string>;
25
+ required: z.ZodMiniPrefault<z.ZodMiniBoolean<boolean>>;
26
+ }, z.core.$strip>, z.ZodMiniObject<{
27
+ options: z.ZodMiniArray<z.ZodMiniObject<{
28
+ label: z.ZodMiniString<string>;
29
+ value: z.ZodMiniString<string>;
30
+ }, z.core.$strip>>;
31
+ placeholder: z.ZodMiniOptional<z.ZodMiniString<string>>;
32
+ type: z.ZodMiniLiteral<"select">;
33
+ description: z.ZodMiniOptional<z.ZodMiniString<string>>;
34
+ label: z.ZodMiniString<string>;
35
+ required: z.ZodMiniPrefault<z.ZodMiniBoolean<boolean>>;
36
+ }, z.core.$strip>, z.ZodMiniObject<{
37
+ type: z.ZodMiniLiteral<"checkbox">;
38
+ description: z.ZodMiniOptional<z.ZodMiniString<string>>;
39
+ label: z.ZodMiniString<string>;
40
+ required: z.ZodMiniPrefault<z.ZodMiniBoolean<boolean>>;
41
+ }, z.core.$strip>], "type">>;
42
+ submitLabel: z.ZodMiniPrefault<z.ZodMiniString<string>>;
43
+ title: z.ZodMiniString<string>;
44
+ }, z.core.$strip>;
1
45
  export declare const coreTriggerDefinitions: {
2
46
  readonly automationInvoked: {
3
47
  readonly getDetails: ({ config }: import("..").TriggerPresentationContext) => {
@@ -26,8 +70,74 @@ export declare const coreTriggerDefinitions: {
26
70
  readonly name: "HTTP request";
27
71
  readonly type: "http.request";
28
72
  };
73
+ readonly mailhookEmailReceived: {
74
+ readonly getPrimary: ({ automationId, config, hookSlot, projectId, scopePath }: import("..").TriggerPresentationContext) => {
75
+ copyable: true;
76
+ value: string;
77
+ };
78
+ readonly icon: "webhook";
79
+ readonly name: "Mailhook";
80
+ readonly type: "mailhook.email.received";
81
+ };
82
+ readonly dashboardRun: {
83
+ readonly getDetails: ({ config }: import("..").TriggerPresentationContext) => {
84
+ label: string;
85
+ value: string;
86
+ }[];
87
+ readonly icon: "automation";
88
+ readonly name: "Dashboard run";
89
+ readonly type: "dashboard.run";
90
+ };
29
91
  };
92
+ interface DashboardRunFieldBase {
93
+ /** Supporting text shown below the field. */
94
+ description?: string;
95
+ /** Visible field label. */
96
+ label: string;
97
+ /** Whether the form must contain a value. Defaults to true. */
98
+ required?: boolean;
99
+ }
100
+ export type DashboardRunField = (DashboardRunFieldBase & {
101
+ maxLength?: number;
102
+ minLength?: number;
103
+ placeholder?: string;
104
+ type: "email" | "text" | "textarea" | "url";
105
+ }) | (DashboardRunFieldBase & {
106
+ max?: number;
107
+ min?: number;
108
+ placeholder?: string;
109
+ /** Increment used by the number input. Defaults to 1. */
110
+ step?: number;
111
+ type: "number";
112
+ }) | (DashboardRunFieldBase & {
113
+ options: readonly {
114
+ label: string;
115
+ value: string;
116
+ }[];
117
+ placeholder?: string;
118
+ type: "select";
119
+ }) | (DashboardRunFieldBase & {
120
+ type: "checkbox";
121
+ });
122
+ export interface DashboardRunConfig<TFields extends Record<string, DashboardRunField> = Record<string, DashboardRunField>> {
123
+ /** Supporting text shown below the form title. */
124
+ description?: string;
125
+ /** Named fields rendered in declaration order. */
126
+ fields: TFields;
127
+ /** Submit button text. Defaults to "Run". */
128
+ submitLabel?: string;
129
+ /** Form heading. */
130
+ title: string;
131
+ }
132
+ export interface DashboardRunEndpointOptions {
133
+ appOrigin: string;
134
+ automationId: string;
135
+ hookSlot: number;
136
+ scopePath?: readonly number[];
137
+ }
30
138
  export type HttpTriggerScope = "trigger" | "automation" | "project";
139
+ export type MailhookScope = HttpTriggerScope;
140
+ export declare const PLATFORM_EMAIL_DOMAIN = "automations.automate.ax";
31
141
  export interface HttpTriggerEndpointOptions {
32
142
  appOrigin: string;
33
143
  automationId: string;
@@ -36,6 +146,14 @@ export interface HttpTriggerEndpointOptions {
36
146
  scope: HttpTriggerScope;
37
147
  scopePath?: readonly number[];
38
148
  }
149
+ export interface MailhookAddressOptions {
150
+ automationId: string;
151
+ hookSlot: number;
152
+ plusPath?: string;
153
+ projectId: string;
154
+ scope: MailhookScope;
155
+ scopePath?: readonly number[];
156
+ }
39
157
  /**
40
158
  * Returns the public URL for one deployed HTTP trigger.
41
159
  *
@@ -48,3 +166,32 @@ export declare function getHttpTriggerEndpoint(options: HttpTriggerEndpointOptio
48
166
  * @param options - Trigger and owning resource identity.
49
167
  */
50
168
  export declare function getHttpTriggerEndpointKey(options: Omit<HttpTriggerEndpointOptions, "appOrigin">): string;
169
+ /**
170
+ * Returns the unique inbound address for one deployed mailhook.
171
+ *
172
+ * Add `+suffix` before the `@` to carry a routing value into the event.
173
+ *
174
+ * @param options - Mailhook identity and sharing scope.
175
+ * @throws When the generated local part exceeds the email size limit.
176
+ */
177
+ export declare function getMailhookAddress(options: MailhookAddressOptions): string;
178
+ /**
179
+ * Returns the local-part router key for one configured mailhook scope.
180
+ *
181
+ * @param options - Mailhook identity and sharing scope.
182
+ */
183
+ export declare function getMailhookAddressKey(options: MailhookAddressOptions): string;
184
+ /**
185
+ * Returns the organization-authenticated submission endpoint for one dashboard
186
+ * run.
187
+ *
188
+ * @param options - Public origin and trigger identity.
189
+ */
190
+ export declare function getDashboardRunEndpoint(options: DashboardRunEndpointOptions): string;
191
+ /**
192
+ * Returns the durable endpoint identity for one dashboard run trigger.
193
+ *
194
+ * @param options - Trigger and owning automation identity.
195
+ */
196
+ export declare function getDashboardRunEndpointKey(options: Omit<DashboardRunEndpointOptions, "appOrigin">): string;
197
+ export {};
@@ -1,4 +1,6 @@
1
1
  import * as z from "zod/mini";
2
+ const MAX_EMAIL_LOCAL_PART_BYTES = 64;
3
+ const EMAIL_SCHEMA = z.email();
2
4
  const CRON_PRESENTATION_CONFIG_SCHEMA = z.object({
3
5
  schedule: z.string(),
4
6
  timeZone: z.prefault(z.string(), "UTC"),
@@ -6,9 +8,66 @@ const CRON_PRESENTATION_CONFIG_SCHEMA = z.object({
6
8
  const HTTP_PRESENTATION_CONFIG_SCHEMA = z.object({
7
9
  scope: z.prefault(z.enum(["trigger", "automation", "project"]), "trigger"),
8
10
  });
11
+ const MAILHOOK_PRESENTATION_CONFIG_SCHEMA = z.object({
12
+ scope: z.prefault(z.enum(["trigger", "automation", "project"]), "trigger"),
13
+ });
9
14
  const INVOCATION_PRESENTATION_CONFIG_SCHEMA = z.object({
10
15
  entrypoint: z.string(),
11
16
  });
17
+ const FIELD_NAME_SCHEMA = z
18
+ .string()
19
+ .check(z.trim(), z.minLength(1), z.maxLength(100));
20
+ const FIELD_LABEL_SCHEMA = z
21
+ .string()
22
+ .check(z.trim(), z.minLength(1), z.maxLength(255));
23
+ const FIELD_DESCRIPTION_SCHEMA = z.string().check(z.maxLength(2_000));
24
+ const FIELD_LENGTH_SCHEMA = z.int().check(z.nonnegative());
25
+ const DASHBOARD_RUN_FIELD_BASE_SCHEMA = {
26
+ description: z.optional(FIELD_DESCRIPTION_SCHEMA),
27
+ label: FIELD_LABEL_SCHEMA,
28
+ required: z.prefault(z.boolean(), true),
29
+ };
30
+ const DASHBOARD_RUN_TEXT_FIELD_SCHEMA = z.object({
31
+ ...DASHBOARD_RUN_FIELD_BASE_SCHEMA,
32
+ maxLength: z.optional(FIELD_LENGTH_SCHEMA),
33
+ minLength: z.optional(FIELD_LENGTH_SCHEMA),
34
+ placeholder: z.optional(z.string()),
35
+ type: z.enum(["email", "text", "textarea", "url"]),
36
+ });
37
+ const DASHBOARD_RUN_NUMBER_FIELD_SCHEMA = z.object({
38
+ ...DASHBOARD_RUN_FIELD_BASE_SCHEMA,
39
+ max: z.optional(z.number()),
40
+ min: z.optional(z.number()),
41
+ placeholder: z.optional(z.string()),
42
+ step: z.prefault(z.number().check(z.positive()), 1),
43
+ type: z.literal("number"),
44
+ });
45
+ const DASHBOARD_RUN_SELECT_FIELD_SCHEMA = z.object({
46
+ ...DASHBOARD_RUN_FIELD_BASE_SCHEMA,
47
+ options: z
48
+ .array(z.object({
49
+ label: FIELD_LABEL_SCHEMA,
50
+ value: FIELD_NAME_SCHEMA,
51
+ }))
52
+ .check(z.minLength(1)),
53
+ placeholder: z.optional(z.string()),
54
+ type: z.literal("select"),
55
+ });
56
+ const DASHBOARD_RUN_CHECKBOX_FIELD_SCHEMA = z.object({
57
+ ...DASHBOARD_RUN_FIELD_BASE_SCHEMA,
58
+ type: z.literal("checkbox"),
59
+ });
60
+ export const DASHBOARD_RUN_CONFIG_SCHEMA = z.object({
61
+ description: z.optional(FIELD_DESCRIPTION_SCHEMA),
62
+ fields: z.record(FIELD_NAME_SCHEMA, z.discriminatedUnion("type", [
63
+ DASHBOARD_RUN_TEXT_FIELD_SCHEMA,
64
+ DASHBOARD_RUN_NUMBER_FIELD_SCHEMA,
65
+ DASHBOARD_RUN_SELECT_FIELD_SCHEMA,
66
+ DASHBOARD_RUN_CHECKBOX_FIELD_SCHEMA,
67
+ ])),
68
+ submitLabel: z.prefault(z.string().check(z.trim(), z.minLength(1), z.maxLength(100)), "Run"),
69
+ title: z.string().check(z.trim(), z.minLength(1), z.maxLength(255)),
70
+ });
12
71
  export const coreTriggerDefinitions = {
13
72
  automationInvoked: {
14
73
  getDetails: ({ config }) => [
@@ -49,7 +108,34 @@ export const coreTriggerDefinitions = {
49
108
  name: "HTTP request",
50
109
  type: "http.request",
51
110
  },
111
+ mailhookEmailReceived: {
112
+ getPrimary: ({ automationId, config, hookSlot, projectId, scopePath }) => ({
113
+ copyable: true,
114
+ value: getMailhookAddress({
115
+ automationId,
116
+ hookSlot,
117
+ projectId,
118
+ scope: MAILHOOK_PRESENTATION_CONFIG_SCHEMA.parse(config).scope,
119
+ scopePath,
120
+ }),
121
+ }),
122
+ icon: "webhook",
123
+ name: "Mailhook",
124
+ type: "mailhook.email.received",
125
+ },
126
+ dashboardRun: {
127
+ getDetails: ({ config }) => [
128
+ {
129
+ label: "Run form",
130
+ value: DASHBOARD_RUN_CONFIG_SCHEMA.parse(config).title,
131
+ },
132
+ ],
133
+ icon: "automation",
134
+ name: "Dashboard run",
135
+ type: "dashboard.run",
136
+ },
52
137
  };
138
+ export const PLATFORM_EMAIL_DOMAIN = "automations.automate.ax";
53
139
  /**
54
140
  * Returns the public URL for one deployed HTTP trigger.
55
141
  *
@@ -73,3 +159,64 @@ export function getHttpTriggerEndpointKey(options) {
73
159
  options.hookSlot,
74
160
  ].join(".")}`;
75
161
  }
162
+ /**
163
+ * Returns the unique inbound address for one deployed mailhook.
164
+ *
165
+ * Add `+suffix` before the `@` to carry a routing value into the event.
166
+ *
167
+ * @param options - Mailhook identity and sharing scope.
168
+ * @throws When the generated local part exceeds the email size limit.
169
+ */
170
+ export function getMailhookAddress(options) {
171
+ const localPart = `${getMailhookAddressKey(options)}${options.plusPath ? `+${options.plusPath}` : ""}`;
172
+ if (new TextEncoder().encode(localPart).length > MAX_EMAIL_LOCAL_PART_BYTES) {
173
+ throw new RangeError("Mailhook address local part exceeds 64 bytes.");
174
+ }
175
+ return EMAIL_SCHEMA.parse(`${localPart}@${PLATFORM_EMAIL_DOMAIN}`);
176
+ }
177
+ /**
178
+ * Returns the local-part router key for one configured mailhook scope.
179
+ *
180
+ * @param options - Mailhook identity and sharing scope.
181
+ */
182
+ export function getMailhookAddressKey(options) {
183
+ if (options.scope === "project")
184
+ return `p${typeIdSuffix(options.projectId)}`;
185
+ if (options.scope === "automation") {
186
+ return `a${typeIdSuffix(options.automationId)}`;
187
+ }
188
+ return `a${typeIdSuffix(options.automationId)}.${[
189
+ ...(options.scopePath ?? []),
190
+ options.hookSlot,
191
+ ]
192
+ .map((segment) => segment.toString(36))
193
+ .join(".")}`;
194
+ }
195
+ /**
196
+ * Returns the organization-authenticated submission endpoint for one dashboard
197
+ * run.
198
+ *
199
+ * @param options - Public origin and trigger identity.
200
+ */
201
+ export function getDashboardRunEndpoint(options) {
202
+ return new URL(`/api/dashboard-runs/${getDashboardRunEndpointKey(options)}`, options.appOrigin).toString();
203
+ }
204
+ /**
205
+ * Returns the durable endpoint identity for one dashboard run trigger.
206
+ *
207
+ * @param options - Trigger and owning automation identity.
208
+ */
209
+ export function getDashboardRunEndpointKey(options) {
210
+ return `${options.automationId}:${[
211
+ ...(options.scopePath ?? []),
212
+ options.hookSlot,
213
+ ].join(".")}`;
214
+ }
215
+ /**
216
+ * Removes the redundant TypeID prefix from an address router.
217
+ *
218
+ * @param id - Project or automation TypeID.
219
+ */
220
+ function typeIdSuffix(id) {
221
+ return id.includes("_") ? id.slice(id.indexOf("_") + 1) : id;
222
+ }
@@ -1,5 +1,5 @@
1
1
  import type { TriggerDefinition, TriggerPresentation, TriggerPresentationContext, TriggerScopePresentation } from "../types.js";
2
- export { getHttpTriggerEndpoint, getHttpTriggerEndpointKey, type HttpTriggerEndpointOptions, type HttpTriggerScope, } from "./core.js";
2
+ export { getDashboardRunEndpoint, getDashboardRunEndpointKey, getHttpTriggerEndpoint, getHttpTriggerEndpointKey, getMailhookAddress, getMailhookAddressKey, PLATFORM_EMAIL_DOMAIN, DASHBOARD_RUN_CONFIG_SCHEMA, type DashboardRunConfig, type DashboardRunEndpointOptions, type DashboardRunField, type HttpTriggerEndpointOptions, type HttpTriggerScope, type MailhookAddressOptions, type MailhookScope, } from "./core.js";
3
3
  /** Plain shared definitions for every public trigger type. */
4
4
  export declare const triggerDefinitions: {
5
5
  readonly whatsappMessageDelivered: {
@@ -1075,6 +1075,24 @@ export declare const triggerDefinitions: {
1075
1075
  readonly name: "HTTP request";
1076
1076
  readonly type: "http.request";
1077
1077
  };
1078
+ readonly mailhookEmailReceived: {
1079
+ readonly getPrimary: ({ automationId, config, hookSlot, projectId, scopePath }: TriggerPresentationContext) => {
1080
+ copyable: true;
1081
+ value: string;
1082
+ };
1083
+ readonly icon: "webhook";
1084
+ readonly name: "Mailhook";
1085
+ readonly type: "mailhook.email.received";
1086
+ };
1087
+ readonly dashboardRun: {
1088
+ readonly getDetails: ({ config }: TriggerPresentationContext) => {
1089
+ label: string;
1090
+ value: string;
1091
+ }[];
1092
+ readonly icon: "automation";
1093
+ readonly name: "Dashboard run";
1094
+ readonly type: "dashboard.run";
1095
+ };
1078
1096
  readonly brevoTransactionalBlocked: {
1079
1097
  readonly account: {
1080
1098
  readonly connectionOptions: readonly [{
@@ -1555,6 +1573,22 @@ export declare const triggerCatalog: ({
1555
1573
  };
1556
1574
  icon: "webhook";
1557
1575
  type: "http.request";
1576
+ } | {
1577
+ name: string;
1578
+ getPrimary: ({ automationId, config, hookSlot, projectId, scopePath }: TriggerPresentationContext) => {
1579
+ copyable: true;
1580
+ value: string;
1581
+ };
1582
+ icon: "webhook";
1583
+ type: "mailhook.email.received";
1584
+ } | {
1585
+ name: string;
1586
+ getDetails: ({ config }: TriggerPresentationContext) => {
1587
+ label: string;
1588
+ value: string;
1589
+ }[];
1590
+ icon: "automation";
1591
+ type: "dashboard.run";
1558
1592
  } | {
1559
1593
  name: string;
1560
1594
  account: {
@@ -12,7 +12,7 @@ import { trelloTriggerDefinitions } from "./trello.js";
12
12
  import { vercelTriggerDefinitions } from "./vercel.js";
13
13
  import { whatsappTriggerDefinitions } from "./whatsapp.js";
14
14
  import { getIntegrationService } from "../catalog.js";
15
- export { getHttpTriggerEndpoint, getHttpTriggerEndpointKey, } from "./core.js";
15
+ export { getDashboardRunEndpoint, getDashboardRunEndpointKey, getHttpTriggerEndpoint, getHttpTriggerEndpointKey, getMailhookAddress, getMailhookAddressKey, PLATFORM_EMAIL_DOMAIN, DASHBOARD_RUN_CONFIG_SCHEMA, } from "./core.js";
16
16
  /** Plain shared definitions for every public trigger type. */
17
17
  export const triggerDefinitions = {
18
18
  ...airtableTriggerDefinitions,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automate.ax/catalog",
3
- "version": "0.62.1",
3
+ "version": "0.64.0",
4
4
  "description": "Shared integration service and trigger definitions for Automate.ax.",
5
5
  "license": "MIT",
6
6
  "repository": {
package/src/index.ts CHANGED
@@ -57,15 +57,26 @@ export {
57
57
  type TriggerPresentationValue,
58
58
  } from "./types"
59
59
  export {
60
+ getDashboardRunEndpoint,
61
+ getDashboardRunEndpointKey,
60
62
  getHttpTriggerEndpoint,
61
63
  getHttpTriggerEndpointKey,
64
+ getMailhookAddress,
65
+ getMailhookAddressKey,
66
+ DASHBOARD_RUN_CONFIG_SCHEMA,
62
67
  getTriggerDefinition,
63
68
  getTriggerName,
64
69
  getTriggerPresentation,
65
70
  isTriggerVisible,
71
+ PLATFORM_EMAIL_DOMAIN,
66
72
  triggerCatalog,
67
73
  triggerDefinitions,
74
+ type DashboardRunConfig,
75
+ type DashboardRunEndpointOptions,
76
+ type DashboardRunField,
68
77
  type HttpTriggerEndpointOptions,
69
78
  type HttpTriggerScope,
79
+ type MailhookAddressOptions,
80
+ type MailhookScope,
70
81
  type TriggerType,
71
82
  } from "./triggers"
@@ -1,6 +1,8 @@
1
1
  import type { TriggerDefinition } from "../types"
2
2
  import * as z from "zod/mini"
3
3
 
4
+ const MAX_EMAIL_LOCAL_PART_BYTES = 64
5
+ const EMAIL_SCHEMA = z.email()
4
6
  const CRON_PRESENTATION_CONFIG_SCHEMA = z.object({
5
7
  schedule: z.string(),
6
8
  timeZone: z.prefault(z.string(), "UTC"),
@@ -8,9 +10,75 @@ const CRON_PRESENTATION_CONFIG_SCHEMA = z.object({
8
10
  const HTTP_PRESENTATION_CONFIG_SCHEMA = z.object({
9
11
  scope: z.prefault(z.enum(["trigger", "automation", "project"]), "trigger"),
10
12
  })
13
+ const MAILHOOK_PRESENTATION_CONFIG_SCHEMA = z.object({
14
+ scope: z.prefault(z.enum(["trigger", "automation", "project"]), "trigger"),
15
+ })
11
16
  const INVOCATION_PRESENTATION_CONFIG_SCHEMA = z.object({
12
17
  entrypoint: z.string(),
13
18
  })
19
+ const FIELD_NAME_SCHEMA = z
20
+ .string()
21
+ .check(z.trim(), z.minLength(1), z.maxLength(100))
22
+ const FIELD_LABEL_SCHEMA = z
23
+ .string()
24
+ .check(z.trim(), z.minLength(1), z.maxLength(255))
25
+ const FIELD_DESCRIPTION_SCHEMA = z.string().check(z.maxLength(2_000))
26
+ const FIELD_LENGTH_SCHEMA = z.int().check(z.nonnegative())
27
+ const DASHBOARD_RUN_FIELD_BASE_SCHEMA = {
28
+ description: z.optional(FIELD_DESCRIPTION_SCHEMA),
29
+ label: FIELD_LABEL_SCHEMA,
30
+ required: z.prefault(z.boolean(), true),
31
+ }
32
+ const DASHBOARD_RUN_TEXT_FIELD_SCHEMA = z.object({
33
+ ...DASHBOARD_RUN_FIELD_BASE_SCHEMA,
34
+ maxLength: z.optional(FIELD_LENGTH_SCHEMA),
35
+ minLength: z.optional(FIELD_LENGTH_SCHEMA),
36
+ placeholder: z.optional(z.string()),
37
+ type: z.enum(["email", "text", "textarea", "url"]),
38
+ })
39
+ const DASHBOARD_RUN_NUMBER_FIELD_SCHEMA = z.object({
40
+ ...DASHBOARD_RUN_FIELD_BASE_SCHEMA,
41
+ max: z.optional(z.number()),
42
+ min: z.optional(z.number()),
43
+ placeholder: z.optional(z.string()),
44
+ step: z.prefault(z.number().check(z.positive()), 1),
45
+ type: z.literal("number"),
46
+ })
47
+ const DASHBOARD_RUN_SELECT_FIELD_SCHEMA = z.object({
48
+ ...DASHBOARD_RUN_FIELD_BASE_SCHEMA,
49
+ options: z
50
+ .array(
51
+ z.object({
52
+ label: FIELD_LABEL_SCHEMA,
53
+ value: FIELD_NAME_SCHEMA,
54
+ }),
55
+ )
56
+ .check(z.minLength(1)),
57
+ placeholder: z.optional(z.string()),
58
+ type: z.literal("select"),
59
+ })
60
+ const DASHBOARD_RUN_CHECKBOX_FIELD_SCHEMA = z.object({
61
+ ...DASHBOARD_RUN_FIELD_BASE_SCHEMA,
62
+ type: z.literal("checkbox"),
63
+ })
64
+
65
+ export const DASHBOARD_RUN_CONFIG_SCHEMA = z.object({
66
+ description: z.optional(FIELD_DESCRIPTION_SCHEMA),
67
+ fields: z.record(
68
+ FIELD_NAME_SCHEMA,
69
+ z.discriminatedUnion("type", [
70
+ DASHBOARD_RUN_TEXT_FIELD_SCHEMA,
71
+ DASHBOARD_RUN_NUMBER_FIELD_SCHEMA,
72
+ DASHBOARD_RUN_SELECT_FIELD_SCHEMA,
73
+ DASHBOARD_RUN_CHECKBOX_FIELD_SCHEMA,
74
+ ]),
75
+ ),
76
+ submitLabel: z.prefault(
77
+ z.string().check(z.trim(), z.minLength(1), z.maxLength(100)),
78
+ "Run",
79
+ ),
80
+ title: z.string().check(z.trim(), z.minLength(1), z.maxLength(255)),
81
+ })
14
82
 
15
83
  export const coreTriggerDefinitions = {
16
84
  automationInvoked: {
@@ -60,9 +128,100 @@ export const coreTriggerDefinitions = {
60
128
  name: "HTTP request",
61
129
  type: "http.request",
62
130
  },
131
+ mailhookEmailReceived: {
132
+ getPrimary: ({ automationId, config, hookSlot, projectId, scopePath }) => ({
133
+ copyable: true,
134
+ value: getMailhookAddress({
135
+ automationId,
136
+ hookSlot,
137
+ projectId,
138
+ scope: MAILHOOK_PRESENTATION_CONFIG_SCHEMA.parse(config).scope,
139
+ scopePath,
140
+ }),
141
+ }),
142
+ icon: "webhook",
143
+ name: "Mailhook",
144
+ type: "mailhook.email.received",
145
+ },
146
+ dashboardRun: {
147
+ getDetails: ({ config }) => [
148
+ {
149
+ label: "Run form",
150
+ value: DASHBOARD_RUN_CONFIG_SCHEMA.parse(config).title,
151
+ },
152
+ ],
153
+ icon: "automation",
154
+ name: "Dashboard run",
155
+ type: "dashboard.run",
156
+ },
63
157
  } as const satisfies Record<string, TriggerDefinition>
64
158
 
159
+ interface DashboardRunFieldBase {
160
+ /** Supporting text shown below the field. */
161
+ description?: string
162
+
163
+ /** Visible field label. */
164
+ label: string
165
+
166
+ /** Whether the form must contain a value. Defaults to true. */
167
+ required?: boolean
168
+ }
169
+
170
+ export type DashboardRunField =
171
+ | (DashboardRunFieldBase & {
172
+ maxLength?: number
173
+ minLength?: number
174
+ placeholder?: string
175
+ type: "email" | "text" | "textarea" | "url"
176
+ })
177
+ | (DashboardRunFieldBase & {
178
+ max?: number
179
+ min?: number
180
+ placeholder?: string
181
+
182
+ /** Increment used by the number input. Defaults to 1. */
183
+ step?: number
184
+ type: "number"
185
+ })
186
+ | (DashboardRunFieldBase & {
187
+ options: readonly { label: string; value: string }[]
188
+ placeholder?: string
189
+ type: "select"
190
+ })
191
+ | (DashboardRunFieldBase & {
192
+ type: "checkbox"
193
+ })
194
+
195
+ export interface DashboardRunConfig<
196
+ TFields extends Record<string, DashboardRunField> = Record<
197
+ string,
198
+ DashboardRunField
199
+ >,
200
+ > {
201
+ /** Supporting text shown below the form title. */
202
+ description?: string
203
+
204
+ /** Named fields rendered in declaration order. */
205
+ fields: TFields
206
+
207
+ /** Submit button text. Defaults to "Run". */
208
+ submitLabel?: string
209
+
210
+ /** Form heading. */
211
+ title: string
212
+ }
213
+
214
+ export interface DashboardRunEndpointOptions {
215
+ appOrigin: string
216
+ automationId: string
217
+ hookSlot: number
218
+ scopePath?: readonly number[]
219
+ }
220
+
65
221
  export type HttpTriggerScope = "trigger" | "automation" | "project"
222
+ export type MailhookScope = HttpTriggerScope
223
+
224
+ export const PLATFORM_EMAIL_DOMAIN = "automations.automate.ax"
66
225
 
67
226
  export interface HttpTriggerEndpointOptions {
68
227
  appOrigin: string
@@ -73,6 +232,15 @@ export interface HttpTriggerEndpointOptions {
73
232
  scopePath?: readonly number[]
74
233
  }
75
234
 
235
+ export interface MailhookAddressOptions {
236
+ automationId: string
237
+ hookSlot: number
238
+ plusPath?: string
239
+ projectId: string
240
+ scope: MailhookScope
241
+ scopePath?: readonly number[]
242
+ }
243
+
76
244
  /**
77
245
  * Returns the public URL for one deployed HTTP trigger.
78
246
  *
@@ -100,3 +268,75 @@ export function getHttpTriggerEndpointKey(
100
268
  options.hookSlot,
101
269
  ].join(".")}`
102
270
  }
271
+
272
+ /**
273
+ * Returns the unique inbound address for one deployed mailhook.
274
+ *
275
+ * Add `+suffix` before the `@` to carry a routing value into the event.
276
+ *
277
+ * @param options - Mailhook identity and sharing scope.
278
+ * @throws When the generated local part exceeds the email size limit.
279
+ */
280
+ export function getMailhookAddress(options: MailhookAddressOptions) {
281
+ const localPart = `${getMailhookAddressKey(options)}${options.plusPath ? `+${options.plusPath}` : ""}`
282
+ if (new TextEncoder().encode(localPart).length > MAX_EMAIL_LOCAL_PART_BYTES) {
283
+ throw new RangeError("Mailhook address local part exceeds 64 bytes.")
284
+ }
285
+
286
+ return EMAIL_SCHEMA.parse(`${localPart}@${PLATFORM_EMAIL_DOMAIN}`)
287
+ }
288
+
289
+ /**
290
+ * Returns the local-part router key for one configured mailhook scope.
291
+ *
292
+ * @param options - Mailhook identity and sharing scope.
293
+ */
294
+ export function getMailhookAddressKey(options: MailhookAddressOptions) {
295
+ if (options.scope === "project") return `p${typeIdSuffix(options.projectId)}`
296
+ if (options.scope === "automation") {
297
+ return `a${typeIdSuffix(options.automationId)}`
298
+ }
299
+
300
+ return `a${typeIdSuffix(options.automationId)}.${[
301
+ ...(options.scopePath ?? []),
302
+ options.hookSlot,
303
+ ]
304
+ .map((segment) => segment.toString(36))
305
+ .join(".")}`
306
+ }
307
+
308
+ /**
309
+ * Returns the organization-authenticated submission endpoint for one dashboard
310
+ * run.
311
+ *
312
+ * @param options - Public origin and trigger identity.
313
+ */
314
+ export function getDashboardRunEndpoint(options: DashboardRunEndpointOptions) {
315
+ return new URL(
316
+ `/api/dashboard-runs/${getDashboardRunEndpointKey(options)}`,
317
+ options.appOrigin,
318
+ ).toString()
319
+ }
320
+
321
+ /**
322
+ * Returns the durable endpoint identity for one dashboard run trigger.
323
+ *
324
+ * @param options - Trigger and owning automation identity.
325
+ */
326
+ export function getDashboardRunEndpointKey(
327
+ options: Omit<DashboardRunEndpointOptions, "appOrigin">,
328
+ ) {
329
+ return `${options.automationId}:${[
330
+ ...(options.scopePath ?? []),
331
+ options.hookSlot,
332
+ ].join(".")}`
333
+ }
334
+
335
+ /**
336
+ * Removes the redundant TypeID prefix from an address router.
337
+ *
338
+ * @param id - Project or automation TypeID.
339
+ */
340
+ function typeIdSuffix(id: string) {
341
+ return id.includes("_") ? id.slice(id.indexOf("_") + 1) : id
342
+ }
@@ -20,10 +20,21 @@ import type {
20
20
  } from "../types"
21
21
 
22
22
  export {
23
+ getDashboardRunEndpoint,
24
+ getDashboardRunEndpointKey,
23
25
  getHttpTriggerEndpoint,
24
26
  getHttpTriggerEndpointKey,
27
+ getMailhookAddress,
28
+ getMailhookAddressKey,
29
+ PLATFORM_EMAIL_DOMAIN,
30
+ DASHBOARD_RUN_CONFIG_SCHEMA,
31
+ type DashboardRunConfig,
32
+ type DashboardRunEndpointOptions,
33
+ type DashboardRunField,
25
34
  type HttpTriggerEndpointOptions,
26
35
  type HttpTriggerScope,
36
+ type MailhookAddressOptions,
37
+ type MailhookScope,
27
38
  } from "./core"
28
39
 
29
40
  /** Plain shared definitions for every public trigger type. */