@zapier/zapier-sdk 0.102.4 → 0.103.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 +6 -0
- package/dist/{chunk-6TIBB6TI.mjs → chunk-JJHKZ4XK.mjs} +536 -129
- package/dist/{chunk-WVRZG6I6.cjs → chunk-RHL6GGME.cjs} +536 -129
- package/dist/experimental.cjs +355 -355
- package/dist/experimental.d.mts +3 -2
- package/dist/experimental.d.ts +3 -2
- package/dist/experimental.mjs +2 -2
- package/dist/{index-CfJjkJU-.d.mts → index-DT4MnaD0.d.mts} +8 -0
- package/dist/{index-CfJjkJU-.d.ts → index-DT4MnaD0.d.ts} +8 -0
- package/dist/index.cjs +277 -277
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
|
@@ -2031,8 +2031,528 @@ function parseDeprecationDate(value) {
|
|
|
2031
2031
|
return Number(match[1]) * 1e3;
|
|
2032
2032
|
}
|
|
2033
2033
|
|
|
2034
|
+
// src/api/routing/config.ts
|
|
2035
|
+
var pathConfig = {
|
|
2036
|
+
// e.g. /relay -> https://sdkapi.zapier.com/api/v0/sdk/relay/...
|
|
2037
|
+
"/relay": {
|
|
2038
|
+
authHeader: "X-Relay-Authorization",
|
|
2039
|
+
pathPrefix: "/api/v0/sdk/relay",
|
|
2040
|
+
omitDeprecationMessaging: true
|
|
2041
|
+
},
|
|
2042
|
+
// The concrete gateway form of the relay route. Callers that pass the
|
|
2043
|
+
// already-prefixed path reach the same third-party upstreams, so it must
|
|
2044
|
+
// classify as relay too; without this entry it would match nothing and
|
|
2045
|
+
// sniff deprecation headers off a relay response.
|
|
2046
|
+
"/api/v0/sdk/relay": {
|
|
2047
|
+
override: { enabled: false },
|
|
2048
|
+
omitDeprecationMessaging: true
|
|
2049
|
+
},
|
|
2050
|
+
// Concrete sdkapi routes that do not live behind /api/v0/sdk/<service>.
|
|
2051
|
+
"/api/v0": {},
|
|
2052
|
+
// e.g. /zapier -> https://sdkapi.zapier.com/api/v0/sdk/zapier/...
|
|
2053
|
+
"/zapier": {
|
|
2054
|
+
authHeader: "Authorization",
|
|
2055
|
+
pathPrefix: "/api/v0/sdk/zapier"
|
|
2056
|
+
},
|
|
2057
|
+
// e.g. /tables -> https://sdkapi.zapier.com/api/v0/sdk/tables/...
|
|
2058
|
+
"/tables": {
|
|
2059
|
+
authHeader: "Authorization",
|
|
2060
|
+
pathPrefix: "/api/v0/sdk/tables"
|
|
2061
|
+
},
|
|
2062
|
+
// e.g. /trigger-inbox -> https://sdkapi.zapier.com/api/v0/sdk/trigger-inbox/...
|
|
2063
|
+
"/trigger-inbox": {
|
|
2064
|
+
authHeader: "Authorization",
|
|
2065
|
+
pathPrefix: "/api/v0/sdk/trigger-inbox"
|
|
2066
|
+
},
|
|
2067
|
+
// e.g. /sdkdurableapi -> https://sdkapi.zapier.com/api/v0/sdk/sdkdurableapi/...
|
|
2068
|
+
// sdkapi proxies to the sdkdurableapi backend.
|
|
2069
|
+
"/sdkdurableapi": {
|
|
2070
|
+
authHeader: "Authorization",
|
|
2071
|
+
pathPrefix: "/api/v0/sdk/sdkdurableapi"
|
|
2072
|
+
},
|
|
2073
|
+
// e.g. /durableworkflowzaps -> https://sdkapi.zapier.com/api/v0/sdk/durableworkflowzaps/...
|
|
2074
|
+
// sdkapi proxies to the durableworkflowzaps backend.
|
|
2075
|
+
"/durableworkflowzaps": {
|
|
2076
|
+
authHeader: "Authorization",
|
|
2077
|
+
pathPrefix: "/api/v0/sdk/durableworkflowzaps"
|
|
2078
|
+
},
|
|
2079
|
+
// e.g. /code-substrate-runner -> https://sdkapi.zapier.com/api/v0/sdk/code-substrate-runner/...
|
|
2080
|
+
// sdkapi proxies to the code-substrate-runner backend.
|
|
2081
|
+
"/code-substrate-runner": {
|
|
2082
|
+
authHeader: "Authorization",
|
|
2083
|
+
pathPrefix: "/api/v0/sdk/code-substrate-runner"
|
|
2084
|
+
},
|
|
2085
|
+
// e.g. /code-substrate-workflows -> https://sdkapi.zapier.com/api/v0/sdk/code-substrate-workflows/...
|
|
2086
|
+
// sdkapi proxies to the code-substrate-workflows backend.
|
|
2087
|
+
"/code-substrate-workflows": {
|
|
2088
|
+
authHeader: "Authorization",
|
|
2089
|
+
pathPrefix: "/api/v0/sdk/code-substrate-workflows"
|
|
2090
|
+
},
|
|
2091
|
+
// e.g. /code-substrate-analyzer/validations ->
|
|
2092
|
+
// https://api.zapier.com/code-substrate-analyzer/v0/validations
|
|
2093
|
+
"/code-substrate-analyzer": {
|
|
2094
|
+
authHeader: "Authorization",
|
|
2095
|
+
pathPrefix: "/code-substrate-analyzer/v0",
|
|
2096
|
+
subdomain: "api",
|
|
2097
|
+
override: { pathPrefixMode: "preserve" }
|
|
2098
|
+
},
|
|
2099
|
+
// e.g. /forms/v0/forms -> https://api.zapier.com/forms/v0/forms
|
|
2100
|
+
// The Forms API is registered on the Public API Gateway and has no sdkapi
|
|
2101
|
+
// proxy route, so it goes straight to the gateway. Its governance metadata
|
|
2102
|
+
// rewrites /forms/v0/... to the backend's /api/forms/v0/..., which is why no
|
|
2103
|
+
// pathPrefix is applied here.
|
|
2104
|
+
"/forms": {
|
|
2105
|
+
authHeader: "Authorization",
|
|
2106
|
+
subdomain: "api"
|
|
2107
|
+
}
|
|
2108
|
+
};
|
|
2109
|
+
|
|
2110
|
+
// src/api/routing/default.ts
|
|
2111
|
+
function resolveDefaultRoute({
|
|
2112
|
+
path,
|
|
2113
|
+
baseUrl
|
|
2114
|
+
}) {
|
|
2115
|
+
const matchingPathEntries = findPathConfigEntries({ path });
|
|
2116
|
+
const routingMatch = matchingPathEntries[0];
|
|
2117
|
+
let finalPath = path;
|
|
2118
|
+
if (routingMatch?.config.pathPrefix) {
|
|
2119
|
+
const pathWithoutPrefix = path.slice(routingMatch.configPath.length) || "/";
|
|
2120
|
+
finalPath = `${routingMatch.config.pathPrefix}${pathWithoutPrefix}`;
|
|
2121
|
+
}
|
|
2122
|
+
const zapierBaseUrl = getZapierBaseUrl(baseUrl);
|
|
2123
|
+
if (zapierBaseUrl === baseUrl.replace(/\/$/, "")) {
|
|
2124
|
+
const originalBaseUrl = new URL(baseUrl);
|
|
2125
|
+
const subdomain = routingMatch?.config.subdomain ?? "sdkapi";
|
|
2126
|
+
const finalBaseUrl = `https://${subdomain}.${originalBaseUrl.hostname}`;
|
|
2127
|
+
return buildRouteResult({
|
|
2128
|
+
url: new URL(finalPath, finalBaseUrl),
|
|
2129
|
+
matchingPathEntries,
|
|
2130
|
+
routingMatch
|
|
2131
|
+
});
|
|
2132
|
+
}
|
|
2133
|
+
const parsedBaseUrl = new URL(baseUrl);
|
|
2134
|
+
const basePath = parsedBaseUrl.pathname.replace(/\/$/, "");
|
|
2135
|
+
return buildRouteResult({
|
|
2136
|
+
url: new URL(basePath + finalPath, parsedBaseUrl.origin),
|
|
2137
|
+
matchingPathEntries,
|
|
2138
|
+
routingMatch
|
|
2139
|
+
});
|
|
2140
|
+
}
|
|
2141
|
+
function buildRouteResult({
|
|
2142
|
+
url,
|
|
2143
|
+
matchingPathEntries,
|
|
2144
|
+
routingMatch
|
|
2145
|
+
}) {
|
|
2146
|
+
const resolvedPathEntries = findPathConfigEntries({
|
|
2147
|
+
path: url.pathname,
|
|
2148
|
+
matchResolvedGatewayPath: true
|
|
2149
|
+
});
|
|
2150
|
+
const deprecationPathMatches = [
|
|
2151
|
+
...matchingPathEntries,
|
|
2152
|
+
...resolvedPathEntries
|
|
2153
|
+
];
|
|
2154
|
+
const canSendDeprecationMessaging = deprecationPathMatches.length > 0 && deprecationPathMatches.every(
|
|
2155
|
+
({ config }) => config.omitDeprecationMessaging !== true
|
|
2156
|
+
);
|
|
2157
|
+
return {
|
|
2158
|
+
url,
|
|
2159
|
+
pathConfig: routingMatch?.config,
|
|
2160
|
+
canSendDeprecationMessaging
|
|
2161
|
+
};
|
|
2162
|
+
}
|
|
2163
|
+
function findPathConfigEntries({
|
|
2164
|
+
path,
|
|
2165
|
+
matchResolvedGatewayPath = false
|
|
2166
|
+
}) {
|
|
2167
|
+
const pathSegments = path.split("/").filter(Boolean);
|
|
2168
|
+
return Object.entries(pathConfig).filter(([configPath, config]) => {
|
|
2169
|
+
if (!matchResolvedGatewayPath) {
|
|
2170
|
+
return path === configPath || path.startsWith(`${configPath}/`);
|
|
2171
|
+
}
|
|
2172
|
+
const prefixSegments = (config.pathPrefix ?? configPath).split("/").filter(Boolean);
|
|
2173
|
+
return pathSegments.some(
|
|
2174
|
+
(_, startIndex) => prefixSegments.every(
|
|
2175
|
+
(segment, offset) => pathSegments[startIndex + offset] === segment
|
|
2176
|
+
)
|
|
2177
|
+
);
|
|
2178
|
+
}).map(([configPath, config]) => ({ configPath, config }));
|
|
2179
|
+
}
|
|
2180
|
+
|
|
2181
|
+
// src/api/routing/overrides.ts
|
|
2182
|
+
var ROUTE_ORIGIN_ENV_PREFIX = "ZAPIER_ROUTE_ORIGIN_";
|
|
2183
|
+
function createRoutingConfig({
|
|
2184
|
+
pathConfig: pathConfig2
|
|
2185
|
+
}) {
|
|
2186
|
+
const routeByEnvName = new Map(
|
|
2187
|
+
Object.entries(pathConfig2).filter(([, routeConfig]) => isRouteOverrideEnabled({ routeConfig })).map(([route]) => [encodeRouteOriginEnvName({ route }), route])
|
|
2188
|
+
);
|
|
2189
|
+
return { pathConfig: pathConfig2, routeByEnvName };
|
|
2190
|
+
}
|
|
2191
|
+
function encodeRouteOriginEnvName({ route }) {
|
|
2192
|
+
return `${ROUTE_ORIGIN_ENV_PREFIX}${route.slice(1).split("/").map((segment) => segment.replace(/-/g, "_").toUpperCase()).join("__")}`;
|
|
2193
|
+
}
|
|
2194
|
+
function createRouteOverrideEntry({
|
|
2195
|
+
route,
|
|
2196
|
+
source,
|
|
2197
|
+
sourceReference,
|
|
2198
|
+
origin
|
|
2199
|
+
}) {
|
|
2200
|
+
return {
|
|
2201
|
+
route,
|
|
2202
|
+
source,
|
|
2203
|
+
sourceReference,
|
|
2204
|
+
origin: parseRouteOverrideOrigin({
|
|
2205
|
+
origin,
|
|
2206
|
+
sourceLabel: describeRouteOverrideSource({ source, sourceReference })
|
|
2207
|
+
})
|
|
2208
|
+
};
|
|
2209
|
+
}
|
|
2210
|
+
function describeRouteOverrideSource({
|
|
2211
|
+
source,
|
|
2212
|
+
sourceReference
|
|
2213
|
+
}) {
|
|
2214
|
+
return source === "environment-variable" ? `environment variable ${sourceReference}` : `routeOverrides[${JSON.stringify(sourceReference)}]`;
|
|
2215
|
+
}
|
|
2216
|
+
function readOptionRouteOverrideEntries({
|
|
2217
|
+
routeOverrides,
|
|
2218
|
+
routingConfig: routingConfig2
|
|
2219
|
+
}) {
|
|
2220
|
+
const entries = [];
|
|
2221
|
+
if (!routeOverrides) {
|
|
2222
|
+
return entries;
|
|
2223
|
+
}
|
|
2224
|
+
for (const [route, origin] of Object.entries(routeOverrides)) {
|
|
2225
|
+
assertSupportedRouteOverride({ route, routingConfig: routingConfig2 });
|
|
2226
|
+
entries.push(
|
|
2227
|
+
createRouteOverrideEntry({
|
|
2228
|
+
route,
|
|
2229
|
+
source: "sdk-option",
|
|
2230
|
+
sourceReference: route,
|
|
2231
|
+
origin
|
|
2232
|
+
})
|
|
2233
|
+
);
|
|
2234
|
+
}
|
|
2235
|
+
return entries;
|
|
2236
|
+
}
|
|
2237
|
+
function buildRouteOverrideMap({
|
|
2238
|
+
environmentEntries,
|
|
2239
|
+
optionEntries
|
|
2240
|
+
}) {
|
|
2241
|
+
const routeOverrideMap = /* @__PURE__ */ new Map();
|
|
2242
|
+
for (const entry of environmentEntries) {
|
|
2243
|
+
routeOverrideMap.set(entry.route, entry);
|
|
2244
|
+
}
|
|
2245
|
+
for (const entry of optionEntries) {
|
|
2246
|
+
routeOverrideMap.set(entry.route, entry);
|
|
2247
|
+
}
|
|
2248
|
+
return routeOverrideMap;
|
|
2249
|
+
}
|
|
2250
|
+
function collectRouteOverrideSources({
|
|
2251
|
+
routingOptions,
|
|
2252
|
+
environment,
|
|
2253
|
+
routingConfig: routingConfig2
|
|
2254
|
+
}) {
|
|
2255
|
+
try {
|
|
2256
|
+
const optionEntries = routingOptions?.routeOverrideEntries ?? [];
|
|
2257
|
+
const environmentEntries = readEnvironmentRouteOverrideEntries({
|
|
2258
|
+
environment,
|
|
2259
|
+
routingConfig: routingConfig2
|
|
2260
|
+
});
|
|
2261
|
+
if (optionEntries.length === 0 && environmentEntries.length === 0) {
|
|
2262
|
+
return void 0;
|
|
2263
|
+
}
|
|
2264
|
+
return { optionEntries, environmentEntries };
|
|
2265
|
+
} catch (error) {
|
|
2266
|
+
if (isZapierError(error) && error.code === "ZAPIER_CONFIGURATION_ERROR") {
|
|
2267
|
+
throw error;
|
|
2268
|
+
}
|
|
2269
|
+
return void 0;
|
|
2270
|
+
}
|
|
2271
|
+
}
|
|
2272
|
+
function findRouteOverrideMatch({
|
|
2273
|
+
path,
|
|
2274
|
+
routeOverrideMap,
|
|
2275
|
+
routingConfig: routingConfig2
|
|
2276
|
+
}) {
|
|
2277
|
+
let bestMatch;
|
|
2278
|
+
const { pathname } = splitPathReference({ path });
|
|
2279
|
+
for (const override of routeOverrideMap.values()) {
|
|
2280
|
+
const { route } = override;
|
|
2281
|
+
for (const candidate of getRouteCandidates({
|
|
2282
|
+
route,
|
|
2283
|
+
override,
|
|
2284
|
+
routingConfig: routingConfig2
|
|
2285
|
+
})) {
|
|
2286
|
+
if (!pathnameMatchesPrefix({
|
|
2287
|
+
pathname,
|
|
2288
|
+
prefix: candidate.matchedPrefix
|
|
2289
|
+
})) {
|
|
2290
|
+
continue;
|
|
2291
|
+
}
|
|
2292
|
+
if (!bestMatch || compareRouteOverrideMatches(candidate, bestMatch) < 0) {
|
|
2293
|
+
bestMatch = candidate;
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
}
|
|
2297
|
+
return bestMatch;
|
|
2298
|
+
}
|
|
2299
|
+
function resolveOverrideRoute({
|
|
2300
|
+
overrideMatch,
|
|
2301
|
+
path
|
|
2302
|
+
}) {
|
|
2303
|
+
const { matchedPrefix, routeConfig, override } = overrideMatch;
|
|
2304
|
+
const directPath = deriveDirectPath({ path, matchedPrefix, routeConfig });
|
|
2305
|
+
return {
|
|
2306
|
+
url: buildRouteOverrideUrl({ origin: override.origin, path: directPath }),
|
|
2307
|
+
pathConfig: routeConfig,
|
|
2308
|
+
canSendDeprecationMessaging: false
|
|
2309
|
+
};
|
|
2310
|
+
}
|
|
2311
|
+
function deriveDirectPath({
|
|
2312
|
+
path,
|
|
2313
|
+
matchedPrefix,
|
|
2314
|
+
routeConfig
|
|
2315
|
+
}) {
|
|
2316
|
+
const { pathPrefix } = routeConfig;
|
|
2317
|
+
if (!pathPrefix) {
|
|
2318
|
+
return path;
|
|
2319
|
+
}
|
|
2320
|
+
const remainingPath = path.slice(matchedPrefix.length) || "/";
|
|
2321
|
+
const override = routeConfig.override;
|
|
2322
|
+
const pathPrefixMode = override?.enabled === false ? "strip" : override?.pathPrefixMode ?? "strip";
|
|
2323
|
+
return pathPrefixMode === "preserve" ? `${pathPrefix}${remainingPath}` : remainingPath;
|
|
2324
|
+
}
|
|
2325
|
+
function readEnvironmentRouteOverrideEntries({
|
|
2326
|
+
environment,
|
|
2327
|
+
routingConfig: routingConfig2
|
|
2328
|
+
}) {
|
|
2329
|
+
const entries = [];
|
|
2330
|
+
if (!environment) {
|
|
2331
|
+
return entries;
|
|
2332
|
+
}
|
|
2333
|
+
for (const [envName, route] of routingConfig2.routeByEnvName) {
|
|
2334
|
+
let value;
|
|
2335
|
+
try {
|
|
2336
|
+
if (!Object.prototype.hasOwnProperty.call(environment, envName)) {
|
|
2337
|
+
continue;
|
|
2338
|
+
}
|
|
2339
|
+
value = environment[envName];
|
|
2340
|
+
} catch {
|
|
2341
|
+
continue;
|
|
2342
|
+
}
|
|
2343
|
+
if (isUnsetEnvironmentValue(value)) {
|
|
2344
|
+
continue;
|
|
2345
|
+
}
|
|
2346
|
+
entries.push(
|
|
2347
|
+
createRouteOverrideEntry({
|
|
2348
|
+
route,
|
|
2349
|
+
source: "environment-variable",
|
|
2350
|
+
sourceReference: envName,
|
|
2351
|
+
origin: value
|
|
2352
|
+
})
|
|
2353
|
+
);
|
|
2354
|
+
}
|
|
2355
|
+
return entries;
|
|
2356
|
+
}
|
|
2357
|
+
function isUnsetEnvironmentValue(value) {
|
|
2358
|
+
if (value === void 0 || value === null) {
|
|
2359
|
+
return true;
|
|
2360
|
+
}
|
|
2361
|
+
return typeof value === "string" && value.trim() === "";
|
|
2362
|
+
}
|
|
2363
|
+
function assertSupportedRouteOverride({
|
|
2364
|
+
route,
|
|
2365
|
+
routingConfig: routingConfig2
|
|
2366
|
+
}) {
|
|
2367
|
+
if (!Object.prototype.hasOwnProperty.call(routingConfig2.pathConfig, route)) {
|
|
2368
|
+
throw new ZapierConfigurationError(
|
|
2369
|
+
`Route override is not supported for ${route}`,
|
|
2370
|
+
{ configType: "routeOverrides" }
|
|
2371
|
+
);
|
|
2372
|
+
}
|
|
2373
|
+
const routeConfig = routingConfig2.pathConfig[route];
|
|
2374
|
+
if (!isRouteOverrideEnabled({ routeConfig })) {
|
|
2375
|
+
throw new ZapierConfigurationError(
|
|
2376
|
+
`Route override is disabled for ${route}`,
|
|
2377
|
+
{ configType: "routeOverrides" }
|
|
2378
|
+
);
|
|
2379
|
+
}
|
|
2380
|
+
}
|
|
2381
|
+
function parseRouteOverrideOrigin({
|
|
2382
|
+
origin,
|
|
2383
|
+
sourceLabel
|
|
2384
|
+
}) {
|
|
2385
|
+
if (typeof origin !== "string") {
|
|
2386
|
+
throw new ZapierConfigurationError(
|
|
2387
|
+
`Invalid route override origin for ${sourceLabel}`,
|
|
2388
|
+
{ configType: "routeOverrides" }
|
|
2389
|
+
);
|
|
2390
|
+
}
|
|
2391
|
+
let url;
|
|
2392
|
+
try {
|
|
2393
|
+
url = new URL(origin);
|
|
2394
|
+
} catch {
|
|
2395
|
+
throw new ZapierConfigurationError(
|
|
2396
|
+
`Invalid route override origin for ${sourceLabel}`,
|
|
2397
|
+
{ configType: "routeOverrides" }
|
|
2398
|
+
);
|
|
2399
|
+
}
|
|
2400
|
+
const includesOnlyOrigin = url.username === "" && url.password === "" && url.pathname === "/" && url.search === "" && url.hash === "";
|
|
2401
|
+
if (!includesOnlyOrigin) {
|
|
2402
|
+
throw new ZapierConfigurationError(
|
|
2403
|
+
`Invalid route override origin for ${sourceLabel}`,
|
|
2404
|
+
{ configType: "routeOverrides" }
|
|
2405
|
+
);
|
|
2406
|
+
}
|
|
2407
|
+
if (url.protocol === "https:") {
|
|
2408
|
+
return url.origin;
|
|
2409
|
+
}
|
|
2410
|
+
if (url.protocol === "http:" && isLoopbackHost(url.hostname)) {
|
|
2411
|
+
return url.origin;
|
|
2412
|
+
}
|
|
2413
|
+
throw new ZapierConfigurationError(
|
|
2414
|
+
`Invalid route override origin for ${sourceLabel}: expected https, or http on a loopback host`,
|
|
2415
|
+
{ configType: "routeOverrides" }
|
|
2416
|
+
);
|
|
2417
|
+
}
|
|
2418
|
+
function isLoopbackHost(hostname) {
|
|
2419
|
+
return hostname === "localhost" || hostname === "[::1]" || // pii:allow
|
|
2420
|
+
// RFC 6761 reserves .localhost names for loopback.
|
|
2421
|
+
hostname.endsWith(".localhost") || /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(hostname);
|
|
2422
|
+
}
|
|
2423
|
+
function compareRouteOverrideMatches(a, b) {
|
|
2424
|
+
return b.matchedPrefix.length - a.matchedPrefix.length || Number(b.isExactRouteSpelling) - Number(a.isExactRouteSpelling);
|
|
2425
|
+
}
|
|
2426
|
+
function getRouteCandidates({
|
|
2427
|
+
route,
|
|
2428
|
+
override,
|
|
2429
|
+
routingConfig: routingConfig2
|
|
2430
|
+
}) {
|
|
2431
|
+
const routeConfig = routingConfig2.pathConfig[route];
|
|
2432
|
+
if (!routeConfig || !isRouteOverrideEnabled({ routeConfig })) {
|
|
2433
|
+
return [];
|
|
2434
|
+
}
|
|
2435
|
+
const candidates = [
|
|
2436
|
+
{
|
|
2437
|
+
route,
|
|
2438
|
+
matchedPrefix: route,
|
|
2439
|
+
isExactRouteSpelling: true,
|
|
2440
|
+
routeConfig,
|
|
2441
|
+
override
|
|
2442
|
+
}
|
|
2443
|
+
];
|
|
2444
|
+
if (routeConfig.pathPrefix && routeConfig.pathPrefix !== route) {
|
|
2445
|
+
candidates.push({
|
|
2446
|
+
route,
|
|
2447
|
+
matchedPrefix: routeConfig.pathPrefix,
|
|
2448
|
+
isExactRouteSpelling: false,
|
|
2449
|
+
routeConfig,
|
|
2450
|
+
override
|
|
2451
|
+
});
|
|
2452
|
+
}
|
|
2453
|
+
return candidates;
|
|
2454
|
+
}
|
|
2455
|
+
function buildRouteOverrideUrl({
|
|
2456
|
+
origin,
|
|
2457
|
+
path
|
|
2458
|
+
}) {
|
|
2459
|
+
const url = new URL(origin);
|
|
2460
|
+
const { pathname, search, hash } = splitPathReference({ path });
|
|
2461
|
+
url.pathname = pathname;
|
|
2462
|
+
url.search = search;
|
|
2463
|
+
url.hash = hash;
|
|
2464
|
+
return url;
|
|
2465
|
+
}
|
|
2466
|
+
function splitPathReference({ path }) {
|
|
2467
|
+
const hashStart = path.indexOf("#");
|
|
2468
|
+
const pathWithoutHash = hashStart === -1 ? path : path.slice(0, hashStart);
|
|
2469
|
+
const searchStart = pathWithoutHash.indexOf("?");
|
|
2470
|
+
return {
|
|
2471
|
+
pathname: searchStart === -1 ? pathWithoutHash : pathWithoutHash.slice(0, searchStart),
|
|
2472
|
+
search: searchStart === -1 ? "" : pathWithoutHash.slice(searchStart),
|
|
2473
|
+
hash: hashStart === -1 ? "" : path.slice(hashStart)
|
|
2474
|
+
};
|
|
2475
|
+
}
|
|
2476
|
+
function pathnameMatchesPrefix({
|
|
2477
|
+
pathname,
|
|
2478
|
+
prefix
|
|
2479
|
+
}) {
|
|
2480
|
+
return pathname === prefix || pathname.startsWith(`${prefix}/`);
|
|
2481
|
+
}
|
|
2482
|
+
function isRouteOverrideEnabled({
|
|
2483
|
+
routeConfig
|
|
2484
|
+
}) {
|
|
2485
|
+
return routeConfig.override?.enabled !== false;
|
|
2486
|
+
}
|
|
2487
|
+
|
|
2488
|
+
// src/api/routing/index.ts
|
|
2489
|
+
var routingConfig = createRoutingConfig({ pathConfig });
|
|
2490
|
+
function parseRoutingOptions({
|
|
2491
|
+
options
|
|
2492
|
+
}) {
|
|
2493
|
+
try {
|
|
2494
|
+
return {
|
|
2495
|
+
routeOverrideEntries: readOptionRouteOverrideEntries({
|
|
2496
|
+
routeOverrides: options.routeOverrides,
|
|
2497
|
+
routingConfig
|
|
2498
|
+
})
|
|
2499
|
+
};
|
|
2500
|
+
} catch (error) {
|
|
2501
|
+
if (isZapierError(error) && error.code === "ZAPIER_CONFIGURATION_ERROR") {
|
|
2502
|
+
throw error;
|
|
2503
|
+
}
|
|
2504
|
+
throw new ZapierConfigurationError("Failed to read SDK routing options", {
|
|
2505
|
+
configType: "routeOverrides",
|
|
2506
|
+
cause: error
|
|
2507
|
+
});
|
|
2508
|
+
}
|
|
2509
|
+
}
|
|
2510
|
+
function resolveRoute({
|
|
2511
|
+
path,
|
|
2512
|
+
baseUrl,
|
|
2513
|
+
routingOptions = { routeOverrideEntries: [] },
|
|
2514
|
+
environment,
|
|
2515
|
+
debugLog
|
|
2516
|
+
}) {
|
|
2517
|
+
const overrideSources = collectRouteOverrideSources({
|
|
2518
|
+
routingOptions,
|
|
2519
|
+
environment,
|
|
2520
|
+
routingConfig
|
|
2521
|
+
});
|
|
2522
|
+
if (!overrideSources) {
|
|
2523
|
+
return resolveDefaultRoute({ path, baseUrl });
|
|
2524
|
+
}
|
|
2525
|
+
const routeOverrideMap = buildRouteOverrideMap(overrideSources);
|
|
2526
|
+
const overrideMatch = findRouteOverrideMatch({
|
|
2527
|
+
path,
|
|
2528
|
+
routeOverrideMap,
|
|
2529
|
+
routingConfig
|
|
2530
|
+
});
|
|
2531
|
+
if (overrideMatch) {
|
|
2532
|
+
const resolved = resolveOverrideRoute({ overrideMatch, path });
|
|
2533
|
+
logRouteOverride({ path, resolved, overrideMatch, debugLog });
|
|
2534
|
+
return resolved;
|
|
2535
|
+
}
|
|
2536
|
+
return resolveDefaultRoute({ path, baseUrl });
|
|
2537
|
+
}
|
|
2538
|
+
function logRouteOverride({
|
|
2539
|
+
path,
|
|
2540
|
+
resolved,
|
|
2541
|
+
overrideMatch,
|
|
2542
|
+
debugLog
|
|
2543
|
+
}) {
|
|
2544
|
+
if (!debugLog) {
|
|
2545
|
+
return;
|
|
2546
|
+
}
|
|
2547
|
+
const { route, override } = overrideMatch;
|
|
2548
|
+
const source = describeRouteOverrideSource(override);
|
|
2549
|
+
debugLog(
|
|
2550
|
+
`Route override: ${path} -> ${resolved.url.toString()} (route ${route} via ${source})`
|
|
2551
|
+
);
|
|
2552
|
+
}
|
|
2553
|
+
|
|
2034
2554
|
// src/sdk-version.ts
|
|
2035
|
-
var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.
|
|
2555
|
+
var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.103.0" : void 0) || "unknown";
|
|
2036
2556
|
|
|
2037
2557
|
// src/utils/open-url.ts
|
|
2038
2558
|
var nodePrefix = "node:";
|
|
@@ -2156,23 +2676,6 @@ function validateSdkPath(path) {
|
|
|
2156
2676
|
);
|
|
2157
2677
|
}
|
|
2158
2678
|
}
|
|
2159
|
-
function findPathConfigEntries({
|
|
2160
|
-
path,
|
|
2161
|
-
matchResolvedGatewayPath = false
|
|
2162
|
-
}) {
|
|
2163
|
-
const pathSegments = path.split("/").filter(Boolean);
|
|
2164
|
-
return Object.entries(pathConfig).filter(([configPath, config]) => {
|
|
2165
|
-
if (!matchResolvedGatewayPath) {
|
|
2166
|
-
return path === configPath || path.startsWith(`${configPath}/`);
|
|
2167
|
-
}
|
|
2168
|
-
const prefixSegments = (config.pathPrefix ?? configPath).split("/").filter(Boolean);
|
|
2169
|
-
return pathSegments.some(
|
|
2170
|
-
(_, startIndex) => prefixSegments.every(
|
|
2171
|
-
(segment, offset) => pathSegments[startIndex + offset] === segment
|
|
2172
|
-
)
|
|
2173
|
-
);
|
|
2174
|
-
}).map(([configPath, config]) => ({ configPath, config }));
|
|
2175
|
-
}
|
|
2176
2679
|
function parseRateLimitHeaders(response) {
|
|
2177
2680
|
const info = {};
|
|
2178
2681
|
const retryAfter = response.headers.get("retry-after");
|
|
@@ -2214,78 +2717,6 @@ function parseRateLimitHeaders(response) {
|
|
|
2214
2717
|
}
|
|
2215
2718
|
return info;
|
|
2216
2719
|
}
|
|
2217
|
-
var pathConfig = {
|
|
2218
|
-
// e.g. /relay -> https://sdkapi.zapier.com/api/v0/sdk/relay/...
|
|
2219
|
-
"/relay": {
|
|
2220
|
-
authHeader: "X-Relay-Authorization",
|
|
2221
|
-
pathPrefix: "/api/v0/sdk/relay",
|
|
2222
|
-
omitDeprecationMessaging: true
|
|
2223
|
-
},
|
|
2224
|
-
// The concrete gateway form of the relay route. Callers that pass the
|
|
2225
|
-
// already-prefixed path reach the same third-party upstreams, so it must
|
|
2226
|
-
// classify as relay too; without this entry it would match nothing and
|
|
2227
|
-
// sniff deprecation headers off a relay response.
|
|
2228
|
-
"/api/v0/sdk/relay": {
|
|
2229
|
-
omitDeprecationMessaging: true
|
|
2230
|
-
},
|
|
2231
|
-
// Concrete sdkapi routes that do not live behind /api/v0/sdk/<service>.
|
|
2232
|
-
"/api/v0": {},
|
|
2233
|
-
// e.g. /zapier -> https://sdkapi.zapier.com/api/v0/sdk/zapier/...
|
|
2234
|
-
"/zapier": {
|
|
2235
|
-
authHeader: "Authorization",
|
|
2236
|
-
pathPrefix: "/api/v0/sdk/zapier"
|
|
2237
|
-
},
|
|
2238
|
-
// e.g. /tables -> https://sdkapi.zapier.com/api/v0/sdk/tables/...
|
|
2239
|
-
"/tables": {
|
|
2240
|
-
authHeader: "Authorization",
|
|
2241
|
-
pathPrefix: "/api/v0/sdk/tables"
|
|
2242
|
-
},
|
|
2243
|
-
// e.g. /trigger-inbox -> https://sdkapi.zapier.com/api/v0/sdk/trigger-inbox/...
|
|
2244
|
-
"/trigger-inbox": {
|
|
2245
|
-
authHeader: "Authorization",
|
|
2246
|
-
pathPrefix: "/api/v0/sdk/trigger-inbox"
|
|
2247
|
-
},
|
|
2248
|
-
// e.g. /sdkdurableapi -> https://sdkapi.zapier.com/api/v0/sdk/sdkdurableapi/...
|
|
2249
|
-
// sdkapi proxies to the sdkdurableapi backend.
|
|
2250
|
-
"/sdkdurableapi": {
|
|
2251
|
-
authHeader: "Authorization",
|
|
2252
|
-
pathPrefix: "/api/v0/sdk/sdkdurableapi"
|
|
2253
|
-
},
|
|
2254
|
-
// e.g. /durableworkflowzaps -> https://sdkapi.zapier.com/api/v0/sdk/durableworkflowzaps/...
|
|
2255
|
-
// sdkapi proxies to the durableworkflowzaps backend.
|
|
2256
|
-
"/durableworkflowzaps": {
|
|
2257
|
-
authHeader: "Authorization",
|
|
2258
|
-
pathPrefix: "/api/v0/sdk/durableworkflowzaps"
|
|
2259
|
-
},
|
|
2260
|
-
// e.g. /code-substrate-runner -> https://sdkapi.zapier.com/api/v0/sdk/code-substrate-runner/...
|
|
2261
|
-
// sdkapi proxies to the code-substrate-runner backend.
|
|
2262
|
-
"/code-substrate-runner": {
|
|
2263
|
-
authHeader: "Authorization",
|
|
2264
|
-
pathPrefix: "/api/v0/sdk/code-substrate-runner"
|
|
2265
|
-
},
|
|
2266
|
-
// e.g. /code-substrate-workflows -> https://sdkapi.zapier.com/api/v0/sdk/code-substrate-workflows/...
|
|
2267
|
-
// sdkapi proxies to the code-substrate-workflows backend.
|
|
2268
|
-
"/code-substrate-workflows": {
|
|
2269
|
-
authHeader: "Authorization",
|
|
2270
|
-
pathPrefix: "/api/v0/sdk/code-substrate-workflows"
|
|
2271
|
-
},
|
|
2272
|
-
// e.g. /code-substrate-analyzer/validations ->
|
|
2273
|
-
// https://api.zapier.com/code-substrate-analyzer/v0/validations
|
|
2274
|
-
"/code-substrate-analyzer": {
|
|
2275
|
-
authHeader: "Authorization",
|
|
2276
|
-
pathPrefix: "/code-substrate-analyzer/v0",
|
|
2277
|
-
subdomain: "api"
|
|
2278
|
-
},
|
|
2279
|
-
// e.g. /forms/v0/forms -> https://api.zapier.com/forms/v0/forms
|
|
2280
|
-
// The Forms API is registered on the Public API Gateway and has no sdkapi
|
|
2281
|
-
// proxy route, so it goes straight to the gateway. Its governance metadata
|
|
2282
|
-
// rewrites /forms/v0/... to the backend's /api/forms/v0/..., which is why no
|
|
2283
|
-
// pathPrefix is applied here.
|
|
2284
|
-
"/forms": {
|
|
2285
|
-
authHeader: "Authorization",
|
|
2286
|
-
subdomain: "api"
|
|
2287
|
-
}
|
|
2288
|
-
};
|
|
2289
2720
|
var ZapierApiClient = class {
|
|
2290
2721
|
constructor(options) {
|
|
2291
2722
|
this.options = options;
|
|
@@ -2830,43 +3261,13 @@ var ZapierApiClient = class {
|
|
|
2830
3261
|
}
|
|
2831
3262
|
// Apply any special routing logic for configured paths.
|
|
2832
3263
|
applyPathConfiguration(path) {
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
const deprecationPathMatches = [
|
|
2841
|
-
...matchingPathEntries,
|
|
2842
|
-
...resolvedPathEntries
|
|
2843
|
-
];
|
|
2844
|
-
const canSendDeprecationMessaging = deprecationPathMatches.length > 0 && deprecationPathMatches.every(
|
|
2845
|
-
({ config }) => config.omitDeprecationMessaging !== true
|
|
2846
|
-
);
|
|
2847
|
-
return {
|
|
2848
|
-
url: url2,
|
|
2849
|
-
pathConfig: routingMatch?.config,
|
|
2850
|
-
canSendDeprecationMessaging
|
|
2851
|
-
};
|
|
2852
|
-
};
|
|
2853
|
-
let finalPath = path;
|
|
2854
|
-
if (routingMatch?.config.pathPrefix) {
|
|
2855
|
-
const pathWithoutPrefix = path.slice(routingMatch.configPath.length) || "/";
|
|
2856
|
-
finalPath = `${routingMatch.config.pathPrefix}${pathWithoutPrefix}`;
|
|
2857
|
-
}
|
|
2858
|
-
const zapierBaseUrl = getZapierBaseUrl(this.options.baseUrl);
|
|
2859
|
-
if (zapierBaseUrl === this.options.baseUrl.replace(/\/$/, "")) {
|
|
2860
|
-
const originalBaseUrl = new URL(this.options.baseUrl);
|
|
2861
|
-
const subdomain = routingMatch?.config.subdomain ?? "sdkapi";
|
|
2862
|
-
const finalBaseUrl = `https://${subdomain}.${originalBaseUrl.hostname}`;
|
|
2863
|
-
const url2 = new URL(finalPath, finalBaseUrl);
|
|
2864
|
-
return buildResult(url2);
|
|
2865
|
-
}
|
|
2866
|
-
const baseUrl = new URL(this.options.baseUrl);
|
|
2867
|
-
const basePath = baseUrl.pathname.replace(/\/$/, "");
|
|
2868
|
-
const url = new URL(basePath + finalPath, baseUrl.origin);
|
|
2869
|
-
return buildResult(url);
|
|
3264
|
+
return resolveRoute({
|
|
3265
|
+
path,
|
|
3266
|
+
baseUrl: this.options.baseUrl,
|
|
3267
|
+
routingOptions: this.options.routingOptions,
|
|
3268
|
+
environment: globalThis.process?.env,
|
|
3269
|
+
debugLog: this.options.debugLog
|
|
3270
|
+
});
|
|
2870
3271
|
}
|
|
2871
3272
|
// Helper to build full URLs and return routing info
|
|
2872
3273
|
buildUrl(path, searchParams) {
|
|
@@ -3395,6 +3796,7 @@ var ZapierApiClient = class {
|
|
|
3395
3796
|
};
|
|
3396
3797
|
var createZapierApi = (options) => {
|
|
3397
3798
|
const { debug = false, fetch: originalFetch = globalThis.fetch } = options;
|
|
3799
|
+
const routingOptions = parseRoutingOptions({ options });
|
|
3398
3800
|
const debugLog = createDebugLogger(debug);
|
|
3399
3801
|
const debugFetch = createDebugFetch({ originalFetch, debugLog });
|
|
3400
3802
|
return new ZapierApiClient({
|
|
@@ -3405,7 +3807,9 @@ var createZapierApi = (options) => {
|
|
|
3405
3807
|
fetch: debugFetch,
|
|
3406
3808
|
// Built from the caller's own `fetch`, not `debugFetch`: the pipeline wraps
|
|
3407
3809
|
// for debug itself, and passing the wrapped one would log twice.
|
|
3408
|
-
sendHttpRequest: options.sendHttpRequest ?? createZapierSendHttpRequest({ fetch: options.fetch, debug })
|
|
3810
|
+
sendHttpRequest: options.sendHttpRequest ?? createZapierSendHttpRequest({ fetch: options.fetch, debug }),
|
|
3811
|
+
debugLog,
|
|
3812
|
+
routingOptions
|
|
3409
3813
|
});
|
|
3410
3814
|
};
|
|
3411
3815
|
|
|
@@ -3494,7 +3898,8 @@ var apiPlugin = defineProperty({
|
|
|
3494
3898
|
maxApprovalRetries,
|
|
3495
3899
|
approvalMode,
|
|
3496
3900
|
openAutoModeApprovalsInBrowser,
|
|
3497
|
-
callerPackage
|
|
3901
|
+
callerPackage,
|
|
3902
|
+
routeOverrides
|
|
3498
3903
|
} = imports.sdkOptions ?? {};
|
|
3499
3904
|
return createZapierApi({
|
|
3500
3905
|
baseUrl,
|
|
@@ -3511,6 +3916,7 @@ var apiPlugin = defineProperty({
|
|
|
3511
3916
|
approvalMode,
|
|
3512
3917
|
openAutoModeApprovalsInBrowser,
|
|
3513
3918
|
callerPackage,
|
|
3919
|
+
routeOverrides,
|
|
3514
3920
|
// Inject the graph-composed transport so host `dispatchHttpRequest` wraps
|
|
3515
3921
|
// apply.
|
|
3516
3922
|
sendHttpRequest: imports.sendHttpRequest
|
|
@@ -11905,6 +12311,7 @@ var BaseSdkOptionsSchema = z.object({
|
|
|
11905
12311
|
),
|
|
11906
12312
|
debug: z.boolean().optional().describe("Enable debug logging."),
|
|
11907
12313
|
baseUrl: z.string().optional().describe("Base URL for Zapier API endpoints.").meta({ valueHint: "url" }),
|
|
12314
|
+
routeOverrides: z.record(z.string(), z.string()).optional().describe("Maps SDK route prefixes to direct origins.").meta({ internal: true }),
|
|
11908
12315
|
trackingBaseUrl: z.string().optional().describe("Base URL for Zapier tracking endpoints.").meta({ valueHint: "url" }),
|
|
11909
12316
|
/**
|
|
11910
12317
|
* Maximum number of retries for rate-limited requests (429 responses).
|