@zapier/zapier-sdk 0.107.2 → 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.
@@ -863,8 +863,16 @@ var processResponse = async (response, successStatus, pendingStatus, isPending,
863
863
  };
864
864
  }
865
865
  if (response.status === successStatus) {
866
+ let resultJson;
867
+ try {
868
+ resultJson = await response.json();
869
+ } catch (error) {
870
+ throw new ZapierApiError("Poll response body was not valid JSON", {
871
+ statusCode: response.status,
872
+ cause: error
873
+ });
874
+ }
866
875
  try {
867
- const resultJson = await response.json();
868
876
  if (isPending && isPending(resultJson)) {
869
877
  return {
870
878
  status: "continue" /* Continue */,
@@ -877,13 +885,7 @@ var processResponse = async (response, successStatus, pendingStatus, isPending,
877
885
  errorCount: 0
878
886
  };
879
887
  } 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
- );
888
+ return { status: "failed" /* Failed */, error, errorCount };
887
889
  }
888
890
  }
889
891
  if (response.status !== pendingStatus) {
@@ -956,13 +958,10 @@ async function pollUntilComplete(options) {
956
958
  if (signal?.aborted) throw makeAbortError();
957
959
  }
958
960
  attempts++;
961
+ let terminalThrow;
959
962
  try {
960
963
  const response = await fetchPoll();
961
- const {
962
- result,
963
- errorCount: newErrorCount,
964
- status
965
- } = await processResponse(
964
+ const pollResult = await processResponse(
966
965
  response,
967
966
  successStatus,
968
967
  pendingStatus,
@@ -970,15 +969,18 @@ async function pollUntilComplete(options) {
970
969
  resultExtractor,
971
970
  errorCount
972
971
  );
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
- );
972
+ errorCount = pollResult.errorCount;
973
+ if (pollResult.status === "failed" /* Failed */) {
974
+ terminalThrow = { error: pollResult.error };
975
+ } else if (pollResult.status === "success" /* Success */) {
976
+ return pollResult.result;
977
+ } else if (errorCount >= MAX_CONSECUTIVE_ERRORS) {
978
+ terminalThrow = {
979
+ error: new ZapierApiError(
980
+ `Poll request failed: ${response.status} ${response.statusText}`,
981
+ { statusCode: response.status }
982
+ )
983
+ };
982
984
  }
983
985
  } catch (error) {
984
986
  if (isAbortError(error)) throw error;
@@ -992,6 +994,7 @@ async function pollUntilComplete(options) {
992
994
  );
993
995
  }
994
996
  }
997
+ if (terminalThrow) throw terminalThrow.error;
995
998
  }
996
999
  }
997
1000
 
@@ -2333,6 +2336,15 @@ var pathConfig = {
2333
2336
  "/agentic-management": {
2334
2337
  authHeader: "Authorization",
2335
2338
  subdomain: "api"
2339
+ },
2340
+ // e.g. /vfs/v1/files -> https://api.zapier.com/vfs/v1/files
2341
+ // The VFS API is registered on the Public API Gateway and has no sdkapi
2342
+ // proxy route, so it goes straight to the gateway. Its governance metadata
2343
+ // rewrites /vfs/v1/... to the backend's /api/v1/fs/..., which is why no
2344
+ // pathPrefix is applied here.
2345
+ "/vfs": {
2346
+ authHeader: "Authorization",
2347
+ subdomain: "api"
2336
2348
  }
2337
2349
  };
2338
2350
 
