@zapier/zapier-sdk 0.108.0 → 0.108.1

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.
@@ -4,7 +4,7 @@ import { withPositional, declareOptionalProperty, defineProperty, createDeprecat
4
4
  export { CONTEXT, CORE_ERROR_SYMBOL, CORE_OPTIONS_ID, CORE_SIGNAL_SYMBOL, CoreCancelledSignal, CoreDisposeError, CoreErrorCode, CoreSignal, addPlugin, composePlugins, createController, createCorePlugin, createFunction, createPaginatedFunction, createPaginatedPluginMethod, createPluginMethod, createPluginStack, createSdk, declareMethod, declareOptionalProperty, declarePlugin, declareProperty, defineFormatter, defineLegacyMerge, defineMethod, defineMethodOverride, defineOverride, definePlugin, defineProperty, defineResolver, disposeSdk, fromFunctionPlugin, getContext, getCoreErrorCause, getCoreErrorCode, getNegatable, getRegistryPlugin, isCoreCancelledSignal, isCoreError, isCoreSignal, isPositional, omitExports, resolvePlugin, runInMethodScope, runWithTelemetryContext, selectExports, toSnakeCase, toTitleCase } from '@zapier/kitcore';
5
5
  import { buildHttpRequestContext, buildActionRunContext } from '@zapier/policy-context';
6
6
  import { ListAppsQuerySchema, AppItemSchema as AppItemSchema$1 } from '@zapier/zapier-sdk-core/v0/schemas/apps';
7
- import { ListConnectionsQuerySchema as ListConnectionsQuerySchema$1, ConnectionSchema, ConnectionItemSchema } from '@zapier/zapier-sdk-core/v0/schemas/connections';
7
+ import { ListConnectionsQuerySchema as ListConnectionsQuerySchema$1, ConnectionSchema, ConnectionsResponseSchema, ConnectionItemSchema } from '@zapier/zapier-sdk-core/v0/schemas/connections';
8
8
  import { ListClientCredentialsQuerySchema as ListClientCredentialsQuerySchema$1, ClientCredentialsItemSchema as ClientCredentialsItemSchema$1, CreateClientCredentialsRequestSchema, ClientCredentialsCreatedItemSchema as ClientCredentialsCreatedItemSchema$1 } from '@zapier/zapier-sdk-core/v0/schemas/client-credentials';
9
9
 
10
10
  // src/constants.ts
@@ -862,8 +862,16 @@ var processResponse = async (response, successStatus, pendingStatus, isPending,
862
862
  };
863
863
  }
