@zapier/zapier-sdk 0.102.3 → 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.
@@ -1071,6 +1071,51 @@ function createSemaphore(maxPermits) {
1071
1071
  }
1072
1072
  };
1073
1073
  }
1074
+ var SDK_OPTIONS_ID = "zapier/sdkOptions";
1075
+ var sdkOptionsPluginRef = kitcore.declareOptionalProperty({
1076
+ id: SDK_OPTIONS_ID
1077
+ });
1078
+
1079
+ // src/plugins/transport/options.ts
1080
+ function resolveTransportFetch({
1081
+ fetch: customFetch,
1082
+ debug = false
1083
+ }) {
1084
+ const originalFetch = customFetch ?? ((input, init) => globalThis.fetch(input, init));
1085
+ if (!debug) return originalFetch;
1086
+ return createDebugFetch({
1087
+ originalFetch,
1088
+ debugLog: createDebugLogger(debug)
1089
+ });
1090
+ }
1091
+
1092
+ // src/plugins/transport/http-fetch.ts
1093
+ var httpFetchPlugin = kitcore.defineProperty({
1094
+ namespace: "kitcore",
1095
+ name: "httpFetch",
1096
+ imports: [sdkOptionsPluginRef],
1097
+ setup: ({ imports }) => resolveTransportFetch({
1098
+ fetch: imports.sdkOptions?.fetch,
1099
+ debug: imports.sdkOptions?.debug
1100
+ }),
1101
+ get: ({ state }) => state
1102
+ });
1103
+
1104
+ // src/plugins/transport/standalone.ts
1105
+ function createZapierSendHttpRequest({
1106
+ fetch: customFetch,
1107
+ debug
1108
+ }) {
1109
+ const sdk = kitcore.createSdk(
1110
+ kitcore.definePlugin({
1111
+ name: "zapierStandaloneHttpTransport",
1112
+ imports: [kitcore.sendHttpRequestPlugin, httpFetchPlugin],
1113
+ exports: [kitcore.sendHttpRequestPlugin]
1114
+ }),
1115
+ { configuration: { [SDK_OPTIONS_ID]: { fetch: customFetch, debug } } }
1116
+ );
1117
+ return sdk.sendHttpRequest;
1118
+ }
1074
1119
 
1075
1120
  // src/api/correlation.ts