@@ -2867,7 +2879,7 @@ function logRouteOverride({
2867
2879
  }
2868
2880
 
2869
2881
  // src/sdk-version.ts
2870
- var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.107.2" : void 0) || "unknown";
2882
+ var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.108.1" : void 0) || "unknown";
2871
2883
 
2872
2884
  // src/utils/open-url.ts
2873
2885
  var nodePrefix = "node:";
@@ -8129,7 +8141,7 @@ var ListConnectionsQuerySchema = connections.ListConnectionsQuerySchema.omit({
8129
8141
  "Include connections shared with you. By default, only your own connections are returned (owner=me). Set to true to also include shared connections."
8130
8142
  ),
8131
8143
  // Filters on connection expiry. Not a mirror of a server-side status
8132
- // field: the API expresses this as the is_expired filter, which we send as
8144
+ // field: the API expresses this as the stale filter, which we send as
8133
8145
  // false for "active", true for "expired", and omit for "all".
8134
8146
  status: zod.z.enum(["active", "expired", "all"]).optional().describe(
8135
8147
  "Filter connections by expiry: 'active' (default) returns only non-expired connections, 'expired' only expired ones, and 'all' returns both."
@@ -8146,7 +8158,11 @@ var ListConnectionsQuerySchema = connections.ListConnectionsQuerySchema.omit({
8146
8158
  deprecated: true,
8147
8159
  deprecationMessage: "Use --status expired instead to show only expired connections, or --status all for both."
8148
8160
  }),
8149
- // Override pageSize to make optional
8161
+ // Override pageSize to make optional, and deliberately leave it uncapped:
8162
+ // the authentications endpoint accepts a `limit` well above 1000 (it sets
8163
+ // no max_limit of its own), so a local ceiling would reject input the API
8164
+ // takes. The description keeps hedging because the endpoint stays free to
8165
+ // add one.
8150
8166
  pageSize: zod.z.number().min(1).optional().describe(
8151
8167
  "Number of connections per page. The upstream API may cap this and reject values above its limit."
8152
8168
  ),
@@ -8155,13 +8171,86 @@ var ListConnectionsQuerySchema = connections.ListConnectionsQuerySchema.omit({
8155
8171
  // SDK specific property for pagination/iterable helpers
8156
8172
  cursor: zod.z.string().optional().describe("Cursor to start from")
8157
8173
  }).describe("List available connections with optional filtering");
8158
- connections.ConnectionSchema.extend({
8174
+ var RawConnectionSchema = connections.ConnectionSchema.extend({
8159
8175
  is_stale: zod.z.boolean().optional(),
8160
8176
  is_shared: zod.z.boolean().optional(),
8161
8177
  members: zod.z.array(zod.z.record(zod.z.string(), zod.z.any())).optional(),
8162
8178
  customuser_id: zod.z.number().nullable().optional(),
8163
8179
  customuser_public_id: zod.z.string().nullable().optional()
8164
8180
  });
8181
+ var RawConnectionsResponseSchema = connections.ConnectionsResponseSchema.extend({
8182
+ results: zod.z.array(RawConnectionSchema)
8183
+ });
8184
+
8185
+ // src/normalizers/shared.ts
8186
+ function fastifyToString(value) {
8187
+ if (value === void 0) {
8188
+ return void 0;
8189
+ }
8190
+ if (typeof value === "string") {
8191
+ return value;
8192
+ }
8193
+ if (value === null) {
8194
+ return "";
8195
+ }
8196
+ if (value instanceof Date) {
8197
+ return value.toISOString();
8198
+ }
8199
+ if (value instanceof RegExp) {
8200
+ return value.source;
8201
+ }
8202
+ try {
8203
+ return String(value.toString());
8204
+ } catch {
8205
+ return "[unserializable]";
8206
+ }
8207
+ }
8208
+
8209
+ // src/normalizers/connection.ts
8210
+ function normalizeConnectionItem({
8211
+ connection,
8212
+ appKey: providedAppKey,
8213
+ appVersion: providedAppVersion,
8214
+ adaptError
8215
+ }) {
8216
+ let appKey = providedAppKey;
8217
+ let appVersion = providedAppVersion;
8218
+ if (connection.selected_api && typeof connection.selected_api === "string") {
8219
+ const [extractedAppKey, extractedVersion] = splitVersionedKey(
8220
+ connection.selected_api
8221
+ );
8222
+ if (!appKey) {
8223
+ appKey = extractedAppKey;
8224
+ }
8225
+ if (!appVersion) {
8226
+ appVersion = extractedVersion;
8227
+ }
8228
+ }
8229
+ const {
8230
+ selected_api: selectedApi,
8231
+ customuser_id: profileId,
8232
+ id,
8233
+ account_id: accountId,
8234
+ ...restOfConnection
8235
+ } = connection;
8236
+ const normalized = {
8237
+ ...restOfConnection,
8238
+ id: String(id),
8239
+ account_id: String(accountId),
8240
+ implementation_id: selectedApi,
8241
+ title: connection.title || connection.label || void 0,
8242
+ is_stale: fastifyToString(connection.is_stale),
8243
+ is_expired: fastifyToString(connection.is_stale),
8244
+ is_shared: fastifyToString(connection.is_shared),
8245
+ members: fastifyToString(connection.members),
8246
+ customuser_public_id: fastifyToString(connection.customuser_public_id),
8247
+ expired_at: connection.marked_stale_at,
8248
+ app_key: appKey,
8249
+ app_version: appVersion,
8250
+ profile_id: profileId != null ? String(profileId) : void 0
8251
+ };
8252
+ return kitcore.createValidator(connections.ConnectionItemSchema, { adaptError })(normalized);
8253
+ }
8165
8254
  function formatConnectionItem(item) {
8166
8255
  const details = [];
8167
8256
  const appKey = item.app_key ?? "unknown";
@@ -8202,7 +8291,8 @@ var listConnectionsPlugin = kitcore.defineMethod({
8202
8291
  connectionsPluginRef,
8203
8292
  apiPluginRef,
8204
8293
  manifestPluginRef,
8205
- capabilitiesPluginRef
8294
+ capabilitiesPluginRef,
8295
+ kitcore.coreOptionsPluginRef
8206
8296
  ],
8207
8297
  categories: ["connection"],
8208
8298
  itemType: "Connection",
@@ -8230,18 +8320,17 @@ var listConnectionsPlugin = kitcore.defineMethod({
8230
8320
  await imports.capabilities.checkCapability("canIncludeSharedConnections");
8231
8321
  }
8232
8322
  const searchParams = {};
8233
- if (input.pageSize !== void 0) {
8234
- searchParams.page_size = input.pageSize.toString();
8235
- }
8323
+ searchParams.limit = (input.pageSize ?? DEFAULT_PAGE_SIZE).toString();
8236
8324
  const appKey = input.app ?? input.appKey;
8237
8325
  if (appKey) {
8238
8326
  const implementationId = await getVersionedImplementationId(appKey);
8239
8327
  if (implementationId) {
8240
8328
  annotate({ selectedApi: implementationId });
8241
8329
  const [versionlessSelectedApi] = splitVersionedKey(implementationId);
8242
- searchParams.app_key = versionlessSelectedApi;
8330
+ searchParams.versionless_selected_api = versionlessSelectedApi;
8243
8331
  } else {
8244
- searchParams.app_key = appKey;
8332
+ const [versionlessAppKey] = splitVersionedKey(appKey);
8333
+ searchParams.versionless_selected_api = versionlessAppKey;
8245
8334
  }
8246
8335
  }
8247
8336
  const connectionRefs = input.connections;
@@ -8255,15 +8344,14 @@ var listConnectionsPlugin = kitcore.defineMethod({
8255
8344
  })
8256
8345
  )
8257
8346
  );
8258
- searchParams.connection_ids = resolvedIds.filter((id) => id != null).join(",");
8347
+ searchParams.ids = resolvedIds.filter((id) => id != null).join(",");
8259
8348
  } else if (legacyConnectionIds && legacyConnectionIds.length > 0) {
8260
- searchParams.connection_ids = legacyConnectionIds.join(",");
8349
+ searchParams.ids = legacyConnectionIds.join(",");
8261
8350
  }
8262
8351
  if (input.search) {
8263
8352
  searchParams.search = input.search;
8264
- }
8265
- if (input.title) {
8266
- searchParams.title = input.title;
8353
+ } else if (input.title) {
8354
+ searchParams.search = input.title;
8267
8355
  }
8268
8356
  const accountId = input.account ?? input.accountId;
8269
8357
  if (accountId) {
@@ -8286,18 +8374,31 @@ var listConnectionsPlugin = kitcore.defineMethod({
8286
8374
  }
8287
8375
  const status = input.status ?? (expiredFilter ? "expired" : "active");
8288
8376
  if (status !== "all") {
8289
- searchParams.is_expired = (status === "expired").toString();
8377
+ searchParams.stale = (status === "expired").toString();
8290
8378
  }
8291
8379
  if (input.cursor) {
8292
8380
  searchParams.offset = input.cursor;
8293
8381
  }
8294
- const response = await api.get(
8295
- "/api/v0/connections",
8296
- { searchParams, authRequired: true }
8382
+ searchParams.ordering = "personal_first";
8383
+ const rawResponse = await api.get("/zapier/api/v4/authentications", {
8384
+ searchParams,
8385
+ authRequired: true
8386
+ });
8387
+ const raw = kitcore.createValidator(RawConnectionsResponseSchema, {
8388
+ adaptError: imports.coreOptions?.adaptError
8389
+ })(rawResponse);
8390
+ let connections = raw.results.map(
8391
+ (connection) => normalizeConnectionItem({
8392
+ connection,
8393
+ adaptError: imports.coreOptions?.adaptError
8394
+ })
8297
8395
  );
8396
+ if (input.title) {
8397
+ connections = connections.filter((conn) => conn.title === input.title);
8398
+ }
8298
8399
  return {
8299
- ...response,
8300
- data: response.data.map(transformConnectionItem)
8400
+ data: connections.map(transformConnectionItem),
8401
+ next: raw.next ?? null
8301
8402
  };
8302
8403
  }
8303
8404
  });
@@ -8473,76 +8574,6 @@ var getAppPlugin = kitcore.defineMethod({
8473
8574
  throw new ZapierAppNotFoundError("App not found", { appKey });
8474
8575
  }
8475
8576
  });
8476
-
8477
- // src/normalizers/shared.ts
8478
- function fastifyToString(value) {
8479
- if (value === void 0) {
8480
- return void 0;
8481
- }
8482
- if (typeof value === "string") {
8483
- return value;
8484
- }
8485
- if (value === null) {
8486
- return "";
8487
- }
8488
- if (value instanceof Date) {
8489
- return value.toISOString();
8490
- }
8491
- if (value instanceof RegExp) {
8492
- return value.source;
8493
- }
8494
- try {
8495
- return String(value.toString());
8496
- } catch {
8497
- return "[unserializable]";
8498
- }
8499
- }
8500
-
8501
- // src/normalizers/connection.ts
8502
- function normalizeConnectionItem({
8503
- connection,
8504
- appKey: providedAppKey,
8505
- appVersion: providedAppVersion,
8506
- adaptError
8507
- }) {
8508
- let appKey = providedAppKey;
8509
- let appVersion = providedAppVersion;
8510
- if (connection.selected_api && typeof connection.selected_api === "string") {
8511
- const [extractedAppKey, extractedVersion] = splitVersionedKey(
8512
- connection.selected_api
8513
- );
8514
- if (!appKey) {
8515
- appKey = extractedAppKey;
8516
- }
8517
- if (!appVersion) {
8518
- appVersion = extractedVersion;
8519
- }
8520
- }
8521
- const {
8522
- selected_api: selectedApi,
8523
- customuser_id: profileId,
8524
- id,
8525
- account_id: accountId,
8526
- ...restOfConnection
8527
- } = connection;
8528
- const normalized = {
8529
- ...restOfConnection,
8530
- id: String(id),
8531
- account_id: String(accountId),
8532
- implementation_id: selectedApi,
8533
- title: connection.title || connection.label || void 0,
8534
- is_stale: fastifyToString(connection.is_stale),
8535
- is_expired: fastifyToString(connection.is_stale),
8536
- is_shared: fastifyToString(connection.is_shared),
8537
- members: fastifyToString(connection.members),
8538
- customuser_public_id: fastifyToString(connection.customuser_public_id),
8539
- expired_at: connection.marked_stale_at,
8540
- app_key: appKey,
8541
- app_version: appVersion,
8542
- profile_id: profileId != null ? String(profileId) : void 0
8543
- };
8544
- return kitcore.createValidator(connections.ConnectionItemSchema, { adaptError })(normalized);
8545
- }
8546
8577
  var GetConnectionDescription = "Get details for a specific connection";
8547
8578
  var GetConnectionSchema = zod.z.object({
8548
8579
  connection: ConnectionPropertySchema
@@ -8937,7 +8968,7 @@ var WaitForNewConnectionSchema = zod.z.object({
8937
8968
  "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)."
8938
8969
  ).meta({ deprecated: true })
8939
8970
  }).describe(
8940
- "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```"
8971
+ "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```"
8941
8972
  );
8942
8973
  var WaitForNewConnectionItemSchema = zod.z.object({
8943
8974
  id: zod.z.string().describe(
@@ -8950,12 +8981,22 @@ var WaitForNewConnectionItemSchema = zod.z.object({
8950
8981
  "Human-readable connection title set by the auth flow, when available."
8951
8982
  )
8952
8983
  }).describe("The new connection that was detected.");
8984
+ var WaitForNewConnectionRowSchema = zod.z.object({
8985
+ id: zod.z.union([zod.z.string(), zod.z.number()]),
8986
+ public_id: zod.z.string().optional(),
8987
+ date: zod.z.string().optional(),
8988
+ title: zod.z.string().nullable().optional(),
8989
+ label: zod.z.string().nullable().optional()
8990
+ });
8991
+ var WaitForNewConnectionResponseSchema = zod.z.object({
8992
+ results: zod.z.array(WaitForNewConnectionRowSchema)
8993
+ });
8953
8994
 
8954
8995
  // src/plugins/waitForNewConnection/index.ts
8955
- var CONNECTIONS_PATH = "/api/v0/connections";
8996
+ var CONNECTIONS_PATH = "/zapier/api/v4/authentications";
8956
8997
  var waitForNewConnectionPlugin = kitcore.defineMethod({
8957
8998
  name: "waitForNewConnection",
8958
- imports: [manifestPluginRef, apiPluginRef],
8999
+ imports: [manifestPluginRef, apiPluginRef, kitcore.coreOptionsPluginRef],
8959
9000
  categories: ["connection"],
8960
9001
  itemType: "Connection",
8961
9002
  inputSchema: WaitForNewConnectionSchema,
@@ -8966,27 +9007,31 @@ var waitForNewConnectionPlugin = kitcore.defineMethod({
8966
9007
  run: async ({ imports, input, annotate }) => {
8967
9008
  const api = imports.api;
8968
9009
  const getVersionedImplementationId = imports.manifest.getVersionedImplementationId;
9010
+ const validateConnectionsResponse = kitcore.createValidator(
9011
+ WaitForNewConnectionResponseSchema,
9012
+ { adaptError: imports.coreOptions?.adaptError }
9013
+ );
8969
9014
  const versionedKey = await getVersionedImplementationId(input.app);
8970
- const appKey = versionedKey ? versionedKey.split("@")[0] : input.app;
9015
+ const [appKey] = splitVersionedKey(versionedKey ?? input.app);
8971
9016
  annotate({ selectedApi: appKey });
8972
9017
  try {
8973
9018
  const top = await api.poll(CONNECTIONS_PATH, {
8974
9019
  searchParams: {
8975
- app_key: appKey,
9020
+ versionless_selected_api: appKey,
8976
9021
  // Scope to the current user's own connections. The connection we're
8977
9022
  // waiting on is by definition owned by the caller; without this the
8978
9023
  // one-row head-check could match a teammate's freshly created
8979
9024
  // connection for the same app.
8980
9025
  owner: "me",
8981
- is_expired: "false",
9026
+ stale: "false",
8982
9027
  ordering: "-date",
8983
- page_size: "1"
9028
+ limit: "1"
8984
9029
  },
8985
9030
  authRequired: true,
8986
9031
  timeoutMilliseconds: input.timeoutSeconds != null ? input.timeoutSeconds * 1e3 : input.timeoutMs ?? 3e5,
8987
9032
  initialDelayMilliseconds: input.pollIntervalMilliseconds ?? input.pollIntervalMs ?? 3e3,
8988
9033
  isPending: (body) => {
8989
- const rows = body.data ?? [];
9034
+ const rows = validateConnectionsResponse(body).results;
8990
9035
  const head = rows[0];
8991
9036
  if (!head?.date) return true;
8992
9037
  const created = Math.floor(new Date(head.date).getTime() / 1e3);
@@ -8994,14 +9039,14 @@ var waitForNewConnectionPlugin = kitcore.defineMethod({
8994
9039
  },
8995
9040
  resultExtractor: (body) => (
8996
9041
  // `isPending` guaranteed a fresh row at index 0 before this fires.
8997
- body.data[0]
9042
+ validateConnectionsResponse(body).results[0]
8998
9043
  )
8999
9044
  });
9000
9045
  return {
9001
9046
  data: WaitForNewConnectionItemSchema.parse({
9002
9047
  id: String(top.public_id ?? top.id),
9003
9048
  app: appKey,
9004
- title: top.title ?? null
9049
+ title: top.title || top.label || null
9005
9050
  })
9006
9051
  };
9007
9052
  } catch (err) {