@zapier/kitcore 0.18.0 → 0.20.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.
package/dist/index.mjs CHANGED
@@ -643,6 +643,11 @@ function toIterable(source) {
643
643
  return { [Symbol.asyncIterator]: () => source[Symbol.asyncIterator]() };
644
644
  }
645
645
 
646
+ // src/utils/promise-utils.ts
647
+ function isPromiseLike(value) {
648
+ return value !== null && typeof value === "object" && typeof value.then === "function";
649
+ }
650
+
646
651
  // src/utils/validation.ts
647
652
  var parseOrThrow = (schema, input, { adaptError } = {}) => {
648
653
  const result = schema.safeParse(input);
@@ -1111,7 +1116,7 @@ function createRawFunction(coreFn, options) {
1111
1116
  try {
1112
1117
  const parsed = schema ? validateOptions(schema, input, { adaptError }) : input;
1113
1118
  const result = coreFn(parsed, context);
1114
- if (result !== null && typeof result === "object" && typeof result.then === "function") {
1119
+ if (isPromiseLike(result)) {
1115
1120
  return result.then(
1116
1121
  (value) => {
1117
1122
  fireEnd();
@@ -1893,8 +1898,9 @@ function declareOptionalMethod(config) {
1893
1898
  `Plugin "${id}" is an optional stand-in (declareOptionalMethod) with no implementation. Its binding is \`undefined\` unless a real plugin is registered under this id.`
1894
1899
  );
1895
1900
  }
1896
- // Requires nothing (phantom carrier `<never, never>`): a consumer that
1897
- // imports it still passes `createSdk`'s completeness check unprovided. The
1901
+ // Requires nothing: a consumer that imports it still passes `createSdk`'s
1902
+ // completeness check unprovided. The contract is still carried, so a
1903
+ // provider that DOES appear under the id is checked against it. The
1898
1904
  // `optional: true` literal drives `PluginSurface` to type the binding
1899
1905
  // `| undefined`.
1900
1906
  };
@@ -1944,9 +1950,12 @@ function declareOptionalProperty(config) {
1944
1950
  optional: true,
1945
1951
  imports: [],
1946
1952
  importBindings: []
1947
- // Requires nothing (phantom carrier `<never, never>`): a consumer that
1948
- // imports it still passes `createSdk`'s completeness check unprovided. The
1949
- // import binding is still typed `TValue | undefined` from the descriptor.
1953
+ // Requires nothing: a consumer that imports it still passes `createSdk`'s
1954
+ // completeness check unprovided. The contract is the binding a consumer
1955
+ // sees, `TValue | undefined`, which is also what a by-reference provider
1956
+ // (`defineProperty(ref, { value })`) is allowed to pass. A consumer of an
1957
+ // optional reference has to handle the absent case either way, so an
1958
+ // explicit `undefined` breaks nothing a narrower contract would protect.
1950
1959
  };
1951
1960
  }
1952
1961
  function declareDefault({
@@ -2443,9 +2452,6 @@ function applyListOutputPolicy(page, policy) {
2443
2452
  var FRAMEWORK_CONFIGURATION_IDS = /* @__PURE__ */ new Set([
2444
2453
  CORE_OPTIONS_ID
2445
2454
  ]);
2446
- function isPromiseLike(value) {
2447
- return value !== null && typeof value === "object" && typeof value.then === "function";
2448
- }
2449
2455
  function normalizeOutput(output) {
2450
2456
  if (output === void 0) return { type: "raw" };
2451
2457
  if (typeof output === "string") return { type: output };
@@ -4932,6 +4938,7 @@ var DEFAULT_IDEMPOTENT_METHODS = [
4932
4938
  "TRACE"
4933
4939
  ];
4934
4940
  var BASE_BACKOFF_MILLISECONDS = 1e3;
4941
+ var MIN_BACKOFF_MILLISECONDS = 100;
4935
4942
  var JITTER_FACTOR = 0.5;
4936
4943
  var EPOCH_THRESHOLD_SECONDS = 1e9;
4937
4944
  function directedDelayMilliseconds(response) {
@@ -4956,6 +4963,12 @@ function backoffMilliseconds(attemptNumber) {
4956
4963
  const base = BASE_BACKOFF_MILLISECONDS * 2 ** (attemptNumber - 1);
4957
4964
  return base + Math.random() * JITTER_FACTOR * base;
4958
4965
  }
4966
+ function clampBackoffMilliseconds(attemptNumber, maxDelayMilliseconds) {
4967
+ return Math.max(
4968
+ Math.min(backoffMilliseconds(attemptNumber), maxDelayMilliseconds),
4969
+ MIN_BACKOFF_MILLISECONDS
4970
+ );
4971
+ }
4959
4972
  function abortReason(signal) {
4960
4973
  const reason = signal?.reason;
4961
4974
  return reason ?? new Error("The request was aborted.");
@@ -4990,6 +5003,20 @@ var retryHttpRequestPlugin = defineHook({
4990
5003
  const maxDelayMilliseconds = options.maxDelayMilliseconds ?? DEFAULT_MAX_DELAY_MILLISECONDS;
4991
5004
  const idempotentMethods = options.idempotentMethods ?? DEFAULT_IDEMPOTENT_METHODS;
4992
5005
  const statuses = isIdempotent(input.request, idempotentMethods) ? options.retryStatuses ?? DEFAULT_RETRY_STATUSES : options.nonIdempotentRetryStatuses ?? DEFAULT_NON_IDEMPOTENT_RETRY_STATUSES;
5006
+ const notifyRetry = (notice) => {
5007
+ try {
5008
+ const observed = options.onRetry?.({
5009
+ ...notice,
5010
+ request: input.attempt.operation.request,
5011
+ operationId: input.attempt.operation.operationId
5012
+ });
5013
+ if (isPromiseLike(observed)) {
5014
+ void observed.then(void 0, () => {
5015
+ });
5016
+ }
5017
+ } catch {
5018
+ }
5019
+ };
4993
5020
  for (let attemptNumber = 1; ; attemptNumber++) {
4994
5021
  const attempt = {
4995
5022
  ...input.attempt,
@@ -5011,10 +5038,16 @@ var retryHttpRequestPlugin = defineHook({
5011
5038
  )) {
5012
5039
  throw error;
5013
5040
  }
5014
- await sleep(
5015
- Math.min(backoffMilliseconds(attemptNumber), maxDelayMilliseconds),
5016
- attempt.signal
5041
+ const errorDelay = clampBackoffMilliseconds(
5042
+ attemptNumber,
5043
+ maxDelayMilliseconds
5017
5044
  );
5045
+ notifyRetry({
5046
+ attemptNumber,
5047
+ delayMilliseconds: errorDelay,
5048
+ error
5049
+ });
5050
+ await sleep(errorDelay, attempt.signal);
5018
5051
  continue;
5019
5052
  }
5020
5053
  if (!statuses.includes(response.status) || !canRetry(
@@ -5027,10 +5060,8 @@ var retryHttpRequestPlugin = defineHook({
5027
5060
  const directed = directedDelayMilliseconds(response);
5028
5061
  if (directed != null && directed > maxDelayMilliseconds)
5029
5062
  return response;
5030
- const delay = Math.min(
5031
- directed ?? backoffMilliseconds(attemptNumber),
5032
- maxDelayMilliseconds
5033
- );
5063
+ const delay = directed ?? clampBackoffMilliseconds(attemptNumber, maxDelayMilliseconds);
5064
+ notifyRetry({ attemptNumber, delayMilliseconds: delay, response });
5034
5065
  await response.body?.cancel().catch(() => {
5035
5066
  });
5036
5067
  await sleep(delay, attempt.signal);