1076
1121
  var CORRELATION_CALL_ID = Symbol(
@@ -1987,8 +2032,528 @@ function parseDeprecationDate(value) {
1987
2032
  return Number(match[1]) * 1e3;
1988
2033
  }
1989
2034
 
2035
+ // src/api/routing/config.ts
2036
+ var pathConfig = {
2037
+ // e.g. /relay -> https://sdkapi.zapier.com/api/v0/sdk/relay/...
2038
+ "/relay": {
2039
+ authHeader: "X-Relay-Authorization",
2040
+ pathPrefix: "/api/v0/sdk/relay",
2041
+ omitDeprecationMessaging: true
2042
+ },
2043
+ // The concrete gateway form of the relay route. Callers that pass the
2044
+ // already-prefixed path reach the same third-party upstreams, so it must
2045
+ // classify as relay too; without this entry it would match nothing and
2046
+ // sniff deprecation headers off a relay response.
2047
+ "/api/v0/sdk/relay": {
2048
+ override: { enabled: false },
2049
+ omitDeprecationMessaging: true
2050
+ },
2051
+ // Concrete sdkapi routes that do not live behind /api/v0/sdk/<service>.
2052
+ "/api/v0": {},
2053
+ // e.g. /zapier -> https://sdkapi.zapier.com/api/v0/sdk/zapier/...
2054
+ "/zapier": {
2055
+ authHeader: "Authorization",
2056
+ pathPrefix: "/api/v0/sdk/zapier"
2057
+ },
2058
+ // e.g. /tables -> https://sdkapi.zapier.com/api/v0/sdk/tables/...
2059
+ "/tables": {
2060
+ authHeader: "Authorization",
2061
+ pathPrefix: "/api/v0/sdk/tables"
2062
+ },
2063
+ // e.g. /trigger-inbox -> https://sdkapi.zapier.com/api/v0/sdk/trigger-inbox/...
2064
+ "/trigger-inbox": {
2065
+ authHeader: "Authorization",
2066
+ pathPrefix: "/api/v0/sdk/trigger-inbox"
2067
+ },
2068
+ // e.g. /sdkdurableapi -> https://sdkapi.zapier.com/api/v0/sdk/sdkdurableapi/...
2069
+ // sdkapi proxies to the sdkdurableapi backend.
2070
+ "/sdkdurableapi": {
2071
+ authHeader: "Authorization",
2072
+ pathPrefix: "/api/v0/sdk/sdkdurableapi"
2073
+ },
2074
+ // e.g. /durableworkflowzaps -> https://sdkapi.zapier.com/api/v0/sdk/durableworkflowzaps/...
2075
+ // sdkapi proxies to the durableworkflowzaps backend.
2076
+ "/durableworkflowzaps": {
2077
+ authHeader: "Authorization",
2078
+ pathPrefix: "/api/v0/sdk/durableworkflowzaps"
2079
+ },
2080
+ // e.g. /code-substrate-runner -> https://sdkapi.zapier.com/api/v0/sdk/code-substrate-runner/...
2081
+ // sdkapi proxies to the code-substrate-runner backend.
2082
+ "/code-substrate-runner": {
2083
+ authHeader: "Authorization",
2084
+ pathPrefix: "/api/v0/sdk/code-substrate-runner"
2085
+ },
2086
+ // e.g. /code-substrate-workflows -> https://sdkapi.zapier.com/api/v0/sdk/code-substrate-workflows/...
2087
+ // sdkapi proxies to the code-substrate-workflows backend.
2088
+ "/code-substrate-workflows": {
2089
+ authHeader: "Authorization",
2090
+ pathPrefix: "/api/v0/sdk/code-substrate-workflows"
2091
+ },
2092
+ // e.g. /code-substrate-analyzer/validations ->
2093
+ // https://api.zapier.com/code-substrate-analyzer/v0/validations
2094
+ "/code-substrate-analyzer": {
2095
+ authHeader: "Authorization",
2096
+ pathPrefix: "/code-substrate-analyzer/v0",
2097
+ subdomain: "api",
2098
+ override: { pathPrefixMode: "preserve" }
2099
+ },
2100
+ // e.g. /forms/v0/forms -> https://api.zapier.com/forms/v0/forms
2101
+ // The Forms API is registered on the Public API Gateway and has no sdkapi
2102
+ // proxy route, so it goes straight to the gateway. Its governance metadata
2103
+ // rewrites /forms/v0/... to the backend's /api/forms/v0/..., which is why no
2104
+ // pathPrefix is applied here.
2105
+ "/forms": {
2106
+ authHeader: "Authorization",
2107
+ subdomain: "api"
2108
+ }
2109
+ };
2110
+
2111
+ // src/api/routing/default.ts
2112
+ function resolveDefaultRoute({
2113
+ path,
2114
+ baseUrl
2115
+ }) {
2116
+ const matchingPathEntries = findPathConfigEntries({ path });
2117
+ const routingMatch = matchingPathEntries[0];
2118
+ let finalPath = path;
2119
+ if (routingMatch?.config.pathPrefix) {
2120
+ const pathWithoutPrefix = path.slice(routingMatch.configPath.length) || "/";
2121
+ finalPath = `${routingMatch.config.pathPrefix}${pathWithoutPrefix}`;
2122
+ }
2123
+ const zapierBaseUrl = getZapierBaseUrl(baseUrl);
2124
+ if (zapierBaseUrl === baseUrl.replace(/\/$/, "")) {
2125
+ const originalBaseUrl = new URL(baseUrl);
2126
+ const subdomain = routingMatch?.config.subdomain ?? "sdkapi";
2127
+ const finalBaseUrl = `https://${subdomain}.${originalBaseUrl.hostname}`;
2128
+ return buildRouteResult({
2129
+ url: new URL(finalPath, finalBaseUrl),
2130
+ matchingPathEntries,
2131
+ routingMatch
2132
+ });
2133
+ }
2134
+ const parsedBaseUrl = new URL(baseUrl);
2135
+ const basePath = parsedBaseUrl.pathname.replace(/\/$/, "");
2136
+ return buildRouteResult({
2137
+ url: new URL(basePath + finalPath, parsedBaseUrl.origin),
2138
+ matchingPathEntries,
2139
+ routingMatch
2140
+ });
2141
+ }
2142
+ function buildRouteResult({
2143
+ url,
2144
+ matchingPathEntries,
2145
+ routingMatch
2146
+ }) {
2147
+ const resolvedPathEntries = findPathConfigEntries({
2148
+ path: url.pathname,
2149
+ matchResolvedGatewayPath: true
2150
+ });
2151
+ const deprecationPathMatches = [
2152
+ ...matchingPathEntries,
2153
+ ...resolvedPathEntries
2154
+ ];
2155
+ const canSendDeprecationMessaging = deprecationPathMatches.length > 0 && deprecationPathMatches.every(
2156
+ ({ config }) => config.omitDeprecationMessaging !== true
2157
+ );
2158
+ return {
2159
+ url,
2160
+ pathConfig: routingMatch?.config,
2161
+ canSendDeprecationMessaging
2162
+ };
2163
+ }
2164
+ function findPathConfigEntries({
2165
+ path,
2166
+ matchResolvedGatewayPath = false
2167
+ }) {
2168
+ const pathSegments = path.split("/").filter(Boolean);
2169
+ return Object.entries(pathConfig).filter(([configPath, config]) => {
2170
+ if (!matchResolvedGatewayPath) {
2171
+ return path === configPath || path.startsWith(`${configPath}/`);
2172
+ }
2173
+ const prefixSegments = (config.pathPrefix ?? configPath).split("/").filter(Boolean);
2174
+ return pathSegments.some(
2175
+ (_, startIndex) => prefixSegments.every(
2176
+ (segment, offset) => pathSegments[startIndex + offset] === segment
2177
+ )
2178
+ );
2179
+ }).map(([configPath, config]) => ({ configPath, config }));
2180
+ }
2181
+
2182
+ // src/api/routing/overrides.ts
2183
+ var ROUTE_ORIGIN_ENV_PREFIX = "ZAPIER_ROUTE_ORIGIN_";
2184
+ function createRoutingConfig({
2185
+ pathConfig: pathConfig2
2186
+ }) {
2187
+ const routeByEnvName = new Map(
2188
+ Object.entries(pathConfig2).filter(([, routeConfig]) => isRouteOverrideEnabled({ routeConfig })).map(([route]) => [encodeRouteOriginEnvName({ route }), route])
2189
+ );
2190
+ return { pathConfig: pathConfig2, routeByEnvName };
2191
+ }
2192
+ function encodeRouteOriginEnvName({ route }) {
2193
+ return `${ROUTE_ORIGIN_ENV_PREFIX}${route.slice(1).split("/").map((segment) => segment.replace(/-/g, "_").toUpperCase()).join("__")}`;
2194
+ }
2195
+ function createRouteOverrideEntry({
2196
+ route,
2197
+ source,
2198
+ sourceReference,
2199
+ origin
2200
+ }) {
2201
+ return {
2202
+ route,
2203
+ source,
2204
+ sourceReference,
2205
+ origin: parseRouteOverrideOrigin({
2206
+ origin,
2207
+ sourceLabel: describeRouteOverrideSource({ source, sourceReference })
2208
+ })
2209
+ };
2210
+ }
2211
+ function describeRouteOverrideSource({
2212
+ source,
2213
+ sourceReference
2214
+ }) {
2215
+ return source === "environment-variable" ? `environment variable ${sourceReference}` : `routeOverrides[${JSON.stringify(sourceReference)}]`;
2216
+ }
2217
+ function readOptionRouteOverrideEntries({
2218
+ routeOverrides,
2219
+ routingConfig: routingConfig2
2220
+ }) {
2221
+ const entries = [];
2222
+ if (!routeOverrides) {
2223
+ return entries;
2224
+ }
2225
+ for (const [route, origin] of Object.entries(routeOverrides)) {
2226
+ assertSupportedRouteOverride({ route, routingConfig: routingConfig2 });
2227
+ entries.push(
2228
+ createRouteOverrideEntry({
2229
+ route,
2230
+ source: "sdk-option",
2231
+ sourceReference: route,
2232
+ origin
2233
+ })
2234
+ );
2235
+ }
2236
+ return entries;
2237
+ }
2238
+ function buildRouteOverrideMap({
2239
+ environmentEntries,
2240
+ optionEntries
2241
+ }) {
2242
+ const routeOverrideMap = /* @__PURE__ */ new Map();
2243
+ for (const entry of environmentEntries) {
2244
+ routeOverrideMap.set(entry.route, entry);
2245
+ }
2246
+ for (const entry of optionEntries) {
2247
+ routeOverrideMap.set(entry.route, entry);
2248
+ }
2249
+ return routeOverrideMap;
2250
+ }
2251
+ function collectRouteOverrideSources({
2252
+ routingOptions,
2253
+ environment,
2254
+ routingConfig: routingConfig2
2255
+ }) {
2256
+ try {
2257
+ const optionEntries = routingOptions?.routeOverrideEntries ?? [];
2258
+ const environmentEntries = readEnvironmentRouteOverrideEntries({
2259
+ environment,
2260
+ routingConfig: routingConfig2
2261
+ });
2262
+ if (optionEntries.length === 0 && environmentEntries.length === 0) {
2263
+ return void 0;
2264
+ }
2265
+ return { optionEntries, environmentEntries };
2266
+ } catch (error) {
2267
+ if (isZapierError(error) && error.code === "ZAPIER_CONFIGURATION_ERROR") {
2268
+ throw error;
2269
+ }
2270
+ return void 0;
2271
+ }
2272
+ }
2273
+ function findRouteOverrideMatch({
2274
+ path,
2275
+ routeOverrideMap,
2276
+ routingConfig: routingConfig2
2277
+ }) {
2278
+ let bestMatch;
2279
+ const { pathname } = splitPathReference({ path });
2280
+ for (const override of routeOverrideMap.values()) {
2281
+ const { route } = override;
2282
+ for (const candidate of getRouteCandidates({
2283
+ route,
2284
+ override,
2285
+ routingConfig: routingConfig2
2286
+ })) {
2287
+ if (!pathnameMatchesPrefix({
2288
+ pathname,
2289
+ prefix: candidate.matchedPrefix
2290
+ })) {
2291
+ continue;
2292
+ }
2293
+ if (!bestMatch || compareRouteOverrideMatches(candidate, bestMatch) < 0) {
2294
+ bestMatch = candidate;
2295
+ }
2296
+ }
2297
+ }
2298
+ return bestMatch;
2299
+ }
2300
+ function resolveOverrideRoute({
2301
+ overrideMatch,
2302
+ path
2303
+ }) {
2304
+ const { matchedPrefix, routeConfig, override } = overrideMatch;
2305
+ const directPath = deriveDirectPath({ path, matchedPrefix, routeConfig });
2306
+ return {
2307
+ url: buildRouteOverrideUrl({ origin: override.origin, path: directPath }),
2308
+ pathConfig: routeConfig,
2309
+ canSendDeprecationMessaging: false
2310
+ };
2311
+ }
2312
+ function deriveDirectPath({
2313
+ path,
2314
+ matchedPrefix,
2315
+ routeConfig
2316
+ }) {
2317
+ const { pathPrefix } = routeConfig;
2318
+ if (!pathPrefix) {
2319
+ return path;
2320
+ }
2321
+ const remainingPath = path.slice(matchedPrefix.length) || "/";
2322
+ const override = routeConfig.override;
2323
+ const pathPrefixMode = override?.enabled === false ? "strip" : override?.pathPrefixMode ?? "strip";
2324
+ return pathPrefixMode === "preserve" ? `${pathPrefix}${remainingPath}` : remainingPath;
2325
+ }
2326
+ function readEnvironmentRouteOverrideEntries({
2327
+ environment,
2328
+ routingConfig: routingConfig2
2329
+ }) {
2330
+ const entries = [];
2331
+ if (!environment) {
2332
+ return entries;
2333
+ }
2334
+ for (const [envName, route] of routingConfig2.routeByEnvName) {
2335
+ let value;
2336
+ try {
2337
+ if (!Object.prototype.hasOwnProperty.call(environment, envName)) {
2338
+ continue;
2339
+ }
2340
+ value = environment[envName];
2341
+ } catch {
2342
+ continue;
2343
+ }
2344
+ if (isUnsetEnvironmentValue(value)) {
2345
+ continue;
2346
+ }
2347
+ entries.push(
2348
+ createRouteOverrideEntry({
2349
+ route,
2350
+ source: "environment-variable",
2351
+ sourceReference: envName,
2352
+ origin: value
2353
+ })
2354
+ );
2355
+ }
2356
+ return entries;
2357
+ }
2358
+ function isUnsetEnvironmentValue(value) {
2359
+ if (value === void 0 || value === null) {
2360
+ return true;
2361
+ }
2362
+ return typeof value === "string" && value.trim() === "";
2363
+ }
2364
+ function assertSupportedRouteOverride({
2365
+ route,
2366
+ routingConfig: routingConfig2
2367
+ }) {
2368
+ if (!Object.prototype.hasOwnProperty.call(routingConfig2.pathConfig, route)) {
2369
+ throw new ZapierConfigurationError(
2370
+ `Route override is not supported for ${route}`,
2371
+ { configType: "routeOverrides" }
2372
+ );
2373
+ }
2374
+ const routeConfig = routingConfig2.pathConfig[route];
2375
+ if (!isRouteOverrideEnabled({ routeConfig })) {
2376
+ throw new ZapierConfigurationError(
2377
+ `Route override is disabled for ${route}`,
2378
+ { configType: "routeOverrides" }
2379
+ );
2380
+ }
2381
+ }
2382
+ function parseRouteOverrideOrigin({
2383
+ origin,
2384
+ sourceLabel
2385
+ }) {
2386
+ if (typeof origin !== "string") {
2387
+ throw new ZapierConfigurationError(
2388
+ `Invalid route override origin for ${sourceLabel}`,
2389
+ { configType: "routeOverrides" }
2390
+ );
2391
+ }
2392
+ let url;
2393
+ try {
2394
+ url = new URL(origin);
2395
+ } catch {
2396
+ throw new ZapierConfigurationError(
2397
+ `Invalid route override origin for ${sourceLabel}`,
2398
+ { configType: "routeOverrides" }
2399
+ );
2400
+ }
2401
+ const includesOnlyOrigin = url.username === "" && url.password === "" && url.pathname === "/" && url.search === "" && url.hash === "";
2402
+ if (!includesOnlyOrigin) {
2403
+ throw new ZapierConfigurationError(
2404
+ `Invalid route override origin for ${sourceLabel}`,
2405
+ { configType: "routeOverrides" }
2406
+ );
2407
+ }
2408
+ if (url.protocol === "https:") {
2409
+ return url.origin;
2410
+ }
2411
+ if (url.protocol === "http:" && isLoopbackHost(url.hostname)) {
2412
+ return url.origin;
2413
+ }
2414
+ throw new ZapierConfigurationError(
2415
+ `Invalid route override origin for ${sourceLabel}: expected https, or http on a loopback host`,
2416
+ { configType: "routeOverrides" }
2417
+ );
2418
+ }
2419
+ function isLoopbackHost(hostname) {
2420
+ return hostname === "localhost" || hostname === "[::1]" || // pii:allow
2421
+ // RFC 6761 reserves .localhost names for loopback.
2422
+ hostname.endsWith(".localhost") || /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(hostname);
2423
+ }
2424
+ function compareRouteOverrideMatches(a, b) {
2425
+ return b.matchedPrefix.length - a.matchedPrefix.length || Number(b.isExactRouteSpelling) - Number(a.isExactRouteSpelling);
2426
+ }
2427
+ function getRouteCandidates({
2428
+ route,
2429
+ override,
2430
+ routingConfig: routingConfig2
2431
+ }) {
2432
+ const routeConfig = routingConfig2.pathConfig[route];
2433
+ if (!routeConfig || !isRouteOverrideEnabled({ routeConfig })) {
2434
+ return [];
2435
+ }
2436
+ const candidates = [
2437
+ {
2438
+ route,
2439
+ matchedPrefix: route,
2440
+ isExactRouteSpelling: true,
2441
+ routeConfig,
2442
+ override
2443
+ }
2444
+ ];
2445
+ if (routeConfig.pathPrefix && routeConfig.pathPrefix !== route) {
2446
+ candidates.push({
2447
+ route,
2448
+ matchedPrefix: routeConfig.pathPrefix,
2449
+ isExactRouteSpelling: false,
2450
+ routeConfig,
2451
+ override
2452
+ });
2453
+ }
2454
+ return candidates;
2455
+ }
2456
+ function buildRouteOverrideUrl({
2457
+ origin,
2458
+ path
2459
+ }) {
2460
+ const url = new URL(origin);
2461
+ const { pathname, search, hash } = splitPathReference({ path });
2462
+ url.pathname = pathname;
2463
+ url.search = search;
2464
+ url.hash = hash;
2465
+ return url;
2466
+ }
2467
+ function splitPathReference({ path }) {
2468
+ const hashStart = path.indexOf("#");
2469
+ const pathWithoutHash = hashStart === -1 ? path : path.slice(0, hashStart);
2470
+ const searchStart = pathWithoutHash.indexOf("?");
2471
+ return {
2472
+ pathname: searchStart === -1 ? pathWithoutHash : pathWithoutHash.slice(0, searchStart),
2473
+ search: searchStart === -1 ? "" : pathWithoutHash.slice(searchStart),
2474
+ hash: hashStart === -1 ? "" : path.slice(hashStart)
2475
+ };
2476
+ }
2477
+ function pathnameMatchesPrefix({
2478
+ pathname,
2479
+ prefix
2480
+ }) {
2481
+ return pathname === prefix || pathname.startsWith(`${prefix}/`);
2482
+ }
2483
+ function isRouteOverrideEnabled({
2484
+ routeConfig
2485
+ }) {
2486
+ return routeConfig.override?.enabled !== false;
2487
+ }
2488
+
2489
+ // src/api/routing/index.ts
2490
+ var routingConfig = createRoutingConfig({ pathConfig });
2491
+ function parseRoutingOptions({
2492
+ options
2493
+ }) {
2494
+ try {
2495
+ return {
2496
+ routeOverrideEntries: readOptionRouteOverrideEntries({
2497
+ routeOverrides: options.routeOverrides,
2498
+ routingConfig
2499
+ })
2500
+ };
2501
+ } catch (error) {
2502
+ if (isZapierError(error) && error.code === "ZAPIER_CONFIGURATION_ERROR") {
2503
+ throw error;
2504
+ }
2505
+ throw new ZapierConfigurationError("Failed to read SDK routing options", {
2506
+ configType: "routeOverrides",
2507
+ cause: error
2508
+ });
2509
+ }
2510
+ }
2511
+ function resolveRoute({
2512
+ path,
2513
+ baseUrl,
2514
+ routingOptions = { routeOverrideEntries: [] },
2515
+ environment,
2516
+ debugLog
2517
+ }) {
2518
+ const overrideSources = collectRouteOverrideSources({
2519
+ routingOptions,
2520
+ environment,
2521
+ routingConfig
2522
+ });
2523
+ if (!overrideSources) {
2524
+ return resolveDefaultRoute({ path, baseUrl });
2525
+ }
2526
+ const routeOverrideMap = buildRouteOverrideMap(overrideSources);
2527
+ const overrideMatch = findRouteOverrideMatch({
2528
+ path,
2529
+ routeOverrideMap,
2530
+ routingConfig
2531
+ });
2532
+ if (overrideMatch) {
2533
+ const resolved = resolveOverrideRoute({ overrideMatch, path });
2534
+ logRouteOverride({ path, resolved, overrideMatch, debugLog });
2535
+ return resolved;
2536
+ }
2537
+ return resolveDefaultRoute({ path, baseUrl });
2538
+ }
2539
+ function logRouteOverride({
2540
+ path,
2541
+ resolved,
2542
+ overrideMatch,
2543
+ debugLog
2544
+ }) {
2545
+ if (!debugLog) {
2546
+ return;
2547
+ }
2548
+ const { route, override } = overrideMatch;
2549
+ const source = describeRouteOverrideSource(override);
2550
+ debugLog(
2551
+ `Route override: ${path} -> ${resolved.url.toString()} (route ${route} via ${source})`
2552
+ );
2553
+ }
2554
+
1990
2555
  // src/sdk-version.ts
1991
- var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.102.3" : void 0) || "unknown";
2556
+ var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.103.0" : void 0) || "unknown";
1992
2557
 
1993
2558
  // src/utils/open-url.ts
1994
2559
  var nodePrefix = "node:";
@@ -2112,23 +2677,6 @@ function validateSdkPath(path) {
2112
2677
  );
2113
2678
  }