864
864
  if (response.status === successStatus) {
865
+ let resultJson;
866
+ try {
867
+ resultJson = await response.json();
868
+ } catch (error) {
869
+ throw new ZapierApiError("Poll response body was not valid JSON", {
870
+ statusCode: response.status,
871
+ cause: error
872
+ });
873
+ }
865
874
  try {
866
- const resultJson = await response.json();
867
875
  if (isPending && isPending(resultJson)) {
868
876
  return {
869
877
  status: "continue" /* Continue */,
@@ -876,13 +884,7 @@ var processResponse = async (response, successStatus, pendingStatus, isPending,
876
884
  errorCount: 0
877
885
  };
878
886
  } catch (error) {
879
- throw new ZapierApiError(
880
- "Result extractor failed to parse successful response as JSON",
881
- {
882
- statusCode: response.status,
883
- cause: error
884
- }
885
- );
887
+ return { status: "failed" /* Failed */, error, errorCount };
886
888
  }
887
889
  }
888
890
  if (response.status !== pendingStatus) {
@@ -955,13 +957,10 @@ async function pollUntilComplete(options) {
955
957
  if (signal?.aborted) throw makeAbortError();
956
958
  }
957
959
  attempts++;
960
+ let terminalThrow;
958
961
  try {
959
962
  const response = await fetchPoll();
960
- const {
961
- result,
962
- errorCount: newErrorCount,
963
- status
964
- } = await processResponse(
963
+ const pollResult = await processResponse(
965
964
  response,
966
965
  successStatus,
967
966
  pendingStatus,
@@ -969,15 +968,18 @@ async function pollUntilComplete(options) {
969
968
  resultExtractor,
970
969
  errorCount
971
970
  );
972
- errorCount = newErrorCount;
973
- if (status === "success" /* Success */) {
974
- return result;
975
- }
976
- if (errorCount >= MAX_CONSECUTIVE_ERRORS) {
977
- throw new ZapierApiError(
978
- `Poll request failed: ${response.status} ${response.statusText}`,
979
- { statusCode: response.status }
980
- );
971
+ errorCount = pollResult.errorCount;
972
+ if (pollResult.status === "failed" /* Failed */) {
973
+ terminalThrow = { error: pollResult.error };
974
+ } else if (pollResult.status === "success" /* Success */) {
975
+ return pollResult.result;
976
+ } else if (errorCount >= MAX_CONSECUTIVE_ERRORS) {
977
+ terminalThrow = {
978
+ error: new ZapierApiError(
979
+ `Poll request failed: ${response.status} ${response.statusText}`,
980
+ { statusCode: response.status }
981
+ )
982
+ };
981
983
  }
982
984
  } catch (error) {
983
985
  if (isAbortError(error)) throw error;
@@ -991,6 +993,7 @@ async function pollUntilComplete(options) {
991
993
  );
992
994
  }
993
995
  }
996
+ if (terminalThrow) throw terminalThrow.error;
994
997
  }
995
998
  }
996
999
 
@@ -2875,7 +2878,7 @@ function logRouteOverride({
2875
2878
  }
2876
2879
 
2877
2880
  // src/sdk-version.ts
2878
- var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.108.0" : void 0) || "unknown";
2881
+ var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.108.1" : void 0) || "unknown";
2879
2882
 
2880
2883
  // src/utils/open-url.ts
2881
2884
  var nodePrefix = "node:";
@@ -8137,7 +8140,7 @@ var ListConnectionsQuerySchema = ListConnectionsQuerySchema$1.omit({
8137
8140
  "Include connections shared with you. By default, only your own connections are returned (owner=me). Set to true to also include shared connections."
8138
8141
  ),
8139
8142
  // Filters on connection expiry. Not a mirror of a server-side status
8140
- // field: the API expresses this as the is_expired filter, which we send as
8143
+ // field: the API expresses this as the stale filter, which we send as
8141
8144
  // false for "active", true for "expired", and omit for "all".
8142
8145
  status: z.enum(["active", "expired", "all"]).optional().describe(
8143
8146
  "Filter connections by expiry: 'active' (default) returns only non-expired connections, 'expired' only expired ones, and 'all' returns both."
@@ -8154,7 +8157,11 @@ var ListConnectionsQuerySchema = ListConnectionsQuerySchema$1.omit({
8154
8157
  deprecated: true,
8155
8158
  deprecationMessage: "Use --status expired instead to show only expired connections, or --status all for both."
8156
8159
  }),
8157
- // Override pageSize to make optional
8160
+ // Override pageSize to make optional, and deliberately leave it uncapped:
8161
+ // the authentications endpoint accepts a `limit` well above 1000 (it sets
8162
+ // no max_limit of its own), so a local ceiling would reject input the API
8163
+ // takes. The description keeps hedging because the endpoint stays free to
8164
+ // add one.
8158
8165
  pageSize: z.number().min(1).optional().describe(
8159
8166
  "Number of connections per page. The upstream API may cap this and reject values above its limit."
8160
8167
  ),
@@ -8163,13 +8170,86 @@ var ListConnectionsQuerySchema = ListConnectionsQuerySchema$1.omit({
8163
8170
  // SDK specific property for pagination/iterable helpers
8164
8171
  cursor: z.string().optional().describe("Cursor to start from")
8165
8172
  }).describe("List available connections with optional filtering");
8166
- ConnectionSchema.extend({
8173
+ var RawConnectionSchema = ConnectionSchema.extend({
8167
8174
  is_stale: z.boolean().optional(),
8168
8175
  is_shared: z.boolean().optional(),
8169
8176
  members: z.array(z.record(z.string(), z.any())).optional(),
8170
8177
  customuser_id: z.number().nullable().optional(),
8171
8178
  customuser_public_id: z.string().nullable().optional()
8172
8179
  });
8180
+ var RawConnectionsResponseSchema = ConnectionsResponseSchema.extend({
8181
+ results: z.array(RawConnectionSchema)
8182
+ });
8183
+
8184
+ // src/normalizers/shared.ts
8185
+ function fastifyToString(value) {
8186
+ if (value === void 0) {
8187
+ return void 0;
8188
+ }
8189
+ if (typeof value === "string") {
8190
+ return value;
8191
+ }
8192
+ if (value === null) {
8193
+ return "";
8194
+ }
8195
+ if (value instanceof Date) {
8196
+ return value.toISOString();
8197
+ }
8198
+ if (value instanceof RegExp) {
8199
+ return value.source;
8200
+ }
8201
+ try {
8202
+ return String(value.toString());
8203
+ } catch {
8204
+ return "[unserializable]";
8205
+ }
8206
+ }
8207
+
8208
+ // src/normalizers/connection.ts
8209
+ function normalizeConnectionItem({
8210
+ connection,
8211
+ appKey: providedAppKey,
8212
+ appVersion: providedAppVersion,
8213
+ adaptError
8214
+ }) {
8215
+ let appKey = providedAppKey;
8216
+ let appVersion = providedAppVersion;
8217
+ if (connection.selected_api && typeof connection.selected_api === "string") {
8218
+ const [extractedAppKey, extractedVersion] = splitVersionedKey(
8219
+ connection.selected_api
8220
+ );
8221
+ if (!appKey) {
8222
+ appKey = extractedAppKey;
8223
+ }
8224
+ if (!appVersion) {
8225
+ appVersion = extractedVersion;
8226
+ }
8227
+ }
8228
+ const {
8229
+ selected_api: selectedApi,
8230
+ customuser_id: profileId,
8231
+ id,
8232
+ account_id: accountId,
8233
+ ...restOfConnection
8234
+ } = connection;
8235
+ const normalized = {
8236
+ ...restOfConnection,
8237
+ id: String(id),
8238
+ account_id: String(accountId),
8239
+ implementation_id: selectedApi,
8240
+ title: connection.title || connection.label || void 0,
8241
+ is_stale: fastifyToString(connection.is_stale),
8242
+ is_expired: fastifyToString(connection.is_stale),
8243
+ is_shared: fastifyToString(connection.is_shared),
8244
+ members: fastifyToString(connection.members),
8245
+ customuser_public_id: fastifyToString(connection.customuser_public_id),
8246
+ expired_at: connection.marked_stale_at,
8247
+ app_key: appKey,
8248
+ app_version: appVersion,
8249
+ profile_id: profileId != null ? String(profileId) : void 0
8250
+ };
8251
+ return createValidator(ConnectionItemSchema, { adaptError })(normalized);
8252
+ }
8173
8253
  function formatConnectionItem(item) {
8174
8254
  const details = [];
8175
8255
  const appKey = item.app_key ?? "unknown";
@@ -8210,7 +8290,8 @@ var listConnectionsPlugin = defineMethod({
8210
8290
  connectionsPluginRef,
8211
8291
  apiPluginRef,
8212
8292
  manifestPluginRef,
8213
- capabilitiesPluginRef
8293
+ capabilitiesPluginRef,
8294
+ coreOptionsPluginRef
8214
8295
  ],
8215
8296
  categories: ["connection"],
8216
8297
  itemType: "Connection",
@@ -8238,18 +8319,17 @@ var listConnectionsPlugin = defineMethod({
8238
8319
  await imports.capabilities.checkCapability("canIncludeSharedConnections");
8239
8320
  }
8240
8321
  const searchParams = {};
8241
- if (input.pageSize !== void 0) {
8242
- searchParams.page_size = input.pageSize.toString();
8243
- }
8322
+ searchParams.limit = (input.pageSize ?? DEFAULT_PAGE_SIZE).toString();
8244
8323
  const appKey = input.app ?? input.appKey;
8245
8324
  if (appKey) {
8246
8325
  const implementationId = await getVersionedImplementationId(appKey);
8247
8326
  if (implementationId) {
8248
8327
  annotate({ selectedApi: implementationId });
8249
8328
  const [versionlessSelectedApi] = splitVersionedKey(implementationId);
8250
- searchParams.app_key = versionlessSelectedApi;
8329
+ searchParams.versionless_selected_api = versionlessSelectedApi;
8251
8330
  } else {
8252
- searchParams.app_key = appKey;
8331
+ const [versionlessAppKey] = splitVersionedKey(appKey);
8332
+ searchParams.versionless_selected_api = versionlessAppKey;
8253
8333
  }
8254
8334
  }
8255
8335
  const connectionRefs = input.connections;
@@ -8263,15 +8343,14 @@ var listConnectionsPlugin = defineMethod({
8263
8343
  })
8264
8344
  )
8265
8345
  );
8266
- searchParams.connection_ids = resolvedIds.filter((id) => id != null).join(",");
8346
+ searchParams.ids = resolvedIds.filter((id) => id != null).join(",");
8267
8347
  } else if (legacyConnectionIds && legacyConnectionIds.length > 0) {
8268
- searchParams.connection_ids = legacyConnectionIds.join(",");
8348
+ searchParams.ids = legacyConnectionIds.join(",");
8269
8349
  }
8270
8350
  if (input.search) {
8271
8351
  searchParams.search = input.search;
8272
- }
8273
- if (input.title) {
8274
- searchParams.title = input.title;
8352
+ } else if (input.title) {
8353
+ searchParams.search = input.title;
8275
8354
  }
8276
8355
  const accountId = input.account ?? input.accountId;
8277
8356
  if (accountId) {
@@ -8294,18 +8373,31 @@ var listConnectionsPlugin = defineMethod({
8294
8373
  }
8295
8374
  const status = input.status ?? (expiredFilter ? "expired" : "active");
8296
8375
  if (status !== "all") {
8297
- searchParams.is_expired = (status === "expired").toString();
8376
+ searchParams.stale = (status === "expired").toString();
8298
8377
  }
8299
8378
  if (input.cursor) {
8300
8379
  searchParams.offset = input.cursor;
8301
8380
  }
8302
- const response = await api.get(
8303
- "/api/v0/connections",
8304
- { searchParams, authRequired: true }
8381
+ searchParams.ordering = "personal_first";
8382
+ const rawResponse = await api.get("/zapier/api/v4/authentications", {
8383
+ searchParams,
8384
+ authRequired: true
8385
+ });
8386
+ const raw = createValidator(RawConnectionsResponseSchema, {
8387
+ adaptError: imports.coreOptions?.adaptError
8388
+ })(rawResponse);
8389
+ let connections = raw.results.map(
8390
+ (connection) => normalizeConnectionItem({
8391
+ connection,
8392
+ adaptError: imports.coreOptions?.adaptError
8393
+ })
8305
8394
  );
8395
+ if (input.title) {
8396
+ connections = connections.filter((conn) => conn.title === input.title);
8397
+ }
8306
8398
  return {
8307
- ...response,
8308
- data: response.data.map(transformConnectionItem)
8399
+ data: connections.map(transformConnectionItem),
8400
+ next: raw.next ?? null
8309
8401
  };
8310
8402
  }
8311
8403
  });
@@ -8481,76 +8573,6 @@ var getAppPlugin = defineMethod({
8481
8573
  throw new ZapierAppNotFoundError("App not found", { appKey });
8482
8574
  }
8483
8575
  });
8484
-
8485
- // src/normalizers/shared.ts
8486
- function fastifyToString(value) {
8487
- if (value === void 0) {
8488
- return void 0;
8489
- }
8490
- if (typeof value === "string") {
8491
- return value;
8492
- }
8493
- if (value === null) {
8494
- return "";
8495
- }
8496
- if (value instanceof Date) {
8497
- return value.toISOString();
8498
- }
8499
- if (value instanceof RegExp) {
8500
- return value.source;
8501
- }
8502
- try {
8503
- return String(value.toString());
8504
- } catch {
8505
- return "[unserializable]";
8506
- }
8507
- }
8508
-
8509
- // src/normalizers/connection.ts
8510
- function normalizeConnectionItem({
8511
- connection,
8512
- appKey: providedAppKey,
8513
- appVersion: providedAppVersion,
8514
- adaptError
8515
- }) {
8516
- let appKey = providedAppKey;
8517
- let appVersion = providedAppVersion;
8518
- if (connection.selected_api && typeof connection.selected_api === "string") {
8519
- const [extractedAppKey, extractedVersion] = splitVersionedKey(
8520
- connection.selected_api
8521
- );
8522
- if (!appKey) {
8523
- appKey = extractedAppKey;
8524
- }
8525
- if (!appVersion) {
8526
- appVersion = extractedVersion;
8527
- }
8528
- }
8529
- const {
8530
- selected_api: selectedApi,
8531
- customuser_id: profileId,
8532
- id,
8533
- account_id: accountId,
8534
- ...restOfConnection
8535
- } = connection;
8536
- const normalized = {
8537
- ...restOfConnection,
8538
- id: String(id),
8539
- account_id: String(accountId),
8540
- implementation_id: selectedApi,
8541
- title: connection.title || connection.label || void 0,
8542
- is_stale: fastifyToString(connection.is_stale),
8543
- is_expired: fastifyToString(connection.is_stale),
8544
- is_shared: fastifyToString(connection.is_shared),
8545
- members: fastifyToString(connection.members),
8546
- customuser_public_id: fastifyToString(connection.customuser_public_id),
8547
- expired_at: connection.marked_stale_at,
8548
- app_key: appKey,
8549
- app_version: appVersion,
8550
- profile_id: profileId != null ? String(profileId) : void 0
8551
- };
8552
- return createValidator(ConnectionItemSchema, { adaptError })(normalized);
8553
- }
8554
8576
  var GetConnectionDescription = "Get details for a specific connection";
8555
8577
  var GetConnectionSchema = z.object({
8556
8578
  connection: ConnectionPropertySchema
@@ -8945,7 +8967,7 @@ var WaitForNewConnectionSchema = z.object({
8945
8967
  "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)."
8946
8968
  ).meta({ deprecated: true })
8947
8969
  }).describe(
8948
- "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```"
8970
+ "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```"
8949
8971
  );
8950
8972
  var WaitForNewConnectionItemSchema = z.object({
8951
8973
  id: z.string().describe(
@@ -8958,12 +8980,22 @@ var WaitForNewConnectionItemSchema = z.object({
8958
8980
  "Human-readable connection title set by the auth flow, when available."
8959
8981
  )
8960
8982
  }).describe("The new connection that was detected.");
8983
+ var WaitForNewConnectionRowSchema = z.object({
8984
+ id: z.union([z.string(), z.number()]),
8985
+ public_id: z.string().optional(),
8986
+ date: z.string().optional(),
8987
+ title: z.string().nullable().optional(),
8988
+ label: z.string().nullable().optional()
8989
+ });
8990
+ var WaitForNewConnectionResponseSchema = z.object({
8991
+ results: z.array(WaitForNewConnectionRowSchema)
8992
+ });
8961
8993
 
8962
8994
  // src/plugins/waitForNewConnection/index.ts
8963
- var CONNECTIONS_PATH = "/api/v0/connections";
8995
+ var CONNECTIONS_PATH = "/zapier/api/v4/authentications";
8964
8996
  var waitForNewConnectionPlugin = defineMethod({
8965
8997
  name: "waitForNewConnection",
8966
- imports: [manifestPluginRef, apiPluginRef],
8998
+ imports: [manifestPluginRef, apiPluginRef, coreOptionsPluginRef],
8967
8999
  categories: ["connection"],
8968
9000
  itemType: "Connection",
8969
9001
  inputSchema: WaitForNewConnectionSchema,
@@ -8974,27 +9006,31 @@ var waitForNewConnectionPlugin = defineMethod({
8974
9006
  run: async ({ imports, input, annotate }) => {
8975
9007
  const api = imports.api;
8976
9008
  const getVersionedImplementationId = imports.manifest.getVersionedImplementationId;
9009
+ const validateConnectionsResponse = createValidator(
9010
+ WaitForNewConnectionResponseSchema,
9011
+ { adaptError: imports.coreOptions?.adaptError }
9012
+ );
8977
9013
  const versionedKey = await getVersionedImplementationId(input.app);
8978
- const appKey = versionedKey ? versionedKey.split("@")[0] : input.app;
9014
+ const [appKey] = splitVersionedKey(versionedKey ?? input.app);
8979
9015
  annotate({ selectedApi: appKey });
8980
9016
  try {
8981
9017
  const top = await api.poll(CONNECTIONS_PATH, {
8982
9018
  searchParams: {
8983
- app_key: appKey,
9019
+ versionless_selected_api: appKey,
8984
9020
  // Scope to the current user's own connections. The connection we're
8985
9021
  // waiting on is by definition owned by the caller; without this the
8986
9022
  // one-row head-check could match a teammate's freshly created
8987
9023
  // connection for the same app.
8988
9024
  owner: "me",
8989
- is_expired: "false",
9025
+ stale: "false",
8990
9026
  ordering: "-date",
8991
- page_size: "1"
9027
+ limit: "1"
8992
9028
  },
8993
9029
  authRequired: true,
8994
9030
  timeoutMilliseconds: input.timeoutSeconds != null ? input.timeoutSeconds * 1e3 : input.timeoutMs ?? 3e5,
8995
9031
  initialDelayMilliseconds: input.pollIntervalMilliseconds ?? input.pollIntervalMs ?? 3e3,
8996
9032
  isPending: (body) => {
8997
- const rows = body.data ?? [];
9033
+ const rows = validateConnectionsResponse(body).results;
8998
9034
  const head = rows[0];
8999
9035
  if (!head?.date) return true;
9000
9036
  const created = Math.floor(new Date(head.date).getTime() / 1e3);
@@ -9002,14 +9038,14 @@ var waitForNewConnectionPlugin = defineMethod({
9002
9038
  },
9003
9039
  resultExtractor: (body) => (
9004
9040
  // `isPending` guaranteed a fresh row at index 0 before this fires.
9005
- body.data[0]
9041
+ validateConnectionsResponse(body).results[0]
9006
9042
  )
9007
9043
  });
9008
9044
  return {
9009
9045
  data: WaitForNewConnectionItemSchema.parse({
9010
9046
  id: String(top.public_id ?? top.id),
9011
9047
  app: appKey,
9012
- title: top.title ?? null
9048
+ title: top.title || top.label || null
9013
9049
  })
9014
9050
  };
9015
9051
  } catch (err) {