@zapier/zapier-sdk 0.84.2 → 0.84.3

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.
@@ -201,7 +201,8 @@ function getCoreErrorCause(value) {
201
201
  var CURSOR_VERSION = 1;
202
202
  var CURSOR_SOURCE = {
203
203
  API: "api",
204
- SDK: "sdk"
204
+ SDK: "sdk",
205
+ CONCAT: "concat"
205
206
  };
206
207
  function encodeBase64(str) {
207
208
  return btoa(
@@ -385,10 +386,32 @@ async function* paginateBuffered(pageFunction, pageOptions) {
385
386
  }
386
387
  }
387
388
  var paginate = paginateBuffered;
389
+ function encodeConcatCursor(index, cursor) {
390
+ const envelope = {
391
+ v: CURSOR_VERSION,
392
+ source: CURSOR_SOURCE.CONCAT,
393
+ index,
394
+ cursor
395
+ };
396
+ return encodeBase64(JSON.stringify(envelope));
397
+ }
398
+ function decodeConcatCursor(incoming) {
399
+ if (!incoming) {
400
+ return { index: 0, cursor: void 0 };
401
+ }
402
+ try {
403
+ const envelope = JSON.parse(decodeBase64(incoming));
404
+ if (envelope.v === CURSOR_VERSION && envelope.source === CURSOR_SOURCE.CONCAT && typeof envelope.index === "number") {
405
+ return { index: envelope.index, cursor: envelope.cursor };
406
+ }
407
+ } catch {
408
+ }
409
+ return { index: 0, cursor: incoming };
410
+ }
388
411
  function concatPaginated({
389
412
  sources,
390
- dedupe,
391
- pageSize = 100
413
+ pageSize = 100,
414
+ cursor
392
415
  }) {
393
416
  if (sources.length === 0) {
394
417
  const empty = { data: [] };
@@ -398,40 +421,24 @@ function concatPaginated({
398
421
  }
399
422
  });
400
423
  }
401
- let sourceIndex = 0;
402
- let currentIterator = null;
403
- const seen = /* @__PURE__ */ new Set();
404
- const pageFunction = async (_options) => {
405
- while (sourceIndex < sources.length) {
406
- if (!currentIterator) {
407
- const result = sources[sourceIndex]();
408
- currentIterator = result[Symbol.asyncIterator]();
409
- }
410
- const next = await currentIterator.next();
411
- if (next.done) {
412
- sourceIndex++;
413
- currentIterator = null;
424
+ const pageFunction = async (options) => {
425
+ let { index, cursor: sourceCursor } = decodeConcatCursor(options.cursor);
426
+ while (index < sources.length) {
427
+ const page = await sources[index]({ cursor: sourceCursor });
428
+ const hasMoreInSource = page.nextCursor != null;
429
+ if (page.data.length === 0 && !hasMoreInSource) {
430
+ index++;
431
+ sourceCursor = void 0;
414
432
  continue;
415
433
  }
416
- let items = next.value.data;
417
- if (dedupe) {
418
- if (sourceIndex > 0) {
419
- items = items.filter((item) => !seen.has(dedupe(item)));
420
- }
421
- for (const item of items) {
422
- seen.add(dedupe(item));
423
- }
424
- }
425
- const hasMoreInSource = next.value.nextCursor != null;
426
- const hasMoreSources = sourceIndex < sources.length - 1;
427
434
  return {
428
- data: items,
429
- nextCursor: hasMoreInSource || hasMoreSources ? "__has_more__" : void 0
435
+ data: page.data,
436
+ nextCursor: hasMoreInSource ? encodeConcatCursor(index, page.nextCursor) : index < sources.length - 1 ? encodeConcatCursor(index + 1, void 0) : void 0
430
437
  };
431
438
  }
432
439
  return { data: [] };
433
440
  };
434
- const iterator = paginateBuffered(pageFunction, { pageSize });
441
+ const iterator = paginateBuffered(pageFunction, { pageSize, cursor });
435
442
  const firstPagePromise = iterator.next().then((result) => {
436
443
  if (result.done) {
437
444
  return { data: [] };
@@ -1283,6 +1290,7 @@ function defineResolver(config) {
1283
1290
  getContext: config.getContext,
1284
1291
  listItems: config.listItems,
1285
1292
  prompt: config.prompt,
1293
+ validate: config.validate,
1286
1294
  tryResolveWithoutPrompt: config.tryResolveWithoutPrompt,
1287
1295
  tryResolveFromSearch: config.tryResolveFromSearch
1288
1296
  };
@@ -1928,6 +1936,7 @@ function bindResolver(resolver, plugins) {
1928
1936
  const {
1929
1937
  getContext: getContext2,
1930
1938
  listItems,
1939
+ validate,
1931
1940
  tryResolveWithoutPrompt,
1932
1941
  tryResolveFromSearch
1933
1942
  } = resolver;
@@ -1941,6 +1950,9 @@ function bindResolver(resolver, plugins) {
1941
1950
  };
1942
1951
  if (getContext2)
1943
1952
  bound.getContext = ({ input }) => getContext2({ imports, input });
1953
+ if (validate) {
1954
+ bound.validate = ({ value, input, context }) => validate({ imports, value, input, context });
1955
+ }
1944
1956
  if (tryResolveWithoutPrompt) {
1945
1957
  bound.tryResolveWithoutPrompt = ({ input }) => tryResolveWithoutPrompt({ imports, input });
1946
1958
  }
@@ -2609,14 +2621,14 @@ function coerce(leaf, raw) {
2609
2621
  }
2610
2622
  async function validationError(leaf, value, state) {
2611
2623
  if (leaf.resolver?.type !== "dynamic") return null;
2624
+ const validate = leaf.resolver.validate;
2625
+ if (!validate) return null;
2612
2626
  const context = await resolveContext(leaf, state.resolved);
2613
- const config = leaf.resolver.prompt?.({
2614
- items: state.listing?.items ?? [],
2627
+ const verdict = await validate({
2628
+ value,
2615
2629
  input: mergeInput(state.resolved, leaf.extraInput),
2616
2630
  context
2617
2631
  });
2618
- if (!config?.validate) return null;
2619
- const verdict = config.validate(value);
2620
2632
  if (verdict === true) return null;
2621
2633
  return typeof verdict === "string" ? verdict : `${leaf.name}: invalid value`;
2622
2634
  }
@@ -2742,20 +2754,36 @@ async function resolveContext(leaf, input) {
2742
2754
  input: mergeInput(input, leaf.extraInput)
2743
2755
  });
2744
2756
  }
2745
- async function fetchListing(leaf, input, opts = {}) {
2757
+ function firstPagePosition(opts = {}) {
2758
+ return {
2759
+ ...opts.search !== void 0 ? { search: opts.search } : {},
2760
+ pageCursor: null,
2761
+ previousCursors: [],
2762
+ generation: opts.generation ?? 0
2763
+ };
2764
+ }
2765
+ async function fetchListing(leaf, input, position, context) {
2766
+ if (leaf.resolver?.type === "dynamic" && leaf.resolver.inputType === "search" && position.search === void 0) {
2767
+ return { position, items: [] };
2768
+ }
2746
2769
  const page = await firstPage(
2747
2770
  leaf.resolver?.type === "dynamic" ? leaf.resolver.listItems({
2748
2771
  input: mergeInput(input, leaf.extraInput),
2749
- context: opts.context,
2750
- search: opts.search,
2751
- cursor: opts.cursor
2772
+ context,
2773
+ search: position.search,
2774
+ cursor: position.pageCursor ?? void 0
2752
2775
  }) : void 0
2753
2776
  );
2754
2777
  return {
2755
- items: [...opts.priorItems ?? [], ...page.data],
2756
- cursor: page.nextCursor,
2757
- search: opts.search,
2758
- exhausted: page.nextCursor == null
2778
+ position,
2779
+ items: page.data,
2780
+ ...page.nextCursor != null ? { nextCursor: page.nextCursor } : {}
2781
+ };
2782
+ }
2783
+ function toPagination(page) {
2784
+ return {
2785
+ position: page.position,
2786
+ ...page.nextCursor !== void 0 ? { nextCursor: page.nextCursor } : {}
2759
2787
  };
2760
2788
  }
2761
2789
  function toChoice(c) {
@@ -2775,23 +2803,32 @@ var AFFORDANCE = {
2775
2803
  description: "Filter the options by a search term",
2776
2804
  supply: "term"
2777
2805
  },
2778
- more: { action: "more", description: "Load more options" },
2806
+ nextPage: {
2807
+ action: "next_page",
2808
+ description: "Fetch the next page of options"
2809
+ },
2810
+ previousPage: {
2811
+ action: "previous_page",
2812
+ description: "Return to the previous page of options"
2813
+ },
2779
2814
  skip: { action: "skip", description: "Omit this optional parameter" },
2780
2815
  add: { action: "add", description: "Add another item" },
2781
2816
  done: { action: "done", description: "Finish the list" },
2782
2817
  retry: { action: "retry", description: "Retry loading the options" },
2783
2818
  cancel: { action: "cancel", description: "Cancel resolution" }
2784
2819
  };
2785
- function selectActions(leaf, listing, multiple) {
2820
+ function selectActions(leaf, page, multiple) {
2786
2821
  const searchMode = leaf.resolver?.type === "dynamic" && leaf.resolver.inputType === "search";
2787
- if (searchMode && listing.search === void 0 && listing.items.length === 0) {
2822
+ if (searchMode && page.position.search === void 0 && page.items.length === 0) {
2788
2823
  const actions2 = multiple ? [AFFORDANCE.search] : [AFFORDANCE.search, AFFORDANCE.custom];
2789
2824
  if (!leaf.required) actions2.push(AFFORDANCE.skip);
2790
2825
  return actions2;
2791
2826
  }
2792
2827
  const actions = multiple ? [AFFORDANCE.choose] : [AFFORDANCE.choose, AFFORDANCE.custom];
2793
2828
  if (searchMode) actions.push(AFFORDANCE.search);
2794
- if (listing.cursor) actions.push(AFFORDANCE.more);
2829
+ if (page.nextCursor) actions.push(AFFORDANCE.nextPage);
2830
+ if (page.position.previousCursors.length > 0)
2831
+ actions.push(AFFORDANCE.previousPage);
2795
2832
  if (!leaf.required) actions.push(AFFORDANCE.skip);
2796
2833
  return actions;
2797
2834
  }
@@ -2799,16 +2836,17 @@ function labeledMessage(leaf) {
2799
2836
  if (!leaf.label) return void 0;
2800
2837
  return `${leaf.label} (${leaf.required ? "required" : "optional"}):`;
2801
2838
  }
2802
- function selectQuestion(leaf, input, listing, context) {
2839
+ function selectQuestion(leaf, path, input, page, context) {
2803
2840
  const resolver = leaf.resolver?.type === "dynamic" ? leaf.resolver : void 0;
2804
2841
  const config = resolver?.prompt?.({
2805
- items: listing.items,
2842
+ items: page.items,
2806
2843
  input: mergeInput(input, leaf.extraInput),
2807
2844
  context
2808
2845
  });
2809
2846
  const multiple = config?.type === "checkbox";
2810
2847
  return {
2811
2848
  type: "select",
2849
+ path,
2812
2850
  // A labeled field's title beats the resolver's message: per-field
2813
2851
  // resolvers are shared across fields (one choices-fetcher for every
2814
2852
  // field), so only the leaf knows which field is being asked.
@@ -2816,9 +2854,13 @@ function selectQuestion(leaf, input, listing, context) {
2816
2854
  choices: (config?.choices ?? []).map(toChoice),
2817
2855
  ...multiple ? { multiple: true } : {},
2818
2856
  ...config?.notes?.length ? { notes: config.notes } : {},
2819
- ...listing.search !== void 0 ? { search: listing.search } : {},
2857
+ ...page.position.search !== void 0 ? { search: page.position.search } : {},
2820
2858
  ...resolver?.placeholder ? { placeholder: resolver.placeholder } : {},
2821
- actions: selectActions(leaf, listing, multiple)
2859
+ page: {
2860
+ generation: page.position.generation,
2861
+ index: page.position.previousCursors.length
2862
+ },
2863
+ actions: selectActions(leaf, page, multiple)
2822
2864
  };
2823
2865
  }
2824
2866
  function toControllerError(error) {
@@ -2840,6 +2882,7 @@ function failedResult(state, name, error) {
2840
2882
  error: toControllerError(error),
2841
2883
  question: {
2842
2884
  type: "select",
2885
+ path: state.current ?? [],
2843
2886
  message: `Could not load options for ${name}.`,
2844
2887
  choices: [],
2845
2888
  actions: [AFFORDANCE.retry, AFFORDANCE.cancel]
@@ -2847,27 +2890,15 @@ function failedResult(state, name, error) {
2847
2890
  }
2848
2891
  };
2849
2892
  }
2850
- async function buildQuestion(leaf, input) {
2893
+ async function buildQuestion(leaf, path, input) {
2851
2894
  const optional = !leaf.required;
2852
2895
  const resolver = leaf.resolver;
2853
2896
  if (resolver?.type === "dynamic") {
2854
2897
  const context = await resolveContext(leaf, input);
2855
- if (resolver.inputType === "search") {
2856
- const listing2 = {
2857
- items: [],
2858
- cursor: void 0,
2859
- search: void 0,
2860
- exhausted: true
2861
- };
2862
- return {
2863
- question: selectQuestion(leaf, input, listing2, context),
2864
- listing: listing2
2865
- };
2866
- }
2867
- const listing = await fetchListing(leaf, input, { context });
2898
+ const page = await fetchListing(leaf, input, firstPagePosition(), context);
2868
2899
  return {
2869
- question: selectQuestion(leaf, input, listing, context),
2870
- listing
2900
+ question: selectQuestion(leaf, path, input, page, context),
2901
+ pagination: toPagination(page)
2871
2902
  };
2872
2903
  }
2873
2904
  if (leaf.staticChoices) {
@@ -2876,6 +2907,7 @@ async function buildQuestion(leaf, input) {
2876
2907
  return {
2877
2908
  question: {
2878
2909
  type: "select",
2910
+ path,
2879
2911
  message: `Select ${leaf.name}:`,
2880
2912
  choices: leaf.staticChoices,
2881
2913
  actions: actions2
@@ -2889,6 +2921,7 @@ async function buildQuestion(leaf, input) {
2889
2921
  return {
2890
2922
  question: {
2891
2923
  type: "input",
2924
+ path,
2892
2925
  // The optional marker makes Enter-to-pass discoverable on a bare
2893
2926
  // parameter; a labeled field carries its marker via labeledMessage.
2894
2927
  message: labeledMessage(leaf) ?? `Enter ${leaf.name}${optional ? " (optional)" : ""}:`,
@@ -2903,6 +2936,7 @@ function collectionQuestion(t) {
2903
2936
  if (t.count >= t.min) actions.push(AFFORDANCE.done);
2904
2937
  return {
2905
2938
  type: "collection",
2939
+ path: t.path,
2906
2940
  message: `Add ${t.path[t.path.length - 1]}[${t.count}]?`,
2907
2941
  container: "array",
2908
2942
  count: t.count,
@@ -2916,6 +2950,7 @@ function collectionQuestion(t) {
2916
2950
  function objectGateQuestion(path) {
2917
2951
  return {
2918
2952
  type: "collection",
2953
+ path,
2919
2954
  message: `Add ${path[path.length - 1]}?`,
2920
2955
  container: "object",
2921
2956
  actions: [
@@ -2927,9 +2962,10 @@ function objectGateQuestion(path) {
2927
2962
  ]
2928
2963
  };
2929
2964
  }
2930
- function optionalsGateQuestion(pending) {
2965
+ function optionalsGateQuestion(path, pending) {
2931
2966
  return {
2932
2967
  type: "collection",
2968
+ path,
2933
2969
  // The prompt and its context ride separately so a host renders the info
2934
2970
  // line above the confirm without composing any text of its own.
2935
2971
  message: "Would you like to configure optional fields?",
@@ -3077,8 +3113,12 @@ async function askLeaf(state, path, leaf, opts = {}) {
3077
3113
  state.current = path;
3078
3114
  delete state.gate;
3079
3115
  try {
3080
- const { question, listing } = await buildQuestion(leaf, state.resolved);
3081
- state.listing = listing;
3116
+ const { question, pagination } = await buildQuestion(
3117
+ leaf,
3118
+ path,
3119
+ state.resolved
3120
+ );
3121
+ state.pagination = pagination;
3082
3122
  return {
3083
3123
  state,
3084
3124
  result: {
@@ -3088,7 +3128,7 @@ async function askLeaf(state, path, leaf, opts = {}) {
3088
3128
  }
3089
3129
  };
3090
3130
  } catch (error) {
3091
- state.listing = { items: [], exhausted: false };
3131
+ state.pagination = failedPagination(void 0, firstPagePosition());
3092
3132
  return failedResult(state, leaf.name, error);
3093
3133
  }
3094
3134
  }
@@ -3098,13 +3138,13 @@ async function advance(ctx, state) {
3098
3138
  if (!target) {
3099
3139
  delete state.current;
3100
3140
  delete state.gate;
3101
- delete state.listing;
3141
+ delete state.pagination;
3102
3142
  return { state, result: finalize(ctx, state.resolved) };
3103
3143
  }
3104
3144
  if (target.kind === "array") {
3105
3145
  state.current = target.path;
3106
3146
  state.gate = "array";
3107
- delete state.listing;
3147
+ delete state.pagination;
3108
3148
  return {
3109
3149
  state,
3110
3150
  result: { status: "ask", question: collectionQuestion(target) }
@@ -3113,7 +3153,7 @@ async function advance(ctx, state) {
3113
3153
  if (target.kind === "object") {
3114
3154
  state.current = target.path;
3115
3155
  state.gate = "entry";
3116
- delete state.listing;
3156
+ delete state.pagination;
3117
3157
  return {
3118
3158
  state,
3119
3159
  result: { status: "ask", question: objectGateQuestion(target.path) }
@@ -3122,12 +3162,12 @@ async function advance(ctx, state) {
3122
3162
  if (target.kind === "optionals") {
3123
3163
  state.current = target.path;
3124
3164
  state.gate = "optionals";
3125
- delete state.listing;
3165
+ delete state.pagination;
3126
3166
  return {
3127
3167
  state,
3128
3168
  result: {
3129
3169
  status: "ask",
3130
- question: optionalsGateQuestion(target.pending)
3170
+ question: optionalsGateQuestion(target.path, target.pending)
3131
3171
  }
3132
3172
  };
3133
3173
  }
@@ -3178,13 +3218,13 @@ async function step(ctx, prior, action) {
3178
3218
  if (action.type === "cancel") {
3179
3219
  delete state.current;
3180
3220
  delete state.gate;
3181
- delete state.listing;
3221
+ delete state.pagination;
3182
3222
  return { state, result: { status: "cancelled" } };
3183
3223
  }
3184
3224
  const path = state.current;
3185
3225
  if (!path) throw new Error("step called with no outstanding question");
3186
3226
  const leaf = await leafAt(ctx, path, state.resolved);
3187
- if (leaf && (action.type === "search" || action.type === "more" || action.type === "retry")) {
3227
+ if (leaf && (action.type === "search" || action.type === "next_page" || action.type === "previous_page" || action.type === "retry")) {
3188
3228
  return refine(ctx, state, leaf, path, action);
3189
3229
  }
3190
3230
  if (action.type === "add" || action.type === "done") {
@@ -3196,7 +3236,7 @@ async function step(ctx, prior, action) {
3196
3236
  }
3197
3237
  delete state.current;
3198
3238
  delete state.gate;
3199
- delete state.listing;
3239
+ delete state.pagination;
3200
3240
  if (action.type === "done") {
3201
3241
  settle(state, path);
3202
3242
  return advance(ctx, state);
@@ -3225,23 +3265,44 @@ async function step(ctx, prior, action) {
3225
3265
  case "choose":
3226
3266
  case "custom": {
3227
3267
  if (leaf) {
3228
- const error = await validationError(leaf, action.value, state);
3268
+ let error;
3269
+ try {
3270
+ error = await validationError(leaf, action.value, state);
3271
+ } catch (thrown) {
3272
+ return failedResult(state, leaf.name, thrown);
3273
+ }
3229
3274
  if (error) {
3230
- if (state.listing && leaf.resolver?.type === "dynamic") {
3231
- const context = await resolveContext(leaf, state.resolved);
3232
- return {
3233
- state,
3234
- result: {
3235
- status: "ask",
3236
- question: selectQuestion(
3237
- leaf,
3238
- state.resolved,
3239
- state.listing,
3240
- context
3241
- ),
3242
- error
3243
- }
3244
- };
3275
+ if (state.pagination && leaf.resolver?.type === "dynamic") {
3276
+ try {
3277
+ const context = await resolveContext(leaf, state.resolved);
3278
+ const page = await fetchListing(
3279
+ leaf,
3280
+ state.resolved,
3281
+ state.pagination.position,
3282
+ context
3283
+ );
3284
+ state.pagination = toPagination(page);
3285
+ return {
3286
+ state,
3287
+ result: {
3288
+ status: "ask",
3289
+ question: selectQuestion(
3290
+ leaf,
3291
+ path,
3292
+ state.resolved,
3293
+ page,
3294
+ context
3295
+ ),
3296
+ error
3297
+ }
3298
+ };
3299
+ } catch (fetchError) {
3300
+ state.pagination = failedPagination(
3301
+ state.pagination,
3302
+ state.pagination.position
3303
+ );
3304
+ return failedResult(state, leaf.name, fetchError);
3305
+ }
3245
3306
  }
3246
3307
  return askLeaf(state, path, leaf, { error });
3247
3308
  }
@@ -3260,15 +3321,11 @@ async function step(ctx, prior, action) {
3260
3321
  throw new Error(`action "${action.type}" is not supported here`);
3261
3322
  }
3262
3323
  delete state.current;
3263
- delete state.listing;
3324
+ delete state.pagination;
3264
3325
  return advance(ctx, state);
3265
3326
  }
3266
3327
  async function refine(ctx, state, leaf, path, action) {
3267
- const attempt = action.type === "search" ? { search: action.term, cursor: void 0, priorItems: [] } : {
3268
- search: state.listing?.search,
3269
- cursor: state.listing?.cursor,
3270
- priorItems: state.listing?.items ?? []
3271
- };
3328
+ const position = positionAfter(state.pagination, action);
3272
3329
  try {
3273
3330
  if (action.type === "search") {
3274
3331
  const exact = leaf.resolver?.type === "dynamic" ? await leaf.resolver.tryResolveFromSearch?.({
@@ -3278,32 +3335,62 @@ async function refine(ctx, state, leaf, path, action) {
3278
3335
  if (exact) {
3279
3336
  setAtPath(state.resolved, path, coerce(leaf, exact.resolvedValue));
3280
3337
  delete state.current;
3281
- delete state.listing;
3338
+ delete state.pagination;
3282
3339
  return advance(ctx, state);
3283
3340
  }
3284
3341
  }
3285
3342
  const context = await resolveContext(leaf, state.resolved);
3286
- state.listing = await fetchListing(leaf, state.resolved, {
3287
- ...attempt,
3288
- context
3289
- });
3343
+ const page = await fetchListing(leaf, state.resolved, position, context);
3344
+ state.pagination = toPagination(page);
3290
3345
  return {
3291
3346
  state,
3292
3347
  result: {
3293
3348
  status: "ask",
3294
- question: selectQuestion(leaf, state.resolved, state.listing, context)
3349
+ question: selectQuestion(leaf, path, state.resolved, page, context)
3295
3350
  }
3296
3351
  };
3297
3352
  } catch (error) {
3298
- state.listing = {
3299
- items: attempt.priorItems,
3300
- search: attempt.search,
3301
- cursor: attempt.cursor,
3302
- exhausted: false
3303
- };
3353
+ state.pagination = failedPagination(state.pagination, position);
3304
3354
  return failedResult(state, leaf.name, error);
3305
3355
  }
3306
3356
  }
3357
+ function failedPagination(pagination, retryPosition) {
3358
+ return {
3359
+ position: pagination?.position ?? firstPagePosition(),
3360
+ ...pagination?.nextCursor !== void 0 ? { nextCursor: pagination.nextCursor } : {},
3361
+ retryPosition
3362
+ };
3363
+ }
3364
+ function positionAfter(pagination, action) {
3365
+ const current = pagination?.position ?? firstPagePosition();
3366
+ switch (action.type) {
3367
+ case "search":
3368
+ return firstPagePosition({
3369
+ search: action.term,
3370
+ generation: current.generation + 1
3371
+ });
3372
+ case "next_page": {
3373
+ if (pagination?.nextCursor == null) return current;
3374
+ return {
3375
+ ...current.search !== void 0 ? { search: current.search } : {},
3376
+ pageCursor: pagination.nextCursor,
3377
+ previousCursors: [...current.previousCursors, current.pageCursor],
3378
+ generation: current.generation
3379
+ };
3380
+ }
3381
+ case "previous_page": {
3382
+ if (current.previousCursors.length === 0) return current;
3383
+ return {
3384
+ ...current.search !== void 0 ? { search: current.search } : {},
3385
+ pageCursor: current.previousCursors[current.previousCursors.length - 1],
3386
+ previousCursors: current.previousCursors.slice(0, -1),
3387
+ generation: current.generation
3388
+ };
3389
+ }
3390
+ case "retry":
3391
+ return pagination?.retryPosition ?? current;
3392
+ }
3393
+ }
3307
3394
  function toJsonSchema(schema) {
3308
3395
  if (!schema) return void 0;
3309
3396
  try {
@@ -5194,7 +5281,7 @@ function parseDeprecationDate(value) {
5194
5281
  }
5195
5282
 
5196
5283
  // src/sdk-version.ts
5197
- var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.84.2" : void 0) || "unknown";
5284
+ var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.84.3" : void 0) || "unknown";
5198
5285
 
5199
5286
  // src/utils/open-url.ts
5200
5287
  var nodePrefix = "node:";
@@ -8089,8 +8176,9 @@ var appKeyResolver = defineResolver({
8089
8176
  },
8090
8177
  listItems: ({
8091
8178
  imports,
8092
- search
8093
- }) => imports.listApps({ search }),
8179
+ search,
8180
+ cursor
8181
+ }) => imports.listApps({ search, cursor }),
8094
8182
  prompt: ({ items }) => ({
8095
8183
  type: "list",
8096
8184
  message: "Select app:",
@@ -8111,9 +8199,11 @@ var actionTypeResolver = defineResolver({
8111
8199
  imports,
8112
8200
  input
8113
8201
  }) => {
8114
- const { data } = await imports.listActions({ app: input.app });
8115
- const types = [...new Set(data.map((action) => action.action_type))];
8116
- return { data: types.map((type) => ({ key: type, name: type })) };
8202
+ const types = /* @__PURE__ */ new Set();
8203
+ for await (const action of imports.listActions({ app: input.app }).items()) {
8204
+ types.add(action.action_type);
8205
+ }
8206
+ return { data: [...types].map((type) => ({ key: type, name: type })) };
8117
8207
  },
8118
8208
  prompt: ({ items }) => ({
8119
8209
  type: "list",
@@ -8129,13 +8219,15 @@ var actionKeyResolver = defineResolver({
8129
8219
  requireParameters: ["app", "actionType"],
8130
8220
  listItems: async ({
8131
8221
  imports,
8132
- input
8222
+ input,
8223
+ cursor
8133
8224
  }) => {
8134
- const { data } = await imports.listActions({ app: input.app });
8225
+ const page = await imports.listActions({ app: input.app, cursor });
8135
8226
  return {
8136
- data: data.filter(
8227
+ data: page.data.filter(
8137
8228
  (action) => action.action_type === input.actionType && !action.is_hidden
8138
- )
8229
+ ),
8230
+ nextCursor: page.nextCursor
8139
8231
  };
8140
8232
  },
8141
8233
  prompt: ({ items }) => ({
@@ -8252,9 +8344,10 @@ var connectionIdResolver = defineResolver({
8252
8344
  }
8253
8345
  return null;
8254
8346
  },
8255
- listItems: ({ imports, input, context }) => imports.listConnections({
8347
+ listItems: ({ imports, input, context, cursor }) => imports.listConnections({
8256
8348
  app: input.app,
8257
- includeShared: context?.canIncludeShared || void 0
8349
+ includeShared: context?.canIncludeShared || void 0,
8350
+ cursor
8258
8351
  }),
8259
8352
  prompt: ({ items, input, context }) => buildConnectionPrompt(
8260
8353
  items,
@@ -8270,9 +8363,10 @@ var connectionIdGenericResolver = defineResolver({
8270
8363
  );
8271
8364
  return { canIncludeShared: canIncludeShared ?? false };
8272
8365
  },
8273
- listItems: ({ imports, input, context }) => imports.listConnections({
8366
+ listItems: ({ imports, input, context, cursor }) => imports.listConnections({
8274
8367
  app: input.app,
8275
- includeShared: context?.canIncludeShared || void 0
8368
+ includeShared: context?.canIncludeShared || void 0,
8369
+ cursor
8276
8370
  }),
8277
8371
  prompt: ({ items, input, context }) => buildConnectionPrompt(
8278
8372
  items,
@@ -8300,12 +8394,13 @@ var listActionInputFieldChoicesRef = declareMethod({ id: "listActionInputFieldCh
8300
8394
  var choiceResolver = defineResolver({
8301
8395
  imports: [listActionInputFieldChoicesRef],
8302
8396
  requireParameters: ["app", "action", "actionType"],
8303
- listItems: ({ imports, input }) => imports.listActionInputFieldChoices({
8397
+ listItems: ({ imports, input, cursor }) => imports.listActionInputFieldChoices({
8304
8398
  app: input.app,
8305
8399
  action: input.action,
8306
8400
  actionType: input.actionType,
8307
8401
  connection: input.connection,
8308
- inputField: input.inputField
8402
+ inputField: input.inputField,
8403
+ cursor
8309
8404
  }),
8310
8405
  prompt: ({ items }) => ({
8311
8406
  type: "list",
@@ -8464,7 +8559,7 @@ var clientCredentialsNameResolver = defineResolver({
8464
8559
  var listClientCredentialsRef = declareMethod({ id: "listClientCredentials" });
8465
8560
  var clientIdResolver = defineResolver({
8466
8561
  imports: [listClientCredentialsRef],
8467
- listItems: ({ imports }) => imports.listClientCredentials({}),
8562
+ listItems: ({ imports, cursor }) => imports.listClientCredentials({ cursor }),
8468
8563
  prompt: ({ items }) => ({
8469
8564
  type: "list",
8470
8565
  message: "Select client credentials to delete:",
@@ -8476,9 +8571,9 @@ var clientIdResolver = defineResolver({
8476
8571
  });
8477
8572
 
8478
8573
  // src/resolvers/tableId.ts
8479
- var listTablesRef = declareMethod({ id: "listTables" });
8574
+ var listTablesInternalRef = declareMethod({ id: "listTablesInternal" });
8480
8575
  var tableIdResolver = defineResolver({
8481
- imports: [listTablesRef, capabilitiesPluginRef],
8576
+ imports: [listTablesInternalRef, capabilitiesPluginRef],
8482
8577
  getContext: async ({ imports }) => {
8483
8578
  const includeShared = await imports.capabilities.hasCapability?.(
8484
8579
  "canIncludeSharedTables"
@@ -8486,27 +8581,36 @@ var tableIdResolver = defineResolver({
8486
8581
  return { includeShared: includeShared ?? false };
8487
8582
  },
8488
8583
  // Unlike connections, the tables API does not return personal tables first,
8489
- // so we use concatPaginated to hoist own tables above shared.
8490
- listItems: ({ imports, context }) => {
8584
+ // so we concatenate personal-only and shared-only slices to hoist own
8585
+ // tables above shared. The slices are disjoint by construction, so the
8586
+ // concatenation paginates with stateless cursors and needs no dedupe.
8587
+ listItems: ({ imports, context, cursor }) => {
8491
8588
  const includeShared = context?.includeShared;
8492
8589
  if (includeShared) {
8493
8590
  return concatPaginated({
8494
8591
  sources: [
8495
- () => imports.listTables({}),
8496
- () => imports.listTables({ includeShared: true })
8592
+ ({ cursor: sourceCursor }) => imports.listTablesInternal({ cursor: sourceCursor }),
8593
+ ({ cursor: sourceCursor }) => imports.listTablesInternal({
8594
+ includeShared: true,
8595
+ includePersonal: false,
8596
+ cursor: sourceCursor
8597
+ })
8497
8598
  ],
8498
- dedupe: (table) => table.id
8599
+ cursor
8499
8600
  });
8500
8601
  }
8501
- return imports.listTables({});
8602
+ return imports.listTablesInternal({ cursor });
8502
8603
  },
8503
- prompt: ({ items }) => ({
8604
+ prompt: ({ items, context }) => ({
8504
8605
  type: "list",
8505
8606
  message: "Select a table:",
8506
8607
  choices: items.map((table) => ({
8507
8608
  label: table.name,
8508
8609
  value: table.id
8509
- }))
8610
+ })),
8611
+ // The capability hint the legacy picker showed as a fake disabled row:
8612
+ // without it, a gated account just sees fewer tables with no explanation.
8613
+ ...context?.includeShared ? {} : { notes: ["Shared tables are hidden for this account."] }
8510
8614
  })
8511
8615
  });
8512
8616
 
@@ -8514,7 +8618,7 @@ var tableIdResolver = defineResolver({
8514
8618
  var listTriggerInboxesRef = declareMethod({ id: "listTriggerInboxes" });
8515
8619
  var triggerInboxResolver = defineResolver({
8516
8620
  imports: [listTriggerInboxesRef],
8517
- listItems: ({ imports }) => imports.listTriggerInboxes({}),
8621
+ listItems: ({ imports, cursor }) => imports.listTriggerInboxes({ cursor }),
8518
8622
  prompt: ({ items }) => ({
8519
8623
  type: "list",
8520
8624
  message: "Select a trigger inbox:",
@@ -8532,7 +8636,7 @@ var triggerInboxResolver = defineResolver({
8532
8636
  var listWorkflowsRef = declareMethod({ id: "listWorkflows" });
8533
8637
  var workflowIdResolver = defineResolver({
8534
8638
  imports: [listWorkflowsRef],
8535
- listItems: ({ imports }) => imports.listWorkflows({}),
8639
+ listItems: ({ imports, cursor }) => imports.listWorkflows({ cursor }),
8536
8640
  prompt: ({ items }) => ({
8537
8641
  type: "list",
8538
8642
  message: "Select a workflow:",
@@ -8548,7 +8652,7 @@ var workflowIdResolver = defineResolver({
8548
8652
  var listDurableRunsRef = declareMethod({ id: "listDurableRuns" });
8549
8653
  var durableRunIdResolver = defineResolver({
8550
8654
  imports: [listDurableRunsRef],
8551
- listItems: ({ imports }) => imports.listDurableRuns({}),
8655
+ listItems: ({ imports, cursor }) => imports.listDurableRuns({ cursor }),
8552
8656
  prompt: ({ items }) => ({
8553
8657
  type: "list",
8554
8658
  message: "Select a run:",
@@ -8565,7 +8669,14 @@ var listWorkflowVersionsRef = declareMethod({ id: "listWorkflowVersions" });
8565
8669
  var workflowVersionIdResolver = defineResolver({
8566
8670
  imports: [listWorkflowVersionsRef],
8567
8671
  requireParameters: ["workflow"],
8568
- listItems: ({ imports, input }) => imports.listWorkflowVersions({ workflow: input.workflow }),
8672
+ listItems: ({
8673
+ imports,
8674
+ input,
8675
+ cursor
8676
+ }) => imports.listWorkflowVersions({
8677
+ workflow: input.workflow,
8678
+ cursor
8679
+ }),
8569
8680
  prompt: ({ items }) => ({
8570
8681
  type: "list",
8571
8682
  message: "Select a workflow version:",
@@ -8581,7 +8692,11 @@ var listWorkflowRunsRef = declareMethod({ id: "listWorkflowRuns" });
8581
8692
  var workflowRunIdResolver = defineResolver({
8582
8693
  imports: [listWorkflowRunsRef],
8583
8694
  requireParameters: ["workflow"],
8584
- listItems: ({ imports, input }) => imports.listWorkflowRuns({ workflow: input.workflow }),
8695
+ listItems: ({
8696
+ imports,
8697
+ input,
8698
+ cursor
8699
+ }) => imports.listWorkflowRuns({ workflow: input.workflow, cursor }),
8585
8700
  prompt: ({ items }) => ({
8586
8701
  type: "list",
8587
8702
  message: "Select a workflow run:",
@@ -8599,8 +8714,9 @@ var triggerMessagesResolver = defineResolver({
8599
8714
  requireParameters: ["inbox"],
8600
8715
  listItems: ({
8601
8716
  imports,
8602
- input
8603
- }) => imports.listTriggerInboxMessages({ inbox: input.inbox }),
8717
+ input,
8718
+ cursor
8719
+ }) => imports.listTriggerInboxMessages({ inbox: input.inbox, cursor }),
8604
8720
  prompt: ({ items }) => ({
8605
8721
  type: "checkbox",
8606
8722
  message: "Select messages:",
@@ -8873,9 +8989,10 @@ function recordChoices(records) {
8873
8989
  var tableRecordIdResolver = defineResolver({
8874
8990
  imports: [listTableRecordsRef],
8875
8991
  requireParameters: ["table"],
8876
- listItems: ({ imports, input }) => imports.listTableRecords({
8992
+ listItems: ({ imports, input, cursor }) => imports.listTableRecords({
8877
8993
  table: input.table,
8878
- keyMode: "names"
8994
+ keyMode: "names",
8995
+ cursor
8879
8996
  }),
8880
8997
  prompt: ({ items }) => ({
8881
8998
  type: "list",
@@ -8886,16 +9003,17 @@ var tableRecordIdResolver = defineResolver({
8886
9003
  var tableRecordIdsResolver = defineResolver({
8887
9004
  imports: [listTableRecordsRef],
8888
9005
  requireParameters: ["table"],
8889
- listItems: ({ imports, input }) => imports.listTableRecords({
9006
+ listItems: ({ imports, input, cursor }) => imports.listTableRecords({
8890
9007
  table: input.table,
8891
- keyMode: "names"
9008
+ keyMode: "names",
9009
+ cursor
8892
9010
  }),
8893
9011
  prompt: ({ items }) => ({
8894
9012
  type: "checkbox",
8895
9013
  message: "Select records to delete:",
8896
- choices: recordChoices(items),
8897
- validate: (value) => Array.isArray(value) && value.length > 0 ? true : "Select at least one record"
8898
- })
9014
+ choices: recordChoices(items)
9015
+ }),
9016
+ validate: ({ value }) => Array.isArray(value) && value.length > 0 ? true : "Select at least one record"
8899
9017
  });
8900
9018
 
8901
9019
  // src/resolvers/tableFieldIds.ts
@@ -8903,6 +9021,8 @@ var listTableFieldsRef = declareMethod({ id: "listTableFields" });
8903
9021
  var tableFieldIdsResolver = defineResolver({
8904
9022
  imports: [listTableFieldsRef],
8905
9023
  requireParameters: ["table"],
9024
+ // No cursor forwarding: the fields API is unpaginated (no cursor on the
9025
+ // response), so the listing is always exhausted after one page.
8906
9026
  listItems: ({ imports, input }) => imports.listTableFields({ table: input.table }),
8907
9027
  prompt: ({ items }) => ({
8908
9028
  type: "checkbox",
@@ -8911,9 +9031,9 @@ var tableFieldIdsResolver = defineResolver({
8911
9031
  label: field.name,
8912
9032
  hint: [field.id, field.type],
8913
9033
  value: field.id
8914
- })),
8915
- validate: (value) => Array.isArray(value) && value.length > 0 ? true : "Select at least one field"
8916
- })
9034
+ }))
9035
+ }),
9036
+ validate: ({ value }) => Array.isArray(value) && value.length > 0 ? true : "Select at least one field"
8917
9037
  });
8918
9038
 
8919
9039
  // src/resolvers/tableName.ts
@@ -13088,27 +13208,31 @@ var ListTablesOptionsSchema = z.object({
13088
13208
  maxItems: z.number().min(1).optional().describe("Maximum total items to return across all pages"),
13089
13209
  cursor: z.string().optional().describe("Cursor to start from")
13090
13210
  }).describe("List tables available to the authenticated user");
13211
+ var ListTablesInternalOptionsSchema = ListTablesOptionsSchema.extend({
13212
+ includePersonal: z.boolean().optional().describe(
13213
+ "Include your own tables (default true). Set false with includeShared to list only tables shared with you."
13214
+ )
13215
+ });
13091
13216
 
13092
- // src/plugins/tables/shared.ts
13093
- var tableCategories = ["table"];
13094
-
13095
- // src/plugins/tables/listTables/index.ts
13096
- var listTablesPlugin = defineMethod({
13097
- name: "listTables",
13217
+ // src/plugins/tables/listTables/internal.ts
13218
+ var listTablesInternalPlugin = defineMethod({
13219
+ name: "listTablesInternal",
13098
13220
  imports: [apiPluginRef, capabilitiesPluginRef],
13099
- categories: tableCategories,
13100
- itemType: "Table",
13101
- inputSchema: ListTablesOptionsSchema,
13102
- outputSchema: TableItemSchema,
13221
+ inputSchema: ListTablesInternalOptionsSchema,
13103
13222
  output: {
13104
13223
  type: "list",
13105
13224
  adaptPage: adaptZapierPage,
13106
13225
  defaultPageSize: DEFAULT_PAGE_SIZE
13107
13226
  },
13108
13227
  run: async ({ imports, input }) => {
13109
- if (input.includeShared) {
13228
+ const includePersonal = input.includePersonal ?? true;
13229
+ const includeShared = input.includeShared ?? false;
13230
+ if (includeShared) {
13110
13231
  await imports.capabilities.checkCapability("canIncludeSharedTables");
13111
13232
  }
13233
+ if (!includePersonal && !includeShared) {
13234
+ return { data: [] };
13235
+ }
13112
13236
  const api = imports.api;
13113
13237
  const searchParams = {};
13114
13238
  if (input.pageSize !== void 0) {
@@ -13124,23 +13248,18 @@ var listTablesPlugin = defineMethod({
13124
13248
  if (input.search) {
13125
13249
  searchParams.q = input.search;
13126
13250
  }
13127
- if (input.owner && input.owner !== "me" && !input.includeShared) {
13251
+ if (input.owner && input.owner !== "me" && !includeShared) {
13128
13252
  throw new ZapierValidationError(
13129
13253
  'The "owner" option requires "includeShared" to be true. Without includeShared, only your own tables are returned.'
13130
13254
  );
13131
13255
  }
13132
- const owner = input.includeShared ? input.owner : "me";
13256
+ const owner = includeShared ? input.owner : "me";
13257
+ const needsProfileId = owner === "me" || !includePersonal && includeShared;
13258
+ const profileId = needsProfileId ? (await api.get("/zapier/api/v4/profile/", {
13259
+ authRequired: true
13260
+ })).id : void 0;
13133
13261
  if (owner) {
13134
- if (owner === "me") {
13135
- const profile = await api.get("/zapier/api/v4/profile/", {
13136
- authRequired: true
13137
- });
13138
- searchParams.owner_customuser_id = String(
13139
- profile.id
13140
- );
13141
- } else {
13142
- searchParams.owner_customuser_id = owner;
13143
- }
13262
+ searchParams.owner_customuser_id = owner === "me" ? String(profileId) : owner;
13144
13263
  }
13145
13264
  if (input.cursor) {
13146
13265
  searchParams.offset = input.cursor;
@@ -13150,12 +13269,35 @@ var listTablesPlugin = defineMethod({
13150
13269
  authRequired: true
13151
13270
  });
13152
13271
  const response = ListTablesApiResponseSchema.parse(rawResponse);
13272
+ const apiItems = includePersonal ? response.data : response.data.filter(
13273
+ (item) => item.owner_zapier_customuser_id !== profileId
13274
+ );
13153
13275
  return {
13154
- data: response.data.map(transformTableItem),
13276
+ data: apiItems.map(transformTableItem),
13155
13277
  links: response.links
13156
13278
  };
13157
13279
  }
13158
13280
  });
13281
+
13282
+ // src/plugins/tables/shared.ts
13283
+ var tableCategories = ["table"];
13284
+
13285
+ // src/plugins/tables/listTables/index.ts
13286
+ var listTablesPlugin = defineMethod({
13287
+ name: "listTables",
13288
+ imports: [listTablesInternalPlugin],
13289
+ categories: tableCategories,
13290
+ itemType: "Table",
13291
+ inputSchema: ListTablesOptionsSchema,
13292
+ outputSchema: TableItemSchema,
13293
+ output: "list",
13294
+ run: async ({ imports, input }) => {
13295
+ return await imports.listTablesInternal({
13296
+ ...input,
13297
+ includePersonal: void 0
13298
+ });
13299
+ }
13300
+ });
13159
13301
  var GetTableApiResponseSchema = z.object({
13160
13302
  data: TableApiItemSchema
13161
13303
  });