2114
2679
  }
2115
- function findPathConfigEntries({
2116
- path,
2117
- matchResolvedGatewayPath = false
2118
- }) {
2119
- const pathSegments = path.split("/").filter(Boolean);
2120
- return Object.entries(pathConfig).filter(([configPath, config]) => {
2121
- if (!matchResolvedGatewayPath) {
2122
- return path === configPath || path.startsWith(`${configPath}/`);
2123
- }
2124
- const prefixSegments = (config.pathPrefix ?? configPath).split("/").filter(Boolean);
2125
- return pathSegments.some(
2126
- (_, startIndex) => prefixSegments.every(
2127
- (segment, offset) => pathSegments[startIndex + offset] === segment
2128
- )
2129
- );
2130
- }).map(([configPath, config]) => ({ configPath, config }));
2131
- }
2132
2680
  function parseRateLimitHeaders(response) {
2133
2681
  const info = {};
2134
2682
  const retryAfter = response.headers.get("retry-after");
@@ -2170,78 +2718,6 @@ function parseRateLimitHeaders(response) {
2170
2718
  }
2171
2719
  return info;
2172
2720
  }
2173
- var pathConfig = {
2174
- // e.g. /relay -> https://sdkapi.zapier.com/api/v0/sdk/relay/...
2175
- "/relay": {
2176
- authHeader: "X-Relay-Authorization",
2177
- pathPrefix: "/api/v0/sdk/relay",
2178
- omitDeprecationMessaging: true
2179
- },
2180
- // The concrete gateway form of the relay route. Callers that pass the
2181
- // already-prefixed path reach the same third-party upstreams, so it must
2182
- // classify as relay too; without this entry it would match nothing and
2183
- // sniff deprecation headers off a relay response.
2184
- "/api/v0/sdk/relay": {
2185
- omitDeprecationMessaging: true
2186
- },
2187
- // Concrete sdkapi routes that do not live behind /api/v0/sdk/<service>.
2188
- "/api/v0": {},
2189
- // e.g. /zapier -> https://sdkapi.zapier.com/api/v0/sdk/zapier/...
2190
- "/zapier": {
2191
- authHeader: "Authorization",
2192
- pathPrefix: "/api/v0/sdk/zapier"
2193
- },
2194
- // e.g. /tables -> https://sdkapi.zapier.com/api/v0/sdk/tables/...
2195
- "/tables": {
2196
- authHeader: "Authorization",
2197
- pathPrefix: "/api/v0/sdk/tables"
2198
- },
2199
- // e.g. /trigger-inbox -> https://sdkapi.zapier.com/api/v0/sdk/trigger-inbox/...
2200
- "/trigger-inbox": {
2201
- authHeader: "Authorization",
2202
- pathPrefix: "/api/v0/sdk/trigger-inbox"
2203
- },
2204
- // e.g. /sdkdurableapi -> https://sdkapi.zapier.com/api/v0/sdk/sdkdurableapi/...
2205
- // sdkapi proxies to the sdkdurableapi backend.
2206
- "/sdkdurableapi": {
2207
- authHeader: "Authorization",
2208
- pathPrefix: "/api/v0/sdk/sdkdurableapi"
2209
- },
2210
- // e.g. /durableworkflowzaps -> https://sdkapi.zapier.com/api/v0/sdk/durableworkflowzaps/...
2211
- // sdkapi proxies to the durableworkflowzaps backend.
2212
- "/durableworkflowzaps": {
2213
- authHeader: "Authorization",
2214
- pathPrefix: "/api/v0/sdk/durableworkflowzaps"
2215
- },
2216
- // e.g. /code-substrate-runner -> https://sdkapi.zapier.com/api/v0/sdk/code-substrate-runner/...
2217
- // sdkapi proxies to the code-substrate-runner backend.
2218
- "/code-substrate-runner": {
2219
- authHeader: "Authorization",
2220
- pathPrefix: "/api/v0/sdk/code-substrate-runner"
2221
- },
2222
- // e.g. /code-substrate-workflows -> https://sdkapi.zapier.com/api/v0/sdk/code-substrate-workflows/...
2223
- // sdkapi proxies to the code-substrate-workflows backend.
2224
- "/code-substrate-workflows": {
2225
- authHeader: "Authorization",
2226
- pathPrefix: "/api/v0/sdk/code-substrate-workflows"
2227
- },
2228
- // e.g. /code-substrate-analyzer/validations ->
2229
- // https://api.zapier.com/code-substrate-analyzer/v0/validations
2230
- "/code-substrate-analyzer": {
2231
- authHeader: "Authorization",
2232
- pathPrefix: "/code-substrate-analyzer/v0",
2233
- subdomain: "api"
2234
- },
2235
- // e.g. /forms/v0/forms -> https://api.zapier.com/forms/v0/forms
2236
- // The Forms API is registered on the Public API Gateway and has no sdkapi
2237
- // proxy route, so it goes straight to the gateway. Its governance metadata
2238
- // rewrites /forms/v0/... to the backend's /api/forms/v0/..., which is why no
2239
- // pathPrefix is applied here.
2240
- "/forms": {
2241
- authHeader: "Authorization",
2242
- subdomain: "api"
2243
- }
2244
- };
2245
2721
  var ZapierApiClient = class {
2246
2722
  constructor(options) {
2247
2723
  this.options = options;
@@ -2276,11 +2752,23 @@ var ZapierApiClient = class {
2276
2752
  mergedHeaders.set(key, value);
2277
2753
  });
2278
2754
  this.applyTelemetryHeaders({ headers: mergedHeaders, callId });
2755
+ const {
2756
+ authRequired: _authRequired,
2757
+ requiredScopes: _requiredScopes,
2758
+ searchParams: _searchParams,
2759
+ approvalContext: _approvalContext,
2760
+ customErrorHandler: _customErrorHandler,
2761
+ resource: _resource,
2762
+ ...wireInit
2763
+ } = fetchInit;
2279
2764
  let retries = 0;
2280
2765
  while (true) {
2281
- const response = await this.options.fetch(url, {
2282
- ...fetchInit,
2283
- headers: mergedHeaders
2766
+ const response = await this.options.sendHttpRequest({
2767
+ ...wireInit,
2768
+ // Set the resolved URL and merged headers after the spread so caller
2769
+ // values cannot override them.
2770
+ url,
2771
+ headers: Object.fromEntries(mergedHeaders)
2284
2772
  });
2285
2773
  if (response.status !== 429) {
2286
2774
  return response;
@@ -2774,43 +3262,13 @@ var ZapierApiClient = class {
2774
3262
  }
2775
3263
  // Apply any special routing logic for configured paths.
2776
3264
  applyPathConfiguration(path) {
2777
- const matchingPathEntries = findPathConfigEntries({ path });
2778
- const routingMatch = matchingPathEntries[0];
2779
- const buildResult = (url2) => {
2780
- const resolvedPathEntries = findPathConfigEntries({
2781
- path: url2.pathname,
2782
- matchResolvedGatewayPath: true
2783
- });
2784
- const deprecationPathMatches = [
2785
- ...matchingPathEntries,
2786
- ...resolvedPathEntries
2787
- ];
2788
- const canSendDeprecationMessaging = deprecationPathMatches.length > 0 && deprecationPathMatches.every(
2789
- ({ config }) => config.omitDeprecationMessaging !== true
2790
- );
2791
- return {
2792
- url: url2,
2793
- pathConfig: routingMatch?.config,
2794
- canSendDeprecationMessaging
2795
- };
2796
- };
2797
- let finalPath = path;
2798
- if (routingMatch?.config.pathPrefix) {
2799
- const pathWithoutPrefix = path.slice(routingMatch.configPath.length) || "/";
2800
- finalPath = `${routingMatch.config.pathPrefix}${pathWithoutPrefix}`;
2801
- }
2802
- const zapierBaseUrl = getZapierBaseUrl(this.options.baseUrl);
2803
- if (zapierBaseUrl === this.options.baseUrl.replace(/\/$/, "")) {
2804
- const originalBaseUrl = new URL(this.options.baseUrl);
2805
- const subdomain = routingMatch?.config.subdomain ?? "sdkapi";
2806
- const finalBaseUrl = `https://${subdomain}.${originalBaseUrl.hostname}`;
2807
- const url2 = new URL(finalPath, finalBaseUrl);
2808
- return buildResult(url2);
2809
- }
2810
- const baseUrl = new URL(this.options.baseUrl);
2811
- const basePath = baseUrl.pathname.replace(/\/$/, "");
2812
- const url = new URL(basePath + finalPath, baseUrl.origin);
2813
- return buildResult(url);
3265
+ return resolveRoute({
3266
+ path,
3267
+ baseUrl: this.options.baseUrl,
3268
+ routingOptions: this.options.routingOptions,
3269
+ environment: globalThis.process?.env,
3270
+ debugLog: this.options.debugLog
3271
+ });
2814
3272
  }
2815
3273
  // Helper to build full URLs and return routing info
2816
3274
  buildUrl(path, searchParams) {
@@ -3339,12 +3797,20 @@ var ZapierApiClient = class {
3339
3797
  };
3340
3798
  var createZapierApi = (options) => {
3341
3799
  const { debug = false, fetch: originalFetch = globalThis.fetch } = options;
3800
+ const routingOptions = parseRoutingOptions({ options });
3342
3801
  const debugLog = createDebugLogger(debug);
3343
3802
  const debugFetch = createDebugFetch({ originalFetch, debugLog });
3344
3803
  return new ZapierApiClient({
3345
3804
  ...options,
3346
3805
  debug,
3347
- fetch: debugFetch
3806
+ // The credential-exchange transport. Debug-wrapped here rather than in the
3807
+ // pipeline because `resolveAuthToken` is issued outside it.
3808
+ fetch: debugFetch,
3809
+ // Built from the caller's own `fetch`, not `debugFetch`: the pipeline wraps
3810
+ // for debug itself, and passing the wrapped one would log twice.
3811
+ sendHttpRequest: options.sendHttpRequest ?? createZapierSendHttpRequest({ fetch: options.fetch, debug }),
3812
+ debugLog,
3813
+ routingOptions
3348
3814
  });
3349
3815
  };
3350
3816
 
@@ -3381,9 +3847,11 @@ function getOrCreateApiClient(config) {
3381
3847
  callerPackage
3382
3848
  });
3383
3849
  }
3384
- var SDK_OPTIONS_ID = "zapier/sdkOptions";
3385
- var sdkOptionsPluginRef = kitcore.declareOptionalProperty({
3386
- id: SDK_OPTIONS_ID
3850
+ var zapierHttpTransportPlugin = kitcore.definePlugin({
3851
+ namespace: "zapier",
3852
+ name: "httpTransport",
3853
+ imports: [kitcore.sendHttpRequestPlugin, httpFetchPlugin],
3854
+ exports: [kitcore.sendHttpRequestPlugin]
3387
3855
  });
3388
3856
 
3389
3857
  // src/plugins/api/index.ts
@@ -3411,7 +3879,9 @@ function withCorrelationId({
3411
3879
  var apiPlugin = kitcore.defineProperty({
3412
3880
  namespace: "zapier",
3413
3881
  name: "api",
3414
- imports: [sdkOptionsPluginRef],
3882
+ // Import the aggregate so it also provides `kitcore/httpFetch`; importing
3883
+ // `sendHttpRequestPlugin` alone would bypass `sdkOptions.fetch`.
3884
+ imports: [sdkOptionsPluginRef, zapierHttpTransportPlugin],
3415
3885
  setup: ({ imports }) => {
3416
3886
  const {
3417
3887
  fetch: customFetch = globalThis.fetch,
@@ -3429,7 +3899,8 @@ var apiPlugin = kitcore.defineProperty({
3429
3899
  maxApprovalRetries,
3430
3900
  approvalMode,
3431
3901
  openAutoModeApprovalsInBrowser,
3432
- callerPackage
3902
+ callerPackage,
3903
+ routeOverrides
3433
3904
  } = imports.sdkOptions ?? {};
3434
3905
  return createZapierApi({
3435
3906
  baseUrl,
@@ -3445,7 +3916,11 @@ var apiPlugin = kitcore.defineProperty({
3445
3916
  maxApprovalRetries,
3446
3917
  approvalMode,
3447
3918
  openAutoModeApprovalsInBrowser,
3448
- callerPackage
3919
+ callerPackage,
3920
+ routeOverrides,
3921
+ // Inject the graph-composed transport so host `dispatchHttpRequest` wraps
3922
+ // apply.
3923
+ sendHttpRequest: imports.sendHttpRequest
3449
3924
  });
3450
3925
  },
3451
3926
  get: ({ state, callContext }) => callContext?.callId ? withCorrelationId({ client: state, callId: callContext.callId }) : state
@@ -11837,6 +12312,7 @@ var BaseSdkOptionsSchema = zod.z.object({
11837
12312
  ),
11838
12313
  debug: zod.z.boolean().optional().describe("Enable debug logging."),
11839
12314
  baseUrl: zod.z.string().optional().describe("Base URL for Zapier API endpoints.").meta({ valueHint: "url" }),
12315
+ routeOverrides: zod.z.record(zod.z.string(), zod.z.string()).optional().describe("Maps SDK route prefixes to direct origins.").meta({ internal: true }),
11840
12316
  trackingBaseUrl: zod.z.string().optional().describe("Base URL for Zapier tracking endpoints.").meta({ valueHint: "url" }),
11841
12317
  /**
11842
12318
  * Maximum number of retries for rate-limited requests (429 responses).