@zapier/zapier-sdk 0.108.0 → 0.109.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.
@@ -606,6 +606,83 @@ function extractUserIdsFromJwt(token) {
606
606
  };
607
607
  }
608
608
 
609
+ // src/api/concurrency.ts
610
+ var NO_OP_RELEASE = () => {
611
+ };
612
+ var NO_OP_SEMAPHORE = {
613
+ acquire: async () => NO_OP_RELEASE,
614
+ tryAcquire: () => NO_OP_RELEASE
615
+ };
616
+ function createSemaphore(maxPermits) {
617
+ if (maxPermits === Infinity) {
618
+ return NO_OP_SEMAPHORE;
619
+ }
620
+ if (!Number.isInteger(maxPermits) || maxPermits <= 0) {
621
+ throw new Error(
622
+ `maxPermits must be a positive integer or Infinity, got: ${maxPermits}`
623
+ );
624
+ }
625
+ let permits = maxPermits;
626
+ const waiters = [];
627
+ const release = () => {
628
+ const next = waiters.shift();
629
+ if (next) {
630
+ next.grant();
631
+ } else {
632
+ permits++;
633
+ }
634
+ };
635
+ const makeReleaseOnce = () => {
636
+ let released = false;
637
+ return () => {
638
+ if (released) return;
639
+ released = true;
640
+ release();
641
+ };
642
+ };
643
+ return {
644
+ tryAcquire() {
645
+ if (permits > 0) {
646
+ permits--;
647
+ return makeReleaseOnce();
648
+ }
649
+ return null;
650
+ },
651
+ async acquire(signal) {
652
+ if (signal?.aborted) {
653
+ throw signal.reason ?? new DOMException("Aborted", "AbortError");
654
+ }
655
+ if (permits > 0) {
656
+ permits--;
657
+ return makeReleaseOnce();
658
+ }
659
+ return new Promise((resolve2, reject) => {
660
+ const onAbort = () => {
661
+ const idx = waiters.indexOf(waiter);
662
+ if (idx !== -1) {
663
+ waiters.splice(idx, 1);
664
+ waiter.cancel(
665
+ signal?.reason ?? new DOMException("Aborted", "AbortError")
666
+ );
667
+ }
668
+ };
669
+ const waiter = {
670
+ grant: () => {
671
+ signal?.removeEventListener("abort", onAbort);
672
+ resolve2(makeReleaseOnce());
673
+ },
674
+ cancel: (reason) => {
675
+ signal?.removeEventListener("abort", onAbort);
676
+ reject(reason);
677
+ }
678
+ };
679
+ signal?.addEventListener("abort", onAbort);
680
+ waiters.push(waiter);
681
+ });
682
+ }
683
+ };
684
+ }
685
+
609
686
  // src/api/debug.ts
610
687
  var utilModule = null;
611
688
  var utilPromise = null;
@@ -863,8 +940,16 @@ var processResponse = async (response, successStatus, pendingStatus, isPending,
863
940
  };
864
941
  }
