@zapier/zapier-sdk 0.42.0 → 0.43.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.
Files changed (152) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/api/client.d.ts.map +1 -1
  3. package/dist/api/client.js +309 -35
  4. package/dist/api/types.d.ts +29 -0
  5. package/dist/api/types.d.ts.map +1 -1
  6. package/dist/constants.d.ts +25 -0
  7. package/dist/constants.d.ts.map +1 -1
  8. package/dist/constants.js +32 -0
  9. package/dist/index.cjs +616 -197
  10. package/dist/index.d.mts +241 -408
  11. package/dist/index.d.ts +3 -3
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +1 -1
  14. package/dist/index.mjs +611 -198
  15. package/dist/plugins/api/index.d.ts +5 -1
  16. package/dist/plugins/api/index.d.ts.map +1 -1
  17. package/dist/plugins/api/index.js +6 -3
  18. package/dist/plugins/apps/index.d.ts +2 -3
  19. package/dist/plugins/apps/index.d.ts.map +1 -1
  20. package/dist/plugins/apps/index.js +1 -1
  21. package/dist/plugins/capabilities/index.d.ts +8 -6
  22. package/dist/plugins/capabilities/index.d.ts.map +1 -1
  23. package/dist/plugins/capabilities/index.js +3 -3
  24. package/dist/plugins/connections/index.d.ts +3 -1
  25. package/dist/plugins/connections/index.d.ts.map +1 -1
  26. package/dist/plugins/connections/index.js +2 -3
  27. package/dist/plugins/createClientCredentials/index.d.ts +6 -4
  28. package/dist/plugins/createClientCredentials/index.d.ts.map +1 -1
  29. package/dist/plugins/createClientCredentials/index.js +4 -3
  30. package/dist/plugins/createClientCredentials/schemas.d.ts +1 -0
  31. package/dist/plugins/createClientCredentials/schemas.d.ts.map +1 -1
  32. package/dist/plugins/createClientCredentials/schemas.js +6 -0
  33. package/dist/plugins/deleteClientCredentials/index.d.ts +6 -4
  34. package/dist/plugins/deleteClientCredentials/index.d.ts.map +1 -1
  35. package/dist/plugins/deleteClientCredentials/index.js +3 -3
  36. package/dist/plugins/deprecated/authentications.d.ts +9 -9
  37. package/dist/plugins/deprecated/authentications.d.ts.map +1 -1
  38. package/dist/plugins/deprecated/authentications.js +4 -4
  39. package/dist/plugins/eventEmission/index.d.ts +4 -5
  40. package/dist/plugins/eventEmission/index.d.ts.map +1 -1
  41. package/dist/plugins/eventEmission/index.js +8 -7
  42. package/dist/plugins/fetch/index.d.ts +6 -6
  43. package/dist/plugins/fetch/index.d.ts.map +1 -1
  44. package/dist/plugins/fetch/index.js +20 -6
  45. package/dist/plugins/findFirstConnection/index.d.ts +3 -4
  46. package/dist/plugins/findFirstConnection/index.d.ts.map +1 -1
  47. package/dist/plugins/findFirstConnection/index.js +2 -2
  48. package/dist/plugins/findUniqueConnection/index.d.ts +3 -4
  49. package/dist/plugins/findUniqueConnection/index.d.ts.map +1 -1
  50. package/dist/plugins/findUniqueConnection/index.js +2 -2
  51. package/dist/plugins/getAction/index.d.ts +7 -7
  52. package/dist/plugins/getAction/index.d.ts.map +1 -1
  53. package/dist/plugins/getAction/index.js +2 -2
  54. package/dist/plugins/getApp/index.d.ts +2 -3
  55. package/dist/plugins/getApp/index.d.ts.map +1 -1
  56. package/dist/plugins/getApp/index.js +2 -2
  57. package/dist/plugins/getConnection/index.d.ts +6 -6
  58. package/dist/plugins/getConnection/index.d.ts.map +1 -1
  59. package/dist/plugins/getConnection/index.js +3 -3
  60. package/dist/plugins/getInputFieldsSchema/index.d.ts +8 -6
  61. package/dist/plugins/getInputFieldsSchema/index.d.ts.map +1 -1
  62. package/dist/plugins/getInputFieldsSchema/index.js +4 -4
  63. package/dist/plugins/getProfile/index.d.ts +6 -6
  64. package/dist/plugins/getProfile/index.d.ts.map +1 -1
  65. package/dist/plugins/getProfile/index.js +3 -3
  66. package/dist/plugins/listActions/index.d.ts +8 -6
  67. package/dist/plugins/listActions/index.d.ts.map +1 -1
  68. package/dist/plugins/listActions/index.js +3 -3
  69. package/dist/plugins/listApps/index.d.ts +3 -3
  70. package/dist/plugins/listApps/index.d.ts.map +1 -1
  71. package/dist/plugins/listApps/index.js +3 -3
  72. package/dist/plugins/listClientCredentials/index.d.ts +6 -4
  73. package/dist/plugins/listClientCredentials/index.d.ts.map +1 -1
  74. package/dist/plugins/listClientCredentials/index.js +3 -3
  75. package/dist/plugins/listConnections/index.d.ts +8 -6
  76. package/dist/plugins/listConnections/index.d.ts.map +1 -1
  77. package/dist/plugins/listConnections/index.js +5 -5
  78. package/dist/plugins/listInputFieldChoices/index.d.ts +9 -8
  79. package/dist/plugins/listInputFieldChoices/index.d.ts.map +1 -1
  80. package/dist/plugins/listInputFieldChoices/index.js +4 -4
  81. package/dist/plugins/listInputFields/index.d.ts +8 -8
  82. package/dist/plugins/listInputFields/index.d.ts.map +1 -1
  83. package/dist/plugins/listInputFields/index.js +4 -4
  84. package/dist/plugins/manifest/index.d.ts +8 -3
  85. package/dist/plugins/manifest/index.d.ts.map +1 -1
  86. package/dist/plugins/manifest/index.js +2 -3
  87. package/dist/plugins/registry/index.d.ts +1 -2
  88. package/dist/plugins/registry/index.d.ts.map +1 -1
  89. package/dist/plugins/registry/index.js +3 -3
  90. package/dist/plugins/request/index.d.ts +3 -4
  91. package/dist/plugins/request/index.d.ts.map +1 -1
  92. package/dist/plugins/request/index.js +2 -2
  93. package/dist/plugins/runAction/index.d.ts +8 -8
  94. package/dist/plugins/runAction/index.d.ts.map +1 -1
  95. package/dist/plugins/runAction/index.js +17 -6
  96. package/dist/plugins/tables/createTable/index.d.ts +3 -5
  97. package/dist/plugins/tables/createTable/index.d.ts.map +1 -1
  98. package/dist/plugins/tables/createTable/index.js +3 -3
  99. package/dist/plugins/tables/createTableFields/index.d.ts +3 -5
  100. package/dist/plugins/tables/createTableFields/index.d.ts.map +1 -1
  101. package/dist/plugins/tables/createTableFields/index.js +3 -3
  102. package/dist/plugins/tables/createTableRecords/index.d.ts +3 -5
  103. package/dist/plugins/tables/createTableRecords/index.d.ts.map +1 -1
  104. package/dist/plugins/tables/createTableRecords/index.js +3 -3
  105. package/dist/plugins/tables/deleteTable/index.d.ts +5 -5
  106. package/dist/plugins/tables/deleteTable/index.d.ts.map +1 -1
  107. package/dist/plugins/tables/deleteTable/index.js +4 -4
  108. package/dist/plugins/tables/deleteTableFields/index.d.ts +3 -5
  109. package/dist/plugins/tables/deleteTableFields/index.d.ts.map +1 -1
  110. package/dist/plugins/tables/deleteTableFields/index.js +3 -3
  111. package/dist/plugins/tables/deleteTableRecords/index.d.ts +3 -5
  112. package/dist/plugins/tables/deleteTableRecords/index.d.ts.map +1 -1
  113. package/dist/plugins/tables/deleteTableRecords/index.js +3 -3
  114. package/dist/plugins/tables/getTable/index.d.ts +3 -5
  115. package/dist/plugins/tables/getTable/index.d.ts.map +1 -1
  116. package/dist/plugins/tables/getTable/index.js +3 -3
  117. package/dist/plugins/tables/getTableRecord/index.d.ts +3 -5
  118. package/dist/plugins/tables/getTableRecord/index.d.ts.map +1 -1
  119. package/dist/plugins/tables/getTableRecord/index.js +3 -3
  120. package/dist/plugins/tables/listTableFields/index.d.ts +3 -5
  121. package/dist/plugins/tables/listTableFields/index.d.ts.map +1 -1
  122. package/dist/plugins/tables/listTableFields/index.js +3 -3
  123. package/dist/plugins/tables/listTableRecords/index.d.ts +3 -3
  124. package/dist/plugins/tables/listTableRecords/index.d.ts.map +1 -1
  125. package/dist/plugins/tables/listTableRecords/index.js +3 -3
  126. package/dist/plugins/tables/listTables/index.d.ts +5 -3
  127. package/dist/plugins/tables/listTables/index.d.ts.map +1 -1
  128. package/dist/plugins/tables/listTables/index.js +4 -4
  129. package/dist/plugins/tables/updateTableRecords/index.d.ts +3 -5
  130. package/dist/plugins/tables/updateTableRecords/index.d.ts.map +1 -1
  131. package/dist/plugins/tables/updateTableRecords/index.js +3 -3
  132. package/dist/resolvers/connectionId.js +1 -1
  133. package/dist/resolvers/tableId.js +1 -1
  134. package/dist/sdk.d.ts +29 -257
  135. package/dist/sdk.d.ts.map +1 -1
  136. package/dist/sdk.js +33 -43
  137. package/dist/types/errors.d.ts +37 -0
  138. package/dist/types/errors.d.ts.map +1 -1
  139. package/dist/types/errors.js +18 -0
  140. package/dist/types/plugin.d.ts +29 -48
  141. package/dist/types/plugin.d.ts.map +1 -1
  142. package/dist/types/plugin.js +7 -3
  143. package/dist/types/sdk.d.ts +9 -3
  144. package/dist/types/sdk.d.ts.map +1 -1
  145. package/dist/types/sdk.js +20 -0
  146. package/dist/utils/open-approval.d.ts +2 -0
  147. package/dist/utils/open-approval.d.ts.map +1 -0
  148. package/dist/utils/open-approval.js +13 -0
  149. package/dist/utils/open-url.d.ts +3 -0
  150. package/dist/utils/open-url.d.ts.map +1 -0
  151. package/dist/utils/open-url.js +72 -0
  152. package/package.json +3 -1
package/dist/index.cjs CHANGED
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var zod = require('zod');
4
+ var policyContext = require('@zapier/policy-context');
4
5
  var apps = require('@zapier/zapier-sdk-core/v0/schemas/apps');
5
6
  var connections = require('@zapier/zapier-sdk-core/v0/schemas/connections');
6
7
  var clientCredentials = require('@zapier/zapier-sdk-core/v0/schemas/client-credentials');
@@ -58,6 +59,16 @@ function parseIntEnvVar(name) {
58
59
  }
59
60
  var ZAPIER_MAX_NETWORK_RETRIES = parseIntEnvVar("ZAPIER_MAX_NETWORK_RETRIES") ?? 3;
60
61
  var ZAPIER_MAX_NETWORK_RETRY_DELAY_MS = parseIntEnvVar("ZAPIER_MAX_NETWORK_RETRY_DELAY_MS") ?? 6e4;
62
+ function getZapierIsInteractive() {
63
+ return globalThis.process?.env?.ZAPIER_IS_INTERACTIVE === "true";
64
+ }
65
+ function getZapierApprovalMode() {
66
+ const value = globalThis.process?.env?.ZAPIER_APPROVAL_MODE;
67
+ if (value === "poll" || value === "fail") return value;
68
+ return void 0;
69
+ }
70
+ var DEFAULT_APPROVAL_TIMEOUT_MS = 10 * 60 * 1e3;
71
+ var DEFAULT_MAX_APPROVAL_RETRIES = 2;
61
72
 
