@automate.ax/integration-contracts 0.143.8 → 0.144.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/calendly/api.d.ts +55 -0
- package/dist/calendly/api.js +176 -0
- package/dist/calendly/index.d.ts +6023 -0
- package/dist/calendly/index.js +46 -0
- package/dist/calendly/schemas.d.ts +1170 -0
- package/dist/calendly/schemas.js +420 -0
- package/dist/close/events.d.ts +8 -8
- package/dist/close/schemas.d.ts +12 -12
- package/dist/google-ads/api.d.ts +14 -0
- package/dist/google-ads/api.js +51 -0
- package/dist/millionverifier/schemas.d.ts +7 -7
- package/dist/resend/action-schemas.d.ts +9 -9
- package/dist/slack/event-schemas.d.ts +583 -583
- package/dist/slack/index.d.ts +303 -303
- package/dist/slack/schemas.d.ts +1 -1
- package/dist/teams/index.d.ts +5 -5
- package/dist/teams/schemas.d.ts +4 -4
- package/dist/trello/schemas.d.ts +2 -2
- package/dist/triggers.d.ts +2 -1
- package/package.json +8 -2
- package/src/calendly/api.ts +216 -0
- package/src/calendly/index.ts +69 -0
- package/src/calendly/schemas.ts +450 -0
- package/src/google-ads/api.ts +73 -0
- package/src/triggers.ts +2 -0
package/dist/slack/schemas.d.ts
CHANGED
|
@@ -109,8 +109,8 @@ export declare const SLACK_MESSAGE_SCHEMA: z.ZodObject<{
|
|
|
109
109
|
export declare const SLACK_REACTION_ITEM_SCHEMA: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
110
110
|
conversationId: z.ZodString;
|
|
111
111
|
conversationType: z.ZodOptional<z.ZodEnum<{
|
|
112
|
-
channel: "channel";
|
|
113
112
|
group: "group";
|
|
113
|
+
channel: "channel";
|
|
114
114
|
im: "im";
|
|
115
115
|
mpim: "mpim";
|
|
116
116
|
}>>;
|
package/dist/teams/index.d.ts
CHANGED
|
@@ -560,8 +560,8 @@ export declare const TEAMS_CHANGE_EVENT_SCHEMAS: {
|
|
|
560
560
|
changeType: z.ZodLiteral<"updated">;
|
|
561
561
|
data: z.ZodObject<{
|
|
562
562
|
chatType: z.ZodEnum<{
|
|
563
|
-
meeting: "meeting";
|
|
564
563
|
group: "group";
|
|
564
|
+
meeting: "meeting";
|
|
565
565
|
unknownFutureValue: "unknownFutureValue";
|
|
566
566
|
oneOnOne: "oneOnOne";
|
|
567
567
|
}>;
|
|
@@ -580,8 +580,8 @@ export declare const TEAMS_CHANGE_EVENT_SCHEMAS: {
|
|
|
580
580
|
changeType: z.ZodLiteral<"updated">;
|
|
581
581
|
data: z.ZodObject<{
|
|
582
582
|
chatType: z.ZodEnum<{
|
|
583
|
-
meeting: "meeting";
|
|
584
583
|
group: "group";
|
|
584
|
+
meeting: "meeting";
|
|
585
585
|
unknownFutureValue: "unknownFutureValue";
|
|
586
586
|
oneOnOne: "oneOnOne";
|
|
587
587
|
}>;
|
|
@@ -1172,8 +1172,8 @@ export declare const TEAMS_CHANGE_EVENT_SCHEMA: z.ZodUnion<readonly [z.ZodDiscri
|
|
|
1172
1172
|
changeType: z.ZodLiteral<"updated">;
|
|
1173
1173
|
data: z.ZodObject<{
|
|
1174
1174
|
chatType: z.ZodEnum<{
|
|
1175
|
-
meeting: "meeting";
|
|
1176
1175
|
group: "group";
|
|
1176
|
+
meeting: "meeting";
|
|
1177
1177
|
unknownFutureValue: "unknownFutureValue";
|
|
1178
1178
|
oneOnOne: "oneOnOne";
|
|
1179
1179
|
}>;
|
|
@@ -2151,8 +2151,8 @@ export declare const teamsTriggerContracts: {
|
|
|
2151
2151
|
changeType: z.ZodLiteral<"updated">;
|
|
2152
2152
|
data: z.ZodObject<{
|
|
2153
2153
|
chatType: z.ZodEnum<{
|
|
2154
|
-
meeting: "meeting";
|
|
2155
2154
|
group: "group";
|
|
2155
|
+
meeting: "meeting";
|
|
2156
2156
|
unknownFutureValue: "unknownFutureValue";
|
|
2157
2157
|
oneOnOne: "oneOnOne";
|
|
2158
2158
|
}>;
|
|
@@ -2176,8 +2176,8 @@ export declare const teamsTriggerContracts: {
|
|
|
2176
2176
|
changeType: z.ZodLiteral<"updated">;
|
|
2177
2177
|
data: z.ZodObject<{
|
|
2178
2178
|
chatType: z.ZodEnum<{
|
|
2179
|
-
meeting: "meeting";
|
|
2180
2179
|
group: "group";
|
|
2180
|
+
meeting: "meeting";
|
|
2181
2181
|
unknownFutureValue: "unknownFutureValue";
|
|
2182
2182
|
oneOnOne: "oneOnOne";
|
|
2183
2183
|
}>;
|
package/dist/teams/schemas.d.ts
CHANGED
|
@@ -134,8 +134,8 @@ export declare const GRAPH_MEMBER_SCHEMA: z.ZodPipe<z.ZodObject<{
|
|
|
134
134
|
}>>;
|
|
135
135
|
export declare const TEAMS_CHAT_SCHEMA: z.ZodObject<{
|
|
136
136
|
chatType: z.ZodEnum<{
|
|
137
|
-
meeting: "meeting";
|
|
138
137
|
group: "group";
|
|
138
|
+
meeting: "meeting";
|
|
139
139
|
unknownFutureValue: "unknownFutureValue";
|
|
140
140
|
oneOnOne: "oneOnOne";
|
|
141
141
|
}>;
|
|
@@ -148,8 +148,8 @@ export declare const TEAMS_CHAT_SCHEMA: z.ZodObject<{
|
|
|
148
148
|
}, z.core.$strip>;
|
|
149
149
|
export declare const GRAPH_CHAT_SCHEMA: z.ZodPipe<z.ZodObject<{
|
|
150
150
|
chatType: z.ZodEnum<{
|
|
151
|
-
meeting: "meeting";
|
|
152
151
|
group: "group";
|
|
152
|
+
meeting: "meeting";
|
|
153
153
|
unknownFutureValue: "unknownFutureValue";
|
|
154
154
|
oneOnOne: "oneOnOne";
|
|
155
155
|
}>;
|
|
@@ -160,7 +160,7 @@ export declare const GRAPH_CHAT_SCHEMA: z.ZodPipe<z.ZodObject<{
|
|
|
160
160
|
topic: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
161
161
|
webUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
162
162
|
}, z.core.$loose>, z.ZodTransform<{
|
|
163
|
-
chatType: "
|
|
163
|
+
chatType: "group" | "meeting" | "unknownFutureValue" | "oneOnOne";
|
|
164
164
|
createdAt: Date | undefined;
|
|
165
165
|
chatId: string;
|
|
166
166
|
updatedAt: Date | undefined;
|
|
@@ -169,7 +169,7 @@ export declare const GRAPH_CHAT_SCHEMA: z.ZodPipe<z.ZodObject<{
|
|
|
169
169
|
webUrl: string | undefined;
|
|
170
170
|
}, {
|
|
171
171
|
[x: string]: unknown;
|
|
172
|
-
chatType: "
|
|
172
|
+
chatType: "group" | "meeting" | "unknownFutureValue" | "oneOnOne";
|
|
173
173
|
id: string;
|
|
174
174
|
createdDateTime?: string | null | undefined;
|
|
175
175
|
lastUpdatedDateTime?: string | null | undefined;
|
package/dist/trello/schemas.d.ts
CHANGED
|
@@ -32,8 +32,8 @@ export declare const TRELLO_BOARD_MEMBERSHIP_SCHEMA: z.ZodObject<{
|
|
|
32
32
|
id: z.ZodString;
|
|
33
33
|
memberId: z.ZodString;
|
|
34
34
|
memberType: z.ZodEnum<{
|
|
35
|
-
normal: "normal";
|
|
36
35
|
admin: "admin";
|
|
36
|
+
normal: "normal";
|
|
37
37
|
observer: "observer";
|
|
38
38
|
}>;
|
|
39
39
|
unconfirmed: z.ZodBoolean;
|
|
@@ -230,8 +230,8 @@ export declare const TRELLO_PROVIDER_BOARD_MEMBERSHIP_SCHEMA: z.ZodObject<{
|
|
|
230
230
|
id: z.ZodString;
|
|
231
231
|
idMember: z.ZodString;
|
|
232
232
|
memberType: z.ZodEnum<{
|
|
233
|
-
normal: "normal";
|
|
234
233
|
admin: "admin";
|
|
234
|
+
normal: "normal";
|
|
235
235
|
observer: "observer";
|
|
236
236
|
}>;
|
|
237
237
|
unconfirmed: z.ZodBoolean;
|
package/dist/triggers.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ import type { discordTriggerContracts } from "./discord/index.js";
|
|
|
10
10
|
import type { closeTriggerContracts } from "./close/index.js";
|
|
11
11
|
import type { cloudflareTriggerContracts } from "./cloudflare/index.js";
|
|
12
12
|
import type { clickUpTriggerContracts } from "./clickup/index.js";
|
|
13
|
+
import type { calendlyTriggerContracts } from "./calendly/index.js";
|
|
13
14
|
import type { githubTriggerContracts } from "./github/index.js";
|
|
14
15
|
import type { gmailTriggerContracts } from "./gmail/index.js";
|
|
15
16
|
import type { googleCalendarTriggerContracts } from "./google-calendar/index.js";
|
|
@@ -34,7 +35,7 @@ import type { vercelTriggerContracts } from "./vercel/index.js";
|
|
|
34
35
|
import type { webflowTriggerContracts } from "./webflow/index.js";
|
|
35
36
|
import type { whatsappTriggerContracts } from "./whatsapp/index.js";
|
|
36
37
|
import type { z } from "zod";
|
|
37
|
-
export type TriggerContractMap = typeof airtableTriggerContracts & typeof anthropicTriggerContracts & typeof apifyTriggerContracts & typeof axiomTriggerContracts & typeof automateTriggerContracts & typeof asanaTriggerContracts & typeof brevoTriggerContracts & typeof convexTriggerContracts & typeof discordTriggerContracts & typeof closeTriggerContracts & typeof clickUpTriggerContracts & typeof cloudflareTriggerContracts & typeof githubTriggerContracts & typeof gmailTriggerContracts & typeof googleCalendarTriggerContracts & typeof googleDriveTriggerContracts & typeof googleFormsTriggerContracts & typeof googleMeetTriggerContracts & typeof googleAdsTriggerContracts & typeof googleSheetsTriggerContracts & typeof hubspotTriggerContracts & typeof linearTriggerContracts & typeof millionVerifierTriggerContracts & typeof metaAdsTriggerContracts & typeof notionTriggerContracts & typeof outlookTriggerContracts & typeof redditTriggerContracts & typeof resendTriggerContracts & typeof slackTriggerContracts & typeof stripeTriggerContracts & typeof teamsTriggerContracts & typeof trelloTriggerContracts & typeof vercelTriggerContracts & typeof webflowTriggerContracts & typeof whatsappTriggerContracts;
|
|
38
|
+
export type TriggerContractMap = typeof airtableTriggerContracts & typeof anthropicTriggerContracts & typeof apifyTriggerContracts & typeof axiomTriggerContracts & typeof automateTriggerContracts & typeof asanaTriggerContracts & typeof brevoTriggerContracts & typeof convexTriggerContracts & typeof discordTriggerContracts & typeof closeTriggerContracts & typeof clickUpTriggerContracts & typeof calendlyTriggerContracts & typeof cloudflareTriggerContracts & typeof githubTriggerContracts & typeof gmailTriggerContracts & typeof googleCalendarTriggerContracts & typeof googleDriveTriggerContracts & typeof googleFormsTriggerContracts & typeof googleMeetTriggerContracts & typeof googleAdsTriggerContracts & typeof googleSheetsTriggerContracts & typeof hubspotTriggerContracts & typeof linearTriggerContracts & typeof millionVerifierTriggerContracts & typeof metaAdsTriggerContracts & typeof notionTriggerContracts & typeof outlookTriggerContracts & typeof redditTriggerContracts & typeof resendTriggerContracts & typeof slackTriggerContracts & typeof stripeTriggerContracts & typeof teamsTriggerContracts & typeof trelloTriggerContracts & typeof vercelTriggerContracts & typeof webflowTriggerContracts & typeof whatsappTriggerContracts;
|
|
38
39
|
export type IntegrationTriggerType = keyof TriggerContractMap;
|
|
39
40
|
/** Canonical authoring configuration for one integration trigger type. */
|
|
40
41
|
export type TriggerConfig<TType extends IntegrationTriggerType> = z.input<TriggerContractMap[TType]["configSchema"]> extends Record<string, never> ? object : z.input<TriggerContractMap[TType]["configSchema"]>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automate.ax/integration-contracts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.144.0",
|
|
4
4
|
"description": "Shared integration payload contracts and provider primitives for Automate.ax.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"./axiom": "./src/axiom/index.ts",
|
|
26
26
|
"./asana": "./src/asana/index.ts",
|
|
27
27
|
"./clickup": "./src/clickup/index.ts",
|
|
28
|
+
"./calendly": "./src/calendly/index.ts",
|
|
28
29
|
"./brevo": "./src/brevo/index.ts",
|
|
29
30
|
"./cloudflare": "./src/cloudflare/index.ts",
|
|
30
31
|
"./meta-ads": "./src/meta-ads/index.ts",
|
|
@@ -65,7 +66,7 @@
|
|
|
65
66
|
},
|
|
66
67
|
"dependencies": {
|
|
67
68
|
"@anthropic-ai/sdk": "0.123.0",
|
|
68
|
-
"@automate.ax/codec": "0.
|
|
69
|
+
"@automate.ax/codec": "0.144.0",
|
|
69
70
|
"@cfworker/json-schema": "^4.1.1",
|
|
70
71
|
"@googleapis/calendar": "^16.0.0",
|
|
71
72
|
"@googleapis/forms": "^6.0.1",
|
|
@@ -153,6 +154,11 @@
|
|
|
153
154
|
"types": "./dist/clickup/index.d.ts",
|
|
154
155
|
"default": "./dist/clickup/index.js"
|
|
155
156
|
},
|
|
157
|
+
"./calendly": {
|
|
158
|
+
"bun": "./src/calendly/index.ts",
|
|
159
|
+
"types": "./dist/calendly/index.d.ts",
|
|
160
|
+
"default": "./dist/calendly/index.js"
|
|
161
|
+
},
|
|
156
162
|
"./brevo": {
|
|
157
163
|
"bun": "./src/brevo/index.ts",
|
|
158
164
|
"types": "./dist/brevo/index.d.ts",
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import type { Encodable } from "@automate.ax/codec"
|
|
2
|
+
import { encodableSchema } from "@automate.ax/codec"
|
|
3
|
+
import * as z from "zod"
|
|
4
|
+
|
|
5
|
+
const CALENDLY_API_BASE_URL = "https://api.calendly.com/"
|
|
6
|
+
const CALENDLY_API_ORIGIN = new URL(CALENDLY_API_BASE_URL).origin
|
|
7
|
+
const CALENDLY_OAUTH_SECRET_SCHEMA = z.object({
|
|
8
|
+
accessToken: z.string().min(1),
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
/** Resolved Calendly OAuth account accepted by the shared API client. */
|
|
12
|
+
export interface CalendlyResolvedAccount {
|
|
13
|
+
connectionMethodId: string
|
|
14
|
+
secret: Record<string, unknown>
|
|
15
|
+
serviceId: "calendly"
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Options for one authenticated Calendly REST request. */
|
|
19
|
+
export interface CalendlyRequestOptions<TSchema extends z.ZodType> {
|
|
20
|
+
body?: Encodable
|
|
21
|
+
method?: "DELETE" | "GET" | "PATCH" | "POST"
|
|
22
|
+
query?: Record<string, boolean | number | string | undefined>
|
|
23
|
+
responseSchema: TSchema
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Structured Calendly REST error. */
|
|
27
|
+
export class CalendlyApiError extends Error {
|
|
28
|
+
readonly body?: Encodable
|
|
29
|
+
readonly rateLimitReset?: number
|
|
30
|
+
readonly status: number
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Creates a structured Calendly API error.
|
|
34
|
+
*
|
|
35
|
+
* @param options - Provider response details.
|
|
36
|
+
* @param options.body - Parsed provider error body.
|
|
37
|
+
* @param options.rateLimitReset - Provider retry delay, in seconds.
|
|
38
|
+
* @param options.status - HTTP response status.
|
|
39
|
+
*/
|
|
40
|
+
constructor(options: {
|
|
41
|
+
body?: Encodable
|
|
42
|
+
rateLimitReset?: number
|
|
43
|
+
status: number
|
|
44
|
+
}) {
|
|
45
|
+
super(
|
|
46
|
+
getErrorMessage(options.body) ??
|
|
47
|
+
`Calendly API request failed with status ${options.status}.`,
|
|
48
|
+
)
|
|
49
|
+
this.name = "CalendlyApiError"
|
|
50
|
+
this.body = options.body
|
|
51
|
+
this.rateLimitReset = options.rateLimitReset
|
|
52
|
+
this.status = options.status
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Creates an authenticated Calendly REST client.
|
|
58
|
+
*
|
|
59
|
+
* @param account - Resolved Calendly OAuth account.
|
|
60
|
+
* @throws When the account method or secret is invalid.
|
|
61
|
+
*/
|
|
62
|
+
export function getCalendlyApi(account: CalendlyResolvedAccount) {
|
|
63
|
+
if (account.connectionMethodId !== "oauth") {
|
|
64
|
+
throw new Error(
|
|
65
|
+
`Unsupported Calendly connection method: ${account.connectionMethodId}`,
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
const { accessToken } = CALENDLY_OAUTH_SECRET_SCHEMA.parse(account.secret)
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Calls one Calendly endpoint and validates the response.
|
|
72
|
+
*
|
|
73
|
+
* @param path - Calendly API path.
|
|
74
|
+
* @param options - Request options and response schema.
|
|
75
|
+
*/
|
|
76
|
+
async function request<TSchema extends z.ZodType>(
|
|
77
|
+
path: string,
|
|
78
|
+
options: CalendlyRequestOptions<TSchema>,
|
|
79
|
+
): Promise<z.output<TSchema>> {
|
|
80
|
+
const url = new URL(path.replace(/^\//, ""), CALENDLY_API_BASE_URL)
|
|
81
|
+
if (url.origin !== CALENDLY_API_ORIGIN) {
|
|
82
|
+
throw new Error("Calendly API paths must use the Calendly API origin.")
|
|
83
|
+
}
|
|
84
|
+
for (const [name, value] of Object.entries(options.query ?? {})) {
|
|
85
|
+
if (value !== undefined)
|
|
86
|
+
url.searchParams.set(toSnakeCase(name), String(value))
|
|
87
|
+
}
|
|
88
|
+
const response = await fetch(url, {
|
|
89
|
+
body:
|
|
90
|
+
options.body === undefined
|
|
91
|
+
? undefined
|
|
92
|
+
: JSON.stringify(toCalendly(options.body)),
|
|
93
|
+
headers: {
|
|
94
|
+
Accept: "application/json",
|
|
95
|
+
Authorization: `Bearer ${accessToken}`,
|
|
96
|
+
...(options.body === undefined
|
|
97
|
+
? {}
|
|
98
|
+
: { "Content-Type": "application/json" }),
|
|
99
|
+
},
|
|
100
|
+
method: options.method ?? "GET",
|
|
101
|
+
})
|
|
102
|
+
const text = await response.text()
|
|
103
|
+
const normalized = text ? fromCalendly(parseJson(text)) : undefined
|
|
104
|
+
if (!response.ok) {
|
|
105
|
+
const body = encodableSchema.safeParse(normalized)
|
|
106
|
+
throw new CalendlyApiError({
|
|
107
|
+
...(body.success && { body: body.data }),
|
|
108
|
+
rateLimitReset: parseFiniteNumber(
|
|
109
|
+
response.headers.get("X-RateLimit-Reset"),
|
|
110
|
+
),
|
|
111
|
+
status: response.status,
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
return options.responseSchema.parse(normalized)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return { request }
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Converts public camelCase JSON to Calendly wire keys.
|
|
122
|
+
*
|
|
123
|
+
* @param value - Public action input.
|
|
124
|
+
*/
|
|
125
|
+
export function toCalendly(value: Encodable): Encodable {
|
|
126
|
+
if (value instanceof Date) return value.toISOString()
|
|
127
|
+
if (Array.isArray(value)) return value.map(toCalendly)
|
|
128
|
+
if (!isPlainObject(value)) return value
|
|
129
|
+
return Object.fromEntries(
|
|
130
|
+
Object.entries(value).map(([key, item]) => [
|
|
131
|
+
toSnakeCase(key),
|
|
132
|
+
toCalendly(item),
|
|
133
|
+
]),
|
|
134
|
+
)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Converts Calendly wire JSON to public camelCase keys.
|
|
139
|
+
*
|
|
140
|
+
* @param value - Parsed Calendly response value.
|
|
141
|
+
*/
|
|
142
|
+
export function fromCalendly(value: unknown): unknown {
|
|
143
|
+
if (Array.isArray(value)) return value.map(fromCalendly)
|
|
144
|
+
if (!isPlainObject(value)) return value
|
|
145
|
+
return Object.fromEntries(
|
|
146
|
+
Object.entries(value).map(([key, item]) => [
|
|
147
|
+
toCamelCase(key),
|
|
148
|
+
fromCalendly(item),
|
|
149
|
+
]),
|
|
150
|
+
)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Whether a value can be traversed as a plain JSON object.
|
|
155
|
+
*
|
|
156
|
+
* @param value - Candidate JSON value.
|
|
157
|
+
*/
|
|
158
|
+
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
159
|
+
return typeof value === "object" && value !== null && !Array.isArray(value)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Parses a provider body without masking its HTTP failure.
|
|
164
|
+
*
|
|
165
|
+
* @param value - Provider response body.
|
|
166
|
+
*/
|
|
167
|
+
function parseJson(value: string): unknown {
|
|
168
|
+
try {
|
|
169
|
+
return JSON.parse(value)
|
|
170
|
+
} catch {
|
|
171
|
+
return undefined
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Parses a finite numeric response header.
|
|
177
|
+
*
|
|
178
|
+
* @param value - Response header value.
|
|
179
|
+
*/
|
|
180
|
+
function parseFiniteNumber(value: string | null) {
|
|
181
|
+
if (value === null) return undefined
|
|
182
|
+
const number = Number(value)
|
|
183
|
+
return Number.isFinite(number) ? number : undefined
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Extracts Calendly's human-readable error message.
|
|
188
|
+
*
|
|
189
|
+
* @param body - Parsed provider error body.
|
|
190
|
+
*/
|
|
191
|
+
function getErrorMessage(body: Encodable | undefined) {
|
|
192
|
+
if (!isPlainObject(body)) return undefined
|
|
193
|
+
if (typeof body.message === "string") return body.message
|
|
194
|
+
if (typeof body.title === "string") return body.title
|
|
195
|
+
return undefined
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Converts one public field name to Calendly's wire convention.
|
|
200
|
+
*
|
|
201
|
+
* @param value - Public field name.
|
|
202
|
+
*/
|
|
203
|
+
function toSnakeCase(value: string) {
|
|
204
|
+
return value.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Converts one Calendly wire field name to the public convention.
|
|
209
|
+
*
|
|
210
|
+
* @param value - Calendly wire field name.
|
|
211
|
+
*/
|
|
212
|
+
function toCamelCase(value: string) {
|
|
213
|
+
return value.replace(/_([a-z0-9])/g, (_, letter: string) =>
|
|
214
|
+
letter.toUpperCase(),
|
|
215
|
+
)
|
|
216
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export * from "./api"
|
|
2
|
+
export * from "./schemas"
|
|
3
|
+
|
|
4
|
+
import * as z from "zod"
|
|
5
|
+
import {
|
|
6
|
+
CALENDLY_ORGANIZATION_TRIGGER_CONFIG_SCHEMA,
|
|
7
|
+
CALENDLY_PROVIDER_EVENT_NAMES,
|
|
8
|
+
CALENDLY_TRIGGER_CONFIG_SCHEMA,
|
|
9
|
+
CALENDLY_WEBHOOK_EVENT_SCHEMA,
|
|
10
|
+
} from "./schemas"
|
|
11
|
+
|
|
12
|
+
export const CALENDLY_EVENT_TYPE_BY_PROVIDER_EVENT = {
|
|
13
|
+
"event_type.created": "calendly.event-type.created",
|
|
14
|
+
"event_type.deleted": "calendly.event-type.deleted",
|
|
15
|
+
"event_type.updated": "calendly.event-type.updated",
|
|
16
|
+
"invitee.canceled": "calendly.invitee.canceled",
|
|
17
|
+
"invitee.created": "calendly.invitee.created",
|
|
18
|
+
"invitee_no_show.created": "calendly.invitee-no-show.created",
|
|
19
|
+
"invitee_no_show.deleted": "calendly.invitee-no-show.deleted",
|
|
20
|
+
"routing_form_submission.created": "calendly.routing-form-submission.created",
|
|
21
|
+
} as const satisfies Record<
|
|
22
|
+
(typeof CALENDLY_PROVIDER_EVENT_NAMES)[number],
|
|
23
|
+
string
|
|
24
|
+
>
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Builds a semantic contract for one Calendly provider event.
|
|
28
|
+
*
|
|
29
|
+
* @param event - Calendly provider event name.
|
|
30
|
+
*/
|
|
31
|
+
function semanticContract<
|
|
32
|
+
const TEvent extends keyof typeof CALENDLY_EVENT_TYPE_BY_PROVIDER_EVENT,
|
|
33
|
+
>(event: TEvent) {
|
|
34
|
+
return {
|
|
35
|
+
configSchema: CALENDLY_TRIGGER_CONFIG_SCHEMA,
|
|
36
|
+
eventSchema: CALENDLY_WEBHOOK_EVENT_SCHEMA.and(
|
|
37
|
+
z.object({ event: z.literal(event) }),
|
|
38
|
+
),
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const calendlyTriggerContracts = {
|
|
43
|
+
"calendly.scheduling.event": {
|
|
44
|
+
configSchema: CALENDLY_ORGANIZATION_TRIGGER_CONFIG_SCHEMA,
|
|
45
|
+
eventSchema: CALENDLY_WEBHOOK_EVENT_SCHEMA,
|
|
46
|
+
},
|
|
47
|
+
"calendly.event-type.created": semanticContract("event_type.created"),
|
|
48
|
+
"calendly.event-type.deleted": semanticContract("event_type.deleted"),
|
|
49
|
+
"calendly.event-type.updated": semanticContract("event_type.updated"),
|
|
50
|
+
"calendly.invitee.canceled": semanticContract("invitee.canceled"),
|
|
51
|
+
"calendly.invitee.created": semanticContract("invitee.created"),
|
|
52
|
+
"calendly.invitee-no-show.created": semanticContract(
|
|
53
|
+
"invitee_no_show.created",
|
|
54
|
+
),
|
|
55
|
+
"calendly.invitee-no-show.deleted": semanticContract(
|
|
56
|
+
"invitee_no_show.deleted",
|
|
57
|
+
),
|
|
58
|
+
"calendly.routing-form-submission.created": {
|
|
59
|
+
configSchema: CALENDLY_ORGANIZATION_TRIGGER_CONFIG_SCHEMA,
|
|
60
|
+
eventSchema: CALENDLY_WEBHOOK_EVENT_SCHEMA.and(
|
|
61
|
+
z.object({ event: z.literal("routing_form_submission.created") }),
|
|
62
|
+
),
|
|
63
|
+
},
|
|
64
|
+
} as const
|
|
65
|
+
|
|
66
|
+
export const CALENDLY_EVENT_TYPES = [
|
|
67
|
+
"calendly.scheduling.event",
|
|
68
|
+
...Object.values(CALENDLY_EVENT_TYPE_BY_PROVIDER_EVENT),
|
|
69
|
+
] as const
|