@zapier/zapier-sdk 0.107.1 → 0.108.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/CHANGELOG.md +14 -0
- package/README.md +319 -0
- package/dist/{chunk-PFNHJW2F.cjs → chunk-HMEY72T6.cjs} +209 -23
- package/dist/{chunk-MRDFD4MP.mjs → chunk-ULZVDPAK.mjs} +209 -23
- package/dist/experimental.cjs +849 -370
- package/dist/experimental.d.mts +588 -9
- package/dist/experimental.d.ts +588 -9
- package/dist/experimental.mjs +483 -4
- package/dist/index.cjs +279 -279
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
|
@@ -1309,6 +1309,16 @@ function emitOnce(onEvent, event) {
|
|
|
1309
1309
|
var { logDeprecation, resetDeprecationWarnings } = kitcore.createDeprecationLogger("zapier-sdk");
|
|
1310
1310
|
|
|
1311
1311
|
// src/utils/url-utils.ts
|
|
1312
|
+
function withSearchParams({
|
|
1313
|
+
url,
|
|
1314
|
+
searchParams
|
|
1315
|
+
}) {
|
|
1316
|
+
const result = new URL(url);
|
|
1317
|
+
for (const [key, value] of Object.entries(searchParams ?? {})) {
|
|
1318
|
+
result.searchParams.set(key, value);
|
|
1319
|
+
}
|
|
1320
|
+
return result.toString();
|
|
1321
|
+
}
|
|
1312
1322
|
function getZapierBaseUrl(baseUrl) {
|
|
1313
1323
|
if (!baseUrl) {
|
|
1314
1324
|
return void 0;
|
|
@@ -2153,6 +2163,88 @@ function parseDeprecationDate(value) {
|
|
|
2153
2163
|
if (!match) return void 0;
|
|
2154
2164
|
return Number(match[1]) * 1e3;
|
|
2155
2165
|
}
|
|
2166
|
+
var RELAY_ERROR_HEADER = "x-relay-error";
|
|
2167
|
+
var RELAY_TIMEOUT_HEADER = "x-relay-extended-timeout";
|
|
2168
|
+
var SDK_CORRELATION_HEADER = "zapier-correlation-id";
|
|
2169
|
+
var SDK_MAX_TIME_HEADER = "x-zapier-sdk-max-time";
|
|
2170
|
+
var RELAY_NATIVE_TIMEOUT_SECONDS = 30;
|
|
2171
|
+
var RELAY_TIMEOUT_TIERS = [
|
|
2172
|
+
{ seconds: 60, headerValue: "1m" },
|
|
2173
|
+
{ seconds: 180, headerValue: "3m" },
|
|
2174
|
+
{ seconds: 300, headerValue: "5m" },
|
|
2175
|
+
{ seconds: 600, headerValue: "10m" }
|
|
2176
|
+
];
|
|
2177
|
+
function transformRelayRequestHeaders({
|
|
2178
|
+
headers,
|
|
2179
|
+
debugLog
|
|
2180
|
+
}) {
|
|
2181
|
+
applyTimeoutTierPolicy({ headers, debugLog });
|
|
2182
|
+
applyCorrelationIdPolicy({ headers });
|
|
2183
|
+
return headers;
|
|
2184
|
+
}
|
|
2185
|
+
function applyCorrelationIdPolicy({ headers }) {
|
|
2186
|
+
const correlationId = headers.get(SDK_CORRELATION_HEADER);
|
|
2187
|
+
if (correlationId !== null && !isValidRelayCorrelationId(correlationId)) {
|
|
2188
|
+
headers.delete(SDK_CORRELATION_HEADER);
|
|
2189
|
+
}
|
|
2190
|
+
}
|
|
2191
|
+
function applyTimeoutTierPolicy({
|
|
2192
|
+
headers,
|
|
2193
|
+
debugLog
|
|
2194
|
+
}) {
|
|
2195
|
+
const sdkMaxTimeSeconds = headers.get(SDK_MAX_TIME_HEADER);
|
|
2196
|
+
headers.delete(SDK_MAX_TIME_HEADER);
|
|
2197
|
+
if (headers.has(RELAY_TIMEOUT_HEADER) || sdkMaxTimeSeconds === null) {
|
|
2198
|
+
return;
|
|
2199
|
+
}
|
|
2200
|
+
const seconds = parsePositiveInteger(sdkMaxTimeSeconds);
|
|
2201
|
+
if (seconds === void 0 || seconds <= RELAY_NATIVE_TIMEOUT_SECONDS) {
|
|
2202
|
+
return;
|
|
2203
|
+
}
|
|
2204
|
+
const match = RELAY_TIMEOUT_TIERS.find(
|
|
2205
|
+
(candidate) => candidate.seconds >= seconds
|
|
2206
|
+
);
|
|
2207
|
+
const tier = match ?? RELAY_TIMEOUT_TIERS[RELAY_TIMEOUT_TIERS.length - 1];
|
|
2208
|
+
if (!match) {
|
|
2209
|
+
debugLog?.(
|
|
2210
|
+
`Relay timeout of ${seconds}s exceeds the largest tier; capping to ${tier.headerValue}`
|
|
2211
|
+
);
|
|
2212
|
+
}
|
|
2213
|
+
headers.set(RELAY_TIMEOUT_HEADER, tier.headerValue);
|
|
2214
|
+
}
|
|
2215
|
+
function transformRelayResponseHeaders({
|
|
2216
|
+
headers
|
|
2217
|
+
}) {
|
|
2218
|
+
const relayError = headers.get(RELAY_ERROR_HEADER);
|
|
2219
|
+
if (!relayError?.startsWith("Authentication Template Failure")) {
|
|
2220
|
+
return headers;
|
|
2221
|
+
}
|
|
2222
|
+
const templateMatch = relayError.match(
|
|
2223
|
+
/Unable to find template for ([^@]+)@/
|
|
2224
|
+
);
|
|
2225
|
+
if (!templateMatch?.[1]) {
|
|
2226
|
+
return headers;
|
|
2227
|
+
}
|
|
2228
|
+
const appName = templateMatch[1].replace(/CLIAPI$/, "").replace(/([a-z])([A-Z])/g, "$1 $2").trim();
|
|
2229
|
+
if (!appName) {
|
|
2230
|
+
return headers;
|
|
2231
|
+
}
|
|
2232
|
+
headers.set(
|
|
2233
|
+
RELAY_ERROR_HEADER,
|
|
2234
|
+
`${appName} does not support direct HTTP requests. Use zapier.apps.{appKey} or zapier.runAction() to use Actions built for this app.`
|
|
2235
|
+
);
|
|
2236
|
+
return headers;
|
|
2237
|
+
}
|
|
2238
|
+
var RelayCorrelationIdSchema = zod.z.uuid();
|
|
2239
|
+
function isValidRelayCorrelationId(value) {
|
|
2240
|
+
return RelayCorrelationIdSchema.safeParse(value).success;
|
|
2241
|
+
}
|
|
2242
|
+
function parsePositiveInteger(value) {
|
|
2243
|
+
if (!/^[1-9]\d*$/.test(value)) {
|
|
2244
|
+
return void 0;
|
|
2245
|
+
}
|
|
2246
|
+
return Number(value);
|
|
2247
|
+
}
|
|
2156
2248
|
|
|
2157
2249
|
// src/api/routing/config.ts
|
|
2158
2250
|
var pathConfig = {
|
|
@@ -2160,7 +2252,11 @@ var pathConfig = {
|
|
|
2160
2252
|
"/relay": {
|
|
2161
2253
|
authHeader: "X-Relay-Authorization",
|
|
2162
2254
|
pathPrefix: "/api/v0/sdk/relay",
|
|
2163
|
-
omitDeprecationMessaging: true
|
|
2255
|
+
omitDeprecationMessaging: true,
|
|
2256
|
+
override: {
|
|
2257
|
+
transformRequestHeaders: transformRelayRequestHeaders,
|
|
2258
|
+
transformResponseHeaders: transformRelayResponseHeaders
|
|
2259
|
+
}
|
|
2164
2260
|
},
|
|
2165
2261
|
// The concrete gateway form of the relay route. Callers that pass the
|
|
2166
2262
|
// already-prefixed path reach the same third-party upstreams, so it must
|
|
@@ -2237,6 +2333,15 @@ var pathConfig = {
|
|
|
2237
2333
|
"/agentic-management": {
|
|
2238
2334
|
authHeader: "Authorization",
|
|
2239
2335
|
subdomain: "api"
|
|
2336
|
+
},
|
|
2337
|
+
// e.g. /vfs/v1/files -> https://api.zapier.com/vfs/v1/files
|
|
2338
|
+
// The VFS API is registered on the Public API Gateway and has no sdkapi
|
|
2339
|
+
// proxy route, so it goes straight to the gateway. Its governance metadata
|
|
2340
|
+
// rewrites /vfs/v1/... to the backend's /api/v1/fs/..., which is why no
|
|
2341
|
+
// pathPrefix is applied here.
|
|
2342
|
+
"/vfs": {
|
|
2343
|
+
authHeader: "Authorization",
|
|
2344
|
+
subdomain: "api"
|
|
2240
2345
|
}
|
|
2241
2346
|
};
|
|
2242
2347
|
|
|
@@ -2435,10 +2540,13 @@ function resolveOverrideRoute({
|
|
|
2435
2540
|
}) {
|
|
2436
2541
|
const { matchedPrefix, routeConfig, override } = overrideMatch;
|
|
2437
2542
|
const directPath = deriveDirectPath({ path, matchedPrefix, routeConfig });
|
|
2543
|
+
const overrideConfig = routeConfig.override?.enabled === false ? void 0 : routeConfig.override;
|
|
2438
2544
|
return {
|
|
2439
2545
|
url: buildRouteOverrideUrl({ origin: override.origin, path: directPath }),
|
|
2440
2546
|
pathConfig: routeConfig,
|
|
2441
|
-
canSendDeprecationMessaging: false
|
|
2547
|
+
canSendDeprecationMessaging: false,
|
|
2548
|
+
...overrideConfig?.transformRequestHeaders ? { transformRequestHeaders: overrideConfig.transformRequestHeaders } : {},
|
|
2549
|
+
...overrideConfig?.transformResponseHeaders ? { transformResponseHeaders: overrideConfig.transformResponseHeaders } : {}
|
|
2442
2550
|
};
|
|
2443
2551
|
}
|
|
2444
2552
|
function deriveDirectPath({
|
|
@@ -2618,6 +2726,89 @@ function isRouteOverrideEnabled({
|
|
|
2618
2726
|
return routeConfig.override?.enabled !== false;
|
|
2619
2727
|
}
|
|
2620
2728
|
|
|
2729
|
+
// src/api/routing/headers/request.ts
|
|
2730
|
+
function applyRequestHeaderTransform({
|
|
2731
|
+
headers,
|
|
2732
|
+
resolvedRoute,
|
|
2733
|
+
debugLog
|
|
2734
|
+
}) {
|
|
2735
|
+
return resolvedRoute?.transformRequestHeaders?.({ headers, debugLog }) ?? headers;
|
|
2736
|
+
}
|
|
2737
|
+
|
|
2738
|
+
// src/api/routing/headers/response.ts
|
|
2739
|
+
var NULL_BODY_RESPONSE_STATUSES = /* @__PURE__ */ new Set([204, 205, 304]);
|
|
2740
|
+
function applyResponseHeaderTransform({
|
|
2741
|
+
response,
|
|
2742
|
+
resolvedRoute
|
|
2743
|
+
}) {
|
|
2744
|
+
const transformHeaders = resolvedRoute?.transformResponseHeaders;
|
|
2745
|
+
if (!transformHeaders) {
|
|
2746
|
+
return response;
|
|
2747
|
+
}
|
|
2748
|
+
if (!Number.isInteger(response.status) || response.status < 200 || response.status > 599 || response.bodyUsed || response.body?.locked) {
|
|
2749
|
+
return response;
|
|
2750
|
+
}
|
|
2751
|
+
const originalHeaders = response.headers;
|
|
2752
|
+
if (!originalHeaders) {
|
|
2753
|
+
return response;
|
|
2754
|
+
}
|
|
2755
|
+
const transformedHeaders = transformHeaders({
|
|
2756
|
+
headers: new Headers(originalHeaders)
|
|
2757
|
+
});
|
|
2758
|
+
if (areHeadersEqual({ first: originalHeaders, second: transformedHeaders })) {
|
|
2759
|
+
return response;
|
|
2760
|
+
}
|
|
2761
|
+
const transformedResponse = new Response(
|
|
2762
|
+
NULL_BODY_RESPONSE_STATUSES.has(response.status) ? null : response.body,
|
|
2763
|
+
{
|
|
2764
|
+
status: response.status,
|
|
2765
|
+
statusText: response.statusText,
|
|
2766
|
+
headers: transformedHeaders
|
|
2767
|
+
}
|
|
2768
|
+
);
|
|
2769
|
+
return preserveResponseMetadata({
|
|
2770
|
+
response: transformedResponse,
|
|
2771
|
+
source: response
|
|
2772
|
+
});
|
|
2773
|
+
}
|
|
2774
|
+
function preserveResponseMetadata({
|
|
2775
|
+
response,
|
|
2776
|
+
source
|
|
2777
|
+
}) {
|
|
2778
|
+
const nativeClone = response.clone;
|
|
2779
|
+
Object.defineProperties(response, {
|
|
2780
|
+
clone: {
|
|
2781
|
+
configurable: true,
|
|
2782
|
+
writable: true,
|
|
2783
|
+
value: function clone() {
|
|
2784
|
+
const clonedResponse = nativeClone.call(this);
|
|
2785
|
+
return this === response ? preserveResponseMetadata({ response: clonedResponse, source }) : clonedResponse;
|
|
2786
|
+
}
|
|
2787
|
+
},
|
|
2788
|
+
...sourceMetadataDescriptors(source)
|
|
2789
|
+
});
|
|
2790
|
+
return response;
|
|
2791
|
+
}
|
|
2792
|
+
function sourceMetadataDescriptors(source) {
|
|
2793
|
+
const descriptors = {};
|
|
2794
|
+
for (const key of ["redirected", "type", "url"]) {
|
|
2795
|
+
if (source[key] !== void 0) {
|
|
2796
|
+
descriptors[key] = { configurable: true, value: source[key] };
|
|
2797
|
+
}
|
|
2798
|
+
}
|
|
2799
|
+
return descriptors;
|
|
2800
|
+
}
|
|
2801
|
+
function areHeadersEqual({
|
|
2802
|
+
first,
|
|
2803
|
+
second
|
|
2804
|
+
}) {
|
|
2805
|
+
const firstEntries = [...first.entries()];
|
|
2806
|
+
const secondEntries = [...second.entries()];
|
|
2807
|
+
return firstEntries.length === secondEntries.length && firstEntries.every(
|
|
2808
|
+
([key, value], index) => secondEntries[index]?.[0] === key && secondEntries[index]?.[1] === value
|
|
2809
|
+
);
|
|
2810
|
+
}
|
|
2811
|
+
|
|
2621
2812
|
// src/api/routing/index.ts
|
|
2622
2813
|
var routingConfig = createRoutingConfig({ pathConfig });
|
|
2623
2814
|
function parseRoutingOptions({
|
|
@@ -2685,7 +2876,7 @@ function logRouteOverride({
|
|
|
2685
2876
|
}
|
|
2686
2877
|
|
|
2687
2878
|
// src/sdk-version.ts
|
|
2688
|
-
var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.
|
|
2879
|
+
var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.108.0" : void 0) || "unknown";
|
|
2689
2880
|
|
|
2690
2881
|
// src/utils/open-url.ts
|
|
2691
2882
|
var nodePrefix = "node:";
|
|
@@ -2825,14 +3016,14 @@ var ZapierApiClient = class {
|
|
|
2825
3016
|
* auth/retry pipeline instead of reaching for `this.options.fetch`
|
|
2826
3017
|
* directly and drifting.
|
|
2827
3018
|
*/
|
|
2828
|
-
this.rawFetchUrl = async (url, init,
|
|
3019
|
+
this.rawFetchUrl = async (url, init, resolvedRoute) => {
|
|
2829
3020
|
const { [CORRELATION_CALL_ID]: callId, ...fetchInit } = init ?? {};
|
|
2830
3021
|
if (fetchInit.body && (isPlainObject(fetchInit.body) || Array.isArray(fetchInit.body))) {
|
|
2831
3022
|
fetchInit.body = JSON.stringify(fetchInit.body);
|
|
2832
3023
|
}
|
|
2833
3024
|
const builtHeaders = await this.buildHeaders(
|
|
2834
3025
|
fetchInit,
|
|
2835
|
-
|
|
3026
|
+
resolvedRoute?.pathConfig
|
|
2836
3027
|
);
|
|
2837
3028
|
const inputHeaders = new Headers(fetchInit.headers ?? {});
|
|
2838
3029
|
const mergedHeaders = new Headers();
|
|
@@ -2843,6 +3034,11 @@ var ZapierApiClient = class {
|
|
|
2843
3034
|
mergedHeaders.set(key, value);
|
|
2844
3035
|
});
|
|
2845
3036
|
this.applyTelemetryHeaders({ headers: mergedHeaders, callId });
|
|
3037
|
+
const outboundHeaders = applyRequestHeaderTransform({
|
|
3038
|
+
headers: mergedHeaders,
|
|
3039
|
+
resolvedRoute,
|
|
3040
|
+
debugLog: this.options.debugLog
|
|
3041
|
+
});
|
|
2846
3042
|
const {
|
|
2847
3043
|
authRequired: _authRequired,
|
|
2848
3044
|
requiredScopes: _requiredScopes,
|
|
@@ -2855,11 +3051,11 @@ var ZapierApiClient = class {
|
|
|
2855
3051
|
const request = {
|
|
2856
3052
|
...wireInit,
|
|
2857
3053
|
url,
|
|
2858
|
-
headers: Object.fromEntries(
|
|
3054
|
+
headers: Object.fromEntries(outboundHeaders)
|
|
2859
3055
|
};
|
|
2860
3056
|
const response = await this.options.sendHttpRequest(request);
|
|
2861
3057
|
if (response.status !== 429) {
|
|
2862
|
-
return response;
|
|
3058
|
+
return applyResponseHeaderTransform({ response, resolvedRoute });
|
|
2863
3059
|
}
|
|
2864
3060
|
throw new ZapierRateLimitError(
|
|
2865
3061
|
await this.readRateLimitErrorMessage(response),
|
|
@@ -2929,10 +3125,10 @@ var ZapierApiClient = class {
|
|
|
2929
3125
|
*/
|
|
2930
3126
|
this.rawFetch = async (path, init) => {
|
|
2931
3127
|
validateSdkPath(path);
|
|
2932
|
-
const { url,
|
|
3128
|
+
const { url, resolvedRoute } = this.buildUrl(path, init?.searchParams);
|
|
2933
3129
|
return this.withSemaphore(
|
|
2934
3130
|
{ url, method: init?.method ?? "GET", signal: init?.signal },
|
|
2935
|
-
() => this.rawFetchUrl(url, init,
|
|
3131
|
+
() => this.rawFetchUrl(url, init, resolvedRoute)
|
|
2936
3132
|
);
|
|
2937
3133
|
};
|
|
2938
3134
|
this.runApprovalFetchLoop = async ({
|
|
@@ -3342,22 +3538,12 @@ var ZapierApiClient = class {
|
|
|
3342
3538
|
debugLog: this.options.debugLog
|
|
3343
3539
|
});
|
|
3344
3540
|
}
|
|
3345
|
-
// Helper to build full URLs and return routing info
|
|
3346
3541
|
buildUrl(path, searchParams) {
|
|
3347
|
-
const
|
|
3348
|
-
url,
|
|
3349
|
-
pathConfig: config,
|
|
3350
|
-
canSendDeprecationMessaging
|
|
3351
|
-
} = this.applyPathConfiguration(path);
|
|
3352
|
-
if (searchParams) {
|
|
3353
|
-
Object.entries(searchParams).forEach(([key, value]) => {
|
|
3354
|
-
url.searchParams.set(key, value);
|
|
3355
|
-
});
|
|
3356
|
-
}
|
|
3542
|
+
const resolvedRoute = this.applyPathConfiguration(path);
|
|
3357
3543
|
return {
|
|
3358
|
-
url: url.
|
|
3359
|
-
|
|
3360
|
-
canSendDeprecationMessaging
|
|
3544
|
+
url: withSearchParams({ url: resolvedRoute.url, searchParams }),
|
|
3545
|
+
resolvedRoute,
|
|
3546
|
+
canSendDeprecationMessaging: resolvedRoute.canSendDeprecationMessaging
|
|
3361
3547
|
};
|
|
3362
3548
|
}
|
|
3363
3549
|
// Helper to build headers
|
|
@@ -1308,6 +1308,16 @@ function emitOnce(onEvent, event) {
|
|
|
1308
1308
|
var { logDeprecation, resetDeprecationWarnings } = createDeprecationLogger("zapier-sdk");
|
|
1309
1309
|
|
|
1310
1310
|
// src/utils/url-utils.ts
|
|
1311
|
+
function withSearchParams({
|
|
1312
|
+
url,
|
|
1313
|
+
searchParams
|
|
1314
|
+
}) {
|
|
1315
|
+
const result = new URL(url);
|
|
1316
|
+
for (const [key, value] of Object.entries(searchParams ?? {})) {
|
|
1317
|
+
result.searchParams.set(key, value);
|
|
1318
|
+
}
|
|
1319
|
+
return result.toString();
|
|
1320
|
+
}
|
|
1311
1321
|
function getZapierBaseUrl(baseUrl) {
|
|
1312
1322
|
if (!baseUrl) {
|
|
1313
1323
|
return void 0;
|
|
@@ -2152,6 +2162,88 @@ function parseDeprecationDate(value) {
|
|
|
2152
2162
|
if (!match) return void 0;
|
|
2153
2163
|
return Number(match[1]) * 1e3;
|
|
2154
2164
|
}
|
|
2165
|
+
var RELAY_ERROR_HEADER = "x-relay-error";
|
|
2166
|
+
var RELAY_TIMEOUT_HEADER = "x-relay-extended-timeout";
|
|
2167
|
+
var SDK_CORRELATION_HEADER = "zapier-correlation-id";
|
|
2168
|
+
var SDK_MAX_TIME_HEADER = "x-zapier-sdk-max-time";
|
|
2169
|
+
var RELAY_NATIVE_TIMEOUT_SECONDS = 30;
|
|
2170
|
+
var RELAY_TIMEOUT_TIERS = [
|
|
2171
|
+
{ seconds: 60, headerValue: "1m" },
|
|
2172
|
+
{ seconds: 180, headerValue: "3m" },
|
|
2173
|
+
{ seconds: 300, headerValue: "5m" },
|
|
2174
|
+
{ seconds: 600, headerValue: "10m" }
|
|
2175
|
+
];
|
|
2176
|
+
function transformRelayRequestHeaders({
|
|
2177
|
+
headers,
|
|
2178
|
+
debugLog
|
|
2179
|
+
}) {
|
|
2180
|
+
applyTimeoutTierPolicy({ headers, debugLog });
|
|
2181
|
+
applyCorrelationIdPolicy({ headers });
|
|
2182
|
+
return headers;
|
|
2183
|
+
}
|
|
2184
|
+
function applyCorrelationIdPolicy({ headers }) {
|
|
2185
|
+
const correlationId = headers.get(SDK_CORRELATION_HEADER);
|
|
2186
|
+
if (correlationId !== null && !isValidRelayCorrelationId(correlationId)) {
|
|
2187
|
+
headers.delete(SDK_CORRELATION_HEADER);
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
2190
|
+
function applyTimeoutTierPolicy({
|
|
2191
|
+
headers,
|
|
2192
|
+
debugLog
|
|
2193
|
+
}) {
|
|
2194
|
+
const sdkMaxTimeSeconds = headers.get(SDK_MAX_TIME_HEADER);
|
|
2195
|
+
headers.delete(SDK_MAX_TIME_HEADER);
|
|
2196
|
+
if (headers.has(RELAY_TIMEOUT_HEADER) || sdkMaxTimeSeconds === null) {
|
|
2197
|
+
return;
|
|
2198
|
+
}
|
|
2199
|
+
const seconds = parsePositiveInteger(sdkMaxTimeSeconds);
|
|
2200
|
+
if (seconds === void 0 || seconds <= RELAY_NATIVE_TIMEOUT_SECONDS) {
|
|
2201
|
+
return;
|
|
2202
|
+
}
|
|
2203
|
+
const match = RELAY_TIMEOUT_TIERS.find(
|
|
2204
|
+
(candidate) => candidate.seconds >= seconds
|
|
2205
|
+
);
|
|
2206
|
+
const tier = match ?? RELAY_TIMEOUT_TIERS[RELAY_TIMEOUT_TIERS.length - 1];
|
|
2207
|
+
if (!match) {
|
|
2208
|
+
debugLog?.(
|
|
2209
|
+
`Relay timeout of ${seconds}s exceeds the largest tier; capping to ${tier.headerValue}`
|
|
2210
|
+
);
|
|
2211
|
+
}
|
|
2212
|
+
headers.set(RELAY_TIMEOUT_HEADER, tier.headerValue);
|
|
2213
|
+
}
|
|
2214
|
+
function transformRelayResponseHeaders({
|
|
2215
|
+
headers
|
|
2216
|
+
}) {
|
|
2217
|
+
const relayError = headers.get(RELAY_ERROR_HEADER);
|
|
2218
|
+
if (!relayError?.startsWith("Authentication Template Failure")) {
|
|
2219
|
+
return headers;
|
|
2220
|
+
}
|
|
2221
|
+
const templateMatch = relayError.match(
|
|
2222
|
+
/Unable to find template for ([^@]+)@/
|
|
2223
|
+
);
|
|
2224
|
+
if (!templateMatch?.[1]) {
|
|
2225
|
+
return headers;
|
|
2226
|
+
}
|
|
2227
|
+
const appName = templateMatch[1].replace(/CLIAPI$/, "").replace(/([a-z])([A-Z])/g, "$1 $2").trim();
|
|
2228
|
+
if (!appName) {
|
|
2229
|
+
return headers;
|
|
2230
|
+
}
|
|
2231
|
+
headers.set(
|
|
2232
|
+
RELAY_ERROR_HEADER,
|
|
2233
|
+
`${appName} does not support direct HTTP requests. Use zapier.apps.{appKey} or zapier.runAction() to use Actions built for this app.`
|
|
2234
|
+
);
|
|
2235
|
+
return headers;
|
|
2236
|
+
}
|
|
2237
|
+
var RelayCorrelationIdSchema = z.uuid();
|
|
2238
|
+
function isValidRelayCorrelationId(value) {
|
|
2239
|
+
return RelayCorrelationIdSchema.safeParse(value).success;
|
|
2240
|
+
}
|
|
2241
|
+
function parsePositiveInteger(value) {
|
|
2242
|
+
if (!/^[1-9]\d*$/.test(value)) {
|
|
2243
|
+
return void 0;
|
|
2244
|
+
}
|
|
2245
|
+
return Number(value);
|
|
2246
|
+
}
|
|
2155
2247
|
|
|
2156
2248
|
// src/api/routing/config.ts
|
|
2157
2249
|
var pathConfig = {
|
|
@@ -2159,7 +2251,11 @@ var pathConfig = {
|
|
|
2159
2251
|
"/relay": {
|
|
2160
2252
|
authHeader: "X-Relay-Authorization",
|
|
2161
2253
|
pathPrefix: "/api/v0/sdk/relay",
|
|
2162
|
-
omitDeprecationMessaging: true
|
|
2254
|
+
omitDeprecationMessaging: true,
|
|
2255
|
+
override: {
|
|
2256
|
+
transformRequestHeaders: transformRelayRequestHeaders,
|
|
2257
|
+
transformResponseHeaders: transformRelayResponseHeaders
|
|
2258
|
+
}
|
|
2163
2259
|
},
|
|
2164
2260
|
// The concrete gateway form of the relay route. Callers that pass the
|
|
2165
2261
|
// already-prefixed path reach the same third-party upstreams, so it must
|
|
@@ -2236,6 +2332,15 @@ var pathConfig = {
|
|
|
2236
2332
|
"/agentic-management": {
|
|
2237
2333
|
authHeader: "Authorization",
|
|
2238
2334
|
subdomain: "api"
|
|
2335
|
+
},
|
|
2336
|
+
// e.g. /vfs/v1/files -> https://api.zapier.com/vfs/v1/files
|
|
2337
|
+
// The VFS API is registered on the Public API Gateway and has no sdkapi
|
|
2338
|
+
// proxy route, so it goes straight to the gateway. Its governance metadata
|
|
2339
|
+
// rewrites /vfs/v1/... to the backend's /api/v1/fs/..., which is why no
|
|
2340
|
+
// pathPrefix is applied here.
|
|
2341
|
+
"/vfs": {
|
|
2342
|
+
authHeader: "Authorization",
|
|
2343
|
+
subdomain: "api"
|
|
2239
2344
|
}
|
|
2240
2345
|
};
|
|
2241
2346
|
|
|
@@ -2434,10 +2539,13 @@ function resolveOverrideRoute({
|
|
|
2434
2539
|
}) {
|
|
2435
2540
|
const { matchedPrefix, routeConfig, override } = overrideMatch;
|
|
2436
2541
|
const directPath = deriveDirectPath({ path, matchedPrefix, routeConfig });
|
|
2542
|
+
const overrideConfig = routeConfig.override?.enabled === false ? void 0 : routeConfig.override;
|
|
2437
2543
|
return {
|
|
2438
2544
|
url: buildRouteOverrideUrl({ origin: override.origin, path: directPath }),
|
|
2439
2545
|
pathConfig: routeConfig,
|
|
2440
|
-
canSendDeprecationMessaging: false
|
|
2546
|
+
canSendDeprecationMessaging: false,
|
|
2547
|
+
...overrideConfig?.transformRequestHeaders ? { transformRequestHeaders: overrideConfig.transformRequestHeaders } : {},
|
|
2548
|
+
...overrideConfig?.transformResponseHeaders ? { transformResponseHeaders: overrideConfig.transformResponseHeaders } : {}
|
|
2441
2549
|
};
|
|
2442
2550
|
}
|
|
2443
2551
|
function deriveDirectPath({
|
|
@@ -2617,6 +2725,89 @@ function isRouteOverrideEnabled({
|
|
|
2617
2725
|
return routeConfig.override?.enabled !== false;
|
|
2618
2726
|
}
|
|
2619
2727
|
|
|
2728
|
+
// src/api/routing/headers/request.ts
|
|
2729
|
+
function applyRequestHeaderTransform({
|
|
2730
|
+
headers,
|
|
2731
|
+
resolvedRoute,
|
|
2732
|
+
debugLog
|
|
2733
|
+
}) {
|
|
2734
|
+
return resolvedRoute?.transformRequestHeaders?.({ headers, debugLog }) ?? headers;
|
|
2735
|
+
}
|
|
2736
|
+
|
|
2737
|
+
// src/api/routing/headers/response.ts
|
|
2738
|
+
var NULL_BODY_RESPONSE_STATUSES = /* @__PURE__ */ new Set([204, 205, 304]);
|
|
2739
|
+
function applyResponseHeaderTransform({
|
|
2740
|
+
response,
|
|
2741
|
+
resolvedRoute
|
|
2742
|
+
}) {
|
|
2743
|
+
const transformHeaders = resolvedRoute?.transformResponseHeaders;
|
|
2744
|
+
if (!transformHeaders) {
|
|
2745
|
+
return response;
|
|
2746
|
+
}
|
|
2747
|
+
if (!Number.isInteger(response.status) || response.status < 200 || response.status > 599 || response.bodyUsed || response.body?.locked) {
|
|
2748
|
+
return response;
|
|
2749
|
+
}
|
|
2750
|
+
const originalHeaders = response.headers;
|
|
2751
|
+
if (!originalHeaders) {
|
|
2752
|
+
return response;
|
|
2753
|
+
}
|
|
2754
|
+
const transformedHeaders = transformHeaders({
|
|
2755
|
+
headers: new Headers(originalHeaders)
|
|
2756
|
+
});
|
|
2757
|
+
if (areHeadersEqual({ first: originalHeaders, second: transformedHeaders })) {
|
|
2758
|
+
return response;
|
|
2759
|
+
}
|
|
2760
|
+
const transformedResponse = new Response(
|
|
2761
|
+
NULL_BODY_RESPONSE_STATUSES.has(response.status) ? null : response.body,
|
|
2762
|
+
{
|
|
2763
|
+
status: response.status,
|
|
2764
|
+
statusText: response.statusText,
|
|
2765
|
+
headers: transformedHeaders
|
|
2766
|
+
}
|
|
2767
|
+
);
|
|
2768
|
+
return preserveResponseMetadata({
|
|
2769
|
+
response: transformedResponse,
|
|
2770
|
+
source: response
|
|
2771
|
+
});
|
|
2772
|
+
}
|
|
2773
|
+
function preserveResponseMetadata({
|
|
2774
|
+
response,
|
|
2775
|
+
source
|
|
2776
|
+
}) {
|
|
2777
|
+
const nativeClone = response.clone;
|
|
2778
|
+
Object.defineProperties(response, {
|
|
2779
|
+
clone: {
|
|
2780
|
+
configurable: true,
|
|
2781
|
+
writable: true,
|
|
2782
|
+
value: function clone() {
|
|
2783
|
+
const clonedResponse = nativeClone.call(this);
|
|
2784
|
+
return this === response ? preserveResponseMetadata({ response: clonedResponse, source }) : clonedResponse;
|
|
2785
|
+
}
|
|
2786
|
+
},
|
|
2787
|
+
...sourceMetadataDescriptors(source)
|
|
2788
|
+
});
|
|
2789
|
+
return response;
|
|
2790
|
+
}
|
|
2791
|
+
function sourceMetadataDescriptors(source) {
|
|
2792
|
+
const descriptors = {};
|
|
2793
|
+
for (const key of ["redirected", "type", "url"]) {
|
|
2794
|
+
if (source[key] !== void 0) {
|
|
2795
|
+
descriptors[key] = { configurable: true, value: source[key] };
|
|
2796
|
+
}
|
|
2797
|
+
}
|
|
2798
|
+
return descriptors;
|
|
2799
|
+
}
|
|
2800
|
+
function areHeadersEqual({
|
|
2801
|
+
first,
|
|
2802
|
+
second
|
|
2803
|
+
}) {
|
|
2804
|
+
const firstEntries = [...first.entries()];
|
|
2805
|
+
const secondEntries = [...second.entries()];
|
|
2806
|
+
return firstEntries.length === secondEntries.length && firstEntries.every(
|
|
2807
|
+
([key, value], index) => secondEntries[index]?.[0] === key && secondEntries[index]?.[1] === value
|
|
2808
|
+
);
|
|
2809
|
+
}
|
|
2810
|
+
|
|
2620
2811
|
// src/api/routing/index.ts
|
|
2621
2812
|
var routingConfig = createRoutingConfig({ pathConfig });
|
|
2622
2813
|
function parseRoutingOptions({
|
|
@@ -2684,7 +2875,7 @@ function logRouteOverride({
|
|
|
2684
2875
|
}
|
|
2685
2876
|
|
|
2686
2877
|
// src/sdk-version.ts
|
|
2687
|
-
var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.
|
|
2878
|
+
var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.108.0" : void 0) || "unknown";
|
|
2688
2879
|
|
|
2689
2880
|
// src/utils/open-url.ts
|
|
2690
2881
|
var nodePrefix = "node:";
|
|
@@ -2824,14 +3015,14 @@ var ZapierApiClient = class {
|
|
|
2824
3015
|
* auth/retry pipeline instead of reaching for `this.options.fetch`
|
|
2825
3016
|
* directly and drifting.
|
|
2826
3017
|
*/
|
|
2827
|
-
this.rawFetchUrl = async (url, init,
|
|
3018
|
+
this.rawFetchUrl = async (url, init, resolvedRoute) => {
|
|
2828
3019
|
const { [CORRELATION_CALL_ID]: callId, ...fetchInit } = init ?? {};
|
|
2829
3020
|
if (fetchInit.body && (isPlainObject(fetchInit.body) || Array.isArray(fetchInit.body))) {
|
|
2830
3021
|
fetchInit.body = JSON.stringify(fetchInit.body);
|
|
2831
3022
|
}
|
|
2832
3023
|
const builtHeaders = await this.buildHeaders(
|
|
2833
3024
|
fetchInit,
|
|
2834
|
-
|
|
3025
|
+
resolvedRoute?.pathConfig
|
|
2835
3026
|
);
|
|
2836
3027
|
const inputHeaders = new Headers(fetchInit.headers ?? {});
|
|
2837
3028
|
const mergedHeaders = new Headers();
|
|
@@ -2842,6 +3033,11 @@ var ZapierApiClient = class {
|
|
|
2842
3033
|
mergedHeaders.set(key, value);
|
|
2843
3034
|
});
|
|
2844
3035
|
this.applyTelemetryHeaders({ headers: mergedHeaders, callId });
|
|
3036
|
+
const outboundHeaders = applyRequestHeaderTransform({
|
|
3037
|
+
headers: mergedHeaders,
|
|
3038
|
+
resolvedRoute,
|
|
3039
|
+
debugLog: this.options.debugLog
|
|
3040
|
+
});
|
|
2845
3041
|
const {
|
|
2846
3042
|
authRequired: _authRequired,
|
|
2847
3043
|
requiredScopes: _requiredScopes,
|
|
@@ -2854,11 +3050,11 @@ var ZapierApiClient = class {
|
|
|
2854
3050
|
const request = {
|
|
2855
3051
|
...wireInit,
|
|
2856
3052
|
url,
|
|
2857
|
-
headers: Object.fromEntries(
|
|
3053
|
+
headers: Object.fromEntries(outboundHeaders)
|
|
2858
3054
|
};
|
|
2859
3055
|
const response = await this.options.sendHttpRequest(request);
|
|
2860
3056
|
if (response.status !== 429) {
|
|
2861
|
-
return response;
|
|
3057
|
+
return applyResponseHeaderTransform({ response, resolvedRoute });
|
|
2862
3058
|
}
|
|
2863
3059
|
throw new ZapierRateLimitError(
|
|
2864
3060
|
await this.readRateLimitErrorMessage(response),
|
|
@@ -2928,10 +3124,10 @@ var ZapierApiClient = class {
|
|
|
2928
3124
|
*/
|
|
2929
3125
|
this.rawFetch = async (path, init) => {
|
|
2930
3126
|
validateSdkPath(path);
|
|
2931
|
-
const { url,
|
|
3127
|
+
const { url, resolvedRoute } = this.buildUrl(path, init?.searchParams);
|
|
2932
3128
|
return this.withSemaphore(
|
|
2933
3129
|
{ url, method: init?.method ?? "GET", signal: init?.signal },
|
|
2934
|
-
() => this.rawFetchUrl(url, init,
|
|
3130
|
+
() => this.rawFetchUrl(url, init, resolvedRoute)
|
|
2935
3131
|
);
|
|
2936
3132
|
};
|
|
2937
3133
|
this.runApprovalFetchLoop = async ({
|
|
@@ -3341,22 +3537,12 @@ var ZapierApiClient = class {
|
|
|
3341
3537
|
debugLog: this.options.debugLog
|
|
3342
3538
|
});
|
|
3343
3539
|
}
|
|
3344
|
-
// Helper to build full URLs and return routing info
|
|
3345
3540
|
buildUrl(path, searchParams) {
|
|
3346
|
-
const
|
|
3347
|
-
url,
|
|
3348
|
-
pathConfig: config,
|
|
3349
|
-
canSendDeprecationMessaging
|
|
3350
|
-
} = this.applyPathConfiguration(path);
|
|
3351
|
-
if (searchParams) {
|
|
3352
|
-
Object.entries(searchParams).forEach(([key, value]) => {
|
|
3353
|
-
url.searchParams.set(key, value);
|
|
3354
|
-
});
|
|
3355
|
-
}
|
|
3541
|
+
const resolvedRoute = this.applyPathConfiguration(path);
|
|
3356
3542
|
return {
|
|
3357
|
-
url: url.
|
|
3358
|
-
|
|
3359
|
-
canSendDeprecationMessaging
|
|
3543
|
+
url: withSearchParams({ url: resolvedRoute.url, searchParams }),
|
|
3544
|
+
resolvedRoute,
|
|
3545
|
+
canSendDeprecationMessaging: resolvedRoute.canSendDeprecationMessaging
|
|
3360
3546
|
};
|
|
3361
3547
|
}
|
|
3362
3548
|
// Helper to build headers
|