@automate.ax/integration-contracts 0.107.0 → 0.109.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/airtable/api.js +6 -4
- package/dist/airtable/index.d.ts +997 -19
- package/dist/airtable/index.js +30 -2
- package/dist/airtable/schemas.d.ts +2034 -44
- package/dist/airtable/schemas.js +231 -47
- package/dist/brevo/api.d.ts +41 -0
- package/dist/brevo/api.js +74 -4
- package/dist/linear/schemas.d.ts +3 -3
- package/dist/notion/schemas.d.ts +4 -4
- package/package.json +2 -2
- package/src/airtable/api.ts +7 -4
- package/src/airtable/index.ts +36 -1
- package/src/airtable/schemas.ts +294 -63
- package/src/brevo/api.ts +103 -8
package/dist/airtable/schemas.js
CHANGED
|
@@ -32,7 +32,28 @@ const AIRTABLE_VIEW_CHANGE_SCHEMA = z.looseObject({
|
|
|
32
32
|
.optional(),
|
|
33
33
|
destroyedRecordIds: z.string().array().optional(),
|
|
34
34
|
});
|
|
35
|
+
const AIRTABLE_FIELD_DEFINITION_SCHEMA = z.object({
|
|
36
|
+
name: z.string(),
|
|
37
|
+
type: z.string(),
|
|
38
|
+
});
|
|
39
|
+
const AIRTABLE_FIELD_CHANGE_SCHEMA = z.looseObject({
|
|
40
|
+
current: AIRTABLE_FIELD_DEFINITION_SCHEMA.partial(),
|
|
41
|
+
previous: AIRTABLE_FIELD_DEFINITION_SCHEMA.partial().optional(),
|
|
42
|
+
});
|
|
43
|
+
const AIRTABLE_TABLE_METADATA_SCHEMA = z.object({
|
|
44
|
+
description: z.string().nullable(),
|
|
45
|
+
name: z.string(),
|
|
46
|
+
});
|
|
35
47
|
const AIRTABLE_TABLE_CHANGE_SCHEMA = z.looseObject({
|
|
48
|
+
changedFieldsById: z
|
|
49
|
+
.record(z.string(), AIRTABLE_FIELD_CHANGE_SCHEMA)
|
|
50
|
+
.optional(),
|
|
51
|
+
changedMetadata: z
|
|
52
|
+
.looseObject({
|
|
53
|
+
current: AIRTABLE_TABLE_METADATA_SCHEMA.partial(),
|
|
54
|
+
previous: AIRTABLE_TABLE_METADATA_SCHEMA.partial(),
|
|
55
|
+
})
|
|
56
|
+
.optional(),
|
|
36
57
|
changedRecordsById: z
|
|
37
58
|
.record(z.string(), AIRTABLE_CHANGED_RECORD_SCHEMA)
|
|
38
59
|
.optional(),
|
|
@@ -42,8 +63,17 @@ const AIRTABLE_TABLE_CHANGE_SCHEMA = z.looseObject({
|
|
|
42
63
|
createdRecordsById: z
|
|
43
64
|
.record(z.string(), AIRTABLE_CREATED_RECORD_SCHEMA)
|
|
44
65
|
.optional(),
|
|
66
|
+
createdFieldsById: z
|
|
67
|
+
.record(z.string(), AIRTABLE_FIELD_DEFINITION_SCHEMA)
|
|
68
|
+
.optional(),
|
|
69
|
+
destroyedFieldIds: z.string().array().optional(),
|
|
45
70
|
destroyedRecordIds: z.string().array().optional(),
|
|
46
71
|
});
|
|
72
|
+
const AIRTABLE_CREATED_TABLE_SCHEMA = z.looseObject({
|
|
73
|
+
fieldsById: z.record(z.string(), AIRTABLE_FIELD_DEFINITION_SCHEMA).optional(),
|
|
74
|
+
metadata: AIRTABLE_TABLE_METADATA_SCHEMA.optional(),
|
|
75
|
+
recordsById: z.record(z.string(), AIRTABLE_CREATED_RECORD_SCHEMA).optional(),
|
|
76
|
+
});
|
|
47
77
|
/** One provider-native Airtable webhook transaction payload. */
|
|
48
78
|
export const AIRTABLE_WEBHOOK_PAYLOAD_SCHEMA = z
|
|
49
79
|
.looseObject({
|
|
@@ -52,12 +82,62 @@ export const AIRTABLE_WEBHOOK_PAYLOAD_SCHEMA = z
|
|
|
52
82
|
changedTablesById: z
|
|
53
83
|
.record(z.string(), AIRTABLE_TABLE_CHANGE_SCHEMA)
|
|
54
84
|
.optional(),
|
|
85
|
+
createdTablesById: z
|
|
86
|
+
.record(z.string(), AIRTABLE_CREATED_TABLE_SCHEMA)
|
|
87
|
+
.optional(),
|
|
55
88
|
code: z.string().optional(),
|
|
56
89
|
error: z.literal(true).optional(),
|
|
90
|
+
destroyedTableIds: z.string().array().optional(),
|
|
57
91
|
payloadFormat: z.string(),
|
|
58
92
|
timestamp: z.iso.datetime({ offset: true }),
|
|
59
93
|
})
|
|
60
94
|
.catchall(z.json());
|
|
95
|
+
export const AIRTABLE_BASE_EVENT_SCHEMA = z.object({
|
|
96
|
+
/** Airtable base that emitted the transaction. */
|
|
97
|
+
baseId: z.string(),
|
|
98
|
+
/** Complete provider webhook transaction. */
|
|
99
|
+
event: AIRTABLE_WEBHOOK_PAYLOAD_SCHEMA,
|
|
100
|
+
/** Time at which Airtable committed the transaction. */
|
|
101
|
+
occurredAt: z.iso.datetime({ offset: true }),
|
|
102
|
+
/** Airtable system that caused the transaction. */
|
|
103
|
+
source: z.string(),
|
|
104
|
+
/** Provider-specific actor or source details. */
|
|
105
|
+
sourceMetadata: z.record(z.string(), z.json()).optional(),
|
|
106
|
+
/** Base-scoped transaction number assigned by Airtable. */
|
|
107
|
+
transactionNumber: z.number().int().nonnegative(),
|
|
108
|
+
});
|
|
109
|
+
const AIRTABLE_TABLE_EVENT_SCHEMA = AIRTABLE_BASE_EVENT_SCHEMA.extend({
|
|
110
|
+
/** Stable Airtable table ID. */
|
|
111
|
+
tableId: z.string(),
|
|
112
|
+
});
|
|
113
|
+
export const AIRTABLE_TABLE_CREATED_EVENT_SCHEMA = AIRTABLE_TABLE_EVENT_SCHEMA.extend({
|
|
114
|
+
/** Field definitions keyed by stable field ID. */
|
|
115
|
+
fields: z.record(z.string(), AIRTABLE_FIELD_DEFINITION_SCHEMA),
|
|
116
|
+
/** Created table metadata when included by Airtable. */
|
|
117
|
+
metadata: AIRTABLE_TABLE_METADATA_SCHEMA.optional(),
|
|
118
|
+
});
|
|
119
|
+
export const AIRTABLE_TABLE_UPDATED_EVENT_SCHEMA = AIRTABLE_TABLE_EVENT_SCHEMA.extend({
|
|
120
|
+
/** Current table metadata fields changed by the transaction. */
|
|
121
|
+
current: AIRTABLE_TABLE_METADATA_SCHEMA.partial(),
|
|
122
|
+
/** Previous table metadata fields changed by the transaction. */
|
|
123
|
+
previous: AIRTABLE_TABLE_METADATA_SCHEMA.partial(),
|
|
124
|
+
});
|
|
125
|
+
export const AIRTABLE_TABLE_DELETED_EVENT_SCHEMA = AIRTABLE_TABLE_EVENT_SCHEMA;
|
|
126
|
+
const AIRTABLE_FIELD_EVENT_SCHEMA = AIRTABLE_TABLE_EVENT_SCHEMA.extend({
|
|
127
|
+
/** Stable Airtable field ID. */
|
|
128
|
+
fieldId: z.string(),
|
|
129
|
+
});
|
|
130
|
+
export const AIRTABLE_FIELD_CREATED_EVENT_SCHEMA = AIRTABLE_FIELD_EVENT_SCHEMA.extend({
|
|
131
|
+
/** Created field definition. */
|
|
132
|
+
field: AIRTABLE_FIELD_DEFINITION_SCHEMA,
|
|
133
|
+
});
|
|
134
|
+
export const AIRTABLE_FIELD_UPDATED_EVENT_SCHEMA = AIRTABLE_FIELD_EVENT_SCHEMA.extend({
|
|
135
|
+
/** Current field definition values changed by the transaction. */
|
|
136
|
+
current: AIRTABLE_FIELD_DEFINITION_SCHEMA.partial(),
|
|
137
|
+
/** Previous field definition values changed by the transaction. */
|
|
138
|
+
previous: AIRTABLE_FIELD_DEFINITION_SCHEMA.partial().optional(),
|
|
139
|
+
});
|
|
140
|
+
export const AIRTABLE_FIELD_DELETED_EVENT_SCHEMA = AIRTABLE_FIELD_EVENT_SCHEMA;
|
|
61
141
|
const AIRTABLE_RECORD_EVENT_SCHEMA = z.object({
|
|
62
142
|
/** Airtable base containing the affected record. */
|
|
63
143
|
baseId: z.string(),
|
|
@@ -99,7 +179,14 @@ export const AIRTABLE_RECORD_MOVED_OUT_OF_VIEW_EVENT_SCHEMA = AIRTABLE_RECORD_EV
|
|
|
99
179
|
/** Stable ID of the view the record exited. */
|
|
100
180
|
viewId: z.string(),
|
|
101
181
|
});
|
|
102
|
-
export const
|
|
182
|
+
export const AIRTABLE_EVENT_TYPES = [
|
|
183
|
+
"airtable.base.event",
|
|
184
|
+
"airtable.table.created",
|
|
185
|
+
"airtable.table.updated",
|
|
186
|
+
"airtable.table.deleted",
|
|
187
|
+
"airtable.field.created",
|
|
188
|
+
"airtable.field.updated",
|
|
189
|
+
"airtable.field.deleted",
|
|
103
190
|
"airtable.record.created",
|
|
104
191
|
"airtable.record.updated",
|
|
105
192
|
"airtable.record.deleted",
|
|
@@ -107,78 +194,175 @@ export const AIRTABLE_RECORD_EVENT_TYPES = [
|
|
|
107
194
|
"airtable.record.movedOutOfView",
|
|
108
195
|
];
|
|
109
196
|
/**
|
|
110
|
-
* Expands one Airtable webhook transaction into semantic
|
|
197
|
+
* Expands one Airtable webhook transaction into broad and semantic events.
|
|
111
198
|
*
|
|
112
199
|
* @param value - Untrusted provider payload returned by Airtable.
|
|
113
200
|
* @param baseId - Stable ID of the base that owns the webhook.
|
|
114
201
|
*/
|
|
115
|
-
export function
|
|
202
|
+
export function normalizeAirtableEvents(value, baseId) {
|
|
116
203
|
const event = AIRTABLE_WEBHOOK_PAYLOAD_SCHEMA.parse(value);
|
|
117
|
-
return
|
|
118
|
-
|
|
119
|
-
eventType: "airtable.
|
|
120
|
-
payload:
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
204
|
+
return [
|
|
205
|
+
{
|
|
206
|
+
eventType: "airtable.base.event",
|
|
207
|
+
payload: AIRTABLE_BASE_EVENT_SCHEMA.parse(baseEventBase(event, baseId)),
|
|
208
|
+
},
|
|
209
|
+
...Object.entries(event.createdTablesById ?? {}).flatMap(([tableId, table]) => [
|
|
210
|
+
{
|
|
211
|
+
eventType: "airtable.table.created",
|
|
212
|
+
payload: AIRTABLE_TABLE_CREATED_EVENT_SCHEMA.parse({
|
|
213
|
+
...tableEventBase(event, baseId, tableId),
|
|
214
|
+
fields: table.fieldsById ?? {},
|
|
215
|
+
metadata: table.metadata,
|
|
216
|
+
}),
|
|
217
|
+
},
|
|
218
|
+
...Object.entries(table.fieldsById ?? {}).map(([fieldId, field]) => ({
|
|
219
|
+
eventType: "airtable.field.created",
|
|
220
|
+
payload: AIRTABLE_FIELD_CREATED_EVENT_SCHEMA.parse({
|
|
221
|
+
...fieldEventBase(event, baseId, tableId, fieldId),
|
|
222
|
+
field,
|
|
223
|
+
}),
|
|
224
|
+
})),
|
|
225
|
+
...Object.entries(table.recordsById ?? {}).map(([recordId, record]) => ({
|
|
226
|
+
eventType: "airtable.record.created",
|
|
227
|
+
payload: AIRTABLE_RECORD_CREATED_EVENT_SCHEMA.parse({
|
|
228
|
+
...recordEventBase(event, baseId, tableId, recordId),
|
|
229
|
+
createdAt: record.createdTime,
|
|
230
|
+
fields: record.cellValuesByFieldId,
|
|
231
|
+
}),
|
|
232
|
+
})),
|
|
233
|
+
]),
|
|
234
|
+
...(event.destroyedTableIds ?? []).map((tableId) => ({
|
|
235
|
+
eventType: "airtable.table.deleted",
|
|
236
|
+
payload: AIRTABLE_TABLE_DELETED_EVENT_SCHEMA.parse(tableEventBase(event, baseId, tableId)),
|
|
144
237
|
})),
|
|
145
|
-
...Object.entries(
|
|
146
|
-
...
|
|
147
|
-
|
|
148
|
-
|
|
238
|
+
...Object.entries(event.changedTablesById ?? {}).flatMap(([tableId, table]) => [
|
|
239
|
+
...(table.changedMetadata
|
|
240
|
+
? [
|
|
241
|
+
{
|
|
242
|
+
eventType: "airtable.table.updated",
|
|
243
|
+
payload: AIRTABLE_TABLE_UPDATED_EVENT_SCHEMA.parse({
|
|
244
|
+
...tableEventBase(event, baseId, tableId),
|
|
245
|
+
current: table.changedMetadata.current,
|
|
246
|
+
previous: table.changedMetadata.previous,
|
|
247
|
+
}),
|
|
248
|
+
},
|
|
249
|
+
]
|
|
250
|
+
: []),
|
|
251
|
+
...Object.entries(table.createdFieldsById ?? {}).map(([fieldId, field]) => ({
|
|
252
|
+
eventType: "airtable.field.created",
|
|
253
|
+
payload: AIRTABLE_FIELD_CREATED_EVENT_SCHEMA.parse({
|
|
254
|
+
...fieldEventBase(event, baseId, tableId, fieldId),
|
|
255
|
+
field,
|
|
256
|
+
}),
|
|
257
|
+
})),
|
|
258
|
+
...Object.entries(table.changedFieldsById ?? {}).map(([fieldId, field]) => ({
|
|
259
|
+
eventType: "airtable.field.updated",
|
|
260
|
+
payload: AIRTABLE_FIELD_UPDATED_EVENT_SCHEMA.parse({
|
|
261
|
+
...fieldEventBase(event, baseId, tableId, fieldId),
|
|
262
|
+
current: field.current,
|
|
263
|
+
previous: field.previous,
|
|
264
|
+
}),
|
|
265
|
+
})),
|
|
266
|
+
...(table.destroyedFieldIds ?? []).map((fieldId) => ({
|
|
267
|
+
eventType: "airtable.field.deleted",
|
|
268
|
+
payload: AIRTABLE_FIELD_DELETED_EVENT_SCHEMA.parse(fieldEventBase(event, baseId, tableId, fieldId)),
|
|
269
|
+
})),
|
|
270
|
+
...Object.entries(table.createdRecordsById ?? {}).map(([recordId, record]) => ({
|
|
271
|
+
eventType: "airtable.record.created",
|
|
272
|
+
payload: AIRTABLE_RECORD_CREATED_EVENT_SCHEMA.parse({
|
|
149
273
|
...recordEventBase(event, baseId, tableId, recordId),
|
|
150
274
|
createdAt: record.createdTime,
|
|
151
275
|
fields: record.cellValuesByFieldId,
|
|
152
|
-
viewId,
|
|
153
276
|
}),
|
|
154
277
|
})),
|
|
155
|
-
...(
|
|
156
|
-
eventType: "airtable.record.
|
|
157
|
-
payload:
|
|
278
|
+
...Object.entries(table.changedRecordsById ?? {}).map(([recordId, record]) => ({
|
|
279
|
+
eventType: "airtable.record.updated",
|
|
280
|
+
payload: AIRTABLE_RECORD_UPDATED_EVENT_SCHEMA.parse({
|
|
158
281
|
...recordEventBase(event, baseId, tableId, recordId),
|
|
159
|
-
|
|
282
|
+
changedFieldIds: Object.keys(record.current.cellValuesByFieldId),
|
|
283
|
+
fields: {
|
|
284
|
+
...record.unchanged?.cellValuesByFieldId,
|
|
285
|
+
...record.current.cellValuesByFieldId,
|
|
286
|
+
},
|
|
287
|
+
previousFields: {
|
|
288
|
+
...record.unchanged?.cellValuesByFieldId,
|
|
289
|
+
...record.previous?.cellValuesByFieldId,
|
|
290
|
+
},
|
|
160
291
|
}),
|
|
161
292
|
})),
|
|
293
|
+
...(table.destroyedRecordIds ?? []).map((recordId) => ({
|
|
294
|
+
eventType: "airtable.record.deleted",
|
|
295
|
+
payload: AIRTABLE_RECORD_DELETED_EVENT_SCHEMA.parse(recordEventBase(event, baseId, tableId, recordId)),
|
|
296
|
+
})),
|
|
297
|
+
...Object.entries(table.changedViewsById ?? {}).flatMap(([viewId, view]) => [
|
|
298
|
+
...Object.entries(view.createdRecordsById ?? {}).map(([recordId, record]) => ({
|
|
299
|
+
eventType: "airtable.record.movedIntoView",
|
|
300
|
+
payload: AIRTABLE_RECORD_MOVED_INTO_VIEW_EVENT_SCHEMA.parse({
|
|
301
|
+
...recordEventBase(event, baseId, tableId, recordId),
|
|
302
|
+
createdAt: record.createdTime,
|
|
303
|
+
fields: record.cellValuesByFieldId,
|
|
304
|
+
viewId,
|
|
305
|
+
}),
|
|
306
|
+
})),
|
|
307
|
+
...(view.destroyedRecordIds ?? []).map((recordId) => ({
|
|
308
|
+
eventType: "airtable.record.movedOutOfView",
|
|
309
|
+
payload: AIRTABLE_RECORD_MOVED_OUT_OF_VIEW_EVENT_SCHEMA.parse({
|
|
310
|
+
...recordEventBase(event, baseId, tableId, recordId),
|
|
311
|
+
viewId,
|
|
312
|
+
}),
|
|
313
|
+
})),
|
|
314
|
+
]),
|
|
162
315
|
]),
|
|
163
|
-
]
|
|
316
|
+
];
|
|
164
317
|
}
|
|
165
318
|
/**
|
|
166
|
-
* Builds fields shared by every
|
|
319
|
+
* Builds fields shared by every event in one Airtable transaction.
|
|
167
320
|
*
|
|
168
321
|
* @param event - Parsed provider transaction.
|
|
169
|
-
* @param baseId -
|
|
170
|
-
* @param tableId - Table containing the changed record.
|
|
171
|
-
* @param recordId - Stable ID of the changed record.
|
|
322
|
+
* @param baseId - Stable Airtable base ID.
|
|
172
323
|
*/
|
|
173
|
-
function
|
|
324
|
+
function baseEventBase(event, baseId) {
|
|
174
325
|
return {
|
|
175
326
|
baseId,
|
|
176
327
|
event,
|
|
177
328
|
occurredAt: event.timestamp,
|
|
178
|
-
recordId,
|
|
179
329
|
source: event.actionMetadata.source,
|
|
180
330
|
sourceMetadata: event.actionMetadata.sourceMetadata,
|
|
181
|
-
tableId,
|
|
182
331
|
transactionNumber: event.baseTransactionNumber,
|
|
183
332
|
};
|
|
184
333
|
}
|
|
334
|
+
/**
|
|
335
|
+
* Adds a stable table ID to the shared Airtable event fields.
|
|
336
|
+
*
|
|
337
|
+
* @param event - Parsed provider transaction.
|
|
338
|
+
* @param baseId - Stable Airtable base ID.
|
|
339
|
+
* @param tableId - Stable Airtable table ID.
|
|
340
|
+
*/
|
|
341
|
+
function tableEventBase(event, baseId, tableId) {
|
|
342
|
+
return { ...baseEventBase(event, baseId), tableId };
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Adds stable table and field IDs to the shared Airtable event fields.
|
|
346
|
+
*
|
|
347
|
+
* @param event - Parsed provider transaction.
|
|
348
|
+
* @param baseId - Stable Airtable base ID.
|
|
349
|
+
* @param tableId - Stable Airtable table ID.
|
|
350
|
+
* @param fieldId - Stable Airtable field ID.
|
|
351
|
+
*/
|
|
352
|
+
function fieldEventBase(event, baseId, tableId, fieldId) {
|
|
353
|
+
return { ...tableEventBase(event, baseId, tableId), fieldId };
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Builds fields shared by every normalized Airtable record event.
|
|
357
|
+
*
|
|
358
|
+
* @param event - Parsed provider transaction.
|
|
359
|
+
* @param baseId - Base containing the changed record.
|
|
360
|
+
* @param tableId - Table containing the changed record.
|
|
361
|
+
* @param recordId - Stable ID of the changed record.
|
|
362
|
+
*/
|
|
363
|
+
function recordEventBase(event, baseId, tableId, recordId) {
|
|
364
|
+
return {
|
|
365
|
+
...tableEventBase(event, baseId, tableId),
|
|
366
|
+
recordId,
|
|
367
|
+
};
|
|
368
|
+
}
|
package/dist/brevo/api.d.ts
CHANGED
|
@@ -1,4 +1,45 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
|
+
/** Provider rate-limit values returned with a Brevo response. */
|
|
3
|
+
export interface BrevoRateLimitMetadata {
|
|
4
|
+
/** Maximum requests allowed in the current window. */
|
|
5
|
+
limit?: number;
|
|
6
|
+
/** Requests remaining in the current window. */
|
|
7
|
+
remaining?: number;
|
|
8
|
+
/** Seconds until the current window resets. */
|
|
9
|
+
reset?: number;
|
|
10
|
+
}
|
|
11
|
+
/** Structured failure returned by the Brevo API. */
|
|
12
|
+
export declare class BrevoApiError extends Error {
|
|
13
|
+
/** Provider error classification. */
|
|
14
|
+
readonly code?: string;
|
|
15
|
+
/** API path that failed. */
|
|
16
|
+
readonly path: string;
|
|
17
|
+
/** Provider rate-limit metadata. */
|
|
18
|
+
readonly rateLimit: BrevoRateLimitMetadata;
|
|
19
|
+
/** Delay in seconds before the request should be retried. */
|
|
20
|
+
readonly retryAfter?: number;
|
|
21
|
+
/** HTTP status returned by Brevo. */
|
|
22
|
+
readonly status: number;
|
|
23
|
+
/**
|
|
24
|
+
* Creates a structured Brevo provider error.
|
|
25
|
+
*
|
|
26
|
+
* @param options - Provider and transport failure details.
|
|
27
|
+
* @param options.code - Provider error classification.
|
|
28
|
+
* @param options.message - Human-readable provider failure.
|
|
29
|
+
* @param options.path - API path that failed.
|
|
30
|
+
* @param options.rateLimit - Provider rate-limit metadata.
|
|
31
|
+
* @param options.retryAfter - Provider retry delay in seconds.
|
|
32
|
+
* @param options.status - HTTP status.
|
|
33
|
+
*/
|
|
34
|
+
constructor(options: {
|
|
35
|
+
code?: string;
|
|
36
|
+
message: string;
|
|
37
|
+
path: string;
|
|
38
|
+
rateLimit: BrevoRateLimitMetadata;
|
|
39
|
+
retryAfter?: number;
|
|
40
|
+
status: number;
|
|
41
|
+
});
|
|
42
|
+
}
|
|
2
43
|
/** Options accepted by the authenticated Brevo request helper. */
|
|
3
44
|
export interface BrevoRequestOptions extends RequestInit {
|
|
4
45
|
/** Query parameters appended to the request URL. */
|
package/dist/brevo/api.js
CHANGED
|
@@ -8,6 +8,39 @@ const BREVO_ERROR_SCHEMA = z.looseObject({
|
|
|
8
8
|
code: z.string().optional(),
|
|
9
9
|
message: z.string().optional(),
|
|
10
10
|
});
|
|
11
|
+
/** Structured failure returned by the Brevo API. */
|
|
12
|
+
export class BrevoApiError extends Error {
|
|
13
|
+
/** Provider error classification. */
|
|
14
|
+
code;
|
|
15
|
+
/** API path that failed. */
|
|
16
|
+
path;
|
|
17
|
+
/** Provider rate-limit metadata. */
|
|
18
|
+
rateLimit;
|
|
19
|
+
/** Delay in seconds before the request should be retried. */
|
|
20
|
+
retryAfter;
|
|
21
|
+
/** HTTP status returned by Brevo. */
|
|
22
|
+
status;
|
|
23
|
+
/**
|
|
24
|
+
* Creates a structured Brevo provider error.
|
|
25
|
+
*
|
|
26
|
+
* @param options - Provider and transport failure details.
|
|
27
|
+
* @param options.code - Provider error classification.
|
|
28
|
+
* @param options.message - Human-readable provider failure.
|
|
29
|
+
* @param options.path - API path that failed.
|
|
30
|
+
* @param options.rateLimit - Provider rate-limit metadata.
|
|
31
|
+
* @param options.retryAfter - Provider retry delay in seconds.
|
|
32
|
+
* @param options.status - HTTP status.
|
|
33
|
+
*/
|
|
34
|
+
constructor(options) {
|
|
35
|
+
super(`Brevo ${options.path} failed: ${options.message}`);
|
|
36
|
+
this.name = "BrevoApiError";
|
|
37
|
+
this.code = options.code;
|
|
38
|
+
this.path = options.path;
|
|
39
|
+
this.rateLimit = options.rateLimit;
|
|
40
|
+
this.retryAfter = options.retryAfter;
|
|
41
|
+
this.status = options.status;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
11
44
|
/**
|
|
12
45
|
* Creates a small authenticated Brevo REST client.
|
|
13
46
|
*
|
|
@@ -46,10 +79,21 @@ export function getBrevoApi(secret) {
|
|
|
46
79
|
const response = await fetch(url, { ...requestInit, headers });
|
|
47
80
|
if (response.ok)
|
|
48
81
|
return response;
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
:
|
|
82
|
+
const responseText = await response.text();
|
|
83
|
+
const error = BREVO_ERROR_SCHEMA.safeParse(parseJson(responseText));
|
|
84
|
+
throw new BrevoApiError({
|
|
85
|
+
code: error.success ? error.data.code : undefined,
|
|
86
|
+
message: (error.success ? error.data.message : undefined) ??
|
|
87
|
+
(responseText.trim() || `HTTP ${response.status}`),
|
|
88
|
+
path: `${url.pathname}${url.search}`,
|
|
89
|
+
rateLimit: {
|
|
90
|
+
limit: parseNumberHeader(response.headers, "x-sib-ratelimit-limit"),
|
|
91
|
+
remaining: parseNumberHeader(response.headers, "x-sib-ratelimit-remaining"),
|
|
92
|
+
reset: parseNumberHeader(response.headers, "x-sib-ratelimit-reset"),
|
|
93
|
+
},
|
|
94
|
+
retryAfter: parseNumberHeader(response.headers, "retry-after"),
|
|
95
|
+
status: response.status,
|
|
96
|
+
});
|
|
53
97
|
},
|
|
54
98
|
};
|
|
55
99
|
}
|
|
@@ -62,3 +106,29 @@ export function getBrevoApi(secret) {
|
|
|
62
106
|
export async function parseBrevoResponse(response, schema) {
|
|
63
107
|
return schema.parse(await response.json());
|
|
64
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Parses provider JSON without hiding non-JSON error bodies.
|
|
111
|
+
*
|
|
112
|
+
* @param value - Provider response text.
|
|
113
|
+
*/
|
|
114
|
+
function parseJson(value) {
|
|
115
|
+
try {
|
|
116
|
+
return JSON.parse(value);
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Parses an optional numeric HTTP header.
|
|
124
|
+
*
|
|
125
|
+
* @param headers - Provider response headers.
|
|
126
|
+
* @param name - Case-insensitive header name.
|
|
127
|
+
*/
|
|
128
|
+
function parseNumberHeader(headers, name) {
|
|
129
|
+
const value = headers.get(name);
|
|
130
|
+
if (value === null)
|
|
131
|
+
return undefined;
|
|
132
|
+
const parsed = Number(value);
|
|
133
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
134
|
+
}
|
package/dist/linear/schemas.d.ts
CHANGED
|
@@ -4392,10 +4392,10 @@ export declare const LINEAR_ISSUE_RELATION_SCHEMA: z.ZodObject<{
|
|
|
4392
4392
|
updatedAt: z.ZodUnion<readonly [z.ZodDate, z.ZodPipe<z.ZodISODateTime, z.ZodTransform<Date, string>>]>;
|
|
4393
4393
|
}, z.core.$strip>;
|
|
4394
4394
|
export declare const LINEAR_PROVIDER_PROJECT_SCHEMA: z.ZodObject<{
|
|
4395
|
-
createdAt: z.ZodUnion<readonly [z.ZodDate, z.ZodPipe<z.ZodISODateTime, z.ZodTransform<Date, string>>]>;
|
|
4396
|
-
id: z.ZodString;
|
|
4397
4395
|
name: z.ZodString;
|
|
4398
4396
|
description: z.ZodString;
|
|
4397
|
+
createdAt: z.ZodUnion<readonly [z.ZodDate, z.ZodPipe<z.ZodISODateTime, z.ZodTransform<Date, string>>]>;
|
|
4398
|
+
id: z.ZodString;
|
|
4399
4399
|
status: z.ZodObject<{
|
|
4400
4400
|
color: z.ZodString;
|
|
4401
4401
|
description: z.ZodNullable<z.ZodString>;
|
|
@@ -4471,6 +4471,7 @@ export declare const LINEAR_PROVIDER_PROJECT_SCHEMA: z.ZodObject<{
|
|
|
4471
4471
|
}, z.core.$strip>;
|
|
4472
4472
|
export declare const LINEAR_PROVIDER_ISSUE_SCHEMA: z.ZodObject<{
|
|
4473
4473
|
number: z.ZodNumber;
|
|
4474
|
+
description: z.ZodNullable<z.ZodString>;
|
|
4474
4475
|
createdAt: z.ZodUnion<readonly [z.ZodDate, z.ZodPipe<z.ZodISODateTime, z.ZodTransform<Date, string>>]>;
|
|
4475
4476
|
id: z.ZodString;
|
|
4476
4477
|
project: z.ZodNullable<z.ZodObject<{
|
|
@@ -4479,7 +4480,6 @@ export declare const LINEAR_PROVIDER_ISSUE_SCHEMA: z.ZodObject<{
|
|
|
4479
4480
|
slugId: z.ZodString;
|
|
4480
4481
|
url: z.ZodString;
|
|
4481
4482
|
}, z.core.$strip>>;
|
|
4482
|
-
description: z.ZodNullable<z.ZodString>;
|
|
4483
4483
|
completedAt: z.ZodNullable<z.ZodUnion<readonly [z.ZodDate, z.ZodPipe<z.ZodISODateTime, z.ZodTransform<Date, string>>]>>;
|
|
4484
4484
|
startedAt: z.ZodNullable<z.ZodUnion<readonly [z.ZodDate, z.ZodPipe<z.ZodISODateTime, z.ZodTransform<Date, string>>]>>;
|
|
4485
4485
|
team: z.ZodObject<{
|
package/dist/notion/schemas.d.ts
CHANGED
|
@@ -1419,8 +1419,8 @@ declare const RAW_NOTION_EVENT_SCHEMA: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
1419
1419
|
}>;
|
|
1420
1420
|
}, z.core.$strip>;
|
|
1421
1421
|
updated_fields: z.ZodArray<z.ZodEnum<{
|
|
1422
|
-
filter: "filter";
|
|
1423
1422
|
name: "name";
|
|
1423
|
+
filter: "filter";
|
|
1424
1424
|
sorts: "sorts";
|
|
1425
1425
|
configuration: "configuration";
|
|
1426
1426
|
}>>;
|
|
@@ -2877,8 +2877,8 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
2877
2877
|
}>;
|
|
2878
2878
|
}, z.core.$strip>;
|
|
2879
2879
|
updated_fields: z.ZodArray<z.ZodEnum<{
|
|
2880
|
-
filter: "filter";
|
|
2881
2880
|
name: "name";
|
|
2881
|
+
filter: "filter";
|
|
2882
2882
|
sorts: "sorts";
|
|
2883
2883
|
configuration: "configuration";
|
|
2884
2884
|
}>>;
|
|
@@ -3829,7 +3829,7 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
3829
3829
|
type: "team" | "page" | "space" | "agent" | "block" | "database";
|
|
3830
3830
|
dataSourceId?: string | undefined;
|
|
3831
3831
|
};
|
|
3832
|
-
updatedFields: ("
|
|
3832
|
+
updatedFields: ("name" | "filter" | "sorts" | "configuration")[];
|
|
3833
3833
|
};
|
|
3834
3834
|
workspaceId: string;
|
|
3835
3835
|
workspaceName: string;
|
|
@@ -4956,7 +4956,7 @@ export declare const NOTION_EVENT_SCHEMA: z.ZodPipe<z.ZodDiscriminatedUnion<[z.Z
|
|
|
4956
4956
|
type: "team" | "page" | "space" | "agent" | "block" | "database";
|
|
4957
4957
|
data_source_id?: string | undefined;
|
|
4958
4958
|
};
|
|
4959
|
-
updated_fields: ("
|
|
4959
|
+
updated_fields: ("name" | "filter" | "sorts" | "configuration")[];
|
|
4960
4960
|
};
|
|
4961
4961
|
entity: {
|
|
4962
4962
|
id: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automate.ax/integration-contracts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.109.0",
|
|
4
4
|
"description": "Shared integration payload contracts and provider primitives for Automate.ax.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
}
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@automate.ax/codec": "0.
|
|
53
|
+
"@automate.ax/codec": "0.109.0",
|
|
54
54
|
"@cfworker/json-schema": "^4.1.1",
|
|
55
55
|
"@googleapis/calendar": "^15.0.0",
|
|
56
56
|
"@googleapis/forms": "^6.0.1",
|
package/src/airtable/api.ts
CHANGED
|
@@ -2,9 +2,10 @@ import * as z from "zod"
|
|
|
2
2
|
|
|
3
3
|
export const AIRTABLE_API_ORIGIN = "https://api.airtable.com/v0/"
|
|
4
4
|
|
|
5
|
-
const AIRTABLE_SECRET_SCHEMA = z.
|
|
6
|
-
accessToken: z.string().min(1),
|
|
7
|
-
})
|
|
5
|
+
const AIRTABLE_SECRET_SCHEMA = z.union([
|
|
6
|
+
z.object({ accessToken: z.string().min(1) }),
|
|
7
|
+
z.object({ apiKey: z.string().min(1) }),
|
|
8
|
+
])
|
|
8
9
|
const AIRTABLE_ERROR_SCHEMA = z.object({
|
|
9
10
|
error: z.union([
|
|
10
11
|
z.string(),
|
|
@@ -34,7 +35,9 @@ export interface AirtableApi {
|
|
|
34
35
|
* @param secret - Refreshed Airtable integration secret.
|
|
35
36
|
*/
|
|
36
37
|
export function getAirtableApi(secret: Record<string, unknown>): AirtableApi {
|
|
37
|
-
const
|
|
38
|
+
const credential = AIRTABLE_SECRET_SCHEMA.parse(secret)
|
|
39
|
+
const accessToken =
|
|
40
|
+
"accessToken" in credential ? credential.accessToken : credential.apiKey
|
|
38
41
|
|
|
39
42
|
return {
|
|
40
43
|
request: async (path, init) => {
|
package/src/airtable/index.ts
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import * as z from "zod"
|
|
2
2
|
import {
|
|
3
|
+
AIRTABLE_BASE_EVENT_SCHEMA,
|
|
4
|
+
AIRTABLE_FIELD_CREATED_EVENT_SCHEMA,
|
|
5
|
+
AIRTABLE_FIELD_DELETED_EVENT_SCHEMA,
|
|
6
|
+
AIRTABLE_FIELD_UPDATED_EVENT_SCHEMA,
|
|
3
7
|
AIRTABLE_RECORD_CREATED_EVENT_SCHEMA,
|
|
4
8
|
AIRTABLE_RECORD_DELETED_EVENT_SCHEMA,
|
|
5
9
|
AIRTABLE_RECORD_MOVED_INTO_VIEW_EVENT_SCHEMA,
|
|
6
10
|
AIRTABLE_RECORD_MOVED_OUT_OF_VIEW_EVENT_SCHEMA,
|
|
7
11
|
AIRTABLE_RECORD_UPDATED_EVENT_SCHEMA,
|
|
12
|
+
AIRTABLE_TABLE_CREATED_EVENT_SCHEMA,
|
|
13
|
+
AIRTABLE_TABLE_DELETED_EVENT_SCHEMA,
|
|
14
|
+
AIRTABLE_TABLE_UPDATED_EVENT_SCHEMA,
|
|
8
15
|
} from "./schemas"
|
|
9
16
|
|
|
10
17
|
export * from "./api"
|
|
@@ -14,10 +21,26 @@ export * from "./schemas"
|
|
|
14
21
|
export const AIRTABLE_TRIGGER_CONFIG_SCHEMA = z.object({
|
|
15
22
|
baseId: z.string(),
|
|
16
23
|
scopeId: z.string(),
|
|
17
|
-
scopeType: z.enum(["table", "view"]),
|
|
24
|
+
scopeType: z.enum(["base", "table", "view"]),
|
|
18
25
|
})
|
|
19
26
|
|
|
20
27
|
export const airtableTriggerContracts = {
|
|
28
|
+
"airtable.base.event": {
|
|
29
|
+
configSchema: AIRTABLE_TRIGGER_CONFIG_SCHEMA,
|
|
30
|
+
eventSchema: AIRTABLE_BASE_EVENT_SCHEMA,
|
|
31
|
+
},
|
|
32
|
+
"airtable.field.created": {
|
|
33
|
+
configSchema: AIRTABLE_TRIGGER_CONFIG_SCHEMA,
|
|
34
|
+
eventSchema: AIRTABLE_FIELD_CREATED_EVENT_SCHEMA,
|
|
35
|
+
},
|
|
36
|
+
"airtable.field.deleted": {
|
|
37
|
+
configSchema: AIRTABLE_TRIGGER_CONFIG_SCHEMA,
|
|
38
|
+
eventSchema: AIRTABLE_FIELD_DELETED_EVENT_SCHEMA,
|
|
39
|
+
},
|
|
40
|
+
"airtable.field.updated": {
|
|
41
|
+
configSchema: AIRTABLE_TRIGGER_CONFIG_SCHEMA,
|
|
42
|
+
eventSchema: AIRTABLE_FIELD_UPDATED_EVENT_SCHEMA,
|
|
43
|
+
},
|
|
21
44
|
"airtable.record.created": {
|
|
22
45
|
configSchema: AIRTABLE_TRIGGER_CONFIG_SCHEMA,
|
|
23
46
|
eventSchema: AIRTABLE_RECORD_CREATED_EVENT_SCHEMA,
|
|
@@ -38,4 +61,16 @@ export const airtableTriggerContracts = {
|
|
|
38
61
|
configSchema: AIRTABLE_TRIGGER_CONFIG_SCHEMA,
|
|
39
62
|
eventSchema: AIRTABLE_RECORD_UPDATED_EVENT_SCHEMA,
|
|
40
63
|
},
|
|
64
|
+
"airtable.table.created": {
|
|
65
|
+
configSchema: AIRTABLE_TRIGGER_CONFIG_SCHEMA,
|
|
66
|
+
eventSchema: AIRTABLE_TABLE_CREATED_EVENT_SCHEMA,
|
|
67
|
+
},
|
|
68
|
+
"airtable.table.deleted": {
|
|
69
|
+
configSchema: AIRTABLE_TRIGGER_CONFIG_SCHEMA,
|
|
70
|
+
eventSchema: AIRTABLE_TABLE_DELETED_EVENT_SCHEMA,
|
|
71
|
+
},
|
|
72
|
+
"airtable.table.updated": {
|
|
73
|
+
configSchema: AIRTABLE_TRIGGER_CONFIG_SCHEMA,
|
|
74
|
+
eventSchema: AIRTABLE_TABLE_UPDATED_EVENT_SCHEMA,
|
|
75
|
+
},
|
|
41
76
|
} as const
|