@automate.ax/integration-contracts 0.152.5 → 0.153.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.
@@ -1687,8 +1687,8 @@ export declare const closeTriggerContracts: {
1687
1687
  status: z.ZodOptional<z.ZodEnum<{
1688
1688
  error: "error";
1689
1689
  active: "active";
1690
- paused: "paused";
1691
1690
  finished: "finished";
1691
+ paused: "paused";
1692
1692
  goal: "goal";
1693
1693
  }>>;
1694
1694
  statusReason: z.ZodOptional<z.ZodNullable<z.ZodString>>;
@@ -1751,8 +1751,8 @@ export declare const closeTriggerContracts: {
1751
1751
  status: z.ZodOptional<z.ZodEnum<{
1752
1752
  error: "error";
1753
1753
  active: "active";
1754
- paused: "paused";
1755
1754
  finished: "finished";
1755
+ paused: "paused";
1756
1756
  goal: "goal";
1757
1757
  }>>;
1758
1758
  statusReason: z.ZodOptional<z.ZodNullable<z.ZodString>>;
@@ -1795,8 +1795,8 @@ export declare const closeTriggerContracts: {
1795
1795
  status: z.ZodOptional<z.ZodEnum<{
1796
1796
  error: "error";
1797
1797
  active: "active";
1798
- paused: "paused";
1799
1798
  finished: "finished";
1799
+ paused: "paused";
1800
1800
  goal: "goal";
1801
1801
  }>>;
1802
1802
  statusReason: z.ZodOptional<z.ZodNullable<z.ZodString>>;
@@ -1839,8 +1839,8 @@ export declare const closeTriggerContracts: {
1839
1839
  status: z.ZodOptional<z.ZodEnum<{
1840
1840
  error: "error";
1841
1841
  active: "active";
1842
- paused: "paused";
1843
1842
  finished: "finished";
1843
+ paused: "paused";
1844
1844
  goal: "goal";
1845
1845
  }>>;
1846
1846
  statusReason: z.ZodOptional<z.ZodNullable<z.ZodString>>;
@@ -1883,8 +1883,8 @@ export declare const closeTriggerContracts: {
1883
1883
  status: z.ZodOptional<z.ZodEnum<{
1884
1884
  error: "error";
1885
1885
  active: "active";
1886
- paused: "paused";
1887
1886
  finished: "finished";
1887
+ paused: "paused";
1888
1888
  goal: "goal";
1889
1889
  }>>;
1890
1890
  statusReason: z.ZodOptional<z.ZodNullable<z.ZodString>>;
@@ -1927,8 +1927,8 @@ export declare const closeTriggerContracts: {
1927
1927
  status: z.ZodOptional<z.ZodEnum<{
1928
1928
  error: "error";
1929
1929
  active: "active";
1930
- paused: "paused";
1931
1930
  finished: "finished";
1931
+ paused: "paused";
1932
1932
  goal: "goal";
1933
1933
  }>>;
1934
1934
  statusReason: z.ZodOptional<z.ZodNullable<z.ZodString>>;
@@ -1971,8 +1971,8 @@ export declare const closeTriggerContracts: {
1971
1971
  status: z.ZodOptional<z.ZodEnum<{
1972
1972
  error: "error";
1973
1973
  active: "active";
1974
- paused: "paused";
1975
1974
  finished: "finished";
1975
+ paused: "paused";
1976
1976
  goal: "goal";
1977
1977
  }>>;
1978
1978
  statusReason: z.ZodOptional<z.ZodNullable<z.ZodString>>;
@@ -1863,8 +1863,8 @@ export declare const CLOSE_SEQUENCE_SUBSCRIPTION_SCHEMA: z.ZodObject<{
1863
1863
  status: z.ZodEnum<{
1864
1864
  error: "error";
1865
1865
  active: "active";
1866
- paused: "paused";
1867
1866
  finished: "finished";
1867
+ paused: "paused";
1868
1868
  goal: "goal";
1869
1869
  }>;
1870
1870
  statusReason: z.ZodNullable<z.ZodString>;
@@ -20,13 +20,30 @@ export interface CloudflareResolvedAccount {
20
20
  export interface CloudflareRequestOptions<TSchema extends z.ZodType> {
21
21
  /** Public camelCase JSON body. */
22
22
  body?: Encodable;
23
+ /** Provider request-key convention. Defaults to Cloudflare snake_case. */
24
+ keyFormat?: "browser-rendering";
23
25
  /** HTTP verb. Defaults to `GET`. */
24
26
  method?: "DELETE" | "GET" | "PATCH" | "POST" | "PUT";
25
27
  /** Public camelCase query parameters. */
26
28
  query?: Record<string, CloudflareQueryValue>;
29
+ /** Provider result-key convention. Defaults to recursive camelCase. */
30
+ responseKeyFormat?: "preserve";
27
31
  /** Schema for the normalized provider result. */
28
32
  responseSchema: TSchema;
29
33
  }
34
+ /** Options for one authenticated Cloudflare binary REST request. */
35
+ export interface CloudflareBlobRequestOptions {
36
+ /** Expected response media type. */
37
+ accept: string;
38
+ /** Public camelCase JSON body. */
39
+ body?: Encodable;
40
+ /** Provider request-key convention. Defaults to Cloudflare snake_case. */
41
+ keyFormat?: "browser-rendering";
42
+ /** HTTP verb. Defaults to `GET`. */
43
+ method?: "DELETE" | "GET" | "PATCH" | "POST" | "PUT";
44
+ /** Public camelCase query parameters. */
45
+ query?: Record<string, CloudflareQueryValue>;
46
+ }
30
47
  /** One normalized Cloudflare result page. */
31
48
  export interface CloudflarePage<T> {
32
49
  result: T;
@@ -76,6 +93,7 @@ export declare class CloudflareApiError extends Error {
76
93
  */
77
94
  export declare function getCloudflareApi(account: CloudflareResolvedAccount): {
78
95
  request: <TSchema extends z.ZodType>(path: string, options: CloudflareRequestOptions<TSchema>) => Promise<z.output<TSchema>>;
96
+ requestBlob: (path: string, options: CloudflareBlobRequestOptions) => Promise<Blob>;
79
97
  requestPage: <TSchema extends z.ZodType>(path: string, options: CloudflareRequestOptions<TSchema>) => Promise<CloudflarePage<z.output<TSchema>>>;
80
98
  };
81
99
  /**
@@ -84,6 +102,12 @@ export declare function getCloudflareApi(account: CloudflareResolvedAccount): {
84
102
  * @param value - Codec-safe public value.
85
103
  */
86
104
  export declare function toCloudflare(value: Encodable): Encodable;
105
+ /**
106
+ * Converts public JSON to Cloudflare Browser Run's mixed wire keys.
107
+ *
108
+ * @param value - Codec-safe public value.
109
+ */
110
+ export declare function toCloudflareBrowserRendering(value: Encodable): Encodable;
87
111
  /**
88
112
  * Converts Cloudflare wire JSON to public camelCase keys.
89
113
  *
@@ -101,20 +101,63 @@ export function getCloudflareApi(account) {
101
101
  * @param options - Method, parameters, and response schema.
102
102
  */
103
103
  async function requestPage(path, options) {
104
+ const response = await runRequest(path, options, "application/json");
105
+ const parsed = CLOUDFLARE_ENVELOPE_SCHEMA.safeParse(parseJson(await response.text()));
106
+ if (!response.ok || !parsed.success || !parsed.data.success) {
107
+ throw createApiError(response, parsed.success ? parsed.data.errors : []);
108
+ }
109
+ return {
110
+ result: options.responseSchema.parse(options.responseKeyFormat === "preserve"
111
+ ? convertFromCloudflare(parsed.data.result, true)
112
+ : fromCloudflare(parsed.data.result)),
113
+ ...(parsed.data.result_info && {
114
+ resultInfo: CLOUDFLARE_RESULT_INFO_SCHEMA.parse(fromCloudflare(parsed.data.result_info)),
115
+ }),
116
+ };
117
+ }
118
+ /**
119
+ * Runs one request and returns a binary response body.
120
+ *
121
+ * @param path - Cloudflare API path relative to the v4 root.
122
+ * @param options - Method, parameters, and expected media type.
123
+ */
124
+ async function requestBlob(path, options) {
125
+ const response = await runRequest(path, options, options.accept);
126
+ if (!response.ok ||
127
+ response.headers.get("Content-Type")?.includes("application/json")) {
128
+ const parsed = CLOUDFLARE_ENVELOPE_SCHEMA.safeParse(parseJson(await response.text()));
129
+ if (!response.ok || !parsed.success || !parsed.data.success)
130
+ throw createApiError(response, parsed.success ? parsed.data.errors : []);
131
+ throw new Error("Cloudflare returned JSON instead of binary content.");
132
+ }
133
+ return response.blob();
134
+ }
135
+ /**
136
+ * Runs one authenticated Cloudflare request.
137
+ *
138
+ * @param path - Cloudflare API path relative to the v4 root.
139
+ * @param options - Method, body, and query parameters.
140
+ * @param accept - Expected response media type.
141
+ */
142
+ async function runRequest(path, options, accept) {
104
143
  const url = new URL(path.replace(/^\//, ""), CLOUDFLARE_API_BASE_URL);
105
144
  if (url.origin !== CLOUDFLARE_API_ORIGIN) {
106
145
  throw new Error("Cloudflare API paths must use the Cloudflare API origin.");
107
146
  }
108
147
  for (const [name, value] of Object.entries(options.query ?? {})) {
109
148
  if (value !== undefined)
110
- url.searchParams.set(toSnakeCase(name), String(value));
149
+ url.searchParams.set(options.keyFormat === "browser-rendering"
150
+ ? toBrowserRenderingQueryKey(name)
151
+ : toSnakeCase(name), String(value));
111
152
  }
112
- const response = await fetch(url, {
153
+ return fetch(url, {
113
154
  body: options.body === undefined
114
155
  ? undefined
115
- : JSON.stringify(toCloudflare(options.body)),
156
+ : JSON.stringify(options.keyFormat === "browser-rendering"
157
+ ? toCloudflareBrowserRendering(options.body)
158
+ : toCloudflare(options.body)),
116
159
  headers: {
117
- Accept: "application/json",
160
+ Accept: accept,
118
161
  Authorization: `Bearer ${accessToken}`,
119
162
  ...(options.body === undefined
120
163
  ? {}
@@ -122,24 +165,23 @@ export function getCloudflareApi(account) {
122
165
  },
123
166
  method: options.method ?? "GET",
124
167
  });
125
- const parsed = CLOUDFLARE_ENVELOPE_SCHEMA.safeParse(parseJson(await response.text()));
126
- if (!response.ok || !parsed.success || !parsed.data.success) {
127
- throw new CloudflareApiError({
128
- errors: parsed.success ? parsed.data.errors : undefined,
129
- rateLimit: response.headers.get("Ratelimit") ?? undefined,
130
- rateLimitPolicy: response.headers.get("Ratelimit-Policy") ?? undefined,
131
- retryAfter: parseFiniteNumber(response.headers.get("Retry-After")),
132
- status: response.status,
133
- });
134
- }
135
- return {
136
- result: options.responseSchema.parse(fromCloudflare(parsed.data.result)),
137
- ...(parsed.data.result_info && {
138
- resultInfo: CLOUDFLARE_RESULT_INFO_SCHEMA.parse(fromCloudflare(parsed.data.result_info)),
139
- }),
140
- };
141
168
  }
142
- return { request, requestPage };
169
+ return { request, requestBlob, requestPage };
170
+ }
171
+ /**
172
+ * Creates a structured error from one Cloudflare response.
173
+ *
174
+ * @param response - Failed Cloudflare response.
175
+ * @param errors - Parsed provider errors.
176
+ */
177
+ function createApiError(response, errors) {
178
+ return new CloudflareApiError({
179
+ errors,
180
+ rateLimit: response.headers.get("Ratelimit") ?? undefined,
181
+ rateLimitPolicy: response.headers.get("Ratelimit-Policy") ?? undefined,
182
+ retryAfter: parseFiniteNumber(response.headers.get("Retry-After")),
183
+ status: response.status,
184
+ });
143
185
  }
144
186
  /**
145
187
  * Converts public camelCase JSON to Cloudflare wire keys.
@@ -149,6 +191,32 @@ export function getCloudflareApi(account) {
149
191
  export function toCloudflare(value) {
150
192
  return convertToCloudflare(value, false);
151
193
  }
194
+ /**
195
+ * Converts public JSON to Cloudflare Browser Run's mixed wire keys.
196
+ *
197
+ * @param value - Codec-safe public value.
198
+ */
199
+ export function toCloudflareBrowserRendering(value) {
200
+ return convertToCloudflareBrowserRendering(value, false);
201
+ }
202
+ /**
203
+ * Converts one Browser Run value while optionally preserving arbitrary keys.
204
+ *
205
+ * @param value - Public value to convert.
206
+ * @param preserveKeys - Whether this object is a user-defined map.
207
+ */
208
+ function convertToCloudflareBrowserRendering(value, preserveKeys) {
209
+ if (value instanceof Date)
210
+ return value.toISOString();
211
+ if (Array.isArray(value))
212
+ return value.map((item) => convertToCloudflareBrowserRendering(item, preserveKeys));
213
+ if (!isPlainObject(value))
214
+ return value;
215
+ return Object.fromEntries(Object.entries(value).map(([key, item]) => [
216
+ preserveKeys ? key : toBrowserRenderingKey(key),
217
+ convertToCloudflareBrowserRendering(item, preserveKeys || key === "jsonSchema" || key === "setExtraHttpHeaders"),
218
+ ]));
219
+ }
152
220
  /**
153
221
  * Converts one value while optionally preserving object keys.
154
222
  *
@@ -164,7 +232,7 @@ function convertToCloudflare(value, preserveKeys) {
164
232
  return value;
165
233
  return Object.fromEntries(Object.entries(value).map(([key, item]) => [
166
234
  preserveKeys ? key : toSnakeCase(key),
167
- convertToCloudflare(item, key === "header" || key === "headers"),
235
+ convertToCloudflare(item, preserveKeys || preservesNestedKeys(key)),
168
236
  ]));
169
237
  }
170
238
  /**
@@ -188,9 +256,25 @@ function convertFromCloudflare(value, preserveKeys) {
188
256
  return CLOUDFLARE_VALUE_SCHEMA.parse(value);
189
257
  return Object.fromEntries(Object.entries(value).map(([key, item]) => [
190
258
  preserveKeys ? key : toCamelCase(key),
191
- convertFromCloudflare(item, key === "header" || key === "headers"),
259
+ convertFromCloudflare(item, preserveKeys || preservesNestedKeys(key)),
192
260
  ]));
193
261
  }
262
+ /**
263
+ * Returns whether a provider-defined object map must retain its keys.
264
+ *
265
+ * @param key - Public or provider parent key.
266
+ */
267
+ function preservesNestedKeys(key) {
268
+ return [
269
+ "header",
270
+ "headers",
271
+ "json",
272
+ "jsonSchema",
273
+ "json_schema",
274
+ "setExtraHttpHeaders",
275
+ "set_extra_http_headers",
276
+ ].includes(key);
277
+ }
194
278
  const CLOUDFLARE_VALUE_SCHEMA = z.union([
195
279
  z.boolean(),
196
280
  z.number(),
@@ -248,3 +332,27 @@ function toSnakeCase(value) {
248
332
  .replace(/([a-zA-Z])([0-9])/g, "$1_$2")
249
333
  .replace(/[A-Z]/g, (character) => `_${character.toLowerCase()}`);
250
334
  }
335
+ /**
336
+ * Converts a public query key to Cloudflare's endpoint spelling.
337
+ *
338
+ * @param value - Public query key.
339
+ */
340
+ function toBrowserRenderingQueryKey(value) {
341
+ return value === "cacheTtl" ? "cacheTTL" : toSnakeCase(value);
342
+ }
343
+ /**
344
+ * Converts one public Browser Run body key to its exact provider spelling.
345
+ *
346
+ * @param value - Public key.
347
+ */
348
+ function toBrowserRenderingKey(value) {
349
+ if (value === "customAi")
350
+ return "custom_ai";
351
+ if (value === "jsonSchema")
352
+ return "json_schema";
353
+ if (value === "responseFormat")
354
+ return "response_format";
355
+ if (value === "setExtraHttpHeaders")
356
+ return "setExtraHTTPHeaders";
357
+ return value;
358
+ }