@automate.ax/integration-contracts 0.126.0 → 0.127.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.
@@ -53,8 +53,8 @@ export declare const OUTLOOK_MESSAGE_CREATED_EVENT_SCHEMA: z.ZodObject<{
53
53
  internetMessageId: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
54
54
  importance: z.ZodPrefault<z.ZodEnum<{
55
55
  high: "high";
56
- normal: "normal";
57
56
  low: "low";
57
+ normal: "normal";
58
58
  }>>;
59
59
  inferenceClassification: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodEnum<{
60
60
  focused: "focused";
@@ -164,8 +164,8 @@ export declare const OUTLOOK_MESSAGE_UPDATED_EVENT_SCHEMA: z.ZodObject<{
164
164
  internetMessageId: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
165
165
  importance: z.ZodPrefault<z.ZodEnum<{
166
166
  high: "high";
167
- normal: "normal";
168
167
  low: "low";
168
+ normal: "normal";
169
169
  }>>;
170
170
  inferenceClassification: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodEnum<{
171
171
  focused: "focused";
@@ -280,8 +280,8 @@ export declare const OUTLOOK_MESSAGE_CHANGE_EVENT_SCHEMA: z.ZodDiscriminatedUnio
280
280
  internetMessageId: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
281
281
  importance: z.ZodPrefault<z.ZodEnum<{
282
282
  high: "high";
283
- normal: "normal";
284
283
  low: "low";
284
+ normal: "normal";
285
285
  }>>;
286
286
  inferenceClassification: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodEnum<{
287
287
  focused: "focused";
@@ -390,8 +390,8 @@ export declare const OUTLOOK_MESSAGE_CHANGE_EVENT_SCHEMA: z.ZodDiscriminatedUnio
390
390
  internetMessageId: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
391
391
  importance: z.ZodPrefault<z.ZodEnum<{
392
392
  high: "high";
393
- normal: "normal";
394
393
  low: "low";
394
+ normal: "normal";
395
395
  }>>;
396
396
  inferenceClassification: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodEnum<{
397
397
  focused: "focused";
@@ -506,8 +506,8 @@ export declare const outlookTriggerContracts: {
506
506
  internetMessageId: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
507
507
  importance: z.ZodPrefault<z.ZodEnum<{
508
508
  high: "high";
509
- normal: "normal";
510
509
  low: "low";
510
+ normal: "normal";
511
511
  }>>;
512
512
  inferenceClassification: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodEnum<{
513
513
  focused: "focused";
@@ -619,8 +619,8 @@ export declare const outlookTriggerContracts: {
619
619
  internetMessageId: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
620
620
  importance: z.ZodPrefault<z.ZodEnum<{
621
621
  high: "high";
622
- normal: "normal";
623
622
  low: "low";
623
+ normal: "normal";
624
624
  }>>;
625
625
  inferenceClassification: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodEnum<{
626
626
  focused: "focused";
@@ -729,8 +729,8 @@ export declare const outlookTriggerContracts: {
729
729
  internetMessageId: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
730
730
  importance: z.ZodPrefault<z.ZodEnum<{
731
731
  high: "high";
732
- normal: "normal";
733
732
  low: "low";
733
+ normal: "normal";
734
734
  }>>;
735
735
  inferenceClassification: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodEnum<{
736
736
  focused: "focused";
@@ -849,8 +849,8 @@ export declare const outlookTriggerContracts: {
849
849
  internetMessageId: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
850
850
  importance: z.ZodPrefault<z.ZodEnum<{
851
851
  high: "high";
852
- normal: "normal";
853
852
  low: "low";
853
+ normal: "normal";
854
854
  }>>;
855
855
  inferenceClassification: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodEnum<{
856
856
  focused: "focused";
@@ -965,8 +965,8 @@ export declare const outlookTriggerContracts: {
965
965
  internetMessageId: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
966
966
  importance: z.ZodPrefault<z.ZodEnum<{
967
967
  high: "high";
968
- normal: "normal";
969
968
  low: "low";
969
+ normal: "normal";
970
970
  }>>;
971
971
  inferenceClassification: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodEnum<{
972
972
  focused: "focused";
@@ -5,8 +5,8 @@ export declare const OUTLOOK_BODY_TYPE_SCHEMA: z.ZodEnum<{
5
5
  }>;
6
6
  export declare const OUTLOOK_IMPORTANCE_SCHEMA: z.ZodEnum<{
7
7
  high: "high";
8
- normal: "normal";
9
8
  low: "low";
9
+ normal: "normal";
10
10
  }>;
11
11
  export declare const OUTLOOK_FLAG_STATUS_SCHEMA: z.ZodEnum<{
12
12
  complete: "complete";
@@ -84,8 +84,8 @@ export declare const OUTLOOK_MESSAGE_SCHEMA: z.ZodObject<{
84
84
  internetMessageId: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
85
85
  importance: z.ZodPrefault<z.ZodEnum<{
86
86
  high: "high";
87
- normal: "normal";
88
87
  low: "low";
88
+ normal: "normal";
89
89
  }>>;
90
90
  inferenceClassification: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodEnum<{
91
91
  focused: "focused";
@@ -197,8 +197,8 @@ export declare const GRAPH_MESSAGE_SCHEMA: z.ZodPipe<z.ZodObject<{
197
197
  id: z.ZodString;
198
198
  importance: z.ZodOptional<z.ZodEnum<{
199
199
  high: "high";
200
- normal: "normal";
201
200
  low: "low";
201
+ normal: "normal";
202
202
  }>>;
203
203
  inferenceClassification: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
204
204
  focused: "focused";
@@ -242,7 +242,7 @@ export declare const GRAPH_MESSAGE_SCHEMA: z.ZodPipe<z.ZodObject<{
242
242
  hasAttachments: boolean;
243
243
  messageId: string;
244
244
  internetMessageId: string | undefined;
245
- importance: "high" | "normal" | "low";
245
+ importance: "high" | "low" | "normal";
246
246
  inferenceClassification: "focused" | "other" | undefined;
247
247
  isDraft: boolean;
248
248
  isRead: boolean;
@@ -331,7 +331,7 @@ export declare const GRAPH_MESSAGE_SCHEMA: z.ZodPipe<z.ZodObject<{
331
331
  };
332
332
  } | null | undefined;
333
333
  hasAttachments?: boolean | undefined;
334
- importance?: "high" | "normal" | "low" | undefined;
334
+ importance?: "high" | "low" | "normal" | undefined;
335
335
  inferenceClassification?: "focused" | "other" | null | undefined;
336
336
  internetMessageId?: string | null | undefined;
337
337
  isDraft?: boolean | undefined;
@@ -377,7 +377,7 @@ export declare function normalizeOutlookMessage(payload: unknown): {
377
377
  hasAttachments: boolean;
378
378
  messageId: string;
379
379
  internetMessageId: string | undefined;
380
- importance: "high" | "normal" | "low";
380
+ importance: "high" | "low" | "normal";
381
381
  inferenceClassification: "focused" | "other" | undefined;
382
382
  isDraft: boolean;
383
383
  isRead: boolean;
@@ -155,9 +155,9 @@ export declare const TRELLO_CUSTOM_FIELD_SCHEMA: z.ZodObject<{
155
155
  type: z.ZodEnum<{
156
156
  number: "number";
157
157
  date: "date";
158
+ list: "list";
158
159
  text: "text";
159
160
  checkbox: "checkbox";
160
- list: "list";
161
161
  }>;
162
162
  }, z.core.$strip>;
163
163
  export declare const TRELLO_CUSTOM_FIELD_VALUE_SCHEMA: z.ZodDiscriminatedUnion<[z.ZodObject<{
@@ -362,9 +362,9 @@ export declare const TRELLO_PROVIDER_CUSTOM_FIELD_SCHEMA: z.ZodObject<{
362
362
  type: z.ZodEnum<{
363
363
  number: "number";
364
364
  date: "date";
365
+ list: "list";
365
366
  text: "text";
366
367
  checkbox: "checkbox";
367
- list: "list";
368
368
  }>;
369
369
  }, z.core.$loose>;
370
370
  export declare const TRELLO_PROVIDER_CUSTOM_FIELD_ITEM_SCHEMA: z.ZodObject<{
@@ -1,5 +1,6 @@
1
1
  import type { airtableTriggerContracts } from "./airtable/index.js";
2
2
  import type { apifyTriggerContracts } from "./apify/index.js";
3
+ import type { axiomTriggerContracts } from "./axiom/index.js";
3
4
  import type { automateTriggerContracts } from "./automate/index.js";
4
5
  import type { asanaTriggerContracts } from "./asana/index.js";
5
6
  import type { brevoTriggerContracts } from "./brevo/index.js";
@@ -28,7 +29,7 @@ import type { vercelTriggerContracts } from "./vercel/index.js";
28
29
  import type { webflowTriggerContracts } from "./webflow/index.js";
29
30
  import type { whatsappTriggerContracts } from "./whatsapp/index.js";
30
31
  import type { z } from "zod";
31
- export type TriggerContractMap = typeof airtableTriggerContracts & typeof apifyTriggerContracts & typeof automateTriggerContracts & typeof asanaTriggerContracts & typeof brevoTriggerContracts & typeof convexTriggerContracts & typeof closeTriggerContracts & typeof cloudflareTriggerContracts & typeof githubTriggerContracts & typeof gmailTriggerContracts & typeof googleCalendarTriggerContracts & typeof googleDriveTriggerContracts & typeof googleFormsTriggerContracts & typeof googleMeetTriggerContracts & typeof googleSheetsTriggerContracts & typeof hubspotTriggerContracts & typeof linearTriggerContracts & typeof millionVerifierTriggerContracts & typeof notionTriggerContracts & typeof outlookTriggerContracts & typeof redditTriggerContracts & typeof resendTriggerContracts & typeof slackTriggerContracts & typeof stripeTriggerContracts & typeof teamsTriggerContracts & typeof trelloTriggerContracts & typeof vercelTriggerContracts & typeof webflowTriggerContracts & typeof whatsappTriggerContracts;
32
+ export type TriggerContractMap = typeof airtableTriggerContracts & typeof apifyTriggerContracts & typeof axiomTriggerContracts & typeof automateTriggerContracts & typeof asanaTriggerContracts & typeof brevoTriggerContracts & typeof convexTriggerContracts & typeof closeTriggerContracts & typeof cloudflareTriggerContracts & typeof githubTriggerContracts & typeof gmailTriggerContracts & typeof googleCalendarTriggerContracts & typeof googleDriveTriggerContracts & typeof googleFormsTriggerContracts & typeof googleMeetTriggerContracts & typeof googleSheetsTriggerContracts & typeof hubspotTriggerContracts & typeof linearTriggerContracts & typeof millionVerifierTriggerContracts & typeof notionTriggerContracts & typeof outlookTriggerContracts & typeof redditTriggerContracts & typeof resendTriggerContracts & typeof slackTriggerContracts & typeof stripeTriggerContracts & typeof teamsTriggerContracts & typeof trelloTriggerContracts & typeof vercelTriggerContracts & typeof webflowTriggerContracts & typeof whatsappTriggerContracts;
32
33
  export type IntegrationTriggerType = keyof TriggerContractMap;
33
34
  /** Canonical authoring configuration for one integration trigger type. */
34
35
  export type TriggerConfig<TType extends IntegrationTriggerType> = z.input<TriggerContractMap[TType]["configSchema"]> extends Record<string, never> ? object : z.input<TriggerContractMap[TType]["configSchema"]>;
@@ -323,15 +323,15 @@ export declare const whatsappTriggerContracts: {
323
323
  timestamp: z.ZodString;
324
324
  type: z.ZodEnum<{
325
325
  unknown: "unknown";
326
- text: "text";
327
326
  audio: "audio";
328
327
  document: "document";
329
328
  image: "image";
330
329
  video: "video";
330
+ order: "order";
331
+ text: "text";
331
332
  location: "location";
332
333
  system: "system";
333
334
  contacts: "contacts";
334
- order: "order";
335
335
  reaction: "reaction";
336
336
  button: "button";
337
337
  interactive: "interactive";
@@ -418,15 +418,15 @@ export declare const whatsappTriggerContracts: {
418
418
  timestamp: z.ZodString;
419
419
  type: z.ZodEnum<{
420
420
  unknown: "unknown";
421
- text: "text";
422
421
  audio: "audio";
423
422
  document: "document";
424
423
  image: "image";
425
424
  video: "video";
425
+ order: "order";
426
+ text: "text";
426
427
  location: "location";
427
428
  system: "system";
428
429
  contacts: "contacts";
429
- order: "order";
430
430
  reaction: "reaction";
431
431
  button: "button";
432
432
  interactive: "interactive";
@@ -89,15 +89,15 @@ export declare const WHATSAPP_WEBHOOK_SCHEMA: z.ZodObject<{
89
89
  timestamp: z.ZodString;
90
90
  type: z.ZodEnum<{
91
91
  unknown: "unknown";
92
- text: "text";
93
92
  audio: "audio";
94
93
  document: "document";
95
94
  image: "image";
96
95
  video: "video";
96
+ order: "order";
97
+ text: "text";
97
98
  location: "location";
98
99
  system: "system";
99
100
  contacts: "contacts";
100
- order: "order";
101
101
  reaction: "reaction";
102
102
  button: "button";
103
103
  interactive: "interactive";
@@ -182,15 +182,15 @@ export declare const WHATSAPP_MESSAGE_RECEIVED_EVENT_SCHEMA: z.ZodObject<{
182
182
  timestamp: z.ZodString;
183
183
  type: z.ZodEnum<{
184
184
  unknown: "unknown";
185
- text: "text";
186
185
  audio: "audio";
187
186
  document: "document";
188
187
  image: "image";
189
188
  video: "video";
189
+ order: "order";
190
+ text: "text";
190
191
  location: "location";
191
192
  system: "system";
192
193
  contacts: "contacts";
193
- order: "order";
194
194
  reaction: "reaction";
195
195
  button: "button";
196
196
  interactive: "interactive";
@@ -277,15 +277,15 @@ export declare const WHATSAPP_MESSAGE_RECEIVED_EVENT_SCHEMA: z.ZodObject<{
277
277
  timestamp: z.ZodString;
278
278
  type: z.ZodEnum<{
279
279
  unknown: "unknown";
280
- text: "text";
281
280
  audio: "audio";
282
281
  document: "document";
283
282
  image: "image";
284
283
  video: "video";
284
+ order: "order";
285
+ text: "text";
285
286
  location: "location";
286
287
  system: "system";
287
288
  contacts: "contacts";
288
- order: "order";
289
289
  reaction: "reaction";
290
290
  button: "button";
291
291
  interactive: "interactive";
@@ -768,7 +768,7 @@ export declare function normalizeWhatsAppWebhook(input: unknown): {
768
768
  message: {
769
769
  id: string;
770
770
  timestamp: string;
771
- type: "unknown" | "text" | "audio" | "document" | "image" | "video" | "location" | "system" | "contacts" | "order" | "reaction" | "button" | "interactive" | "sticker" | "unsupported";
771
+ type: "unknown" | "audio" | "document" | "image" | "video" | "order" | "text" | "location" | "system" | "contacts" | "reaction" | "button" | "interactive" | "sticker" | "unsupported";
772
772
  content?: z.core.util.JSONType | undefined;
773
773
  context?: {
774
774
  messageId: string;
@@ -781,7 +781,7 @@ export declare function normalizeWhatsAppWebhook(input: unknown): {
781
781
  from: string;
782
782
  id: string;
783
783
  timestamp: string;
784
- type: "unknown" | "text" | "audio" | "document" | "image" | "video" | "location" | "system" | "contacts" | "order" | "reaction" | "button" | "interactive" | "sticker" | "unsupported";
784
+ type: "unknown" | "audio" | "document" | "image" | "video" | "order" | "text" | "location" | "system" | "contacts" | "reaction" | "button" | "interactive" | "sticker" | "unsupported";
785
785
  audio?: {
786
786
  id: string;
787
787
  mime_type?: string | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automate.ax/integration-contracts",
3
- "version": "0.126.0",
3
+ "version": "0.127.0",
4
4
  "description": "Shared integration payload contracts and provider primitives for Automate.ax.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -21,6 +21,7 @@
21
21
  "./apify": "./src/apify/index.ts",
22
22
  "./airtable": "./src/airtable/index.ts",
23
23
  "./automate": "./src/automate/index.ts",
24
+ "./axiom": "./src/axiom/index.ts",
24
25
  "./asana": "./src/asana/index.ts",
25
26
  "./brevo": "./src/brevo/index.ts",
26
27
  "./cloudflare": "./src/cloudflare/index.ts",
@@ -57,7 +58,7 @@
57
58
  }
58
59
  },
59
60
  "dependencies": {
60
- "@automate.ax/codec": "0.126.0",
61
+ "@automate.ax/codec": "0.127.0",
61
62
  "@cfworker/json-schema": "^4.1.1",
62
63
  "@googleapis/calendar": "^15.0.0",
63
64
  "@googleapis/forms": "^6.0.1",
@@ -123,6 +124,11 @@
123
124
  "types": "./dist/automate/index.d.ts",
124
125
  "default": "./dist/automate/index.js"
125
126
  },
127
+ "./axiom": {
128
+ "bun": "./src/axiom/index.ts",
129
+ "types": "./dist/axiom/index.d.ts",
130
+ "default": "./dist/axiom/index.js"
131
+ },
126
132
  "./asana": {
127
133
  "bun": "./src/asana/index.ts",
128
134
  "types": "./dist/asana/index.d.ts",
@@ -0,0 +1,252 @@
1
+ import { encodableSchema, type Encodable } from "@automate.ax/codec"
2
+ import * as z from "zod"
3
+
4
+ const AXIOM_API_ORIGIN = "https://api.axiom.co"
5
+ const AXIOM_SECRET_SCHEMA = z.object({ apiKey: z.string().trim().min(1) })
6
+
7
+ export interface AxiomResolvedAccount {
8
+ connectionMethodId: string
9
+ secret: Record<string, unknown>
10
+ serviceId: "axiom"
11
+ }
12
+
13
+ export interface AxiomRequestOptions<TSchema extends z.ZodType> {
14
+ body?: Encodable
15
+ headers?: Record<string, string>
16
+ method?: "DELETE" | "GET" | "PATCH" | "POST" | "PUT"
17
+ query?: Record<string, boolean | number | string | undefined>
18
+ responseSchema: TSchema
19
+ version?: "v1" | "v2"
20
+ }
21
+
22
+ /** Structured Axiom REST error. */
23
+ export class AxiomApiError extends Error {
24
+ readonly details: Encodable
25
+ readonly ingestLimitReset?: number
26
+ readonly queryLimitReset?: number
27
+ readonly rateLimitReset?: number
28
+ readonly retryAfter?: number
29
+ readonly status: number
30
+
31
+ /**
32
+ * Creates a structured provider error.
33
+ *
34
+ * @param options - Error response details and rate-limit metadata.
35
+ * @param options.details - Parsed provider response body.
36
+ * @param options.ingestLimitReset - Ingest-limit reset timestamp.
37
+ * @param options.queryLimitReset - Query-limit reset timestamp.
38
+ * @param options.rateLimitReset - Request-rate-limit reset timestamp.
39
+ * @param options.retryAfter - Suggested retry delay in seconds.
40
+ * @param options.status - HTTP response status.
41
+ */
42
+ constructor(options: {
43
+ details: Encodable
44
+ ingestLimitReset?: number
45
+ queryLimitReset?: number
46
+ rateLimitReset?: number
47
+ retryAfter?: number
48
+ status: number
49
+ }) {
50
+ const message =
51
+ isPlainObject(options.details) &&
52
+ typeof options.details.message === "string"
53
+ ? options.details.message
54
+ : undefined
55
+ super(
56
+ message
57
+ ? `Axiom API error (${options.status}): ${message}`
58
+ : `Axiom API request failed (${options.status}).`,
59
+ )
60
+ this.name = "AxiomApiError"
61
+ this.details = options.details
62
+ this.ingestLimitReset = options.ingestLimitReset
63
+ this.queryLimitReset = options.queryLimitReset
64
+ this.rateLimitReset = options.rateLimitReset
65
+ this.retryAfter = options.retryAfter
66
+ this.status = options.status
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Creates an authenticated, origin-confined Axiom API client.
72
+ *
73
+ * @param account - Resolved Axiom integration account.
74
+ * @param edgeUrl - Optional Axiom edge origin used by version-one endpoints.
75
+ * @throws When the account method, secret, or edge origin is invalid.
76
+ */
77
+ export function getAxiomApi(
78
+ account: AxiomResolvedAccount,
79
+ edgeUrl = AXIOM_API_ORIGIN,
80
+ ) {
81
+ if (account.connectionMethodId !== "api-token") {
82
+ throw new Error(
83
+ `Unsupported Axiom connection method: ${account.connectionMethodId}`,
84
+ )
85
+ }
86
+ const { apiKey } = AXIOM_SECRET_SCHEMA.parse(account.secret)
87
+ const edgeOrigin = validateAxiomOrigin(edgeUrl)
88
+
89
+ /**
90
+ * Sends one authenticated request and validates its response.
91
+ *
92
+ * @param path - Relative Axiom API path.
93
+ * @param options - Request and response-validation options.
94
+ * @throws {AxiomApiError} When Axiom returns an unsuccessful response.
95
+ */
96
+ async function request<TSchema extends z.ZodType>(
97
+ path: string,
98
+ options: AxiomRequestOptions<TSchema>,
99
+ ): Promise<z.output<TSchema>> {
100
+ const version = options.version ?? "v2"
101
+ const url = confinedUrl(
102
+ version === "v1" ? edgeOrigin : AXIOM_API_ORIGIN,
103
+ version,
104
+ path,
105
+ )
106
+ for (const [name, value] of Object.entries(options.query ?? {})) {
107
+ if (value !== undefined) url.searchParams.set(name, String(value))
108
+ }
109
+
110
+ const response = await fetch(url, {
111
+ body:
112
+ options.body === undefined
113
+ ? undefined
114
+ : JSON.stringify(encodableSchema.parse(options.body)),
115
+ headers: {
116
+ Accept: "application/json",
117
+ Authorization: `Bearer ${apiKey}`,
118
+ ...(options.body === undefined
119
+ ? {}
120
+ : { "Content-Type": "application/json" }),
121
+ ...options.headers,
122
+ },
123
+ method: options.method ?? "GET",
124
+ redirect: "manual",
125
+ })
126
+ const parsed = parseResponse(await response.text())
127
+ if (!response.ok || response.status >= 300) {
128
+ throw new AxiomApiError({
129
+ details: parsed,
130
+ ingestLimitReset: parseFiniteNumber(
131
+ response.headers.get("X-IngestLimit-Reset"),
132
+ ),
133
+ queryLimitReset: parseFiniteNumber(
134
+ response.headers.get("X-QueryLimit-Reset"),
135
+ ),
136
+ rateLimitReset: parseFiniteNumber(
137
+ response.headers.get("X-RateLimit-Reset"),
138
+ ),
139
+ retryAfter: parseRetryAfter(response.headers.get("Retry-After")),
140
+ status: response.status,
141
+ })
142
+ }
143
+ return options.responseSchema.parse(parsed)
144
+ }
145
+
146
+ return { request }
147
+ }
148
+
149
+ /**
150
+ * Restricts edge traffic to Axiom-owned HTTPS origins on the standard port.
151
+ *
152
+ * @param value - Candidate edge URL.
153
+ * @throws {TypeError} When the URL is not a confined Axiom HTTPS origin.
154
+ */
155
+ export function validateAxiomOrigin(value: string) {
156
+ const url = new URL(value)
157
+ const isAxiomHost =
158
+ url.hostname === "api.axiom.co" || url.hostname.endsWith(".edge.axiom.co")
159
+ if (
160
+ url.protocol !== "https:" ||
161
+ url.port !== "" ||
162
+ !isAxiomHost ||
163
+ url.username ||
164
+ url.password ||
165
+ url.search ||
166
+ url.hash
167
+ ) {
168
+ throw new TypeError(
169
+ "Axiom edge URLs must use api.axiom.co or an HTTPS *.edge.axiom.co host.",
170
+ )
171
+ }
172
+ return url.origin
173
+ }
174
+
175
+ /**
176
+ * Resolves a relative path below one confined API-version root.
177
+ *
178
+ * @param origin - Validated Axiom origin.
179
+ * @param version - API version path segment.
180
+ * @param path - Relative request path.
181
+ * @throws {TypeError} When the path escapes its API-version root.
182
+ */
183
+ function confinedUrl(origin: string, version: "v1" | "v2", path: string) {
184
+ const normalizedPath = path.replace(/^\/+/, "")
185
+ if (
186
+ !normalizedPath ||
187
+ normalizedPath.includes("://") ||
188
+ normalizedPath.includes("\\")
189
+ ) {
190
+ throw new TypeError("Axiom API paths must be relative.")
191
+ }
192
+ const root = new URL(`/${version}/`, origin)
193
+ const url = new URL(normalizedPath, root)
194
+ if (url.origin !== root.origin || !url.pathname.startsWith(root.pathname)) {
195
+ throw new TypeError("Axiom API paths must remain below their API version.")
196
+ }
197
+ return url
198
+ }
199
+
200
+ /**
201
+ * Parses an Axiom response into an encodable value.
202
+ *
203
+ * @param text - Raw response body.
204
+ */
205
+ function parseResponse(text: string): Encodable {
206
+ if (!text) return null
207
+ try {
208
+ return encodableSchema.parse(JSON.parse(text))
209
+ } catch {
210
+ return { response: text }
211
+ }
212
+ }
213
+
214
+ /**
215
+ * Parses a finite numeric response header.
216
+ *
217
+ * @param value - Raw header value.
218
+ */
219
+ function parseFiniteNumber(value: string | null) {
220
+ if (value === null) return undefined
221
+ const number = Number(value)
222
+ return Number.isFinite(number) ? number : undefined
223
+ }
224
+
225
+ /**
226
+ * Parses a Retry-After header into seconds.
227
+ *
228
+ * @param value - Raw header value.
229
+ */
230
+ function parseRetryAfter(value: string | null) {
231
+ if (value === null) return undefined
232
+ const seconds = Number(value)
233
+ if (Number.isFinite(seconds)) return seconds
234
+ const timestamp = Date.parse(value)
235
+ return Number.isFinite(timestamp)
236
+ ? Math.max(0, Math.ceil((timestamp - Date.now()) / 1_000))
237
+ : undefined
238
+ }
239
+
240
+ /**
241
+ * Checks whether an encodable value is a plain object.
242
+ *
243
+ * @param value - Value to inspect.
244
+ */
245
+ function isPlainObject(value: Encodable): value is Record<string, Encodable> {
246
+ return (
247
+ typeof value === "object" &&
248
+ value !== null &&
249
+ !Array.isArray(value) &&
250
+ Object.getPrototypeOf(value) === Object.prototype
251
+ )
252
+ }
@@ -0,0 +1,31 @@
1
+ import * as z from "zod"
2
+ import { AXIOM_ID_SCHEMA, AXIOM_MONITOR_NOTIFICATION_SCHEMA } from "./schemas"
3
+
4
+ export const AXIOM_TRIGGER_CONFIG_SCHEMA = z.object({
5
+ monitorId: AXIOM_ID_SCHEMA,
6
+ })
7
+
8
+ export const AXIOM_MONITOR_OPENED_SCHEMA =
9
+ AXIOM_MONITOR_NOTIFICATION_SCHEMA.extend({
10
+ action: z.literal("Open"),
11
+ })
12
+
13
+ export const AXIOM_MONITOR_CLOSED_SCHEMA =
14
+ AXIOM_MONITOR_NOTIFICATION_SCHEMA.extend({
15
+ action: z.literal("Closed"),
16
+ })
17
+
18
+ export const axiomTriggerContracts = {
19
+ "axiom.monitorNotification": {
20
+ configSchema: AXIOM_TRIGGER_CONFIG_SCHEMA,
21
+ eventSchema: AXIOM_MONITOR_NOTIFICATION_SCHEMA,
22
+ },
23
+ "axiom.monitorOpened": {
24
+ configSchema: AXIOM_TRIGGER_CONFIG_SCHEMA,
25
+ eventSchema: AXIOM_MONITOR_OPENED_SCHEMA,
26
+ },
27
+ "axiom.monitorClosed": {
28
+ configSchema: AXIOM_TRIGGER_CONFIG_SCHEMA,
29
+ eventSchema: AXIOM_MONITOR_CLOSED_SCHEMA,
30
+ },
31
+ } as const
@@ -0,0 +1,3 @@
1
+ export * from "./api"
2
+ export * from "./events"
3
+ export * from "./schemas"