865
942
  if (response.status === successStatus) {
943
+ let resultJson;
944
+ try {
945
+ resultJson = await response.json();
946
+ } catch (error) {
947
+ throw new ZapierApiError("Poll response body was not valid JSON", {
948
+ statusCode: response.status,
949
+ cause: error
950
+ });
951
+ }
866
952
  try {
867
- const resultJson = await response.json();
868
953
  if (isPending && isPending(resultJson)) {
869
954
  return {
870
955
  status: "continue" /* Continue */,
@@ -877,13 +962,7 @@ var processResponse = async (response, successStatus, pendingStatus, isPending,
877
962
  errorCount: 0
878
963
  };
879
964
  } catch (error) {
880
- throw new ZapierApiError(
881
- "Result extractor failed to parse successful response as JSON",
882
- {
883
- statusCode: response.status,
884
- cause: error
885
- }
886
- );
965
+ return { status: "failed" /* Failed */, error, errorCount };
887
966
  }
888
967
  }
889
968
  if (response.status !== pendingStatus) {
@@ -956,13 +1035,10 @@ async function pollUntilComplete(options) {
956
1035
  if (signal?.aborted) throw makeAbortError();
957
1036
  }
958
1037
  attempts++;
1038
+ let terminalThrow;
959
1039
  try {
960
1040
  const response = await fetchPoll();
961
- const {
962
- result,
963
- errorCount: newErrorCount,
964
- status
965
- } = await processResponse(
1041
+ const pollResult = await processResponse(
966
1042
  response,
967
1043
  successStatus,
968
1044
  pendingStatus,
@@ -970,15 +1046,18 @@ async function pollUntilComplete(options) {
970
1046
  resultExtractor,
971
1047
  errorCount
972
1048
  );
973
- errorCount = newErrorCount;
974
- if (status === "success" /* Success */) {
975
- return result;
976
- }
977
- if (errorCount >= MAX_CONSECUTIVE_ERRORS) {
978
- throw new ZapierApiError(
979
- `Poll request failed: ${response.status} ${response.statusText}`,
980
- { statusCode: response.status }
981
- );
1049
+ errorCount = pollResult.errorCount;
1050
+ if (pollResult.status === "failed" /* Failed */) {
1051
+ terminalThrow = { error: pollResult.error };
1052
+ } else if (pollResult.status === "success" /* Success */) {
1053
+ return pollResult.result;
1054
+ } else if (errorCount >= MAX_CONSECUTIVE_ERRORS) {
1055
+ terminalThrow = {
1056
+ error: new ZapierApiError(
1057
+ `Poll request failed: ${response.status} ${response.statusText}`,
1058
+ { statusCode: response.status }
1059
+ )
1060
+ };
982
1061
  }
983
1062
  } catch (error) {
984
1063
  if (isAbortError(error)) throw error;
@@ -992,89 +1071,25 @@ async function pollUntilComplete(options) {
992
1071
  );
993
1072
  }
994
1073
  }
1074
+ if (terminalThrow) throw terminalThrow.error;
995
1075
  }
996
1076
  }
997
1077
 
998
- // src/api/concurrency.ts
999
- var NO_OP_RELEASE = () => {
1000
- };
1001
- var NO_OP_SEMAPHORE = {
1002
- acquire: async () => NO_OP_RELEASE,
1003
- tryAcquire: () => NO_OP_RELEASE
1004
- };
1005
- function createSemaphore(maxPermits) {
1006
- if (maxPermits === Infinity) {
1007
- return NO_OP_SEMAPHORE;
1008
- }
1009
- if (!Number.isInteger(maxPermits) || maxPermits <= 0) {
1010
- throw new Error(
1011
- `maxPermits must be a positive integer or Infinity, got: ${maxPermits}`
1012
- );
1013
- }
1014
- let permits = maxPermits;
1015
- const waiters = [];
1016
- const release = () => {
1017
- const next = waiters.shift();
1018
- if (next) {
1019
- next.grant();
1020
- } else {
1021
- permits++;
1022
- }
1023
- };
1024
- const makeReleaseOnce = () => {
1025
- let released = false;
1026
- return () => {
1027
- if (released) return;
1028
- released = true;
1029
- release();
1030
- };
1031
- };
1032
- return {
1033
- tryAcquire() {
1034
- if (permits > 0) {
1035
- permits--;
1036
- return makeReleaseOnce();
1037
- }
1038
- return null;
1039
- },
1040
- async acquire(signal) {
1041
- if (signal?.aborted) {
1042
- throw signal.reason ?? new DOMException("Aborted", "AbortError");
1043
- }
1044
- if (permits > 0) {
1045
- permits--;
1046
- return makeReleaseOnce();
1047
- }
1048
- return new Promise((resolve2, reject) => {
1049
- const onAbort = () => {
1050
- const idx = waiters.indexOf(waiter);
1051
- if (idx !== -1) {
1052
- waiters.splice(idx, 1);
1053
- waiter.cancel(
1054
- signal?.reason ?? new DOMException("Aborted", "AbortError")
1055
- );
1056
- }
1057
- };
1058
- const waiter = {
1059
- grant: () => {
1060
- signal?.removeEventListener("abort", onAbort);
1061
- resolve2(makeReleaseOnce());
1062
- },
1063
- cancel: (reason) => {
1064
- signal?.removeEventListener("abort", onAbort);
1065
- reject(reason);
1066
- }
1067
- };
1068
- signal?.addEventListener("abort", onAbort);
1069
- waiters.push(waiter);
1070
- });
1071
- }
1072
- };
1078
+ // src/api/correlation.ts
1079
+ var CORRELATION_CALL_ID = Symbol(
1080
+ "zapier.correlationCallId"
1081
+ );
1082
+ function resolveCorrelationId({
1083
+ options,
1084
+ callId
1085
+ }) {
1086
+ return options?.correlationId || getZapierCorrelationId() || callId || void 0;
1087
+ }
1088
+ function resolveCausationId({
1089
+ options
1090
+ }) {
1091
+ return options?.causationId || getZapierCausationId();
1073
1092
  }
1074
- var SDK_OPTIONS_ID = "zapier/sdkOptions";
1075
- var sdkOptionsPluginRef = kitcore.declareOptionalProperty({
1076
- id: SDK_OPTIONS_ID
1077
- });
1078
1093
 
1079
1094
  // src/api/rate-limit.ts
1080
1095
  var EPOCH_THRESHOLD_SECONDS = 1e9;
@@ -1160,99 +1175,6 @@ function createRetryObserver({
1160
1175
  }
1161
1176
  };
1162
1177
  }
1163
-
1164
- // src/plugins/transport/options.ts
1165
- var RETRYABLE_STATUSES = [429, 500, 502, 503, 504];
1166
- var NON_IDEMPOTENT_RETRYABLE_STATUSES = [429];
1167
- function resolveRetryHttpRequestOptions({
1168
- maxNetworkRetries,
1169
- maxNetworkRetryDelayMilliseconds,
1170
- onEvent
1171
- }) {
1172
- const retries = maxNetworkRetries ?? ZAPIER_MAX_NETWORK_RETRIES;
1173
- return {
1174
- maxAttempts: retries + 1,
1175
- maxDelayMilliseconds: maxNetworkRetryDelayMilliseconds ?? ZAPIER_MAX_NETWORK_RETRY_DELAY_MILLISECONDS,
1176
- retryStatuses: RETRYABLE_STATUSES,
1177
- nonIdempotentRetryStatuses: NON_IDEMPOTENT_RETRYABLE_STATUSES,
1178
- onRetry: createRetryObserver({ onEvent, maxNetworkRetries: retries })
1179
- };
1180
- }
1181
- function resolveNetworkRetryDelayMilliseconds({
1182
- maxNetworkRetryDelaySeconds,
1183
- maxNetworkRetryDelayMs
1184
- }) {
1185
- return maxNetworkRetryDelaySeconds != null ? maxNetworkRetryDelaySeconds * 1e3 : maxNetworkRetryDelayMs;
1186
- }
1187
- function resolveTransportFetch({
1188
- fetch: customFetch,
1189
- debug = false
1190
- }) {
1191
- const originalFetch = customFetch ?? ((input, init) => globalThis.fetch(input, init));
1192
- if (!debug) return originalFetch;
1193
- return createDebugFetch({
1194
- originalFetch,
1195
- debugLog: createDebugLogger(debug)
1196
- });
1197
- }
1198
-
1199
- // src/plugins/transport/http-fetch.ts
1200
- var httpFetchPlugin = kitcore.defineProperty({
1201
- namespace: "kitcore",
1202
- name: "httpFetch",
1203
- imports: [sdkOptionsPluginRef],
1204
- setup: ({ imports }) => resolveTransportFetch({
1205
- fetch: imports.sdkOptions?.fetch,
1206
- debug: imports.sdkOptions?.debug
1207
- }),
1208
- get: ({ state }) => state
1209
- });
1210
-
1211
- // src/plugins/transport/standalone.ts
1212
- function createZapierSendHttpRequest({
1213
- fetch: customFetch,
1214
- debug,
1215
- maxNetworkRetries,
1216
- maxNetworkRetryDelayMilliseconds,
1217
- onEvent
1218
- }) {
1219
- const sdk = kitcore.createSdk(
1220
- kitcore.definePlugin({
1221
- name: "zapierStandaloneHttpTransport",
1222
- imports: [kitcore.sendHttpRequestPlugin, kitcore.retryHttpRequestPlugin, httpFetchPlugin],
1223
- exports: [kitcore.sendHttpRequestPlugin]
1224
- }),
1225
- {
1226
- configuration: {
1227
- [SDK_OPTIONS_ID]: { fetch: customFetch, debug },
1228
- // Filled by configuration rather than the graph's property plugin: the
1229
- // caller here holds client-shaped ms options, not SDK options.
1230
- [kitcore.RETRY_HTTP_REQUEST_OPTIONS_ID]: resolveRetryHttpRequestOptions({
1231
- maxNetworkRetries,
1232
- maxNetworkRetryDelayMilliseconds,
1233
- onEvent
1234
- })
1235
- }
1236
- }
1237
- );
1238
- return sdk.sendHttpRequest;
1239
- }
1240
-
1241
- // src/api/correlation.ts
1242
- var CORRELATION_CALL_ID = Symbol(
1243
- "zapier.correlationCallId"
1244
- );
1245
- function resolveCorrelationId({
1246
- options,
1247
- callId
1248
- }) {
1249
- return options?.correlationId || getZapierCorrelationId() || callId || void 0;
1250
- }
1251
- function resolveCausationId({
1252
- options
1253
- }) {
1254
- return options?.causationId || getZapierCausationId();
1255
- }
1256
1178
  var ClientCredentialsObjectSchema = zod.z.object({
1257
1179
  type: zod.z.enum(["client_credentials"]).optional().meta({ internal: true }),
1258
1180
  clientId: zod.z.string().describe("OAuth client ID for authentication.").meta({ valueHint: "id" }),
@@ -2876,7 +2798,7 @@ function logRouteOverride({
2876
2798
  }
2877
2799
 
2878
2800
  // src/sdk-version.ts
2879
- var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.108.0" : void 0) || "unknown";
2801
+ var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.109.0" : void 0) || "unknown";
2880
2802
 
2881
2803
  // src/utils/open-url.ts
2882
2804
  var nodePrefix = "node:";
@@ -3895,7 +3817,7 @@ var ZapierApiClient = class {
3895
3817
  }
3896
3818
  await openApproval(approval.approval_url);
3897
3819
  }
3898
- const timeoutMs = this.options.approvalTimeoutMilliseconds ?? this.options.approvalTimeoutMs ?? DEFAULT_APPROVAL_TIMEOUT_MILLISECONDS;
3820
+ const timeoutMs = this.options.approvalTimeoutMilliseconds ?? DEFAULT_APPROVAL_TIMEOUT_MILLISECONDS;
3899
3821
  const approvalDeadline = Date.now() + timeoutMs;
3900
3822
  let streamAbortController;
3901
3823
  let streamPromise;
@@ -4063,7 +3985,7 @@ var ZapierApiClient = class {
4063
3985
  );
4064
3986
  }
4065
3987
  };
4066
- var createZapierApi = (options) => {
3988
+ var createApiClient = (options) => {
4067
3989
  const { debug = false, fetch: originalFetch = globalThis.fetch } = options;
4068
3990
  const routingOptions = parseRoutingOptions({ options });
4069
3991
  const debugLog = createDebugLogger(debug);
@@ -4074,62 +3996,94 @@ var createZapierApi = (options) => {
4074
3996
  // The credential-exchange transport. Debug-wrapped here rather than in the
4075
3997
  // pipeline because `resolveAuthToken` is issued outside it.
4076
3998
  fetch: debugFetch,
4077
- // Built from the caller's own `fetch`, not `debugFetch`: the pipeline wraps
4078
- // for debug itself, and passing the wrapped one would log twice.
4079
- sendHttpRequest: options.sendHttpRequest ?? createZapierSendHttpRequest({
4080
- fetch: options.fetch,
4081
- debug,
4082
- onEvent: options.onEvent,
4083
- maxNetworkRetries: options.maxNetworkRetries,
4084
- maxNetworkRetryDelayMilliseconds: options.maxNetworkRetryDelayMilliseconds ?? options.maxNetworkRetryDelayMs
4085
- }),
3999
+ sendHttpRequest: options.sendHttpRequest,
4086
4000
  debugLog,
4087
4001
  routingOptions
4088
4002
  });
4089
4003
  };
4090
-
4091
- // src/api/error-classification.ts
4092
- function isPermanentHttpError(err) {
4093
- if (!isZapierError(err)) return false;
4094
- if (isZapierAuthenticationError(err) && err.statusCode === void 0) {
4095
- return true;
4004
+ var API_CLIENT_DURATIONS_ID = "zapier/apiClientDurations";
4005
+ var apiClientDurationsPluginRef = kitcore.declareOptionalProperty({
4006
+ id: API_CLIENT_DURATIONS_ID
4007
+ });
4008
+ function resolveNetworkRetryDelayMilliseconds({
4009
+ apiClientDurations,
4010
+ sdkOptions
4011
+ }) {
4012
+ if (apiClientDurations?.maxNetworkRetryDelayMilliseconds != null) {
4013
+ return apiClientDurations.maxNetworkRetryDelayMilliseconds;
4096
4014
  }
4097
- const { statusCode } = err;
4098
- return statusCode !== void 0 && statusCode >= 400 && statusCode < 500 && statusCode !== 429;
4015
+ if (sdkOptions?.maxNetworkRetryDelaySeconds != null) {
4016
+ return sdkOptions.maxNetworkRetryDelaySeconds * 1e3;
4017
+ }
4018
+ return sdkOptions?.maxNetworkRetryDelayMs;
4099
4019
  }
4100
-
4101
- // src/api/index.ts
4102
- function getOrCreateApiClient(config) {
4103
- const {
4104
- baseUrl = ZAPIER_BASE_URL,
4105
- credentials,
4106
- token,
4107
- api: providedApi,
4108
- debug = false,
4109
- fetch: customFetch,
4110
- callerPackage
4111
- } = config;
4112
- if (providedApi) {
4113
- return providedApi;
4020
+ function resolveApprovalTimeoutMilliseconds({
4021
+ apiClientDurations,
4022
+ sdkOptions
4023
+ }) {
4024
+ if (apiClientDurations?.approvalTimeoutMilliseconds != null) {
4025
+ return apiClientDurations.approvalTimeoutMilliseconds;
4114
4026
  }
4115
- return createZapierApi({
4116
- baseUrl,
4117
- credentials,
4118
- token,
4119
- debug,
4120
- fetch: customFetch,
4121
- callerPackage
4027
+ if (sdkOptions?.approvalTimeoutSeconds != null) {
4028
+ return sdkOptions.approvalTimeoutSeconds * 1e3;
4029
+ }
4030
+ return sdkOptions?.approvalTimeoutMs;
4031
+ }
4032
+ var SDK_OPTIONS_ID = "zapier/sdkOptions";
4033
+ var sdkOptionsPluginRef = kitcore.declareOptionalProperty({
4034
+ id: SDK_OPTIONS_ID
4035
+ });
4036
+
4037
+ // src/plugins/transport/options.ts
4038
+ var RETRYABLE_STATUSES = [429, 500, 502, 503, 504];
4039
+ var NON_IDEMPOTENT_RETRYABLE_STATUSES = [429];
4040
+ function resolveRetryHttpRequestOptions({
4041
+ maxNetworkRetries,
4042
+ maxNetworkRetryDelayMilliseconds,
4043
+ onEvent
4044
+ }) {
4045
+ const retries = maxNetworkRetries ?? ZAPIER_MAX_NETWORK_RETRIES;
4046
+ return {
4047
+ maxAttempts: retries + 1,
4048
+ maxDelayMilliseconds: maxNetworkRetryDelayMilliseconds ?? ZAPIER_MAX_NETWORK_RETRY_DELAY_MILLISECONDS,
4049
+ retryStatuses: RETRYABLE_STATUSES,
4050
+ nonIdempotentRetryStatuses: NON_IDEMPOTENT_RETRYABLE_STATUSES,
4051
+ onRetry: createRetryObserver({ onEvent, maxNetworkRetries: retries })
4052
+ };
4053
+ }
4054
+ function resolveTransportFetch({
4055
+ fetch: customFetch,
4056
+ debug = false
4057
+ }) {
4058
+ const originalFetch = customFetch ?? ((input, init) => globalThis.fetch(input, init));
4059
+ if (!debug) return originalFetch;
4060
+ return createDebugFetch({
4061
+ originalFetch,
4062
+ debugLog: createDebugLogger(debug)
4122
4063
  });
4123
4064
  }
4065
+
4066
+ // src/plugins/transport/http-fetch.ts
4067
+ var httpFetchPlugin = kitcore.defineProperty({
4068
+ namespace: "kitcore",
4069
+ name: "httpFetch",
4070
+ imports: [sdkOptionsPluginRef],
4071
+ setup: ({ imports }) => resolveTransportFetch({
4072
+ fetch: imports.sdkOptions?.fetch,
4073
+ debug: imports.sdkOptions?.debug
4074
+ }),
4075
+ get: ({ state }) => state
4076
+ });
4124
4077
  var retryHttpRequestOptionsPlugin = kitcore.defineProperty({
4125
4078
  namespace: "kitcore",
4126
4079
  name: "retryHttpRequestOptions",
4127
- imports: [sdkOptionsPluginRef],
4080
+ imports: [sdkOptionsPluginRef, apiClientDurationsPluginRef],
4128
4081
  setup: ({ imports }) => resolveRetryHttpRequestOptions({
4129
4082
  maxNetworkRetries: imports.sdkOptions?.maxNetworkRetries,
4130
- maxNetworkRetryDelayMilliseconds: resolveNetworkRetryDelayMilliseconds(
4131
- imports.sdkOptions ?? {}
4132
- ),
4083
+ maxNetworkRetryDelayMilliseconds: resolveNetworkRetryDelayMilliseconds({
4084
+ apiClientDurations: imports.apiClientDurations,
4085
+ sdkOptions: imports.sdkOptions
4086
+ }),
4133
4087
  onEvent: imports.sdkOptions?.onEvent
4134
4088
  }),
4135
4089
  get: ({ state }) => state
@@ -4173,10 +4127,14 @@ function withCorrelationId({
4173
4127
  var apiPlugin = kitcore.defineProperty({
4174
4128
  namespace: "zapier",
4175
4129
  name: "api",
4176
- // Import the aggregate so it also provides `kitcore/httpFetch`; importing
4177
- // `sendHttpRequestPlugin` alone would bypass `sdkOptions.fetch`.
4178
- imports: [sdkOptionsPluginRef, zapierHttpTransportPlugin],
4130
+ // Import the aggregate so SDK options and host transport wraps are applied.
4131
+ imports: [
4132
+ sdkOptionsPluginRef,
4133
+ apiClientDurationsPluginRef,
4134
+ zapierHttpTransportPlugin
4135
+ ],
4179
4136
  setup: ({ imports }) => {
4137
+ const sdkOptions = imports.sdkOptions ?? {};
4180
4138
  const {
4181
4139
  fetch: customFetch = globalThis.fetch,
4182
4140
  baseUrl = ZAPIER_BASE_URL,
@@ -4184,38 +4142,33 @@ var apiPlugin = kitcore.defineProperty({
4184
4142
  token,
4185
4143
  onEvent,
4186
4144
  debug = false,
4187
- maxNetworkRetries = ZAPIER_MAX_NETWORK_RETRIES,
4188
- maxNetworkRetryDelaySeconds,
4189
- maxNetworkRetryDelayMs,
4190
4145
  maxConcurrentRequests = ZAPIER_MAX_CONCURRENT_REQUESTS,
4191
- approvalTimeoutSeconds,
4192
- approvalTimeoutMs,
4193
4146
  maxApprovalRetries,
4194
4147
  approvalMode,
4195
4148
  openAutoModeApprovalsInBrowser,
4196
4149
  callerPackage,
4150
+ cache,
4197
4151
  routeOverrides,
4198
4152
  correlationId,
4199
4153
  causationId
4200
- } = imports.sdkOptions ?? {};
4201
- return createZapierApi({
4154
+ } = sdkOptions;
4155
+ return createApiClient({
4202
4156
  baseUrl,
4203
4157
  credentials,
4204
4158
  token,
4205
4159
  debug,
4206
4160
  fetch: customFetch,
4207
4161
  onEvent,
4208
- maxNetworkRetries,
4209
- maxNetworkRetryDelayMilliseconds: resolveNetworkRetryDelayMilliseconds({
4210
- maxNetworkRetryDelaySeconds,
4211
- maxNetworkRetryDelayMs
4212
- }) ?? ZAPIER_MAX_NETWORK_RETRY_DELAY_MILLISECONDS,
4213
4162
  maxConcurrentRequests,
4214
- approvalTimeoutMilliseconds: approvalTimeoutSeconds != null ? approvalTimeoutSeconds * 1e3 : approvalTimeoutMs,
4163
+ approvalTimeoutMilliseconds: resolveApprovalTimeoutMilliseconds({
4164
+ apiClientDurations: imports.apiClientDurations,
4165
+ sdkOptions
4166
+ }),
4215
4167
  maxApprovalRetries,
4216
4168
  approvalMode,
4217
4169
  openAutoModeApprovalsInBrowser,
4218
4170
  callerPackage,
4171
+ cache,
4219
4172
  routeOverrides,
4220
4173
  // Inject the graph-composed transport so host `dispatchHttpRequest` wraps
4221
4174
  // apply.
@@ -8138,7 +8091,7 @@ var ListConnectionsQuerySchema = connections.ListConnectionsQuerySchema.omit({
8138
8091
  "Include connections shared with you. By default, only your own connections are returned (owner=me). Set to true to also include shared connections."
8139
8092
  ),
8140
8093
  // Filters on connection expiry. Not a mirror of a server-side status
8141
- // field: the API expresses this as the is_expired filter, which we send as
8094
+ // field: the API expresses this as the stale filter, which we send as
8142
8095
  // false for "active", true for "expired", and omit for "all".
8143
8096
  status: zod.z.enum(["active", "expired", "all"]).optional().describe(
8144
8097
  "Filter connections by expiry: 'active' (default) returns only non-expired connections, 'expired' only expired ones, and 'all' returns both."
@@ -8155,7 +8108,11 @@ var ListConnectionsQuerySchema = connections.ListConnectionsQuerySchema.omit({
8155
8108
  deprecated: true,
8156
8109
  deprecationMessage: "Use --status expired instead to show only expired connections, or --status all for both."
8157
8110
  }),
8158
- // Override pageSize to make optional
8111
+ // Override pageSize to make optional, and deliberately leave it uncapped:
8112
+ // the authentications endpoint accepts a `limit` well above 1000 (it sets
8113
+ // no max_limit of its own), so a local ceiling would reject input the API
8114
+ // takes. The description keeps hedging because the endpoint stays free to
8115
+ // add one.
8159
8116
  pageSize: zod.z.number().min(1).optional().describe(
8160
8117
  "Number of connections per page. The upstream API may cap this and reject values above its limit."
8161
8118
  ),
@@ -8164,13 +8121,86 @@ var ListConnectionsQuerySchema = connections.ListConnectionsQuerySchema.omit({
8164
8121
  // SDK specific property for pagination/iterable helpers
8165
8122
  cursor: zod.z.string().optional().describe("Cursor to start from")
8166
8123
  }).describe("List available connections with optional filtering");
8167
- connections.ConnectionSchema.extend({
8124
+ var RawConnectionSchema = connections.ConnectionSchema.extend({
8168
8125
  is_stale: zod.z.boolean().optional(),
8169
8126
  is_shared: zod.z.boolean().optional(),
8170
8127
  members: zod.z.array(zod.z.record(zod.z.string(), zod.z.any())).optional(),
8171
8128
  customuser_id: zod.z.number().nullable().optional(),
8172
8129
  customuser_public_id: zod.z.string().nullable().optional()
8173
8130
  });
8131
+ var RawConnectionsResponseSchema = connections.ConnectionsResponseSchema.extend({
8132
+ results: zod.z.array(RawConnectionSchema)
8133
+ });
8134
+
8135
+ // src/normalizers/shared.ts
8136
+ function fastifyToString(value) {
8137
+ if (value === void 0) {
8138
+ return void 0;
8139
+ }
8140
+ if (typeof value === "string") {
8141
+ return value;
8142
+ }
8143
+ if (value === null) {
8144
+ return "";
8145
+ }
8146
+ if (value instanceof Date) {
8147
+ return value.toISOString();
8148
+ }
8149
+ if (value instanceof RegExp) {
8150
+ return value.source;
8151
+ }
8152
+ try {
8153
+ return String(value.toString());
8154
+ } catch {
8155
+ return "[unserializable]";
8156
+ }
8157
+ }
8158
+
8159
+ // src/normalizers/connection.ts
8160
+ function normalizeConnectionItem({
8161
+ connection,
8162
+ appKey: providedAppKey,
8163
+ appVersion: providedAppVersion,
8164
+ adaptError
8165
+ }) {
8166
+ let appKey = providedAppKey;
8167
+ let appVersion = providedAppVersion;
8168
+ if (connection.selected_api && typeof connection.selected_api === "string") {
8169
+ const [extractedAppKey, extractedVersion] = splitVersionedKey(
8170
+ connection.selected_api
8171
+ );
8172
+ if (!appKey) {
8173
+ appKey = extractedAppKey;
8174
+ }
8175
+ if (!appVersion) {
8176
+ appVersion = extractedVersion;
8177
+ }
8178
+ }
8179
+ const {
8180
+ selected_api: selectedApi,
8181
+ customuser_id: profileId,
8182
+ id,
8183
+ account_id: accountId,
8184
+ ...restOfConnection
8185
+ } = connection;
8186
+ const normalized = {
8187
+ ...restOfConnection,
8188
+ id: String(id),
8189
+ account_id: String(accountId),
8190
+ implementation_id: selectedApi,
8191
+ title: connection.title || connection.label || void 0,
8192
+ is_stale: fastifyToString(connection.is_stale),
8193
+ is_expired: fastifyToString(connection.is_stale),
8194
+ is_shared: fastifyToString(connection.is_shared),
8195
+ members: fastifyToString(connection.members),
8196
+ customuser_public_id: fastifyToString(connection.customuser_public_id),
8197
+ expired_at: connection.marked_stale_at,
8198
+ app_key: appKey,
8199
+ app_version: appVersion,
8200
+ profile_id: profileId != null ? String(profileId) : void 0
8201
+ };
8202
+ return kitcore.createValidator(connections.ConnectionItemSchema, { adaptError })(normalized);
8203
+ }
8174
8204
  function formatConnectionItem(item) {
8175
8205
  const details = [];
8176
8206
  const appKey = item.app_key ?? "unknown";
@@ -8211,7 +8241,8 @@ var listConnectionsPlugin = kitcore.defineMethod({
8211
8241
  connectionsPluginRef,
8212
8242
  apiPluginRef,
8213
8243
  manifestPluginRef,
8214
- capabilitiesPluginRef
8244
+ capabilitiesPluginRef,
8245
+ kitcore.coreOptionsPluginRef
8215
8246
  ],
8216
8247
  categories: ["connection"],
8217
8248
  itemType: "Connection",
@@ -8239,18 +8270,17 @@ var listConnectionsPlugin = kitcore.defineMethod({
8239
8270
  await imports.capabilities.checkCapability("canIncludeSharedConnections");
8240
8271
  }
8241
8272
  const searchParams = {};
8242
- if (input.pageSize !== void 0) {
8243
- searchParams.page_size = input.pageSize.toString();
8244
- }
8273
+ searchParams.limit = (input.pageSize ?? DEFAULT_PAGE_SIZE).toString();
8245
8274
  const appKey = input.app ?? input.appKey;
8246
8275
  if (appKey) {
8247
8276
  const implementationId = await getVersionedImplementationId(appKey);
8248
8277
  if (implementationId) {
8249
8278
  annotate({ selectedApi: implementationId });
8250
8279
  const [versionlessSelectedApi] = splitVersionedKey(implementationId);
8251
- searchParams.app_key = versionlessSelectedApi;
8280
+ searchParams.versionless_selected_api = versionlessSelectedApi;
8252
8281
  } else {
8253
- searchParams.app_key = appKey;
8282
+ const [versionlessAppKey] = splitVersionedKey(appKey);
8283
+ searchParams.versionless_selected_api = versionlessAppKey;
8254
8284
  }
8255
8285
  }
8256
8286
  const connectionRefs = input.connections;
@@ -8264,15 +8294,14 @@ var listConnectionsPlugin = kitcore.defineMethod({
8264
8294
  })
8265
8295
  )
8266
8296
  );
8267
- searchParams.connection_ids = resolvedIds.filter((id) => id != null).join(",");
8297
+ searchParams.ids = resolvedIds.filter((id) => id != null).join(",");
8268
8298
  } else if (legacyConnectionIds && legacyConnectionIds.length > 0) {
8269
- searchParams.connection_ids = legacyConnectionIds.join(",");
8299
+ searchParams.ids = legacyConnectionIds.join(",");
8270
8300
  }
8271
8301
  if (input.search) {
8272
8302
  searchParams.search = input.search;
8273
- }
8274
- if (input.title) {
8275
- searchParams.title = input.title;
8303
+ } else if (input.title) {
8304
+ searchParams.search = input.title;
8276
8305
  }
8277
8306
  const accountId = input.account ?? input.accountId;
8278
8307
  if (accountId) {
@@ -8295,18 +8324,31 @@ var listConnectionsPlugin = kitcore.defineMethod({
8295
8324
  }
8296
8325
  const status = input.status ?? (expiredFilter ? "expired" : "active");
8297
8326
  if (status !== "all") {
8298
- searchParams.is_expired = (status === "expired").toString();
8327
+ searchParams.stale = (status === "expired").toString();
8299
8328
  }
8300
8329
  if (input.cursor) {
8301
8330
  searchParams.offset = input.cursor;
8302
8331
  }
8303
- const response = await api.get(
8304
- "/api/v0/connections",
8305
- { searchParams, authRequired: true }
8332
+ searchParams.ordering = "personal_first";
8333
+ const rawResponse = await api.get("/zapier/api/v4/authentications", {
8334
+ searchParams,
8335
+ authRequired: true
8336
+ });
8337
+ const raw = kitcore.createValidator(RawConnectionsResponseSchema, {
8338
+ adaptError: imports.coreOptions?.adaptError
8339
+ })(rawResponse);
8340
+ let connections = raw.results.map(
8341
+ (connection) => normalizeConnectionItem({
8342
+ connection,
8343
+ adaptError: imports.coreOptions?.adaptError
8344
+ })
8306
8345
  );
8346
+ if (input.title) {
8347
+ connections = connections.filter((conn) => conn.title === input.title);
8348
+ }
8307
8349
  return {
8308
- ...response,
8309
- data: response.data.map(transformConnectionItem)
8350
+ data: connections.map(transformConnectionItem),
8351
+ next: raw.next ?? null
8310
8352
  };
8311
8353
  }
8312
8354
  });
@@ -8482,76 +8524,6 @@ var getAppPlugin = kitcore.defineMethod({
8482
8524
  throw new ZapierAppNotFoundError("App not found", { appKey });
8483
8525
  }
8484
8526
  });
8485
-
8486
- // src/normalizers/shared.ts
8487
- function fastifyToString(value) {
8488
- if (value === void 0) {
8489
- return void 0;
8490
- }
8491
- if (typeof value === "string") {
8492
- return value;
8493
- }
8494
- if (value === null) {
8495
- return "";
8496
- }
8497
- if (value instanceof Date) {
8498
- return value.toISOString();
8499
- }
8500
- if (value instanceof RegExp) {
8501
- return value.source;
8502
- }
8503
- try {
8504
- return String(value.toString());
8505
- } catch {
8506
- return "[unserializable]";
8507
- }
8508
- }
8509
-
8510
- // src/normalizers/connection.ts
8511
- function normalizeConnectionItem({
8512
- connection,
8513
- appKey: providedAppKey,
8514
- appVersion: providedAppVersion,
8515
- adaptError
8516
- }) {
8517
- let appKey = providedAppKey;
8518
- let appVersion = providedAppVersion;
8519
- if (connection.selected_api && typeof connection.selected_api === "string") {
8520
- const [extractedAppKey, extractedVersion] = splitVersionedKey(
8521
- connection.selected_api
8522
- );
8523
- if (!appKey) {
8524
- appKey = extractedAppKey;
8525
- }
8526
- if (!appVersion) {
8527
- appVersion = extractedVersion;
8528
- }
8529
- }
8530
- const {
8531
- selected_api: selectedApi,
8532
- customuser_id: profileId,
8533
- id,
8534
- account_id: accountId,
8535
- ...restOfConnection
8536
- } = connection;
8537
- const normalized = {
8538
- ...restOfConnection,
8539
- id: String(id),
8540
- account_id: String(accountId),
8541
- implementation_id: selectedApi,
8542
- title: connection.title || connection.label || void 0,
8543
- is_stale: fastifyToString(connection.is_stale),
8544
- is_expired: fastifyToString(connection.is_stale),
8545
- is_shared: fastifyToString(connection.is_shared),
8546
- members: fastifyToString(connection.members),
8547
- customuser_public_id: fastifyToString(connection.customuser_public_id),
8548
- expired_at: connection.marked_stale_at,
8549
- app_key: appKey,
8550
- app_version: appVersion,
8551
- profile_id: profileId != null ? String(profileId) : void 0
8552
- };
8553
- return kitcore.createValidator(connections.ConnectionItemSchema, { adaptError })(normalized);
8554
- }
8555
8527
  var GetConnectionDescription = "Get details for a specific connection";
8556
8528
  var GetConnectionSchema = zod.z.object({
8557
8529
  connection: ConnectionPropertySchema
@@ -8946,7 +8918,7 @@ var WaitForNewConnectionSchema = zod.z.object({
8946
8918
  "Delay before the first poll request, in ms. Default 3 seconds (3_000). Subsequent polling cadence is managed by the SDK's polling primitive (backoff with sane defaults)."
8947
8919
  ).meta({ deprecated: true })
8948
8920
  }).describe(
8949
- "Wait for a new connection to appear for the given app. Polls `/api/v0/connections` with server-side `ordering=-date` until the most recent matching row's `date` is at or after the started-at timestamp, then returns it. Pair with `get-connection-start-url` \u2014 that mints the URL the user opens, this waits for the resulting connection to land. Errors with a timeout after the configured timeout (default 5 min). Example (JS):\n\n```ts\nconst { data: { url, app, startedAt } } = await zapier.getConnectionStartUrl({ app: 'slack' });\n// show `url` to the user via the channel they're reading from\nconst { data: conn } = await zapier.waitForNewConnection({ app, startedAt });\n```"
8921
+ "Wait for a new connection to appear for the given app. Polls the connections list newest-first until the most recent matching row's `date` is at or after the started-at timestamp, then returns it. Pair with `get-connection-start-url` \u2014 that mints the URL the user opens, this waits for the resulting connection to land. Errors with a timeout after the configured timeout (default 5 min). Example (JS):\n\n```ts\nconst { data: { url, app, startedAt } } = await zapier.getConnectionStartUrl({ app: 'slack' });\n// show `url` to the user via the channel they're reading from\nconst { data: conn } = await zapier.waitForNewConnection({ app, startedAt });\n```"
8950
8922
  );
8951
8923
  var WaitForNewConnectionItemSchema = zod.z.object({
8952
8924
  id: zod.z.string().describe(
@@ -8959,12 +8931,22 @@ var WaitForNewConnectionItemSchema = zod.z.object({
8959
8931
  "Human-readable connection title set by the auth flow, when available."
8960
8932
  )
8961
8933
  }).describe("The new connection that was detected.");
8934
+ var WaitForNewConnectionRowSchema = zod.z.object({
8935
+ id: zod.z.union([zod.z.string(), zod.z.number()]),
8936
+ public_id: zod.z.string().optional(),
8937
+ date: zod.z.string().optional(),
8938
+ title: zod.z.string().nullable().optional(),
8939
+ label: zod.z.string().nullable().optional()
8940
+ });
8941
+ var WaitForNewConnectionResponseSchema = zod.z.object({
8942
+ results: zod.z.array(WaitForNewConnectionRowSchema)
8943
+ });
8962
8944
 
8963
8945
  // src/plugins/waitForNewConnection/index.ts
8964
- var CONNECTIONS_PATH = "/api/v0/connections";
8946
+ var CONNECTIONS_PATH = "/zapier/api/v4/authentications";
8965
8947
  var waitForNewConnectionPlugin = kitcore.defineMethod({
8966
8948
  name: "waitForNewConnection",
8967
- imports: [manifestPluginRef, apiPluginRef],
8949
+ imports: [manifestPluginRef, apiPluginRef, kitcore.coreOptionsPluginRef],
8968
8950
  categories: ["connection"],
8969
8951
  itemType: "Connection",
8970
8952
  inputSchema: WaitForNewConnectionSchema,
@@ -8975,27 +8957,31 @@ var waitForNewConnectionPlugin = kitcore.defineMethod({
8975
8957
  run: async ({ imports, input, annotate }) => {
8976
8958
  const api = imports.api;
8977
8959
  const getVersionedImplementationId = imports.manifest.getVersionedImplementationId;
8960
+ const validateConnectionsResponse = kitcore.createValidator(
8961
+ WaitForNewConnectionResponseSchema,
8962
+ { adaptError: imports.coreOptions?.adaptError }
8963
+ );
8978
8964
  const versionedKey = await getVersionedImplementationId(input.app);
8979
- const appKey = versionedKey ? versionedKey.split("@")[0] : input.app;
8965
+ const [appKey] = splitVersionedKey(versionedKey ?? input.app);
8980
8966
  annotate({ selectedApi: appKey });
8981
8967
  try {
8982
8968
  const top = await api.poll(CONNECTIONS_PATH, {
8983
8969
  searchParams: {
8984
- app_key: appKey,
8970
+ versionless_selected_api: appKey,
8985
8971
  // Scope to the current user's own connections. The connection we're
8986
8972
  // waiting on is by definition owned by the caller; without this the
8987
8973
  // one-row head-check could match a teammate's freshly created
8988
8974
  // connection for the same app.
8989
8975
  owner: "me",
8990
- is_expired: "false",
8976
+ stale: "false",
8991
8977
  ordering: "-date",
8992
- page_size: "1"
8978
+ limit: "1"
8993
8979
  },
8994
8980
  authRequired: true,
8995
8981
  timeoutMilliseconds: input.timeoutSeconds != null ? input.timeoutSeconds * 1e3 : input.timeoutMs ?? 3e5,
8996
8982
  initialDelayMilliseconds: input.pollIntervalMilliseconds ?? input.pollIntervalMs ?? 3e3,
8997
8983
  isPending: (body) => {
8998
- const rows = body.data ?? [];
8984
+ const rows = validateConnectionsResponse(body).results;
8999
8985
  const head = rows[0];
9000
8986
  if (!head?.date) return true;
9001
8987
  const created = Math.floor(new Date(head.date).getTime() / 1e3);
@@ -9003,14 +8989,14 @@ var waitForNewConnectionPlugin = kitcore.defineMethod({
9003
8989
  },
9004
8990
  resultExtractor: (body) => (
9005
8991
  // `isPending` guaranteed a fresh row at index 0 before this fires.
9006
- body.data[0]
8992
+ validateConnectionsResponse(body).results[0]
9007
8993
  )
9008
8994
  });
9009
8995
  return {
9010
8996
  data: WaitForNewConnectionItemSchema.parse({
9011
8997
  id: String(top.public_id ?? top.id),
9012
8998
  app: appKey,
9013
- title: top.title ?? null
8999
+ title: top.title || top.label || null
9014
9000
  })
9015
9001
  };
9016
9002
  } catch (err) {
@@ -10482,6 +10468,112 @@ var drainTriggerInboxPlugin = kitcore.defineMethod({
10482
10468
  });
10483
10469
  }
10484
10470
  });
10471
+ var apiClientRootPlugin = kitcore.definePlugin({
10472
+ namespace: "zapier",
10473
+ name: "apiClientRoot",
10474
+ imports: [apiPlugin],
10475
+ exports: []
10476
+ });
10477
+ function hasStringUrl(request) {
10478
+ return typeof request.url === "string";
10479
+ }
10480
+ function createApiClientGraphConfiguration(options) {
10481
+ const {
10482
+ maxNetworkRetryDelayMilliseconds,
10483
+ maxNetworkRetryDelayMs,
10484
+ approvalTimeoutMilliseconds,
10485
+ approvalTimeoutMs,
10486
+ sendHttpRequest: _sendHttpRequest,
10487
+ ...sdkOptions
10488
+ } = options;
10489
+ return {
10490
+ [SDK_OPTIONS_ID]: sdkOptions,
10491
+ [API_CLIENT_DURATIONS_ID]: {
10492
+ maxNetworkRetryDelayMilliseconds: maxNetworkRetryDelayMilliseconds ?? maxNetworkRetryDelayMs,
10493
+ approvalTimeoutMilliseconds: approvalTimeoutMilliseconds ?? approvalTimeoutMs
10494
+ }
10495
+ };
10496
+ }
10497
+ function createApiClientFromSdkGraph(options) {
10498
+ parseRoutingOptions({ options });
10499
+ const configuration = createApiClientGraphConfiguration(options);
10500
+ const { sendHttpRequest } = options;
10501
+ if (!sendHttpRequest) {
10502
+ const sdk2 = kitcore.createSdk(apiClientRootPlugin, { configuration });
10503
+ return kitcore.resolvePlugin(sdk2, apiPluginRef);
10504
+ }
10505
+ const replaceSendHttpRequestPlugin = kitcore.defineHook({
10506
+ namespace: "zapier",
10507
+ name: "replaceApiClientSendHttpRequest",
10508
+ imports: [kitcore.sendHttpRequestPlugin],
10509
+ wrap: {
10510
+ // Replaces the pipeline rather than wrapping it: `next` is deliberately
10511
+ // unused. A transport supplied through `sendHttpRequest` owns its retry
10512
+ // policy, so running the SDK's stages underneath would nest the caller's
10513
+ // retry loop inside a second one. Dropping them is only safe because the
10514
+ // SDK's retry hook wraps `attemptHttpRequest`, a stage below this seam,
10515
+ // so replacing `sendHttpRequest` removes that loop instead of nesting
10516
+ // inside it. The cost is that the SDK cannot observe retries the caller
10517
+ // performs, and so reports a terminal 429 as zero.
10518
+ sendHttpRequest: ({ input }) => sendHttpRequest(
10519
+ hasStringUrl(input) ? input : { ...input, url: input.url.toString() }
10520
+ )
10521
+ }
10522
+ });
10523
+ const sdk = kitcore.createSdk(
10524
+ kitcore.definePlugin({
10525
+ namespace: "zapier",
10526
+ name: "standaloneApiClientRoot",
10527
+ imports: [apiPlugin, replaceSendHttpRequestPlugin],
10528
+ exports: []
10529
+ }),
10530
+ { configuration }
10531
+ );
10532
+ return kitcore.resolvePlugin(sdk, apiPluginRef);
10533
+ }
10534
+
10535
+ // src/api/error-classification.ts
10536
+ function isPermanentHttpError(err) {
10537
+ if (!isZapierError(err)) return false;
10538
+ if (isZapierAuthenticationError(err) && err.statusCode === void 0) {
10539
+ return true;
10540
+ }
10541
+ const { statusCode } = err;
10542
+ return statusCode !== void 0 && statusCode >= 400 && statusCode < 500 && statusCode !== 429;
10543
+ }
10544
+
10545
+ // src/api/index.ts
10546
+ function createZapierApi(options) {
10547
+ logDeprecation(
10548
+ "createZapierApi is deprecated and will be removed in a future release. Build an SDK with createSdk and access apiPluginRef with resolvePlugin instead."
10549
+ );
10550
+ return createApiClientFromSdkGraph(options);
10551
+ }
10552
+ function getOrCreateApiClient(config) {
10553
+ logDeprecation(
10554
+ "getOrCreateApiClient is deprecated and will be removed in a future release. Use a provided API client directly, or build an SDK with createSdk and access apiPluginRef with resolvePlugin."
10555
+ );
10556
+ const {
10557
+ baseUrl = ZAPIER_BASE_URL,
10558
+ credentials,
10559
+ token,
10560
+ api: providedApi,
10561
+ debug = false,
10562
+ fetch: customFetch,
10563
+ callerPackage
10564
+ } = config;
10565
+ if (providedApi) {
10566
+ return providedApi;
10567
+ }
10568
+ return createApiClientFromSdkGraph({
10569
+ baseUrl,
10570
+ credentials,
10571
+ token,
10572
+ debug,
10573
+ fetch: customFetch,
10574
+ callerPackage
10575
+ });
10576
+ }
10485
10577
 
10486
10578
  // src/plugins/triggers/watchTriggerInbox/sse.ts
10487
10579
  async function* readInboxEvents({