62
73
  // src/types/properties.ts
63
74
  var AppKeyPropertySchema = withPositional(
@@ -226,6 +237,17 @@ var ZapierRateLimitError = class extends ZapierError {
226
237
  this.retries = options.retries ?? 0;
227
238
  }
228
239
  };
240
+ var ZapierApprovalError = class extends ZapierError {
241
+ constructor(message, options = {}) {
242
+ super(message, options);
243
+ this.name = "ZapierApprovalError";
244
+ this.code = "ZAPIER_APPROVAL_ERROR";
245
+ this.approvalId = options.approvalId;
246
+ this.approvalStatus = options.status;
247
+ this.approvalUrl = options.approvalUrl;
248
+ this.pollUrl = options.pollUrl;
249
+ }
250
+ };
229
251
  var ZapierRelayError = class extends ZapierError {
230
252
  constructor(message, options = {}) {
231
253
  super(message, options);
@@ -270,6 +292,10 @@ ${context.join(", ")}`;
270
292
  if (error instanceof ZapierBundleError && error.buildErrors && error.buildErrors.length > 0) {
271
293
  message += "\n\nBuild errors:\n" + error.buildErrors.map((err) => ` \u2022 ${err}`).join("\n");
272
294
  }
295
+ if (error instanceof ZapierApprovalError && error.approvalUrl) {
296
+ message += `
297
+ Approval URL: ${error.approvalUrl}`;
298
+ }
273
299
  if (error instanceof ZapierRateLimitError) {
274
300
  const { limit, remaining, retryAfterMs } = error.rateLimit;
275
301
  const parts = [];
@@ -517,7 +543,7 @@ function createAppsProxy(options) {
517
543
  });
518
544
  return appsProxy;
519
545
  }
520
- var appsPlugin = ({ sdk }) => {
546
+ var appsPlugin = (sdk) => {
521
547
  return {
522
548
  apps: createAppsProxy({ sdk }),
523
549
  context: {
@@ -927,11 +953,11 @@ function buildAbortHandle({
927
953
  }
928
954
  var FetchInitSdkValidationSchema = zod.z.looseObject(FetchInitZapierFieldsSchema.shape).optional();
929
955
  var validateFetchInit = createValidator(FetchInitSdkValidationSchema);
930
- var fetchPlugin = ({ context }) => {
956
+ var fetchPlugin = (sdk) => {
931
957
  return {
932
958
  fetch: async function fetch2(url, init) {
933
959
  return runWithTelemetryContext(async () => {
934
- const { api } = context;
960
+ const { api } = sdk.context;
935
961
  const startTime = Date.now();
936
962
  const isNested = isTelemetryNested();
937
963
  try {
@@ -950,7 +976,7 @@ var fetchPlugin = ({ context }) => {
950
976
  connectionId,
951
977
  connection,
952
978
  authenticationId,
953
- resolveConnection: context.resolveConnection,
979
+ resolveConnection: sdk.context.resolveConnection,
954
980
  label: "fetch"
955
981
  });
956
982
  const relayPath = transformUrlToRelayPath(url);
@@ -977,18 +1003,27 @@ var fetchPlugin = ({ context }) => {
977
1003
  if (maxTime !== void 0) {
978
1004
  headers["X-Zapier-Sdk-Max-Time"] = String(maxTime);
979
1005
  }
1006
+ const upstreamUrl = new URL(url).toString();
1007
+ const method = (fetchInit.method ?? "GET").toUpperCase();
980
1008
  const abortHandle = buildAbortHandle({
981
1009
  maxTimeSeconds: maxTime,
982
1010
  callerSignal: fetchInit.signal
983
1011
  });
984
1012
  try {
985
1013
  const result = await api.fetch(relayPath, {
986
- method: fetchInit.method ?? "GET",
1014
+ method,
987
1015
  body: fetchInit.body,
988
1016
  headers,
989
1017
  redirect: fetchInit.redirect,
990
1018
  signal: abortHandle?.signal,
991
- authRequired: true
1019
+ authRequired: true,
1020
+ approvalContext: () => policyContext.buildHttpRequestContext({
1021
+ method,
1022
+ url: upstreamUrl,
1023
+ headers,
1024
+ body: typeof fetchInit.body === "string" ? fetchInit.body : void 0,
1025
+ connection_id: resolvedConnectionId ? String(resolvedConnectionId) : void 0
1026
+ })
992
1027
  });
993
1028
  const relayError = result.headers.get("x-relay-error");
994
1029
  if (relayError) {
@@ -997,7 +1032,7 @@ var fetchPlugin = ({ context }) => {
997
1032
  });
998
1033
  }
999
1034
  if (!isNested) {
1000
- context.eventEmission.emitMethodCalled({
1035
+ sdk.context.eventEmission.emitMethodCalled({
1001
1036
  method_name: "fetch",
1002
1037
  execution_duration_ms: Date.now() - startTime,
1003
1038
  success_flag: true,
@@ -1019,7 +1054,7 @@ var fetchPlugin = ({ context }) => {
1019
1054
  }
1020
1055
  } catch (error) {
1021
1056
  if (!isNested) {
1022
- context.eventEmission.emitMethodCalled({
1057
+ sdk.context.eventEmission.emitMethodCalled({
1023
1058
  method_name: "fetch",
1024
1059
  execution_duration_ms: Date.now() - startTime,
1025
1060
  success_flag: false,
@@ -1583,9 +1618,9 @@ function createTelemetryCallback(emitMethodCalled, methodName) {
1583
1618
  }
1584
1619
 
1585
1620
  // src/plugins/listApps/index.ts
1586
- var listAppsPlugin = ({ context }) => {
1621
+ var listAppsPlugin = (sdk) => {
1587
1622
  async function listAppsPage(options) {
1588
- const { api, resolveAppKeys: resolveAppKeys2 } = context;
1623
+ const { api, resolveAppKeys: resolveAppKeys2 } = sdk.context;
1589
1624
  const appKeys = options.apps ?? options.appKeys ?? [];
1590
1625
  const appLocators = await resolveAppKeys2({
1591
1626
  appKeys: [...appKeys]
@@ -1629,7 +1664,10 @@ var listAppsPlugin = ({ context }) => {
1629
1664
  const listAppsDefinition = createPaginatedFunction(
1630
1665
  listAppsPage,
1631
1666
  ListAppsSchema,
1632
- createTelemetryCallback(context.eventEmission.emitMethodCalled, methodName),
1667
+ createTelemetryCallback(
1668
+ sdk.context.eventEmission.emitMethodCalled,
1669
+ methodName
1670
+ ),
1633
1671
  methodName,
1634
1672
  DEFAULT_PAGE_SIZE
1635
1673
  );
@@ -2070,7 +2108,7 @@ var actionKeyResolver = {
2070
2108
 
2071
2109
  // src/resolvers/connectionId.ts
2072
2110
  async function fetchConnections(sdk, resolvedParams) {
2073
- const context = sdk.getContext();
2111
+ const context = sdk.context;
2074
2112
  const includeShared = await context.hasCapability?.(
2075
2113
  "canIncludeSharedConnections"
2076
2114
  );
@@ -2238,7 +2276,7 @@ var tableIdResolver = {
2238
2276
  type: "dynamic",
2239
2277
  requireCapabilities: ["canIncludeSharedTables"],
2240
2278
  fetch: async (sdk) => {
2241
- const context = sdk.getContext();
2279
+ const context = sdk.context;
2242
2280
  const includeShared = await context.hasCapability?.(
2243
2281
  "canIncludeSharedTables"
2244
2282
  );
@@ -2878,7 +2916,7 @@ var tableSortResolver = {
2878
2916
  };
2879
2917
 
2880
2918
  // src/plugins/listActions/index.ts
2881
- var listActionsPlugin = ({ context }) => {
2919
+ var listActionsPlugin = (sdk) => {
2882
2920
  const methodMeta = {
2883
2921
  categories: ["action"],
2884
2922
  type: "list",
@@ -2891,7 +2929,7 @@ var listActionsPlugin = ({ context }) => {
2891
2929
  }
2892
2930
  };
2893
2931
  async function listActionsPage(options) {
2894
- const { api, getVersionedImplementationId } = context;
2932
+ const { api, getVersionedImplementationId } = sdk.context;
2895
2933
  const appKey = "app" in options ? options.app : options.appKey;
2896
2934
  const selectedApi = await getVersionedImplementationId(appKey);
2897
2935
  if (!selectedApi) {
@@ -2956,7 +2994,10 @@ var listActionsPlugin = ({ context }) => {
2956
2994
  const listActionsDefinition = createPaginatedFunction(
2957
2995
  listActionsPage,
2958
2996
  ListActionsInputSchema,
2959
- createTelemetryCallback(context.eventEmission.emitMethodCalled, methodName),
2997
+ createTelemetryCallback(
2998
+ sdk.context.eventEmission.emitMethodCalled,
2999
+ methodName
3000
+ ),
2960
3001
  methodName,
2961
3002
  DEFAULT_PAGE_SIZE
2962
3003
  );
@@ -3279,9 +3320,9 @@ function transformNeedsToFields(needs) {
3279
3320
  }
3280
3321
  return rootFields;
3281
3322
  }
3282
- var listInputFieldsPlugin = ({ sdk, context }) => {
3323
+ var listInputFieldsPlugin = (sdk) => {
3283
3324
  async function listInputFieldsPage(options) {
3284
- const { api, getVersionedImplementationId } = context;
3325
+ const { api, getVersionedImplementationId } = sdk.context;
3285
3326
  const appKey = "app" in options ? options.app : options.appKey;
3286
3327
  const actionKey = "action" in options ? options.action : options.actionKey;
3287
3328
  const { actionType, connection, connectionId, authenticationId, inputs } = options;
@@ -3289,7 +3330,7 @@ var listInputFieldsPlugin = ({ sdk, context }) => {
3289
3330
  connection,
3290
3331
  connectionId,
3291
3332
  authenticationId,
3292
- resolveConnection: context.resolveConnection
3333
+ resolveConnection: sdk.context.resolveConnection
3293
3334
  });
3294
3335
  const selectedApi = await getVersionedImplementationId(appKey);
3295
3336
  if (!selectedApi) {
@@ -3327,7 +3368,10 @@ var listInputFieldsPlugin = ({ sdk, context }) => {
3327
3368
  const listInputFieldsDefinition = createPaginatedFunction(
3328
3369
  listInputFieldsPage,
3329
3370
  ListInputFieldsInputSchema,
3330
- createTelemetryCallback(context.eventEmission.emitMethodCalled, methodName),
3371
+ createTelemetryCallback(
3372
+ sdk.context.eventEmission.emitMethodCalled,
3373
+ methodName
3374
+ ),
3331
3375
  methodName,
3332
3376
  DEFAULT_PAGE_SIZE
3333
3377
  );
@@ -3430,12 +3474,12 @@ var ConnectionItemSchema = withFormatter(connections.ConnectionItemSchema, {
3430
3474
  });
3431
3475
 
3432
3476
  // src/plugins/listConnections/index.ts
3433
- var listConnectionsPlugin = ({ context }) => {
3477
+ var listConnectionsPlugin = (sdk) => {
3434
3478
  async function listConnectionsPage(options) {
3435
3479
  if (options.includeShared) {
3436
- await context.checkCapability("canIncludeSharedConnections");
3480
+ await sdk.context.checkCapability("canIncludeSharedConnections");
3437
3481
  }
3438
- const { api, getVersionedImplementationId } = context;
3482
+ const { api, getVersionedImplementationId } = sdk.context;
3439
3483
  const searchParams = {};
3440
3484
  if (options.pageSize !== void 0) {
3441
3485
  searchParams.page_size = options.pageSize.toString();
@@ -3458,7 +3502,7 @@ var listConnectionsPlugin = ({ context }) => {
3458
3502
  connectionRefs.map(
3459
3503
  (ref) => resolveConnectionId({
3460
3504
  connection: ref,
3461
- resolveConnection: context.resolveConnection
3505
+ resolveConnection: sdk.context.resolveConnection
3462
3506
  })
3463
3507
  )
3464
3508
  );
@@ -3524,7 +3568,10 @@ var listConnectionsPlugin = ({ context }) => {
3524
3568
  const listConnectionsDefinition = createPaginatedFunction(
3525
3569
  listConnectionsPage,
3526
3570
  ListConnectionsQuerySchema,
3527
- createTelemetryCallback(context.eventEmission.emitMethodCalled, methodName),
3571
+ createTelemetryCallback(
3572
+ sdk.context.eventEmission.emitMethodCalled,
3573
+ methodName
3574
+ ),
3528
3575
  methodName,
3529
3576
  DEFAULT_PAGE_SIZE
3530
3577
  );
@@ -3600,9 +3647,9 @@ var ClientCredentialsCreatedItemSchema = withFormatter(
3600
3647
  );
3601
3648
 
3602
3649
  // src/plugins/listClientCredentials/index.ts
3603
- var listClientCredentialsPlugin = ({ context }) => {
3650
+ var listClientCredentialsPlugin = (sdk) => {
3604
3651
  async function listClientCredentialsPage(options) {
3605
- const { api } = context;
3652
+ const { api } = sdk.context;
3606
3653
  const searchParams = {};
3607
3654
  if (options.pageSize !== void 0) {
3608
3655
  searchParams.pageSize = options.pageSize.toString();
@@ -3639,7 +3686,10 @@ var listClientCredentialsPlugin = ({ context }) => {
3639
3686
  const listClientCredentialsDefinition = createPaginatedFunction(
3640
3687
  listClientCredentialsPage,
3641
3688
  ListClientCredentialsQuerySchema,
3642
- createTelemetryCallback(context.eventEmission.emitMethodCalled, methodName),
3689
+ createTelemetryCallback(
3690
+ sdk.context.eventEmission.emitMethodCalled,
3691
+ methodName
3692
+ ),
3643
3693
  methodName,
3644
3694
  DEFAULT_PAGE_SIZE
3645
3695
  );
@@ -3659,18 +3709,21 @@ var listClientCredentialsPlugin = ({ context }) => {
3659
3709
  };
3660
3710
  };
3661
3711
  var CreateClientCredentialsSchema = clientCredentials.CreateClientCredentialsRequestSchema.omit({ allowed_scopes: true }).extend({
3662
- allowedScopes: zod.z.array(zod.z.enum(["credentials", "external"])).default(["external"]).describe("Scopes to allow for these credentials")
3712
+ allowedScopes: zod.z.array(zod.z.enum(["credentials", "external"])).default(["external"]).describe("Scopes to allow for these credentials"),
3713
+ // Temporarily hidden while we finalise work to make approvals/policies customer-facing.
3714
+ policy: zod.z.record(zod.z.string(), zod.z.unknown()).optional().describe("Policy document (JSON) to attach to the credentials").meta({ deprecated: true })
3663
3715
  }).describe("Create new client credentials for the authenticated user");
3664
3716
 
3665
3717
  // src/plugins/createClientCredentials/index.ts
3666
- var createClientCredentialsPlugin = ({ context }) => {
3718
+ var createClientCredentialsPlugin = (sdk) => {
3667
3719
  async function createClientCredentials(options) {
3668
- const { api } = context;
3720
+ const { api } = sdk.context;
3669
3721
  const response = await api.post(
3670
3722
  "/api/v0/client-credentials",
3671
3723
  {
3672
3724
  name: options.name,
3673
- allowed_scopes: options.allowedScopes
3725
+ allowed_scopes: options.allowedScopes,
3726
+ ...options.policy && { policy: options.policy }
3674
3727
  },
3675
3728
  {
3676
3729
  customErrorHandler: ({ status }) => {
@@ -3700,7 +3753,7 @@ var createClientCredentialsPlugin = ({ context }) => {
3700
3753
  createClientCredentials,
3701
3754
  CreateClientCredentialsSchema,
3702
3755
  createTelemetryCallback(
3703
- context.eventEmission.emitMethodCalled,
3756
+ sdk.context.eventEmission.emitMethodCalled,
3704
3757
  createClientCredentials.name
3705
3758
  )
3706
3759
  );
@@ -3728,9 +3781,9 @@ var DeleteClientCredentialsSchema = zod.z.object({
3728
3781
  }).describe("Delete client credentials by client ID");
3729
3782
 
3730
3783
  // src/plugins/deleteClientCredentials/index.ts
3731
- var deleteClientCredentialsPlugin = ({ context }) => {
3784
+ var deleteClientCredentialsPlugin = (sdk) => {
3732
3785
  async function deleteClientCredentials(options) {
3733
- const { api } = context;
3786
+ const { api } = sdk.context;
3734
3787
  await api.delete(
3735
3788
  `/api/v0/client-credentials/${options.clientId}`,
3736
3789
  void 0,
@@ -3762,7 +3815,7 @@ var deleteClientCredentialsPlugin = ({ context }) => {
3762
3815
  deleteClientCredentials,
3763
3816
  DeleteClientCredentialsSchema,
3764
3817
  createTelemetryCallback(
3765
- context.eventEmission.emitMethodCalled,
3818
+ sdk.context.eventEmission.emitMethodCalled,
3766
3819
  deleteClientCredentials.name
3767
3820
  )
3768
3821
  );
@@ -3793,7 +3846,7 @@ var GetAppSchemaDeprecated = zod.z.object({
3793
3846
  var GetAppInputSchema = zod.z.union([GetAppSchema, GetAppSchemaDeprecated]).describe(GetAppDescription);
3794
3847
 
3795
3848
  // src/plugins/getApp/index.ts
3796
- var getAppPlugin = ({ sdk, context }) => {
3849
+ var getAppPlugin = (sdk) => {
3797
3850
  async function getApp(options) {
3798
3851
  const appKey = "app" in options ? options.app : options.appKey;
3799
3852
  const appsIterable = sdk.listApps({
@@ -3812,7 +3865,7 @@ var getAppPlugin = ({ sdk, context }) => {
3812
3865
  getApp,
3813
3866
  GetAppInputSchema,
3814
3867
  createTelemetryCallback(
3815
- context.eventEmission.emitMethodCalled,
3868
+ sdk.context.eventEmission.emitMethodCalled,
3816
3869
  getApp.name
3817
3870
  )
3818
3871
  );
@@ -3848,7 +3901,7 @@ var GetActionSchemaDeprecated = zod.z.object({
3848
3901
  var GetActionInputSchema = zod.z.union([GetActionSchema, GetActionSchemaDeprecated]).describe(GetActionDescription);
3849
3902
 
3850
3903
  // src/plugins/getAction/index.ts
3851
- var getActionPlugin = ({ sdk, context }) => {
3904
+ var getActionPlugin = (sdk) => {
3852
3905
  async function getAction(options) {
3853
3906
  const appKey = "app" in options ? options.app : options.appKey;
3854
3907
  const actionKey = "action" in options ? options.action : options.actionKey;
@@ -3871,7 +3924,7 @@ var getActionPlugin = ({ sdk, context }) => {
3871
3924
  getAction,
3872
3925
  GetActionInputSchema,
3873
3926
  createTelemetryCallback(
3874
- context.eventEmission.emitMethodCalled,
3927
+ sdk.context.eventEmission.emitMethodCalled,
3875
3928
  getAction.name
3876
3929
  )
3877
3930
  );
@@ -3908,9 +3961,9 @@ var GetConnectionParamSchema = zod.z.object({
3908
3961
  });
3909
3962
 
3910
3963
  // src/plugins/getConnection/index.ts
3911
- var getConnectionPlugin = ({ context }) => {
3964
+ var getConnectionPlugin = (sdk) => {
3912
3965
  async function getConnection(options) {
3913
- const { api } = context;
3966
+ const { api } = sdk.context;
3914
3967
  const resolvedConnectionId = options.connection ?? options.connectionId ?? options.authenticationId;
3915
3968
  if (!resolvedConnectionId) {
3916
3969
  throw new Error("connection is required");
@@ -3927,7 +3980,7 @@ var getConnectionPlugin = ({ context }) => {
3927
3980
  getConnection,
3928
3981
  GetConnectionParamSchema,
3929
3982
  createTelemetryCallback(
3930
- context.eventEmission.emitMethodCalled,
3983
+ sdk.context.eventEmission.emitMethodCalled,
3931
3984
  getConnection.name
3932
3985
  )
3933
3986
  );
@@ -3961,7 +4014,7 @@ var FindFirstConnectionSchema = ListConnectionsQuerySchema.omit({
3961
4014
  }).describe("Find the first connection matching the criteria");
3962
4015
 
3963
4016
  // src/plugins/findFirstConnection/index.ts
3964
- var findFirstConnectionPlugin = ({ sdk, context }) => {
4017
+ var findFirstConnectionPlugin = (sdk) => {
3965
4018
  async function findFirstConnection(options = {}) {
3966
4019
  const connectionsResponse = await sdk.listConnections({
3967
4020
  ...options,
@@ -3981,7 +4034,7 @@ var findFirstConnectionPlugin = ({ sdk, context }) => {
3981
4034
  findFirstConnection,
3982
4035
  FindFirstConnectionSchema,
3983
4036
  createTelemetryCallback(
3984
- context.eventEmission.emitMethodCalled,
4037
+ sdk.context.eventEmission.emitMethodCalled,
3985
4038
  findFirstConnection.name
3986
4039
  )
3987
4040
  );
@@ -4012,7 +4065,7 @@ var FindUniqueConnectionSchema = ListConnectionsQuerySchema.omit({
4012
4065
  }).describe("Find a unique connection matching the criteria");
4013
4066
 
4014
4067
  // src/plugins/findUniqueConnection/index.ts
4015
- var findUniqueConnectionPlugin = ({ sdk, context }) => {
4068
+ var findUniqueConnectionPlugin = (sdk) => {
4016
4069
  async function findUniqueConnection(options = {}) {
4017
4070
  const connectionsResponse = await sdk.listConnections({
4018
4071
  ...options,
@@ -4038,7 +4091,7 @@ var findUniqueConnectionPlugin = ({ sdk, context }) => {
4038
4091
  findUniqueConnection,
4039
4092
  FindUniqueConnectionSchema,
4040
4093
  createTelemetryCallback(
4041
- context.eventEmission.emitMethodCalled,
4094
+ sdk.context.eventEmission.emitMethodCalled,
4042
4095
  findUniqueConnection.name
4043
4096
  )
4044
4097
  );
@@ -4093,8 +4146,6 @@ var RunActionSchemaDeprecated = zod.z.object({
4093
4146
  actionKey: ActionKeyPropertySchema
4094
4147
  }).merge(RunActionBaseSchema);
4095
4148
  var RunActionInputSchema = zod.z.union([RunActionSchema, RunActionSchemaDeprecated]).describe(RunActionDescription);
4096
-
4097
- // src/plugins/runAction/index.ts
4098
4149
  async function executeAction(actionOptions) {
4099
4150
  const {
4100
4151
  api,
@@ -4125,7 +4176,18 @@ async function executeAction(actionOptions) {
4125
4176
  };
4126
4177
  const runData = await api.post(
4127
4178
  "/zapier/api/actions/v1/runs",
4128
- runRequest
4179
+ runRequest,
4180
+ {
4181
+ approvalContext: () => policyContext.buildActionRunContext({
4182
+ selected_api: selectedApi,
4183
+ action_type: actionType,
4184
+ action_key: actionKey,
4185
+ connection_id: connectionId != null ? String(connectionId) : void 0,
4186
+ // Cast: inputs is Record<string, unknown> at the SDK surface, but
4187
+ // buildActionRunContext coerces to JsonValue at runtime via zod.
4188
+ inputs: executionOptions.inputs ?? {}
4189
+ })
4190
+ }
4129
4191
  );
4130
4192
  const runId = runData.data.id;
4131
4193
  return await api.poll(`/zapier/api/actions/v1/runs/${runId}`, {
@@ -4141,7 +4203,7 @@ async function executeAction(actionOptions) {
4141
4203
  }
4142
4204
  var CONTEXT_CACHE_TTL_MS = 6e4;
4143
4205
  var CONTEXT_CACHE_MAX_SIZE = 500;
4144
- var runActionPlugin = ({ sdk, context }) => {
4206
+ var runActionPlugin = (sdk) => {
4145
4207
  const runActionContextCache = /* @__PURE__ */ new Map();
4146
4208
  function evictIfNeeded() {
4147
4209
  if (runActionContextCache.size < CONTEXT_CACHE_MAX_SIZE) return;
@@ -4185,7 +4247,7 @@ var runActionPlugin = ({ sdk, context }) => {
4185
4247
  }
4186
4248
  async function resolveRunActionContext(options) {
4187
4249
  const { appKey, actionKey, actionType } = options;
4188
- const selectedApi = await context.getVersionedImplementationId(appKey);
4250
+ const selectedApi = await sdk.context.getVersionedImplementationId(appKey);
4189
4251
  if (!selectedApi) {
4190
4252
  throw new ZapierConfigurationError(
4191
4253
  "No current_implementation_id found for app",
@@ -4205,7 +4267,7 @@ var runActionPlugin = ({ sdk, context }) => {
4205
4267
  return { selectedApi, actionId: actionData.data.id };
4206
4268
  }
4207
4269
  async function runActionPage(options) {
4208
- const { api } = context;
4270
+ const { api } = sdk.context;
4209
4271
  const appKey = "app" in options ? options.app : options.appKey;
4210
4272
  const actionKey = "action" in options ? options.action : options.actionKey;
4211
4273
  const {
@@ -4221,7 +4283,7 @@ var runActionPlugin = ({ sdk, context }) => {
4221
4283
  connectionId,
4222
4284
  connection,
4223
4285
  authenticationId,
4224
- resolveConnection: context.resolveConnection
4286
+ resolveConnection: sdk.context.resolveConnection
4225
4287
  });
4226
4288
  const { selectedApi, actionId } = await getRunActionContext({
4227
4289
  appKey,
@@ -4264,7 +4326,10 @@ var runActionPlugin = ({ sdk, context }) => {
4264
4326
  const runActionDefinition = createPaginatedFunction(
4265
4327
  runActionPage,
4266
4328
  RunActionInputSchema,
4267
- createTelemetryCallback(context.eventEmission.emitMethodCalled, methodName),
4329
+ createTelemetryCallback(
4330
+ sdk.context.eventEmission.emitMethodCalled,
4331
+ methodName
4332
+ ),
4268
4333
  methodName
4269
4334
  );
4270
4335
  return {
@@ -4324,7 +4389,7 @@ function resetDeprecationWarnings() {
4324
4389
  }
4325
4390
 
4326
4391
  // src/plugins/request/index.ts
4327
- var requestPlugin = ({ sdk, context }) => {
4392
+ var requestPlugin = (sdk) => {
4328
4393
  async function request(options) {
4329
4394
  logDeprecation("request() is deprecated. Use fetch() instead.");
4330
4395
  const {
@@ -4349,7 +4414,7 @@ var requestPlugin = ({ sdk, context }) => {
4349
4414
  request,
4350
4415
  RelayRequestSchema,
4351
4416
  createTelemetryCallback(
4352
- context.eventEmission.emitMethodCalled,
4417
+ sdk.context.eventEmission.emitMethodCalled,
4353
4418
  request.name
4354
4419
  )
4355
4420
  );
@@ -4658,9 +4723,8 @@ async function resolveAppKeys({
4658
4723
  });
4659
4724
  return slugResolvedLocators.filter(isResolvedAppLocator);
4660
4725
  }
4661
- var manifestPlugin = (params) => {
4662
- const { context } = params;
4663
- const { api, options } = context;
4726
+ var manifestPlugin = (sdk) => {
4727
+ const { api, options } = sdk.context;
4664
4728
  const { manifestPath = DEFAULT_CONFIG_PATH, manifest } = options || {};
4665
4729
  let resolvedManifest;
4666
4730
  async function resolveManifest() {
@@ -4871,9 +4935,9 @@ var UserProfileItemSchema = withFormatter(
4871
4935
  );
4872
4936
 
4873
4937
  // src/plugins/getProfile/index.ts
4874
- var getProfilePlugin = ({ context }) => {
4938
+ var getProfilePlugin = (sdk) => {
4875
4939
  async function getProfile() {
4876
- const profile = await context.api.get(
4940
+ const profile = await sdk.context.api.get(
4877
4941
  "/zapier/api/v4/profile/",
4878
4942
  {
4879
4943
  authRequired: true
@@ -4895,7 +4959,7 @@ var getProfilePlugin = ({ context }) => {
4895
4959
  getProfile,
4896
4960
  GetProfileSchema,
4897
4961
  createTelemetryCallback(
4898
- context.eventEmission.emitMethodCalled,
4962
+ sdk.context.eventEmission.emitMethodCalled,
4899
4963
  getProfile.name
4900
4964
  )
4901
4965
  );
@@ -5672,7 +5736,89 @@ async function invalidateCredentialsToken(options) {
5672
5736
  }
5673
5737
  }
5674
5738
 
5675
- // src/api/client.ts
5739
+ // src/utils/open-url.ts
5740
+ var nodePrefix = "node:";
5741
+ async function loadChildProcess() {
5742
+ return import(`${nodePrefix}child_process`);
5743
+ }
5744
+ async function loadProcess() {
5745
+ return import(`${nodePrefix}process`);
5746
+ }
5747
+ var openUrl = async (url) => {
5748
+ if (typeof url !== "string") {
5749
+ throw new TypeError("Expected `url` to be a string");
5750
+ }
5751
+ let parsed;
5752
+ try {
5753
+ parsed = new URL(url);
5754
+ } catch {
5755
+ throw new Error(`Invalid URL: ${url}`);
5756
+ }
5757
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
5758
+ throw new Error(`Refusing to open non-http(s) URL: ${parsed.protocol}`);
5759
+ }
5760
+ const target = parsed.toString();
5761
+ if (typeof globalThis.window !== "undefined" && typeof globalThis.window.open === "function") {
5762
+ globalThis.window.open(target, "_blank", "noopener");
5763
+ return;
5764
+ }
5765
+ let spawn;
5766
+ let platform;
5767
+ try {
5768
+ const [cp, proc] = await Promise.all([loadChildProcess(), loadProcess()]);
5769
+ spawn = cp.spawn;
5770
+ platform = proc.platform;
5771
+ } catch {
5772
+ throw new Error(
5773
+ "openUrl: no supported runtime. window.open is unavailable and node:child_process could not be loaded."
5774
+ );
5775
+ }
5776
+ if (typeof spawn !== "function") {
5777
+ throw new Error(
5778
+ "openUrl: child_process.spawn is not available in this runtime"
5779
+ );
5780
+ }
5781
+ let command;
5782
+ let args;
5783
+ if (platform === "darwin") {
5784
+ command = "open";
5785
+ args = [target];
5786
+ } else if (platform === "win32") {
5787
+ command = "rundll32";
5788
+ args = ["url.dll,FileProtocolHandler", target];
5789
+ } else {
5790
+ throw new Error(`Unsupported platform: ${platform}`);
5791
+ }
5792
+ const child = spawn(command, args, {
5793
+ stdio: "ignore",
5794
+ detached: true,
5795
+ windowsHide: true
5796
+ });
5797
+ child.once("error", () => {
5798
+ });
5799
+ child.unref();
5800
+ };
5801
+ var open_url_default = openUrl;
5802
+
5803
+ // src/utils/open-approval.ts
5804
+ async function openApproval(url) {
5805
+ console.error(`Approval required. Opening browser: ${url}`);
5806
+ try {
5807
+ await open_url_default(url);
5808
+ } catch {
5809
+ }
5810
+ }
5811
+ var ApprovalStatusSchema = zod.z.enum(["pending_approval", "approved", "denied"]);
5812
+ var CreateApprovalResponseSchema = zod.z.object({
5813
+ status: ApprovalStatusSchema,
5814
+ approval_id: zod.z.string(),
5815
+ approval_url: zod.z.string().url(),
5816
+ poll_url: zod.z.string().url()
5817
+ });
5818
+ var PollApprovalResponseSchema = zod.z.object({
5819
+ status: ApprovalStatusSchema,
5820
+ approval_id: zod.z.string()
5821
+ });
5676
5822
  function parseRateLimitHeaders(response) {
5677
5823
  const info = {};
5678
5824
  const retryAfter = response.headers.get("retry-after");
@@ -5733,16 +5879,23 @@ var pathConfig = {
5733
5879
  var ZapierApiClient = class {
5734
5880
  constructor(options) {
5735
5881
  this.options = options;
5736
- this.fetch = async (path, init) => {
5737
- if (!path.startsWith("/")) {
5738
- throw new ZapierValidationError(
5739
- `fetch expects a path starting with '/', got: ${path}`
5740
- );
5741
- }
5882
+ /**
5883
+ * Perform a request against an already-resolved URL.
5884
+ *
5885
+ * Does auth, header merging, and 429 retry — all the cross-cutting
5886
+ * concerns that every Zapier-bound HTTP call needs. Callers that have a
5887
+ * path (e.g. `/relay/...`) should use `rawFetch` instead, which does
5888
+ * path → URL resolution and delegates here.
5889
+ *
5890
+ * Exposed as a separate helper so call sites with a server-supplied
5891
+ * absolute URL (e.g. an approval poll URL) can still share the same
5892
+ * auth/retry pipeline instead of reaching for `this.options.fetch`
5893
+ * directly and drifting.
5894
+ */
5895
+ this.rawFetchUrl = async (url, init, pathConfig2) => {
5742
5896
  if (init?.body && (isPlainObject(init.body) || Array.isArray(init.body))) {
5743
5897
  init.body = JSON.stringify(init.body);
5744
5898
  }
5745
- const { url, pathConfig: pathConfig2 } = this.buildUrl(path, init?.searchParams);
5746
5899
  const builtHeaders = await this.buildHeaders(
5747
5900
  init,
5748
5901
  pathConfig2
@@ -5761,30 +5914,114 @@ var ZapierApiClient = class {
5761
5914
  ...init,
5762
5915
  headers: mergedHeaders
5763
5916
  });
5764
- if (response.status === 429) {
5765
- const rateLimitInfo = parseRateLimitHeaders(response);
5766
- const delayMs = rateLimitInfo.retryAfterMs ?? calculateExponentialBackoffMs(retries + 1);
5767
- if (delayMs > this.maxNetworkRetryDelayMs || retries >= this.maxNetworkRetries) {
5768
- throw new ZapierRateLimitError("Rate limited", {
5769
- statusCode: 429,
5770
- rateLimit: rateLimitInfo,
5771
- retries
5772
- });
5773
- }
5774
- retries++;
5775
- this.emitEvent("api:rate_limit_retry", {
5776
- retry: retries,
5777
- maxNetworkRetries: this.maxNetworkRetries,
5778
- delayMs,
5779
- path,
5780
- method: init?.method ?? "GET",
5781
- rateLimit: rateLimitInfo
5917
+ if (response.status !== 429) {
5918
+ return response;
5919
+ }
5920
+ const rateLimitInfo = parseRateLimitHeaders(response);
5921
+ const delayMs = rateLimitInfo.retryAfterMs ?? calculateExponentialBackoffMs(retries + 1);
5922
+ if (delayMs > this.maxNetworkRetryDelayMs || retries >= this.maxNetworkRetries) {
5923
+ throw new ZapierRateLimitError("Rate limited", {
5924
+ statusCode: 429,
5925
+ rateLimit: rateLimitInfo,
5926
+ retries
5927
+ });
5928
+ }
5929
+ retries++;
5930
+ this.emitEvent("api:rate_limit_retry", {
5931
+ retry: retries,
5932
+ maxNetworkRetries: this.maxNetworkRetries,
5933
+ delayMs,
5934
+ path: url,
5935
+ method: init?.method ?? "GET",
5936
+ rateLimit: rateLimitInfo
5937
+ });
5938
+ await sleep(delayMs);
5939
+ }
5940
+ };
5941
+ /**
5942
+ * Perform a request with auth, header merging, and rate-limit (429) retries.
5943
+ * Does NOT handle 403 approval_required — that's routed by `fetch`.
5944
+ */
5945
+ this.rawFetch = async (path, init) => {
5946
+ if (!path.startsWith("/")) {
5947
+ throw new ZapierValidationError(
5948
+ `fetch expects a path starting with '/', got: ${path}`
5949
+ );
5950
+ }
5951
+ const { url, pathConfig: pathConfig2 } = this.buildUrl(path, init?.searchParams);
5952
+ return this.rawFetchUrl(url, init, pathConfig2);
5953
+ };
5954
+ /**
5955
+ * Approval-aware HTTP fetch.
5956
+ *
5957
+ * Wraps `rawFetch` with the backend's just-in-time approval protocol. The
5958
+ * backend signals approval state via a 403 response with an
5959
+ * `x-zapier-error-type` header:
5960
+ *
5961
+ * - `request_denied_by_policy` → a policy rule permanently blocks the
5962
+ * request; no human can approve it. Throw.
5963
+ * - `approval_required` → the request needs human approval; the
5964
+ * SDK creates an approval, opens the URL
5965
+ * (poll mode), waits for resolution, and
5966
+ * retries the original request.
5967
+ * - anything else → not our concern, pass through.
5968
+ *
5969
+ * The retry loop exists because a single user action can legitimately
5970
+ * require multiple sequential approvals (e.g. policies that approve one
5971
+ * step at a time). Each iteration is either a first attempt or a post-
5972
+ * approval retry; `maxApprovalRetries` bounds the loop as a runaway-loop
5973
+ * safeguard.
5974
+ *
5975
+ * Loop accounting: `attempt` counts rawFetch calls, not approval rounds.
5976
+ * With `maxRetries = N` we perform up to `N + 1` rawFetch calls and at
5977
+ * most `N` approval rounds. The `attempt === maxRetries` guard ensures we
5978
+ * don't run an (N+1)th approval round we'll never consume — if the final
5979
+ * retry still returns `approval_required`, we break out and throw
5980
+ * `max_retries_exceeded` instead.
5981
+ */
5982
+ this.fetch = async (path, init) => {
5983
+ const maxRetries = this.options.maxApprovalRetries ?? DEFAULT_MAX_APPROVAL_RETRIES;
5984
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
5985
+ const response = await this.rawFetch(path, init);
5986
+ if (response.status !== 403) return response;
5987
+ const errorType = response.headers.get("x-zapier-error-type");
5988
+ if (errorType === "request_denied_by_policy") {
5989
+ const { data } = await this.parseResult(response);
5990
+ const { message, errors } = this.parseErrorResponse({
5991
+ status: response.status,
5992
+ statusText: response.statusText,
5993
+ data
5782
5994
  });
5783
- await sleep(delayMs);
5784
- continue;
5995
+ throw new ZapierApprovalError(
5996
+ message || "Request explicitly denied by policy",
5997
+ {
5998
+ status: "policy_denied",
5999
+ statusCode: response.status,
6000
+ errors
6001
+ }
6002
+ );
6003
+ }
6004
+ if (errorType !== "approval_required") return response;
6005
+ if (attempt === maxRetries) break;
6006
+ const isInteractive = this.options.isInteractive ?? getZapierIsInteractive();
6007
+ if (!isInteractive) {
6008
+ throw new ZapierApprovalError(
6009
+ "Approval required but session is not interactive",
6010
+ { status: "approval_required" }
6011
+ );
5785
6012
  }
5786
- return response;
6013
+ if (!init?.approvalContext) {
6014
+ throw new ZapierApiError(
6015
+ `Received 403 approval_required for ${path}, but the caller did not provide an approvalContext builder. Every approval-capable request must pass approvalContext so the SDK can create the approval with the correct policy context.`,
6016
+ { statusCode: 403 }
6017
+ );
6018
+ }
6019
+ await this.runOneApprovalRound(init.approvalContext);
5787
6020
  }
6021
+ throw new ZapierApprovalError(
6022
+ `Exceeded maximum approval retries (${maxRetries}) for ${path}`,
6023
+ { status: "max_retries_exceeded" }
6024
+ );
5788
6025
  };
5789
6026
  this.get = async (path, options = {}) => {
5790
6027
  return this.fetchJson("GET", path, void 0, options);
@@ -6069,6 +6306,156 @@ var ZapierApiClient = class {
6069
6306
  }
6070
6307
  return result;
6071
6308
  }
6309
+ /**
6310
+ * Run a single approval round: create the approval, open the URL (poll mode)
6311
+ * or throw (fail mode), poll until resolved, and emit events. Throws on
6312
+ * denied/timeout/unexpected status. Returns on approved.
6313
+ */
6314
+ async runOneApprovalRound(buildContext) {
6315
+ const context = buildContext();
6316
+ let approvalResponse;
6317
+ try {
6318
+ approvalResponse = await this.rawFetch("/api/v0/approvals", {
6319
+ method: "POST",
6320
+ headers: {
6321
+ "Content-Type": "application/json",
6322
+ Accept: "application/json"
6323
+ },
6324
+ body: JSON.stringify({ context })
6325
+ });
6326
+ } catch (err) {
6327
+ throw new ZapierApiError("Failed to create approval request", {
6328
+ statusCode: 0,
6329
+ cause: err
6330
+ });
6331
+ }
6332
+ if (!approvalResponse.ok) {
6333
+ const body2 = await approvalResponse.text().catch(() => void 0);
6334
+ throw new ZapierApiError(
6335
+ `Failed to create approval request: ${approvalResponse.status}`,
6336
+ { statusCode: approvalResponse.status, response: body2 }
6337
+ );
6338
+ }
6339
+ let body;
6340
+ try {
6341
+ body = await approvalResponse.text();
6342
+ } catch (err) {
6343
+ throw new ZapierApiError("Failed to read approval response body", {
6344
+ statusCode: approvalResponse.status,
6345
+ cause: err
6346
+ });
6347
+ }
6348
+ let approval;
6349
+ try {
6350
+ approval = CreateApprovalResponseSchema.parse(JSON.parse(body));
6351
+ } catch (err) {
6352
+ throw new ZapierApiError(`Failed to parse approval response: ${body}`, {
6353
+ statusCode: approvalResponse.status,
6354
+ cause: err,
6355
+ response: body
6356
+ });
6357
+ }
6358
+ const sdkapiOrigin = new URL(this.buildUrl("/api/v0/approvals").url).origin;
6359
+ const browserOrigin = getZapierBaseUrl(this.options.baseUrl) ?? sdkapiOrigin;
6360
+ const assertApprovalOrigin = (url, expectedOrigin, label) => {
6361
+ let parsed;
6362
+ try {
6363
+ parsed = new URL(url);
6364
+ } catch {
6365
+ throw new ZapierApiError(`Invalid approval ${label}: ${url}`, {
6366
+ statusCode: approvalResponse.status,
6367
+ response: body
6368
+ });
6369
+ }
6370
+ if (parsed.origin !== expectedOrigin) {
6371
+ throw new ZapierApiError(
6372
+ `Approval ${label} origin ${parsed.origin} does not match expected ${expectedOrigin}`,
6373
+ { statusCode: approvalResponse.status, response: body }
6374
+ );
6375
+ }
6376
+ };
6377
+ assertApprovalOrigin(approval.poll_url, sdkapiOrigin, "poll_url");
6378
+ assertApprovalOrigin(approval.approval_url, browserOrigin, "approval_url");
6379
+ this.emitEvent("approval:required", {
6380
+ approvalId: approval.approval_id,
6381
+ approvalUrl: approval.approval_url
6382
+ });
6383
+ const approvalMode = this.options.approvalMode ?? getZapierApprovalMode();
6384
+ if (approvalMode === "fail") {
6385
+ throw new ZapierApprovalError("This request requires approval.", {
6386
+ approvalId: approval.approval_id,
6387
+ approvalUrl: approval.approval_url,
6388
+ pollUrl: approval.poll_url,
6389
+ status: "pending"
6390
+ });
6391
+ }
6392
+ await openApproval(approval.approval_url);
6393
+ const timeoutMs = this.options.approvalTimeoutMs ?? DEFAULT_APPROVAL_TIMEOUT_MS;
6394
+ let rawPollResult;
6395
+ try {
6396
+ rawPollResult = await pollUntilComplete({
6397
+ // poll_url is an absolute URL supplied by the server, so we use
6398
+ // rawFetchUrl directly (skipping path resolution) but still share
6399
+ // auth + interactive-header + 429-retry with the rest of the SDK.
6400
+ fetchPoll: () => this.rawFetchUrl(approval.poll_url, {
6401
+ method: "GET",
6402
+ headers: { Accept: "application/json" }
6403
+ }),
6404
+ timeoutMs,
6405
+ isPending: (body2) => {
6406
+ const parsed = PollApprovalResponseSchema.safeParse(body2);
6407
+ return parsed.success && parsed.data.status === "pending_approval";
6408
+ }
6409
+ });
6410
+ } catch (err) {
6411
+ if (!(err instanceof ZapierTimeoutError)) {
6412
+ throw err;
6413
+ }
6414
+ this.emitEvent("approval:timeout", {
6415
+ approvalId: approval.approval_id
6416
+ });
6417
+ throw new ZapierApprovalError(
6418
+ `Approval timed out after ${timeoutMs / 1e3} seconds`,
6419
+ {
6420
+ approvalId: approval.approval_id,
6421
+ approvalUrl: approval.approval_url,
6422
+ pollUrl: approval.poll_url,
6423
+ status: "timeout",
6424
+ cause: err
6425
+ }
6426
+ );
6427
+ }
6428
+ const pollParse = PollApprovalResponseSchema.safeParse(rawPollResult);
6429
+ if (!pollParse.success) {
6430
+ const bodyPreview = typeof rawPollResult === "string" ? rawPollResult : JSON.stringify(rawPollResult);
6431
+ throw new ZapierApiError(
6432
+ `Failed to parse approval poll response: ${bodyPreview}`,
6433
+ {
6434
+ statusCode: 0,
6435
+ cause: pollParse.error,
6436
+ response: rawPollResult
6437
+ }
6438
+ );
6439
+ }
6440
+ const pollResult = pollParse.data;
6441
+ if (pollResult.status === "denied") {
6442
+ this.emitEvent("approval:denied", {
6443
+ approvalId: approval.approval_id
6444
+ });
6445
+ throw new ZapierApprovalError("Request denied by user", {
6446
+ approvalId: approval.approval_id,
6447
+ status: "denied"
6448
+ });
6449
+ }
6450
+ if (pollResult.status !== "approved") {
6451
+ throw new ZapierApiError(
6452
+ `Unexpected approval status received: ${pollResult.status}`
6453
+ );
6454
+ }
6455
+ this.emitEvent("approval:approved", {
6456
+ approvalId: approval.approval_id
6457
+ });
6458
+ }
6072
6459
  };
6073
6460
  var createZapierApi = (options) => {
6074
6461
  const { debug = false, fetch: originalFetch = globalThis.fetch } = options;
@@ -6082,7 +6469,7 @@ var createZapierApi = (options) => {
6082
6469
  };
6083
6470
 
6084
6471
  // src/plugins/api/index.ts
6085
- var apiPlugin = (params) => {
6472
+ var apiPlugin = (sdk) => {
6086
6473
  const {
6087
6474
  fetch: customFetch = globalThis.fetch,
6088
6475
  baseUrl = ZAPIER_BASE_URL,
@@ -6091,8 +6478,12 @@ var apiPlugin = (params) => {
6091
6478
  onEvent,
6092
6479
  debug = false,
6093
6480
  maxNetworkRetries = ZAPIER_MAX_NETWORK_RETRIES,
6094
- maxNetworkRetryDelayMs = ZAPIER_MAX_NETWORK_RETRY_DELAY_MS
6095
- } = params.context.options;
6481
+ maxNetworkRetryDelayMs = ZAPIER_MAX_NETWORK_RETRY_DELAY_MS,
6482
+ isInteractive,
6483
+ approvalTimeoutMs,
6484
+ maxApprovalRetries,
6485
+ approvalMode
6486
+ } = sdk.context.options;
6096
6487
  const api = createZapierApi({
6097
6488
  baseUrl,
6098
6489
  credentials,
@@ -6101,7 +6492,11 @@ var apiPlugin = (params) => {
6101
6492
  fetch: customFetch,
6102
6493
  onEvent,
6103
6494
  maxNetworkRetries,
6104
- maxNetworkRetryDelayMs
6495
+ maxNetworkRetryDelayMs,
6496
+ isInteractive,
6497
+ approvalTimeoutMs,
6498
+ maxApprovalRetries,
6499
+ approvalMode
6105
6500
  });
6106
6501
  return {
6107
6502
  context: {
@@ -6207,12 +6602,11 @@ async function batch(tasks, options = {}) {
6207
6602
  }
6208
6603
 
6209
6604
  // src/plugins/connections/index.ts
6210
- var connectionsPlugin = (params) => {
6211
- const { context } = params;
6605
+ var connectionsPlugin = (sdk) => {
6212
6606
  let cachedMap;
6213
6607
  async function loadConnectionsMap() {
6214
6608
  if (cachedMap === void 0) {
6215
- cachedMap = await context.getManifestConnections() ?? null;
6609
+ cachedMap = await sdk.context.getManifestConnections() ?? null;
6216
6610
  }
6217
6611
  return cachedMap;
6218
6612
  }
@@ -6259,12 +6653,12 @@ function isEnabledByEnv(key) {
6259
6653
  if (value === "false" || value === "0") return false;
6260
6654
  return void 0;
6261
6655
  }
6262
- var capabilitiesPlugin = ({ context }) => {
6263
- const options = context.options ?? {};
6656
+ var capabilitiesPlugin = (sdk) => {
6657
+ const options = sdk.context.options ?? {};
6264
6658
  let cached;
6265
6659
  async function resolveFlags() {
6266
6660
  if (cached) return cached;
6267
- const manifest = await context.getResolvedManifest();
6661
+ const manifest = await sdk.context.getResolvedManifest();
6268
6662
  cached = {};
6269
6663
  for (const flag of GATED_FLAGS) {
6270
6664
  cached[flag] = Boolean(
@@ -6350,12 +6744,12 @@ function extractNextCursor(links) {
6350
6744
  return void 0;
6351
6745
  }
6352
6746
  }
6353
- var listTablesPlugin = ({ context }) => {
6747
+ var listTablesPlugin = (sdk) => {
6354
6748
  async function listTablesPage(options) {
6355
6749
  if (options.includeShared) {
6356
- await context.checkCapability("canIncludeSharedTables");
6750
+ await sdk.context.checkCapability("canIncludeSharedTables");
6357
6751
  }
6358
- const { api } = context;
6752
+ const { api } = sdk.context;
6359
6753
  const searchParams = {};
6360
6754
  if (options.pageSize !== void 0) {
6361
6755
  searchParams.limit = options.pageSize.toString();
@@ -6420,7 +6814,10 @@ var listTablesPlugin = ({ context }) => {
6420
6814
  const listTablesDefinition = createPaginatedFunction(
6421
6815
  listTablesPage,
6422
6816
  ListTablesOptionsSchema,
6423
- createTelemetryCallback(context.eventEmission.emitMethodCalled, methodName),
6817
+ createTelemetryCallback(
6818
+ sdk.context.eventEmission.emitMethodCalled,
6819
+ methodName
6820
+ ),
6424
6821
  methodName,
6425
6822
  DEFAULT_PAGE_SIZE
6426
6823
  );
@@ -6452,9 +6849,9 @@ var GetTableOptionsSchemaDeprecated = zod.z.object({
6452
6849
  var GetTableOptionsInputSchema = zod.z.union([GetTableOptionsSchema, GetTableOptionsSchemaDeprecated]).describe(GetTableDescription);
6453
6850
 
6454
6851
  // src/plugins/tables/getTable/index.ts
6455
- var getTablePlugin = ({ context }) => {
6852
+ var getTablePlugin = (sdk) => {
6456
6853
  async function getTable(options) {
6457
- const { api } = context;
6854
+ const { api } = sdk.context;
6458
6855
  const tableId = "table" in options ? options.table : options.tableId;
6459
6856
  const rawResponse = await api.get(`/tables/api/v1/tables/${tableId}`, {
6460
6857
  customErrorHandler: ({ status }) => {
@@ -6486,7 +6883,7 @@ var getTablePlugin = ({ context }) => {
6486
6883
  getTable,
6487
6884
  GetTableOptionsInputSchema,
6488
6885
  createTelemetryCallback(
6489
- context.eventEmission.emitMethodCalled,
6886
+ sdk.context.eventEmission.emitMethodCalled,
6490
6887
  getTable.name
6491
6888
  )
6492
6889
  );
@@ -6517,9 +6914,9 @@ var CreateTableOptionsSchema = zod.z.object({
6517
6914
  }).describe("Create a new table");
6518
6915
 
6519
6916
  // src/plugins/tables/createTable/index.ts
6520
- var createTablePlugin = ({ context }) => {
6917
+ var createTablePlugin = (sdk) => {
6521
6918
  async function createTable(options) {
6522
- const { api } = context;
6919
+ const { api } = sdk.context;
6523
6920
  const rawResponse = await api.post(
6524
6921
  "/tables/api/v1/tables",
6525
6922
  {
@@ -6554,7 +6951,7 @@ var createTablePlugin = ({ context }) => {
6554
6951
  createTable,
6555
6952
  CreateTableOptionsSchema,
6556
6953
  createTelemetryCallback(
6557
- context.eventEmission.emitMethodCalled,
6954
+ sdk.context.eventEmission.emitMethodCalled,
6558
6955
  createTable.name
6559
6956
  )
6560
6957
  );
@@ -6586,10 +6983,10 @@ var DeleteTableOptionsSchemaDeprecated = zod.z.object({
6586
6983
  var DeleteTableOptionsInputSchema = zod.z.union([DeleteTableOptionsSchema, DeleteTableOptionsSchemaDeprecated]).describe(DeleteTableDescription);
6587
6984
 
6588
6985
  // src/plugins/tables/deleteTable/index.ts
6589
- var deleteTablePlugin = ({ context }) => {
6986
+ var deleteTablePlugin = (sdk) => {
6590
6987
  async function deleteTable(options) {
6591
- await context.checkCapability("canDeleteTables");
6592
- const { api } = context;
6988
+ await sdk.context.checkCapability("canDeleteTables");
6989
+ const { api } = sdk.context;
6593
6990
  const tableId = "table" in options ? options.table : options.tableId;
6594
6991
  await api.delete(`/tables/api/v1/tables/${tableId}`, void 0, {
6595
6992
  customErrorHandler: ({ status }) => {
@@ -6617,7 +7014,7 @@ var deleteTablePlugin = ({ context }) => {
6617
7014
  deleteTable,
6618
7015
  DeleteTableOptionsInputSchema,
6619
7016
  createTelemetryCallback(
6620
- context.eventEmission.emitMethodCalled,
7017
+ sdk.context.eventEmission.emitMethodCalled,
6621
7018
  deleteTable.name
6622
7019
  )
6623
7020
  );
@@ -6641,9 +7038,9 @@ var deleteTablePlugin = ({ context }) => {
6641
7038
  };
6642
7039
 
6643
7040
  // src/plugins/tables/listTableFields/index.ts
6644
- var listTableFieldsPlugin = ({ context }) => {
7041
+ var listTableFieldsPlugin = (sdk) => {
6645
7042
  async function listTableFields(options) {
6646
- const { api } = context;
7043
+ const { api } = sdk.context;
6647
7044
  const tableId = "table" in options ? options.table : options.tableId;
6648
7045
  const fieldKeys = "fields" in options ? options.fields : options.fieldKeys;
6649
7046
  const searchParams = {};
@@ -6689,7 +7086,7 @@ var listTableFieldsPlugin = ({ context }) => {
6689
7086
  listTableFields,
6690
7087
  ListTableFieldsOptionsInputSchema,
6691
7088
  createTelemetryCallback(
6692
- context.eventEmission.emitMethodCalled,
7089
+ sdk.context.eventEmission.emitMethodCalled,
6693
7090
  listTableFields.name
6694
7091
  )
6695
7092
  );
@@ -6744,9 +7141,9 @@ var CreateTableFieldsOptionsInputSchema = zod.z.union([
6744
7141
  ]).describe(CreateTableFieldsDescription);
6745
7142
 
6746
7143
  // src/plugins/tables/createTableFields/index.ts
6747
- var createTableFieldsPlugin = ({ context }) => {
7144
+ var createTableFieldsPlugin = (sdk) => {
6748
7145
  async function createTableFields(options) {
6749
- const { api } = context;
7146
+ const { api } = sdk.context;
6750
7147
  const tableId = "table" in options ? options.table : options.tableId;
6751
7148
  const rawResponse = await api.post(
6752
7149
  `/tables/api/v1/tables/${tableId}/fields`,
@@ -6781,7 +7178,7 @@ var createTableFieldsPlugin = ({ context }) => {
6781
7178
  createTableFields,
6782
7179
  CreateTableFieldsOptionsInputSchema,
6783
7180
  createTelemetryCallback(
6784
- context.eventEmission.emitMethodCalled,
7181
+ sdk.context.eventEmission.emitMethodCalled,
6785
7182
  createTableFields.name
6786
7183
  )
6787
7184
  );
@@ -6821,9 +7218,9 @@ var DeleteTableFieldsOptionsInputSchema = zod.z.union([
6821
7218
  ]).describe(DeleteTableFieldsDescription);
6822
7219
 
6823
7220
  // src/plugins/tables/deleteTableFields/index.ts
6824
- var deleteTableFieldsPlugin = ({ context }) => {
7221
+ var deleteTableFieldsPlugin = (sdk) => {
6825
7222
  async function deleteTableFields(options) {
6826
- const { api } = context;
7223
+ const { api } = sdk.context;
6827
7224
  const tableId = "table" in options ? options.table : options.tableId;
6828
7225
  const fieldKeys = "fields" in options ? options.fields : options.fieldKeys;
6829
7226
  const numericFieldIds = await resolveFieldKeys({
@@ -6861,7 +7258,7 @@ var deleteTableFieldsPlugin = ({ context }) => {
6861
7258
  deleteTableFields,
6862
7259
  DeleteTableFieldsOptionsInputSchema,
6863
7260
  createTelemetryCallback(
6864
- context.eventEmission.emitMethodCalled,
7261
+ sdk.context.eventEmission.emitMethodCalled,
6865
7262
  deleteTableFields.name
6866
7263
  )
6867
7264
  );
@@ -6948,9 +7345,9 @@ var tableRecordFormatter = {
6948
7345
  };
6949
7346
 
6950
7347
  // src/plugins/tables/getTableRecord/index.ts
6951
- var getTableRecordPlugin = ({ context }) => {
7348
+ var getTableRecordPlugin = (sdk) => {
6952
7349
  async function getTableRecord(options) {
6953
- const { api } = context;
7350
+ const { api } = sdk.context;
6954
7351
  const tableId = "table" in options ? options.table : options.tableId;
6955
7352
  const recordId = "record" in options ? options.record : options.recordId;
6956
7353
  const rawResponse = await api.get(
@@ -6994,7 +7391,7 @@ var getTableRecordPlugin = ({ context }) => {
6994
7391
  getTableRecord,
6995
7392
  GetTableRecordOptionsInputSchema,
6996
7393
  createTelemetryCallback(
6997
- context.eventEmission.emitMethodCalled,
7394
+ sdk.context.eventEmission.emitMethodCalled,
6998
7395
  getTableRecord.name
6999
7396
  )
7000
7397
  );
@@ -7082,9 +7479,9 @@ function extractNextCursor2(meta) {
7082
7479
  }
7083
7480
  return meta.pagination.end_cursor;
7084
7481
  }
7085
- var listTableRecordsPlugin = ({ context }) => {
7482
+ var listTableRecordsPlugin = (sdk) => {
7086
7483
  async function listTableRecordsPage(options) {
7087
- const { api } = context;
7484
+ const { api } = sdk.context;
7088
7485
  const tableId = "table" in options ? options.table : options.tableId;
7089
7486
  const translator = await createFieldKeyTranslator({
7090
7487
  api,
@@ -7156,7 +7553,10 @@ var listTableRecordsPlugin = ({ context }) => {
7156
7553
  const listTableRecordsDefinition = createPaginatedFunction(
7157
7554
  listTableRecordsPage,
7158
7555
  ListTableRecordsOptionsInputSchema,
7159
- createTelemetryCallback(context.eventEmission.emitMethodCalled, methodName),
7556
+ createTelemetryCallback(
7557
+ sdk.context.eventEmission.emitMethodCalled,
7558
+ methodName
7559
+ ),
7160
7560
  methodName,
7161
7561
  DEFAULT_PAGE_SIZE
7162
7562
  );
@@ -7211,9 +7611,9 @@ var CreateTableRecordsOptionsInputSchema = zod.z.union([
7211
7611
  ]).describe(CreateTableRecordsDescription);
7212
7612
 
7213
7613
  // src/plugins/tables/createTableRecords/index.ts
7214
- var createTableRecordsPlugin = ({ context }) => {
7614
+ var createTableRecordsPlugin = (sdk) => {
7215
7615
  async function createTableRecords(options) {
7216
- const { api } = context;
7616
+ const { api } = sdk.context;
7217
7617
  const tableId = "table" in options ? options.table : options.tableId;
7218
7618
  const translator = await createFieldKeyTranslator({
7219
7619
  api,
@@ -7265,7 +7665,7 @@ var createTableRecordsPlugin = ({ context }) => {
7265
7665
  createTableRecords,
7266
7666
  CreateTableRecordsOptionsInputSchema,
7267
7667
  createTelemetryCallback(
7268
- context.eventEmission.emitMethodCalled,
7668
+ sdk.context.eventEmission.emitMethodCalled,
7269
7669
  createTableRecords.name
7270
7670
  )
7271
7671
  );
@@ -7304,9 +7704,9 @@ var DeleteTableRecordsOptionsInputSchema = zod.z.union([
7304
7704
  ]).describe(DeleteTableRecordsDescription);
7305
7705
 
7306
7706
  // src/plugins/tables/deleteTableRecords/index.ts
7307
- var deleteTableRecordsPlugin = ({ context }) => {
7707
+ var deleteTableRecordsPlugin = (sdk) => {
7308
7708
  async function deleteTableRecords(options) {
7309
- const { api } = context;
7709
+ const { api } = sdk.context;
7310
7710
  const tableId = "table" in options ? options.table : options.tableId;
7311
7711
  const recordIds = "records" in options ? options.records : options.recordIds;
7312
7712
  await api.delete(
@@ -7339,7 +7739,7 @@ var deleteTableRecordsPlugin = ({ context }) => {
7339
7739
  deleteTableRecords,
7340
7740
  DeleteTableRecordsOptionsInputSchema,
7341
7741
  createTelemetryCallback(
7342
- context.eventEmission.emitMethodCalled,
7742
+ sdk.context.eventEmission.emitMethodCalled,
7343
7743
  deleteTableRecords.name
7344
7744
  )
7345
7745
  );
@@ -7393,9 +7793,9 @@ var UpdateTableRecordsOptionsInputSchema = zod.z.union([
7393
7793
  ]).describe(UpdateTableRecordsDescription);
7394
7794
 
7395
7795
  // src/plugins/tables/updateTableRecords/index.ts
7396
- var updateTableRecordsPlugin = ({ context }) => {
7796
+ var updateTableRecordsPlugin = (sdk) => {
7397
7797
  async function updateTableRecords(options) {
7398
- const { api } = context;
7798
+ const { api } = sdk.context;
7399
7799
  const tableId = "table" in options ? options.table : options.tableId;
7400
7800
  const translator = await createFieldKeyTranslator({
7401
7801
  api,
@@ -7448,7 +7848,7 @@ var updateTableRecordsPlugin = ({ context }) => {
7448
7848
  updateTableRecords,
7449
7849
  UpdateTableRecordsOptionsInputSchema,
7450
7850
  createTelemetryCallback(
7451
- context.eventEmission.emitMethodCalled,
7851
+ sdk.context.eventEmission.emitMethodCalled,
7452
7852
  updateTableRecords.name
7453
7853
  )
7454
7854
  );
@@ -7474,8 +7874,8 @@ var updateTableRecordsPlugin = ({ context }) => {
7474
7874
  };
7475
7875
 
7476
7876
  // src/plugins/registry/index.ts
7477
- var registryPlugin = ({ sdk, context }) => {
7478
- const metaKeys = Object.keys(context.meta || {});
7877
+ var registryPlugin = (sdk) => {
7878
+ const metaKeys = Object.keys(sdk.context.meta || {});
7479
7879
  const categoryDefinitions = {
7480
7880
  account: {
7481
7881
  title: "Account"
@@ -7520,7 +7920,7 @@ var registryPlugin = ({ sdk, context }) => {
7520
7920
  }
7521
7921
  return false;
7522
7922
  }).map((key) => {
7523
- const meta = context.meta[key];
7923
+ const meta = sdk.context.meta[key];
7524
7924
  return {
7525
7925
  name: key,
7526
7926
  description: meta.description,
@@ -7588,7 +7988,7 @@ var registryPlugin = ({ sdk, context }) => {
7588
7988
  };
7589
7989
 
7590
7990
  // src/plugins/deprecated/authentications.ts
7591
- var listAuthenticationsPlugin = ({ sdk }) => ({
7991
+ var listAuthenticationsPlugin = (sdk) => ({
7592
7992
  listAuthentications: sdk.listConnections,
7593
7993
  context: {
7594
7994
  meta: {
@@ -7603,7 +8003,7 @@ var listAuthenticationsPlugin = ({ sdk }) => ({
7603
8003
  }
7604
8004
  }
7605
8005
  });
7606
- var getAuthenticationPlugin = ({ sdk }) => ({
8006
+ var getAuthenticationPlugin = (sdk) => ({
7607
8007
  getAuthentication: sdk.getConnection,
7608
8008
  context: {
7609
8009
  meta: {
@@ -7618,7 +8018,7 @@ var getAuthenticationPlugin = ({ sdk }) => ({
7618
8018
  }
7619
8019
  }
7620
8020
  });
7621
- var findFirstAuthenticationPlugin = ({ sdk }) => ({
8021
+ var findFirstAuthenticationPlugin = (sdk) => ({
7622
8022
  findFirstAuthentication: sdk.findFirstConnection,
7623
8023
  context: {
7624
8024
  meta: {
@@ -7633,7 +8033,7 @@ var findFirstAuthenticationPlugin = ({ sdk }) => ({
7633
8033
  }
7634
8034
  }
7635
8035
  });
7636
- var findUniqueAuthenticationPlugin = ({ sdk }) => ({
8036
+ var findUniqueAuthenticationPlugin = (sdk) => ({
7637
8037
  findUniqueAuthentication: sdk.findUniqueConnection,
7638
8038
  context: {
7639
8039
  meta: {
@@ -7696,9 +8096,9 @@ var GetInputFieldsSchemaSchemaDeprecated = zod.z.object({
7696
8096
  var GetInputFieldsSchemaInputSchema = zod.z.union([GetInputFieldsSchemaSchema, GetInputFieldsSchemaSchemaDeprecated]).describe(GetInputFieldsSchemaDescription);
7697
8097
 
7698
8098
  // src/plugins/getInputFieldsSchema/index.ts
7699
- var getInputFieldsSchemaPlugin = ({ sdk, context }) => {
8099
+ var getInputFieldsSchemaPlugin = (sdk) => {
7700
8100
  async function getInputFieldsSchema(options) {
7701
- const { api, getVersionedImplementationId } = context;
8101
+ const { api, getVersionedImplementationId } = sdk.context;
7702
8102
  const appKey = "app" in options ? options.app : options.appKey;
7703
8103
  const actionKey = "action" in options ? options.action : options.actionKey;
7704
8104
  const { actionType, connection, connectionId, authenticationId, inputs } = options;
@@ -7706,7 +8106,7 @@ var getInputFieldsSchemaPlugin = ({ sdk, context }) => {
7706
8106
  connection,
7707
8107
  connectionId,
7708
8108
  authenticationId,
7709
- resolveConnection: context.resolveConnection
8109
+ resolveConnection: sdk.context.resolveConnection
7710
8110
  });
7711
8111
  const selectedApi = await getVersionedImplementationId(appKey);
7712
8112
  if (!selectedApi) {
@@ -7741,7 +8141,7 @@ var getInputFieldsSchemaPlugin = ({ sdk, context }) => {
7741
8141
  getInputFieldsSchema,
7742
8142
  GetInputFieldsSchemaInputSchema,
7743
8143
  createTelemetryCallback(
7744
- context.eventEmission.emitMethodCalled,
8144
+ sdk.context.eventEmission.emitMethodCalled,
7745
8145
  getInputFieldsSchema.name
7746
8146
  )
7747
8147
  );
@@ -7835,9 +8235,9 @@ function transformNeedChoicesToInputFieldChoiceItem(choice) {
7835
8235
  value: choice.value
7836
8236
  };
7837
8237
  }
7838
- var listInputFieldChoicesPlugin = ({ context, sdk }) => {
8238
+ var listInputFieldChoicesPlugin = (sdk) => {
7839
8239
  async function listInputFieldChoicesPage(options) {
7840
- const { api, getVersionedImplementationId } = context;
8240
+ const { api, getVersionedImplementationId } = sdk.context;
7841
8241
  const appKey = "app" in options ? options.app : options.appKey;
7842
8242
  const actionKey = "action" in options ? options.action : options.actionKey;
7843
8243
  const inputFieldKey = "inputField" in options ? options.inputField : options.inputFieldKey;
@@ -7854,7 +8254,7 @@ var listInputFieldChoicesPlugin = ({ context, sdk }) => {
7854
8254
  connection,
7855
8255
  connectionId,
7856
8256
  authenticationId,
7857
- resolveConnection: context.resolveConnection
8257
+ resolveConnection: sdk.context.resolveConnection
7858
8258
  });
7859
8259
  const selectedApi = await getVersionedImplementationId(appKey);
7860
8260
  if (!selectedApi) {
@@ -7932,7 +8332,10 @@ var listInputFieldChoicesPlugin = ({ context, sdk }) => {
7932
8332
  const listInputFieldChoicesDefinition = createPaginatedFunction(
7933
8333
  listInputFieldChoicesPage,
7934
8334
  ListInputFieldChoicesInputSchema,
7935
- createTelemetryCallback(context.eventEmission.emitMethodCalled, methodName),
8335
+ createTelemetryCallback(
8336
+ sdk.context.eventEmission.emitMethodCalled,
8337
+ methodName
8338
+ ),
7936
8339
  methodName,
7937
8340
  DEFAULT_PAGE_SIZE
7938
8341
  );
@@ -8304,19 +8707,20 @@ function getTransportConfig(options) {
8304
8707
  endpoint
8305
8708
  };
8306
8709
  }
8307
- var eventEmissionPlugin = ({ context }) => {
8710
+ var eventEmissionPlugin = (sdk) => {
8711
+ const options = sdk.context.options ?? {};
8308
8712
  const defaultTransport = getTransportConfig({
8309
- trackingBaseUrl: context.options.trackingBaseUrl,
8310
- baseUrl: context.options.baseUrl
8713
+ trackingBaseUrl: options.trackingBaseUrl,
8714
+ baseUrl: options.baseUrl
8311
8715
  });
8312
8716
  const config = {
8313
- enabled: context.options.eventEmission?.enabled ?? true,
8314
- callContext: context.options.eventEmission?.callContext,
8717
+ enabled: options.eventEmission?.enabled ?? true,
8718
+ callContext: options.eventEmission?.callContext,
8315
8719
  transport: (
8316
8720
  // If env var is set, use it (defaultTransport will be from env)
8317
8721
  globalThis.process?.env?.ZAPIER_SDK_TELEMETRY_TRANSPORT ? defaultTransport : (
8318
8722
  // Otherwise, use option transport or default
8319
- context.options.eventEmission?.transport ?? defaultTransport
8723
+ options.eventEmission?.transport ?? defaultTransport
8320
8724
  )
8321
8725
  )
8322
8726
  };
@@ -8324,7 +8728,7 @@ var eventEmissionPlugin = ({ context }) => {
8324
8728
  if (config.enabled) {
8325
8729
  try {
8326
8730
  const token = await resolveAuthToken({
8327
- ...context.options
8731
+ ...options
8328
8732
  });
8329
8733
  if (token) {
8330
8734
  return extractUserIdsFromJwt(token);
@@ -8574,55 +8978,54 @@ var eventEmissionPlugin = ({ context }) => {
8574
8978
  };
8575
8979
 
8576
8980
  // src/sdk.ts
8577
- function createSdk(options = {}, initialSdk = {}, initialContext = { meta: {} }) {
8981
+ function createOptionsPlugin(options) {
8982
+ return () => ({ context: { options } });
8983
+ }
8984
+ function createSdk() {
8985
+ return buildSdk({}, { meta: {} });
8986
+ }
8987
+ function buildSdk(properties, context) {
8988
+ const frozenContext = Object.freeze(context);
8578
8989
  return {
8579
- ...initialSdk,
8580
- getContext: () => initialContext,
8581
- addPlugin(plugin, addPluginOptions = {}) {
8582
- const currentSdkWithContext = {
8583
- ...initialSdk,
8584
- getContext: () => initialContext
8585
- };
8990
+ ...properties,
8991
+ get context() {
8992
+ return frozenContext;
8993
+ },
8994
+ getContext: () => frozenContext,
8995
+ // runtime compat shim, not in types
8996
+ addPlugin(plugin) {
8586
8997
  const pluginResult = plugin({
8587
- sdk: currentSdkWithContext,
8588
- context: {
8589
- ...initialContext,
8590
- // Add the options that createSdk was called with to context
8591
- options
8592
- },
8593
- ...addPluginOptions
8998
+ ...properties,
8999
+ context: frozenContext
8594
9000
  });
8595
- const { context: pluginContext, ...sdkProperties } = pluginResult;
8596
- const newSdk = { ...initialSdk, ...sdkProperties };
8597
- let newContext = {
8598
- ...initialContext,
8599
- ...addPluginOptions,
8600
- meta: initialContext.meta || {}
9001
+ const { context: pluginContext, ...pluginProperties } = pluginResult;
9002
+ const mergedProperties = { ...properties, ...pluginProperties };
9003
+ let mergedContext = {
9004
+ ...context,
9005
+ meta: context.meta || {}
8601
9006
  };
8602
9007
  if (pluginContext) {
8603
- const { meta: pluginMeta, ...otherPluginContext } = pluginContext;
8604
- newContext = {
8605
- ...newContext,
8606
- ...otherPluginContext
9008
+ const { meta: pluginMeta, ...pluginContextRest } = pluginContext;
9009
+ mergedContext = {
9010
+ ...mergedContext,
9011
+ ...pluginContextRest
8607
9012
  };
8608
9013
  if (pluginMeta) {
8609
- newContext = {
8610
- ...newContext,
8611
- meta: {
8612
- ...newContext.meta,
8613
- // Existing meta (now guaranteed to exist)
8614
- ...pluginMeta
8615
- // New meta from plugin
8616
- }
9014
+ mergedContext = {
9015
+ ...mergedContext,
9016
+ meta: { ...mergedContext.meta, ...pluginMeta }
8617
9017
  };
8618
9018
  }
8619
9019
  }
8620
- return createSdk(options, newSdk, newContext);
9020
+ return buildSdk(
9021
+ mergedProperties,
9022
+ mergedContext
9023
+ );
8621
9024
  }
8622
9025
  };
8623
9026
  }
8624
9027
  function createZapierSdkWithoutRegistry(options = {}) {
8625
- return createSdk(options).addPlugin(eventEmissionPlugin).addPlugin(apiPlugin).addPlugin(manifestPlugin).addPlugin(capabilitiesPlugin).addPlugin(connectionsPlugin).addPlugin(listAppsPlugin).addPlugin(getAppPlugin).addPlugin(listActionsPlugin).addPlugin(getActionPlugin).addPlugin(listInputFieldsPlugin).addPlugin(getInputFieldsSchemaPlugin).addPlugin(listInputFieldChoicesPlugin).addPlugin(runActionPlugin).addPlugin(listConnectionsPlugin).addPlugin(getConnectionPlugin).addPlugin(findFirstConnectionPlugin).addPlugin(findUniqueConnectionPlugin).addPlugin(listAuthenticationsPlugin).addPlugin(getAuthenticationPlugin).addPlugin(findFirstAuthenticationPlugin).addPlugin(findUniqueAuthenticationPlugin).addPlugin(listClientCredentialsPlugin).addPlugin(createClientCredentialsPlugin).addPlugin(deleteClientCredentialsPlugin).addPlugin(fetchPlugin).addPlugin(requestPlugin).addPlugin(listTablesPlugin).addPlugin(getTablePlugin).addPlugin(deleteTablePlugin).addPlugin(createTablePlugin).addPlugin(listTableFieldsPlugin).addPlugin(createTableFieldsPlugin).addPlugin(deleteTableFieldsPlugin).addPlugin(getTableRecordPlugin).addPlugin(listTableRecordsPlugin).addPlugin(createTableRecordsPlugin).addPlugin(deleteTableRecordsPlugin).addPlugin(updateTableRecordsPlugin).addPlugin(appsPlugin).addPlugin(getProfilePlugin);
9028
+ return createSdk().addPlugin(createOptionsPlugin(options)).addPlugin(eventEmissionPlugin).addPlugin(apiPlugin).addPlugin(manifestPlugin).addPlugin(capabilitiesPlugin).addPlugin(connectionsPlugin).addPlugin(listAppsPlugin).addPlugin(getAppPlugin).addPlugin(listActionsPlugin).addPlugin(getActionPlugin).addPlugin(listInputFieldsPlugin).addPlugin(getInputFieldsSchemaPlugin).addPlugin(listInputFieldChoicesPlugin).addPlugin(runActionPlugin).addPlugin(listConnectionsPlugin).addPlugin(getConnectionPlugin).addPlugin(findFirstConnectionPlugin).addPlugin(findUniqueConnectionPlugin).addPlugin(listAuthenticationsPlugin).addPlugin(getAuthenticationPlugin).addPlugin(findFirstAuthenticationPlugin).addPlugin(findUniqueAuthenticationPlugin).addPlugin(listClientCredentialsPlugin).addPlugin(createClientCredentialsPlugin).addPlugin(deleteClientCredentialsPlugin).addPlugin(fetchPlugin).addPlugin(requestPlugin).addPlugin(listTablesPlugin).addPlugin(getTablePlugin).addPlugin(deleteTablePlugin).addPlugin(createTablePlugin).addPlugin(listTableFieldsPlugin).addPlugin(createTableFieldsPlugin).addPlugin(deleteTableFieldsPlugin).addPlugin(getTableRecordPlugin).addPlugin(listTableRecordsPlugin).addPlugin(createTableRecordsPlugin).addPlugin(deleteTableRecordsPlugin).addPlugin(updateTableRecordsPlugin).addPlugin(appsPlugin).addPlugin(getProfilePlugin);
8626
9029
  }
8627
9030
  function createZapierSdk(options = {}) {
8628
9031
  return createZapierSdkWithoutRegistry(options).addPlugin(registryPlugin);
@@ -8645,6 +9048,16 @@ var BaseSdkOptionsSchema = zod.z.object({
8645
9048
  * Default is 60000 (60 seconds).
8646
9049
  */
8647
9050
  maxNetworkRetryDelayMs: zod.z.number().optional().describe("Max delay in ms to wait for retry (default: 60000).").meta({ valueHint: "ms" }),
9051
+ isInteractive: zod.z.boolean().optional().describe(
9052
+ "Whether this session is interactive (user can visit approval URLs). Defaults to ZAPIER_IS_INTERACTIVE env var."
9053
+ ).meta({ internal: true }),
9054
+ approvalTimeoutMs: zod.z.number().optional().describe("Timeout in ms for approval polling. Default: 600000 (10 min).").meta({ valueHint: "ms", internal: true }),
9055
+ maxApprovalRetries: zod.z.number().optional().describe(
9056
+ "Maximum number of sequential approval rounds per request (one per gating policy) before giving up. Default: 2."
9057
+ ).meta({ internal: true }),
9058
+ approvalMode: zod.z.enum(["poll", "fail"]).optional().describe(
9059
+ 'Approval flow behavior. "poll" opens browser and polls (default). "fail" creates the approval and throws immediately with the approval URL.'
9060
+ ).meta({ internal: true }),
8648
9061
  // Internal
8649
9062
  manifestPath: zod.z.string().optional().describe("Path to a .zapierrc manifest file for app version locking.").meta({ internal: true }),
8650
9063
  manifest: zod.z.custom().optional().describe("Manifest for app version locking.").meta({ internal: true }),
@@ -8680,7 +9093,9 @@ exports.CredentialsFunctionSchema = CredentialsFunctionSchema;
8680
9093
  exports.CredentialsObjectSchema = CredentialsObjectSchema;
8681
9094
  exports.CredentialsSchema = CredentialsSchema;
8682
9095
  exports.DEFAULT_ACTION_TIMEOUT_MS = DEFAULT_ACTION_TIMEOUT_MS;
9096
+ exports.DEFAULT_APPROVAL_TIMEOUT_MS = DEFAULT_APPROVAL_TIMEOUT_MS;
8683
9097
  exports.DEFAULT_CONFIG_PATH = DEFAULT_CONFIG_PATH;
9098
+ exports.DEFAULT_MAX_APPROVAL_RETRIES = DEFAULT_MAX_APPROVAL_RETRIES;
8684
9099
  exports.DEFAULT_PAGE_SIZE = DEFAULT_PAGE_SIZE;
8685
9100
  exports.DebugPropertySchema = DebugPropertySchema;
8686
9101
  exports.FieldsPropertySchema = FieldsPropertySchema;
@@ -8705,6 +9120,7 @@ exports.ZAPIER_MAX_NETWORK_RETRY_DELAY_MS = ZAPIER_MAX_NETWORK_RETRY_DELAY_MS;
8705
9120
  exports.ZapierActionError = ZapierActionError;
8706
9121
  exports.ZapierApiError = ZapierApiError;
8707
9122
  exports.ZapierAppNotFoundError = ZapierAppNotFoundError;
9123
+ exports.ZapierApprovalError = ZapierApprovalError;
8708
9124
  exports.ZapierAuthenticationError = ZapierAuthenticationError;
8709
9125
  exports.ZapierBundleError = ZapierBundleError;
8710
9126
  exports.ZapierConfigurationError = ZapierConfigurationError;
@@ -8738,6 +9154,7 @@ exports.connectionsPlugin = connectionsPlugin;
8738
9154
  exports.createBaseEvent = createBaseEvent;
8739
9155
  exports.createClientCredentialsPlugin = createClientCredentialsPlugin;
8740
9156
  exports.createFunction = createFunction;
9157
+ exports.createOptionsPlugin = createOptionsPlugin;
8741
9158
  exports.createSdk = createSdk;
8742
9159
  exports.createTableFieldsPlugin = createTableFieldsPlugin;
8743
9160
  exports.createTablePlugin = createTablePlugin;
@@ -8771,6 +9188,8 @@ exports.getReleaseId = getReleaseId;
8771
9188
  exports.getTablePlugin = getTablePlugin;
8772
9189
  exports.getTableRecordPlugin = getTableRecordPlugin;
8773
9190
  exports.getTokenFromCliLogin = getTokenFromCliLogin;
9191
+ exports.getZapierApprovalMode = getZapierApprovalMode;
9192
+ exports.getZapierIsInteractive = getZapierIsInteractive;
8774
9193
  exports.injectCliLogin = injectCliLogin;
8775
9194
  exports.inputFieldKeyResolver = inputFieldKeyResolver;
8776
9195
  exports.inputsAllOptionalResolver = inputsAllOptionalResolver;