@zapier/zapier-sdk 0.6.3 → 0.8.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 (56) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +73 -41
  3. package/dist/api/schemas.d.ts +114 -0
  4. package/dist/api/schemas.d.ts.map +1 -1
  5. package/dist/api/schemas.js +45 -0
  6. package/dist/api/types.d.ts +5 -1
  7. package/dist/api/types.d.ts.map +1 -1
  8. package/dist/index.cjs +2208 -2022
  9. package/dist/index.d.mts +327 -10
  10. package/dist/index.d.ts +18 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +19 -1
  13. package/dist/index.mjs +2191 -2024
  14. package/dist/plugins/findFirstAuthentication/index.test.js +3 -3
  15. package/dist/plugins/findFirstAuthentication/schemas.d.ts +3 -3
  16. package/dist/plugins/findFirstAuthentication/schemas.js +1 -1
  17. package/dist/plugins/findUniqueAuthentication/index.test.js +3 -3
  18. package/dist/plugins/findUniqueAuthentication/schemas.d.ts +3 -3
  19. package/dist/plugins/findUniqueAuthentication/schemas.js +1 -1
  20. package/dist/plugins/getProfile/index.js +1 -1
  21. package/dist/plugins/listAuthentications/index.d.ts.map +1 -1
  22. package/dist/plugins/listAuthentications/index.js +2 -3
  23. package/dist/plugins/listAuthentications/index.test.js +5 -5
  24. package/dist/plugins/listAuthentications/schemas.d.ts +3 -3
  25. package/dist/plugins/listAuthentications/schemas.js +1 -1
  26. package/dist/plugins/listInputFieldChoices/index.d.ts +28 -0
  27. package/dist/plugins/listInputFieldChoices/index.d.ts.map +1 -0
  28. package/dist/plugins/listInputFieldChoices/index.js +78 -0
  29. package/dist/plugins/listInputFieldChoices/index.test.d.ts +2 -0
  30. package/dist/plugins/listInputFieldChoices/index.test.d.ts.map +1 -0
  31. package/dist/plugins/listInputFieldChoices/index.test.js +537 -0
  32. package/dist/plugins/listInputFieldChoices/schemas.d.ts +61 -0
  33. package/dist/plugins/listInputFieldChoices/schemas.d.ts.map +1 -0
  34. package/dist/plugins/listInputFieldChoices/schemas.js +73 -0
  35. package/dist/plugins/registry/index.js +3 -3
  36. package/dist/sdk.d.ts +93 -0
  37. package/dist/sdk.d.ts.map +1 -1
  38. package/dist/sdk.js +7 -2
  39. package/package.json +1 -1
  40. package/src/api/schemas.ts +62 -0
  41. package/src/api/types.ts +14 -0
  42. package/src/index.ts +25 -1
  43. package/src/plugins/findFirstAuthentication/index.test.ts +3 -3
  44. package/src/plugins/findFirstAuthentication/schemas.ts +1 -1
  45. package/src/plugins/findUniqueAuthentication/index.test.ts +3 -3
  46. package/src/plugins/findUniqueAuthentication/schemas.ts +1 -1
  47. package/src/plugins/getProfile/index.ts +1 -1
  48. package/src/plugins/listAuthentications/index.test.ts +5 -5
  49. package/src/plugins/listAuthentications/index.ts +2 -3
  50. package/src/plugins/listAuthentications/schemas.ts +1 -1
  51. package/src/plugins/listInputFieldChoices/index.test.ts +653 -0
  52. package/src/plugins/listInputFieldChoices/index.ts +152 -0
  53. package/src/plugins/listInputFieldChoices/schemas.ts +139 -0
  54. package/src/plugins/registry/index.ts +3 -3
  55. package/src/sdk.ts +8 -1
  56. package/tsconfig.tsbuildinfo +1 -1
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { existsSync, readFileSync, writeFileSync } from 'fs';
2
+ import { readFileSync, existsSync, writeFileSync } from 'fs';
3
3
  import { resolve } from 'path';
4
4
 
5
5
  // src/types/properties.ts
@@ -318,1003 +318,541 @@ var fetchPlugin = ({ sdk }) => {
318
318
  };
319
319
  };
320
320
 
321
- // src/resolvers/appKey.ts
322
- var appKeyResolver = {
323
- type: "static",
324
- inputType: "text",
325
- placeholder: "Enter app key (e.g., 'SlackCLIAPI' or slug like 'github')"
326
- };
327
-
328
- // src/resolvers/actionType.ts
329
- var actionTypeResolver = {
330
- type: "dynamic",
331
- depends: ["appKey"],
332
- fetch: async (sdk, resolvedParams) => {
333
- const actionsResponse = await sdk.listActions({
334
- appKey: resolvedParams.appKey
335
- });
336
- const types = [
337
- ...new Set(actionsResponse.data.map((action) => action.action_type))
338
- ];
339
- return types.map((type) => ({ key: type, name: type }));
340
- },
341
- prompt: (types) => ({
342
- type: "list",
343
- name: "actionType",
344
- message: "Select action type:",
345
- choices: types.map((type) => ({
346
- name: type.name,
347
- value: type.key
348
- }))
349
- })
350
- };
351
-
352
- // src/resolvers/actionKey.ts
353
- var actionKeyResolver = {
354
- type: "dynamic",
355
- depends: ["appKey", "actionType"],
356
- fetch: async (sdk, resolvedParams) => {
357
- const actionsResponse = await sdk.listActions({
358
- appKey: resolvedParams.appKey
359
- });
360
- return actionsResponse.data.filter(
361
- (action) => action.action_type === resolvedParams.actionType
362
- );
363
- },
364
- prompt: (actions) => ({
365
- type: "list",
366
- name: "actionKey",
367
- message: "Select action:",
368
- choices: actions.map((action) => ({
369
- name: `${action.title || action.name || action.key} - ${action.description || "No description"}`,
370
- value: action.key
371
- }))
372
- })
373
- };
374
-
375
- // src/resolvers/authenticationId.ts
376
- var authenticationIdResolver = {
377
- type: "dynamic",
378
- depends: ["appKey"],
379
- fetch: async (sdk, resolvedParams) => {
380
- const myAuths = await sdk.listAuthentications({
381
- appKey: resolvedParams.appKey,
382
- maxItems: 1e3,
383
- owner: "me"
384
- });
385
- const allAuths = await sdk.listAuthentications({
386
- appKey: resolvedParams.appKey,
387
- maxItems: 1e3
388
- });
389
- const otherAuths = allAuths.data.filter(
390
- (auth) => !myAuths.data.some((myAuth) => myAuth.id === auth.id)
391
- );
392
- return [...myAuths.data, ...otherAuths];
393
- },
394
- prompt: (auths, params) => ({
395
- type: "list",
396
- name: "authenticationId",
397
- message: `Select authentication for ${params.appKey}:`,
398
- choices: [
399
- ...auths.map((auth) => ({
400
- name: `${auth.title || auth.label || "Authentication"} (ID: ${auth.id})`,
401
- value: auth.id
402
- })),
403
- {
404
- name: "\u2197 Skip authentication (may fail)",
405
- value: null
406
- }
407
- ]
408
- })
409
- };
410
-
411
- // src/resolvers/inputs.ts
412
- var inputsResolver = {
413
- type: "fields",
414
- depends: ["appKey", "actionKey", "actionType", "authenticationId"],
415
- fetch: async (sdk, resolvedParams) => {
416
- const fieldsResponse = await sdk.listInputFields({
417
- appKey: resolvedParams.appKey,
418
- actionKey: resolvedParams.actionKey,
419
- actionType: resolvedParams.actionType,
420
- authenticationId: resolvedParams.authenticationId,
421
- inputs: resolvedParams.inputs
422
- // Pass along currently resolved inputs
423
- });
424
- return fieldsResponse.data;
321
+ // src/utils/pagination-utils.ts
322
+ var offsetCursorMarker = "$$offset$$";
323
+ function splitOffsetCursor(cursor) {
324
+ if (!cursor) {
325
+ return [0, cursor];
425
326
  }
426
- };
427
-
428
- // src/resolvers/index.ts
429
- var resolverRegistry = {
430
- appKey: appKeyResolver,
431
- actionType: actionTypeResolver,
432
- actionKey: actionKeyResolver,
433
- authenticationId: authenticationIdResolver,
434
- inputs: inputsResolver
435
- };
436
- function getResolver(name) {
437
- return resolverRegistry[name];
438
- }
439
- function getResolversForMissingParams(missingParams) {
440
- const resolvers = {};
441
- for (const param of missingParams) {
442
- const resolver = resolverRegistry[param];
443
- if (resolver) {
444
- resolvers[param] = resolver;
327
+ try {
328
+ const parsedCursor = JSON.parse(cursor);
329
+ if (!Array.isArray(parsedCursor)) {
330
+ return [0, cursor];
331
+ }
332
+ const [marker, offset, currentCursor] = parsedCursor;
333
+ if (marker !== offsetCursorMarker) {
334
+ return [0, cursor];
445
335
  }
336
+ if (typeof offset !== "number") {
337
+ return [0, cursor];
338
+ }
339
+ return [offset, currentCursor];
340
+ } catch {
341
+ return [0, cursor];
446
342
  }
447
- return resolvers;
448
- }
449
- function hasResolver(paramName) {
450
- return paramName in resolverRegistry;
451
343
  }
452
- function getResolvableParams() {
453
- return Object.keys(resolverRegistry);
344
+ function createOffsetCursor(offset, currentCursor) {
345
+ return JSON.stringify([offsetCursorMarker, offset, currentCursor]);
454
346
  }
455
- function getResolutionOrder(paramName, resolved = /* @__PURE__ */ new Set()) {
456
- const resolver = getResolver(paramName);
457
- if (!resolver || resolver.type === "static") {
458
- return [paramName];
459
- }
460
- const order = [];
461
- if ("depends" in resolver && resolver.depends) {
462
- for (const dependency of resolver.depends) {
463
- if (!resolved.has(dependency)) {
464
- order.push(...getResolutionOrder(dependency, resolved));
465
- resolved.add(dependency);
347
+ async function* paginateMaxItems(pageFunction, pageOptions) {
348
+ let cursor = pageOptions?.cursor;
349
+ let totalItemsYielded = 0;
350
+ const maxItems = pageOptions?.maxItems;
351
+ const pageSize = pageOptions?.pageSize;
352
+ do {
353
+ const options = {
354
+ ...pageOptions || {},
355
+ cursor,
356
+ pageSize: maxItems !== void 0 && pageSize !== void 0 ? Math.min(pageSize, maxItems) : pageSize
357
+ };
358
+ const page = await pageFunction(options);
359
+ if (maxItems !== void 0) {
360
+ const remainingItems = maxItems - totalItemsYielded;
361
+ if (page.data.length >= remainingItems) {
362
+ const yieldedPage = {
363
+ ...page,
364
+ data: page.data.slice(0, remainingItems),
365
+ nextCursor: void 0
366
+ };
367
+ yield yieldedPage;
368
+ break;
466
369
  }
467
370
  }
468
- }
469
- if (!resolved.has(paramName)) {
470
- order.push(paramName);
471
- resolved.add(paramName);
472
- }
473
- return order;
371
+ yield page;
372
+ totalItemsYielded += page.data.length;
373
+ cursor = page.nextCursor;
374
+ } while (cursor);
474
375
  }
475
- function getResolutionOrderForParams(paramNames) {
476
- const resolved = /* @__PURE__ */ new Set();
477
- const order = [];
478
- for (const paramName of paramNames) {
479
- const paramOrder = getResolutionOrder(paramName, resolved);
480
- for (const param of paramOrder) {
481
- if (!order.includes(param)) {
482
- order.push(param);
376
+ async function* paginateBuffered(pageFunction, pageOptions) {
377
+ const pageSize = pageOptions?.pageSize;
378
+ const [cursorOffset, currentCursor] = splitOffsetCursor(pageOptions?.cursor);
379
+ const options = {
380
+ ...pageOptions || {},
381
+ cursor: currentCursor
382
+ };
383
+ const iterator = paginateMaxItems(pageFunction, options);
384
+ let bufferedPages = [];
385
+ let isFirstPage = true;
386
+ let cursor;
387
+ for await (let page of iterator) {
388
+ if (isFirstPage) {
389
+ isFirstPage = false;
390
+ if (cursorOffset) {
391
+ page = {
392
+ ...page,
393
+ data: page.data.slice(cursorOffset)
394
+ };
483
395
  }
484
396
  }
485
- }
486
- return order;
487
- }
488
-
489
- // src/auth.ts
490
- function getTokenFromEnv() {
491
- return process.env.ZAPIER_TOKEN;
492
- }
493
- async function getTokenFromCliLogin(options = {}) {
494
- try {
495
- const { getToken } = await import('@zapier/zapier-sdk-cli-login');
496
- return await getToken(options);
497
- } catch {
498
- return void 0;
499
- }
500
- }
501
- async function getTokenFromEnvOrConfig(options = {}) {
502
- const envToken = getTokenFromEnv();
503
- if (envToken) {
504
- return envToken;
505
- }
506
- return getTokenFromCliLogin(options);
507
- }
508
- var RelayRequestSchema = z.object({
509
- url: z.string().url().describe("The URL to request (will be proxied through Relay)"),
510
- method: z.enum(["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]).optional().describe("HTTP method"),
511
- body: z.any().optional().describe("Request body as a string"),
512
- authenticationId: z.number().int().optional().describe("Zapier authentication ID to use for the request"),
513
- callbackUrl: z.string().url().optional().describe("URL to send async response to (makes request async)"),
514
- authenticationTemplate: z.string().optional().describe(
515
- "Optional JSON string authentication template to bypass Notary lookup"
516
- ),
517
- headers: z.union([
518
- z.record(z.string()),
519
- z.instanceof(Headers),
520
- z.array(z.tuple([z.string(), z.string()]))
521
- ]).optional().describe("Request headers")
522
- }).extend({
523
- relayBaseUrl: z.string().optional().describe("Base URL for Relay service")
524
- }).describe("Make authenticated HTTP requests through Zapier's Relay service");
525
- var RelayFetchSchema = RelayRequestSchema;
526
-
527
- // src/plugins/registry/index.ts
528
- var registryPlugin = ({ sdk, context }) => {
529
- const metaKeys = Object.keys(context.meta || {});
530
- const categoryDefinitions = {
531
- app: {
532
- title: "App",
533
- titlePlural: "Apps"
534
- },
535
- authentication: {
536
- title: "Authentication"
537
- },
538
- action: {
539
- title: "Action"
540
- },
541
- http: {
542
- title: "HTTP Request"
543
- },
544
- user: {
545
- title: "User"
546
- },
547
- utility: {
548
- title: "Utility",
549
- titlePlural: "Utilities"
550
- },
551
- other: {
552
- title: "Other"
397
+ if (!pageSize) {
398
+ yield page;
399
+ cursor = page.nextCursor;
400
+ continue;
553
401
  }
554
- };
555
- const functions = metaKeys.filter((key) => typeof sdk[key] === "function").map((key) => {
556
- return {
557
- ...context.meta[key],
558
- categories: context.meta[key].categories || [],
559
- name: key
560
- };
561
- }).sort((a, b) => a.name.localeCompare(b.name));
562
- const knownCategories = Object.keys(categoryDefinitions);
563
- const categories = knownCategories.sort((a, b) => {
564
- if (a === "other") return 1;
565
- if (b === "other") return -1;
566
- const titleA = categoryDefinitions[a].title;
567
- const titleB = categoryDefinitions[b].title;
568
- return titleA.localeCompare(titleB);
569
- }).map((categoryKey) => {
570
- const categoryFunctions = functions.filter(
571
- (f) => f.categories.includes(categoryKey) || // If the category is "other" and the function is not in any other category, include it
572
- categoryKey === "other" && !f.categories.some((c) => knownCategories.includes(c))
573
- ).map((f) => f.name).sort();
574
- const definition = categoryDefinitions[categoryKey];
575
- const title = definition.title;
576
- return {
577
- key: categoryKey,
578
- title,
579
- titlePlural: definition.titlePlural ?? `${title}s`,
580
- functions: categoryFunctions
402
+ const bufferedLength = bufferedPages.reduce(
403
+ (acc, page2) => acc + page2.data.length,
404
+ 0
405
+ );
406
+ if (bufferedLength + page.data.length < pageSize) {
407
+ bufferedPages.push(page);
408
+ cursor = page.nextCursor;
409
+ continue;
410
+ }
411
+ const bufferedItems = bufferedPages.map((p) => p.data).flat();
412
+ const allItems = [...bufferedItems, ...page.data];
413
+ const pageItems = allItems.slice(0, pageSize);
414
+ const remainingItems = allItems.slice(pageItems.length);
415
+ if (remainingItems.length === 0) {
416
+ yield {
417
+ ...page,
418
+ data: pageItems,
419
+ nextCursor: page.nextCursor
420
+ };
421
+ bufferedPages = [];
422
+ cursor = page.nextCursor;
423
+ continue;
424
+ }
425
+ yield {
426
+ ...page,
427
+ data: pageItems,
428
+ nextCursor: createOffsetCursor(
429
+ page.data.length - remainingItems.length,
430
+ cursor
431
+ )
581
432
  };
582
- });
583
- function getRegistry() {
584
- return {
585
- functions,
586
- categories
433
+ while (remainingItems.length > pageSize) {
434
+ const pageItems2 = remainingItems.splice(0, pageSize);
435
+ yield {
436
+ ...page,
437
+ data: pageItems2,
438
+ nextCursor: createOffsetCursor(
439
+ page.data.length - remainingItems.length,
440
+ cursor
441
+ )
442
+ };
443
+ }
444
+ bufferedPages = [
445
+ {
446
+ ...page,
447
+ data: remainingItems
448
+ }
449
+ ];
450
+ cursor = page.nextCursor;
451
+ }
452
+ if (bufferedPages.length > 0) {
453
+ const lastBufferedPage = bufferedPages.slice(-1)[0];
454
+ const bufferedItems = bufferedPages.map((p) => p.data).flat();
455
+ yield {
456
+ ...lastBufferedPage,
457
+ data: bufferedItems
587
458
  };
588
459
  }
589
- return {
590
- getRegistry
460
+ }
461
+ var paginate = paginateBuffered;
462
+
463
+ // src/utils/validation.ts
464
+ var validate = (schema, input) => {
465
+ const result = schema.safeParse(input);
466
+ if (!result.success) {
467
+ const errorMessages = result.error.errors.map((error) => {
468
+ const path = error.path.length > 0 ? error.path.join(".") : "input";
469
+ return `${path}: ${error.message}`;
470
+ });
471
+ const message = `Validation failed:
472
+ ${errorMessages.join("\n ")}`;
473
+ throw new ZapierValidationError(message, {
474
+ details: {
475
+ zodErrors: result.error.errors,
476
+ input
477
+ }
478
+ });
479
+ }
480
+ return result.data;
481
+ };
482
+ function createValidator(schema) {
483
+ return function validateFn(input) {
484
+ return validate(schema, input);
591
485
  };
486
+ }
487
+ var validateOptions = (schema, options) => {
488
+ return validate(schema, options);
592
489
  };
593
490
 
594
- // src/api/auth.ts
595
- function isJwt(token) {
596
- const parts = token.split(".");
597
- if (parts.length !== 3) {
598
- return false;
491
+ // src/utils/function-utils.ts
492
+ function extractCursor(data) {
493
+ if (!data?.next) {
494
+ return void 0;
599
495
  }
600
- const base64UrlPattern = /^[A-Za-z0-9_-]+$/;
601
- return parts.every((part) => part.length > 0 && base64UrlPattern.test(part));
602
- }
603
- function getAuthorizationHeader(token) {
604
- if (isJwt(token)) {
605
- return `JWT ${token}`;
496
+ try {
497
+ const urlObj = new URL(data.next);
498
+ const offset = urlObj.searchParams.get("offset");
499
+ return offset || void 0;
500
+ } catch {
501
+ return void 0;
606
502
  }
607
- return `Bearer ${token}`;
608
503
  }
609
-
610
- // src/api/debug.ts
611
- function createDebugLogger(enabled) {
612
- if (!enabled) {
613
- return () => {
614
- };
504
+ function normalizeError(error) {
505
+ if (error instanceof ZapierError) {
506
+ return error;
615
507
  }
616
- return (message, data) => {
617
- console.log(`[Zapier SDK] ${message}`, data || "");
618
- };
508
+ const message = error instanceof Error ? error.message : String(error);
509
+ return new ZapierUnknownError(`Unknown error: ${message}`, { cause: error });
619
510
  }
620
- function createDebugFetch(options) {
621
- const { originalFetch, debugLog } = options;
622
- return async (input, options2) => {
623
- const startTime = Date.now();
624
- const url = typeof input === "string" ? input : input.toString();
625
- const method = options2?.method || "GET";
626
- debugLog(`\u2192 ${method} ${url}`, {
627
- headers: options2?.headers,
628
- body: options2?.body && typeof options2.body === "string" ? (() => {
629
- try {
630
- return JSON.parse(options2.body);
631
- } catch {
632
- return options2.body;
511
+ function createFunction(coreFn, schema) {
512
+ const functionName = coreFn.name;
513
+ const namedFunctions = {
514
+ [functionName]: async function(options) {
515
+ try {
516
+ const normalizedOptions = options ?? {};
517
+ if (schema) {
518
+ const validatedOptions = validateOptions(schema, normalizedOptions);
519
+ return await coreFn({
520
+ ...normalizedOptions,
521
+ ...validatedOptions
522
+ });
633
523
  }
634
- })() : options2?.body
635
- });
636
- try {
637
- const response = await originalFetch(input, options2);
638
- const duration = Date.now() - startTime;
639
- debugLog(`\u2190 ${response.status} ${response.statusText} (${duration}ms)`, {
640
- url,
641
- method,
642
- status: response.status
643
- });
644
- return response;
645
- } catch (error) {
646
- const duration = Date.now() - startTime;
647
- debugLog(`\u2716 Request failed (${duration}ms)`, {
648
- url,
649
- method,
650
- error: error instanceof Error ? error.message : error
651
- });
652
- throw error;
524
+ return await coreFn(normalizedOptions);
525
+ } catch (error) {
526
+ throw normalizeError(error);
527
+ }
653
528
  }
654
529
  };
530
+ return namedFunctions[functionName];
655
531
  }
656
-
657
- // src/api/polling.ts
658
- async function pollUntilComplete(options) {
659
- const {
660
- fetchPoll,
661
- maxAttempts = 30,
662
- initialDelay = 50,
663
- maxDelay = 1e3,
664
- successStatus = 200,
665
- pendingStatus = 202,
666
- resultExtractor = (response) => response
667
- } = options;
668
- let delay = initialDelay;
669
- let errorCount = 0;
670
- for (let attempt = 0; attempt < maxAttempts; attempt++) {
671
- const response = await fetchPoll();
672
- if (response.status === successStatus) {
673
- errorCount = 0;
674
- const result = await response.json();
675
- return resultExtractor(result);
676
- } else if (response.status === pendingStatus) {
677
- errorCount = 0;
678
- if (attempt < maxAttempts - 1) {
679
- await new Promise((resolve3) => setTimeout(resolve3, delay));
680
- delay = Math.min(delay * 2, maxDelay);
681
- continue;
682
- }
683
- } else {
684
- errorCount++;
685
- if (errorCount >= 3) {
686
- throw new ZapierApiError(
687
- `Poll request failed: ${response.status} ${response.statusText}`,
688
- { statusCode: response.status }
689
- );
690
- }
691
- if (attempt < maxAttempts - 1) {
692
- await new Promise((resolve3) => setTimeout(resolve3, delay));
693
- delay = Math.min(delay * 2, maxDelay);
694
- continue;
532
+ function createPageFunction(coreFn) {
533
+ const functionName = coreFn.name + "Page";
534
+ const namedFunctions = {
535
+ [functionName]: async function(options) {
536
+ try {
537
+ const result = await coreFn(options);
538
+ if (result && typeof result === "object" && "data" in result) {
539
+ const data = result.data;
540
+ return {
541
+ data: Array.isArray(data) ? data : [data],
542
+ nextCursor: result.nextCursor
543
+ };
544
+ }
545
+ if (Array.isArray(result)) {
546
+ return { data: result };
547
+ }
548
+ return { data: [result] };
549
+ } catch (error) {
550
+ throw normalizeError(error);
695
551
  }
696
552
  }
697
- }
698
- throw new ZapierTimeoutError(
699
- `Operation timed out after ${maxAttempts} attempts`,
700
- { attempts: maxAttempts, maxAttempts }
701
- );
553
+ };
554
+ return namedFunctions[functionName];
702
555
  }
703
-
704
- // src/api/client.ts
705
- var SubdomainConfigMap = {
706
- // e.g. https://relay.zapier.com
707
- relay: {
708
- authHeader: "X-Relay-Authorization"
709
- }
710
- };
711
- var ZapierApiClient = class {
712
- constructor(options) {
713
- this.options = options;
714
- this.fetch = async (path, init) => {
715
- return this.plainFetch(path, init);
716
- };
717
- this.get = async (path, options = {}) => {
718
- return this.fetchJson("GET", path, void 0, options);
719
- };
720
- this.post = async (path, data, options = {}) => {
721
- return this.fetchJson("POST", path, data, options);
722
- };
723
- this.put = async (path, data, options = {}) => {
724
- return this.fetchJson("PUT", path, data, options);
725
- };
726
- this.delete = async (path, options = {}) => {
727
- return this.fetchJson("DELETE", path, void 0, options);
728
- };
729
- this.poll = async (path, options = {}) => {
730
- return pollUntilComplete({
731
- fetchPoll: () => this.plainFetch(path, {
732
- method: "GET",
733
- searchParams: options.searchParams,
734
- authRequired: options.authRequired
735
- }),
736
- maxAttempts: options.maxAttempts,
737
- initialDelay: options.initialDelay,
738
- maxDelay: options.maxDelay,
739
- successStatus: options.successStatus,
740
- pendingStatus: options.pendingStatus,
741
- resultExtractor: options.resultExtractor
556
+ function createPaginatedFunction(coreFn, schema) {
557
+ const pageFunction = createPageFunction(coreFn);
558
+ const functionName = coreFn.name;
559
+ const validator = schema ? createValidator(schema) : null;
560
+ const namedFunctions = {
561
+ [functionName]: function(options) {
562
+ const normalizedOptions = options ?? {};
563
+ const validatedOptions = {
564
+ ...normalizedOptions,
565
+ ...validator ? validator(normalizedOptions) : normalizedOptions
566
+ };
567
+ const pageSize = validatedOptions.pageSize || 100;
568
+ const optimizedOptions = {
569
+ ...validatedOptions,
570
+ pageSize
571
+ };
572
+ const iterator = paginate(pageFunction, optimizedOptions);
573
+ const firstPagePromise = iterator.next().then((result) => {
574
+ if (result.done) {
575
+ throw new Error("Paginate should always iterate at least once");
576
+ }
577
+ return result.value;
742
578
  });
743
- };
744
- }
745
- // Helper to parse response data
746
- async parseResult(response) {
747
- try {
748
- return { type: "json", data: await response.json() };
749
- } catch {
750
- return { type: "text", data: await response.text() };
751
- }
752
- }
753
- // Helper to get a token from the different places it could be gotten
754
- async getAuthToken() {
755
- if (this.options.token) {
756
- return this.options.token;
757
- }
758
- if (this.options.getToken) {
759
- const token = await this.options.getToken();
760
- if (token) {
761
- return token;
762
- }
763
- }
764
- return getTokenFromEnvOrConfig({
765
- onEvent: this.options.onEvent,
766
- fetch: this.options.fetch
767
- });
768
- }
769
- // Helper to handle responses
770
- async handleResponse(params) {
771
- const { response, customErrorHandler, wasMissingAuthToken } = params;
772
- const { data: responseData } = await this.parseResult(response);
773
- if (response.ok) {
774
- return responseData;
775
- }
776
- const errorInfo = {
777
- status: response.status,
778
- statusText: response.statusText,
779
- data: responseData
780
- };
781
- if (customErrorHandler) {
782
- const customError = customErrorHandler(errorInfo);
783
- if (customError) {
784
- if (customError instanceof Error) {
785
- throw customError;
786
- } else {
787
- throw new Error(
788
- `customErrorHandler returned a non-Error: ${JSON.stringify(customError)}`
789
- );
579
+ return Object.assign(firstPagePromise, {
580
+ [Symbol.asyncIterator]: async function* () {
581
+ yield await firstPagePromise;
582
+ for await (const page of iterator) {
583
+ yield page;
584
+ }
585
+ },
586
+ items: function() {
587
+ return {
588
+ [Symbol.asyncIterator]: async function* () {
589
+ const firstPage = await firstPagePromise;
590
+ for (const item of firstPage.data) {
591
+ yield item;
592
+ }
593
+ for await (const page of iterator) {
594
+ for (const item of page.data) {
595
+ yield item;
596
+ }
597
+ }
598
+ }
599
+ };
790
600
  }
791
- }
792
- }
793
- const { message, errors } = this.parseErrorResponse(errorInfo);
794
- const errorOptions = {
795
- statusCode: response.status,
796
- errors
797
- };
798
- if (response.status === 404) {
799
- throw new ZapierNotFoundError(message, errorOptions);
800
- }
801
- if (response.status === 401 || response.status === 403) {
802
- if (wasMissingAuthToken) {
803
- throw new ZapierAuthenticationError(
804
- `Authentication required (HTTP ${response.status}). Please provide a token in options or set ZAPIER_TOKEN environment variable.`,
805
- errorOptions
806
- );
807
- }
808
- throw new ZapierAuthenticationError(message, errorOptions);
601
+ });
809
602
  }
810
- if (response.status === 400) {
811
- throw new ZapierValidationError(message, errorOptions);
603
+ };
604
+ return namedFunctions[functionName];
605
+ }
606
+ var AppItemSchema = withFormatter(
607
+ z.object({
608
+ // Essential properties only
609
+ title: z.string(),
610
+ // Mapped from name
611
+ key: z.string(),
612
+ // Mapped from selected_api
613
+ current_implementation_id: z.string(),
614
+ // From id, keeps the full version
615
+ version: z.string().optional(),
616
+ // Extracted from implementation ID
617
+ description: z.string().optional(),
618
+ slug: z.string().optional()
619
+ }),
620
+ {
621
+ format: (item) => {
622
+ return {
623
+ title: item.title,
624
+ subtitle: `(${item.key})`,
625
+ details: []
626
+ };
812
627
  }
813
- throw new ZapierApiError(message, errorOptions);
814
628
  }
815
- hasErrorArray(data) {
816
- return typeof data === "object" && data !== null && "errors" in data && Array.isArray(data.errors);
817
- }
818
- // Helper to check if data has API errors
819
- isApiErrorArray(dataArray) {
820
- const data = dataArray[0];
821
- return typeof data === "object" && data !== null && "message" in data && "code" in data && "title" in data && "detail" in data;
629
+ );
630
+
631
+ // src/plugins/listApps/schemas.ts
632
+ var ListAppsSchema = withOutputSchema(
633
+ z.object({
634
+ appKeys: z.array(z.string()).optional().describe(
635
+ "Filter apps by app keys (e.g., 'SlackCLIAPI' or slug like 'github')"
636
+ ),
637
+ search: z.string().optional().describe("Search for apps by name"),
638
+ pageSize: z.number().min(1).optional().describe("Number of apps per page"),
639
+ maxItems: z.number().min(1).optional().describe("Maximum total items to return across all pages")
640
+ }).describe("List all available apps with optional filtering"),
641
+ AppItemSchema
642
+ );
643
+
644
+ // src/utils/domain-utils.ts
645
+ function splitVersionedKey(versionedKey) {
646
+ const parts = versionedKey.split("@");
647
+ if (parts.length >= 2) {
648
+ const baseKey = parts[0];
649
+ const version = parts.slice(1).join("@");
650
+ return [baseKey, version];
822
651
  }
823
- // Do our best to extract an error message from the response data
824
- extractErrorMessage(data) {
825
- if (typeof data === "string") {
826
- return data;
827
- }
828
- if (typeof data === "object" && data !== null) {
829
- if ("message" in data && typeof data.message === "string") {
830
- return data.message;
831
- }
832
- if ("error" in data) {
833
- if (typeof data.error === "string") {
834
- return data.error;
835
- }
836
- if (typeof data.error === "object" && data.error !== null) {
837
- if ("message" in data.error && typeof data.error.message === "string") {
838
- return data.error.message;
839
- }
840
- }
841
- try {
842
- return JSON.stringify(data.error);
843
- } catch {
844
- }
845
- }
846
- if ("errors" in data && Array.isArray(data.errors)) {
847
- if (this.isApiErrorArray(data.errors)) {
848
- return data.errors[0].detail || data.errors[0].title;
849
- }
850
- }
652
+ return [versionedKey, void 0];
653
+ }
654
+ function normalizeImplementationToAppItem(implementation) {
655
+ const [selectedApi, appVersion] = implementation.selected_api ? splitVersionedKey(implementation.selected_api) : [implementation.selected_api || "", void 0];
656
+ return {
657
+ title: implementation.name || selectedApi,
658
+ key: selectedApi,
659
+ current_implementation_id: implementation.selected_api || "",
660
+ version: appVersion
661
+ // Extract version separately
662
+ };
663
+ }
664
+ function normalizeImplementationMetaToAppItem(implementationMeta) {
665
+ const [selectedApi, appVersion] = splitVersionedKey(implementationMeta.id);
666
+ return {
667
+ title: implementationMeta.name,
668
+ key: selectedApi,
669
+ current_implementation_id: implementationMeta.id,
670
+ // Keep the full versioned ID
671
+ version: appVersion,
672
+ // Extract version separately
673
+ slug: implementationMeta.slug
674
+ };
675
+ }
676
+ function normalizeAuthenticationItem(auth, options = {}) {
677
+ let appKey = options.app_key;
678
+ let version = options.version;
679
+ if (auth.selected_api) {
680
+ const [extractedAppKey, extractedVersion] = splitVersionedKey(
681
+ auth.selected_api
682
+ );
683
+ if (!appKey) {
684
+ appKey = extractedAppKey;
685
+ }
686
+ if (!version) {
687
+ version = extractedVersion;
851
688
  }
852
- return void 0;
853
689
  }
854
- // Helper to parse API error response
855
- parseErrorResponse(errorInfo) {
856
- const fallbackMessage = `HTTP ${errorInfo.status}: ${errorInfo.statusText}`;
857
- try {
858
- if (typeof errorInfo.data === "string") {
859
- return { message: `${fallbackMessage}: ${errorInfo.data}` };
860
- }
861
- const errorMessage = this.extractErrorMessage(errorInfo.data) || fallbackMessage;
862
- if (this.hasErrorArray(errorInfo.data)) {
863
- if (this.isApiErrorArray(errorInfo.data.errors)) {
864
- return {
865
- message: errorMessage,
866
- errors: errorInfo.data.errors
867
- };
868
- } else {
869
- return {
870
- message: errorMessage,
871
- errors: errorInfo.data.errors.map((e) => ({
872
- status: errorInfo.status,
873
- code: String(errorInfo.status),
874
- title: errorInfo.statusText,
875
- detail: JSON.stringify(e)
876
- }))
877
- };
878
- }
690
+ const {
691
+ selected_api: selectedApi,
692
+ customuser_id: userId,
693
+ ...restOfAuth
694
+ } = auth;
695
+ return {
696
+ ...restOfAuth,
697
+ // Pass through all other API response fields except selected_api
698
+ implementation_id: selectedApi,
699
+ // Rename selected_api to implementation_id
700
+ title: auth.title || auth.label || void 0,
701
+ // Coerce title from label if missing
702
+ is_expired: auth.is_stale,
703
+ // Map is_stale to is_expired
704
+ expired_at: auth.marked_stale_at,
705
+ // Map marked_stale_at to expired_at
706
+ app_key: appKey,
707
+ // App key from implementations endpoint or parsed from selected_api
708
+ version,
709
+ // Version from selected_api or provided
710
+ user_id: userId
711
+ // Map customuser_id to user_id
712
+ };
713
+ }
714
+ function normalizeActionItem(action) {
715
+ const { name, type, selected_api: appKey, ...restOfAction } = action;
716
+ return {
717
+ ...restOfAction,
718
+ app_key: appKey || "",
719
+ action_type: type,
720
+ title: name,
721
+ // Map name to title
722
+ type: "action"
723
+ };
724
+ }
725
+ function groupVersionedAppKeysByType(appKeys) {
726
+ const result = {
727
+ selectedApi: [],
728
+ slug: []
729
+ };
730
+ const seenSelectedApi = /* @__PURE__ */ new Set();
731
+ const seenSlugs = /* @__PURE__ */ new Set();
732
+ for (const key of appKeys) {
733
+ const [keyWithoutVersion, version] = splitVersionedKey(key);
734
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
735
+ if (uuidRegex.test(keyWithoutVersion)) {
736
+ throw new Error(
737
+ `UUID app keys are not supported. Use app slug or implementation ID instead of: ${key}`
738
+ );
739
+ }
740
+ if (isSnakeCasedSlug(keyWithoutVersion)) {
741
+ const dashified = dashifySnakeCasedSlug(keyWithoutVersion);
742
+ const slugWithVersion = version ? `${dashified}@${version}` : dashified;
743
+ if (!seenSlugs.has(slugWithVersion)) {
744
+ seenSlugs.add(slugWithVersion);
745
+ result.slug.push(slugWithVersion);
879
746
  }
880
- return { message: errorMessage };
881
- } catch {
882
- return { message: fallbackMessage };
747
+ continue;
883
748
  }
884
- }
885
- // Check if this is a path that needs subdomain routing
886
- // e.g. /relay/workflows -> relay.zapier.com/workflows
887
- applySubdomainBehavior(path) {
888
- const pathSegments = path.split("/").filter(Boolean);
889
- if (pathSegments.length > 0 && pathSegments[0] in SubdomainConfigMap) {
890
- const domainPrefix = pathSegments[0];
891
- const subdomainConfig = SubdomainConfigMap[domainPrefix];
892
- const originalBaseUrl = new URL(this.options.baseUrl);
893
- const finalBaseUrl = `https://${domainPrefix}.${originalBaseUrl.hostname}`;
894
- const pathWithoutPrefix = "/" + pathSegments.slice(1).join("/");
895
- return { url: new URL(pathWithoutPrefix, finalBaseUrl), subdomainConfig };
749
+ if (keyWithoutVersion.match(/^[a-z0-9]+(?:-[a-z0-9]+)*$/)) {
750
+ seenSlugs.add(key);
751
+ result.slug.push(key);
752
+ continue;
896
753
  }
897
- return {
898
- url: new URL(path, this.options.baseUrl),
899
- subdomainConfig: void 0
900
- };
901
- }
902
- // Helper to build full URLs and return routing info
903
- buildUrl(path, searchParams) {
904
- const { url, subdomainConfig } = this.applySubdomainBehavior(path);
905
- if (searchParams) {
906
- Object.entries(searchParams).forEach(([key, value]) => {
907
- url.searchParams.set(key, value);
908
- });
754
+ if (!seenSelectedApi.has(key)) {
755
+ seenSelectedApi.add(key);
756
+ result.selectedApi.push(key);
909
757
  }
910
- return { url: url.toString(), subdomainConfig };
911
758
  }
912
- // Helper to build headers
913
- async buildHeaders(options = {}, subdomainConfig) {
914
- const headers = new Headers(options.headers ?? {});
915
- const authToken = await this.getAuthToken();
916
- if (authToken) {
917
- const authHeaderName = subdomainConfig?.authHeader || "Authorization";
918
- headers.set(authHeaderName, getAuthorizationHeader(authToken));
919
- }
920
- if (options.authRequired) {
921
- if (headers.get("Authorization") == null && authToken == null) {
922
- throw new ZapierAuthenticationError(
923
- `Authentication required but no token available. Please set ZAPIER_TOKEN, or run the 'login' command with the CLI.`
924
- );
759
+ return result;
760
+ }
761
+ function groupAppKeysByType(appKeys) {
762
+ const grouped = groupVersionedAppKeysByType(appKeys);
763
+ return {
764
+ selectedApi: [
765
+ ...new Set(grouped.selectedApi.map((key) => key.split("@")[0]))
766
+ ],
767
+ slug: [...new Set(grouped.slug.map((key) => key.split("@")[0]))]
768
+ };
769
+ }
770
+ function isSnakeCasedSlug(slug) {
771
+ if (slug.match(/^_[0-9]/)) {
772
+ slug = slug.slice(1);
773
+ }
774
+ return !!slug.match(/^[a-z0-9]+(?:_[a-z0-9]+)*$/);
775
+ }
776
+ function dashifySnakeCasedSlug(slug) {
777
+ if (!isSnakeCasedSlug(slug)) {
778
+ return slug;
779
+ }
780
+ if (slug.startsWith("_")) {
781
+ slug = slug.slice(1);
782
+ }
783
+ return slug.replace(/_/g, "-");
784
+ }
785
+
786
+ // src/plugins/listApps/index.ts
787
+ var listAppsPlugin = ({ context }) => {
788
+ const listApps = createPaginatedFunction(async function listAppsPage(options) {
789
+ const api = context.api;
790
+ const opts = options;
791
+ const appKeys = [...opts.appKeys ?? []].map(
792
+ (key) => splitVersionedKey(key)[0]
793
+ );
794
+ if (opts.search) {
795
+ const searchParams2 = {};
796
+ searchParams2.term = opts.search;
797
+ const searchEnvelope = await api.get(
798
+ "/api/v4/implementations-meta/search/",
799
+ {
800
+ searchParams: searchParams2
801
+ }
802
+ );
803
+ const implementations = searchEnvelope.results.map(
804
+ normalizeImplementationMetaToAppItem
805
+ );
806
+ const appKeysSet = new Set(appKeys);
807
+ for (const implementation of implementations) {
808
+ if (!appKeysSet.has(implementation.key)) {
809
+ appKeysSet.add(implementation.key);
810
+ appKeys.push(implementation.key);
811
+ }
925
812
  }
926
813
  }
927
- return headers;
928
- }
929
- // Helper to perform HTTP requests with JSON handling
930
- async fetchJson(method, path, data, options = {}) {
931
- const headers = { ...options.headers };
932
- if (data && typeof data === "object") {
933
- headers["Content-Type"] = "application/json";
814
+ const searchParams = {};
815
+ if (opts.pageSize) {
816
+ searchParams.limit = opts.pageSize.toString();
934
817
  }
935
- const wasMissingAuthToken = options.authRequired && await this.getAuthToken() == null;
936
- const response = await this.plainFetch(path, {
937
- ...options,
938
- method,
939
- body: data != null ? JSON.stringify(data) : void 0,
940
- headers
941
- });
942
- const result = await this.handleResponse({
943
- response,
944
- customErrorHandler: options.customErrorHandler,
945
- wasMissingAuthToken
946
- });
947
- if (typeof result === "string") {
948
- throw new ZapierValidationError(
949
- `Response could not be parsed as JSON: ${result}`
950
- );
951
- }
952
- return result;
953
- }
954
- // Plain fetch method for API paths (must start with /)
955
- async plainFetch(path, fetchOptions) {
956
- if (!path.startsWith("/")) {
957
- throw new ZapierValidationError(
958
- `plainFetch expects a path starting with '/', got: ${path}`
959
- );
818
+ searchParams.latest_only = "true";
819
+ if (opts.cursor) {
820
+ searchParams.offset = opts.cursor;
960
821
  }
961
- if (fetchOptions?.body && typeof fetchOptions.body === "object") {
962
- fetchOptions.body = JSON.stringify(fetchOptions.body);
822
+ if (appKeys.length > 0) {
823
+ const groupedAppKeys = groupAppKeysByType(appKeys);
824
+ if (groupedAppKeys.selectedApi.length > 0) {
825
+ searchParams.selected_apis = groupedAppKeys.selectedApi.join(",");
826
+ }
827
+ if (groupedAppKeys.slug.length > 0) {
828
+ searchParams.slugs = groupedAppKeys.slug.join(",");
829
+ }
963
830
  }
964
- const { url, subdomainConfig } = this.buildUrl(
965
- path,
966
- fetchOptions?.searchParams
967
- );
968
- const builtHeaders = await this.buildHeaders(
969
- fetchOptions,
970
- subdomainConfig
831
+ const implementationsEnvelope = await api.get(
832
+ "/api/v4/implementations-meta/lookup/",
833
+ {
834
+ searchParams
835
+ }
971
836
  );
972
- const inputHeaders = new Headers(fetchOptions?.headers ?? {});
973
- const mergedHeaders = new Headers();
974
- builtHeaders.forEach((value, key) => {
975
- mergedHeaders.set(key, value);
976
- });
977
- inputHeaders.forEach((value, key) => {
978
- mergedHeaders.set(key, value);
979
- });
980
- return await this.options.fetch(url, {
981
- ...fetchOptions,
982
- headers: mergedHeaders
983
- });
984
- }
985
- };
986
- var createZapierApi = (options) => {
987
- const {
988
- baseUrl,
989
- token,
990
- getToken,
991
- debug = false,
992
- fetch: originalFetch = globalThis.fetch,
993
- onEvent
994
- } = options;
995
- const debugLog = createDebugLogger(debug);
996
- const debugFetch = createDebugFetch({ originalFetch, debugLog });
997
- return new ZapierApiClient({
998
- baseUrl,
999
- token,
1000
- getToken,
1001
- debug,
1002
- fetch: debugFetch,
1003
- onEvent
1004
- });
1005
- };
1006
-
1007
- // src/plugins/api/index.ts
1008
- var apiPlugin = (params) => {
1009
- const {
1010
- fetch: customFetch = globalThis.fetch,
1011
- baseUrl = "https://zapier.com",
1012
- token,
1013
- getToken,
1014
- onEvent,
1015
- debug = false
1016
- } = params.context.options;
1017
- const api = createZapierApi({
1018
- baseUrl,
1019
- token,
1020
- getToken,
1021
- debug,
1022
- fetch: customFetch,
1023
- onEvent
1024
- });
837
+ return {
838
+ data: implementationsEnvelope.results.map(
839
+ normalizeImplementationMetaToAppItem
840
+ ),
841
+ nextCursor: extractCursor(implementationsEnvelope)
842
+ };
843
+ }, ListAppsSchema);
1025
844
  return {
845
+ listApps,
1026
846
  context: {
1027
- api
1028
- // Provide API client in context for other plugins to use
1029
- }
1030
- };
1031
- };
1032
-
1033
- // src/utils/pagination-utils.ts
1034
- var offsetCursorMarker = "$$offset$$";
1035
- function splitOffsetCursor(cursor) {
1036
- if (!cursor) {
1037
- return [0, cursor];
1038
- }
1039
- try {
1040
- const parsedCursor = JSON.parse(cursor);
1041
- if (!Array.isArray(parsedCursor)) {
1042
- return [0, cursor];
1043
- }
1044
- const [marker, offset, currentCursor] = parsedCursor;
1045
- if (marker !== offsetCursorMarker) {
1046
- return [0, cursor];
1047
- }
1048
- if (typeof offset !== "number") {
1049
- return [0, cursor];
1050
- }
1051
- return [offset, currentCursor];
1052
- } catch {
1053
- return [0, cursor];
1054
- }
1055
- }
1056
- function createOffsetCursor(offset, currentCursor) {
1057
- return JSON.stringify([offsetCursorMarker, offset, currentCursor]);
1058
- }
1059
- async function* paginateMaxItems(pageFunction, pageOptions) {
1060
- let cursor = pageOptions?.cursor;
1061
- let totalItemsYielded = 0;
1062
- const maxItems = pageOptions?.maxItems;
1063
- const pageSize = pageOptions?.pageSize;
1064
- do {
1065
- const options = {
1066
- ...pageOptions || {},
1067
- cursor,
1068
- pageSize: maxItems !== void 0 && pageSize !== void 0 ? Math.min(pageSize, maxItems) : pageSize
1069
- };
1070
- const page = await pageFunction(options);
1071
- if (maxItems !== void 0) {
1072
- const remainingItems = maxItems - totalItemsYielded;
1073
- if (page.data.length >= remainingItems) {
1074
- const yieldedPage = {
1075
- ...page,
1076
- data: page.data.slice(0, remainingItems),
1077
- nextCursor: void 0
1078
- };
1079
- yield yieldedPage;
1080
- break;
847
+ meta: {
848
+ listApps: {
849
+ categories: ["app"],
850
+ inputSchema: ListAppsSchema
851
+ }
1081
852
  }
1082
853
  }
1083
- yield page;
1084
- totalItemsYielded += page.data.length;
1085
- cursor = page.nextCursor;
1086
- } while (cursor);
1087
- }
1088
- async function* paginateBuffered(pageFunction, pageOptions) {
1089
- const pageSize = pageOptions?.pageSize;
1090
- const [cursorOffset, currentCursor] = splitOffsetCursor(pageOptions?.cursor);
1091
- const options = {
1092
- ...pageOptions || {},
1093
- cursor: currentCursor
1094
854
  };
1095
- const iterator = paginateMaxItems(pageFunction, options);
1096
- let bufferedPages = [];
1097
- let isFirstPage = true;
1098
- let cursor;
1099
- for await (let page of iterator) {
1100
- if (isFirstPage) {
1101
- isFirstPage = false;
1102
- if (cursorOffset) {
1103
- page = {
1104
- ...page,
1105
- data: page.data.slice(cursorOffset)
1106
- };
1107
- }
1108
- }
1109
- if (!pageSize) {
1110
- yield page;
1111
- cursor = page.nextCursor;
1112
- continue;
1113
- }
1114
- const bufferedLength = bufferedPages.reduce(
1115
- (acc, page2) => acc + page2.data.length,
1116
- 0
1117
- );
1118
- if (bufferedLength + page.data.length < pageSize) {
1119
- bufferedPages.push(page);
1120
- cursor = page.nextCursor;
1121
- continue;
1122
- }
1123
- const bufferedItems = bufferedPages.map((p) => p.data).flat();
1124
- const allItems = [...bufferedItems, ...page.data];
1125
- const pageItems = allItems.slice(0, pageSize);
1126
- const remainingItems = allItems.slice(pageItems.length);
1127
- if (remainingItems.length === 0) {
1128
- yield {
1129
- ...page,
1130
- data: pageItems,
1131
- nextCursor: page.nextCursor
1132
- };
1133
- bufferedPages = [];
1134
- cursor = page.nextCursor;
1135
- continue;
1136
- }
1137
- yield {
1138
- ...page,
1139
- data: pageItems,
1140
- nextCursor: createOffsetCursor(
1141
- page.data.length - remainingItems.length,
1142
- cursor
1143
- )
1144
- };
1145
- while (remainingItems.length > pageSize) {
1146
- const pageItems2 = remainingItems.splice(0, pageSize);
1147
- yield {
1148
- ...page,
1149
- data: pageItems2,
1150
- nextCursor: createOffsetCursor(
1151
- page.data.length - remainingItems.length,
1152
- cursor
1153
- )
1154
- };
1155
- }
1156
- bufferedPages = [
1157
- {
1158
- ...page,
1159
- data: remainingItems
1160
- }
1161
- ];
1162
- cursor = page.nextCursor;
1163
- }
1164
- if (bufferedPages.length > 0) {
1165
- const lastBufferedPage = bufferedPages.slice(-1)[0];
1166
- const bufferedItems = bufferedPages.map((p) => p.data).flat();
1167
- yield {
1168
- ...lastBufferedPage,
1169
- data: bufferedItems
1170
- };
1171
- }
1172
- }
1173
- var paginate = paginateBuffered;
1174
-
1175
- // src/utils/validation.ts
1176
- var validate = (schema, input) => {
1177
- const result = schema.safeParse(input);
1178
- if (!result.success) {
1179
- const errorMessages = result.error.errors.map((error) => {
1180
- const path = error.path.length > 0 ? error.path.join(".") : "input";
1181
- return `${path}: ${error.message}`;
1182
- });
1183
- const message = `Validation failed:
1184
- ${errorMessages.join("\n ")}`;
1185
- throw new ZapierValidationError(message, {
1186
- details: {
1187
- zodErrors: result.error.errors,
1188
- input
1189
- }
1190
- });
1191
- }
1192
- return result.data;
1193
- };
1194
- function createValidator(schema) {
1195
- return function validateFn(input) {
1196
- return validate(schema, input);
1197
- };
1198
- }
1199
- var validateOptions = (schema, options) => {
1200
- return validate(schema, options);
1201
855
  };
1202
-
1203
- // src/utils/function-utils.ts
1204
- function extractCursor(data) {
1205
- if (!data?.next) {
1206
- return void 0;
1207
- }
1208
- try {
1209
- const urlObj = new URL(data.next);
1210
- const offset = urlObj.searchParams.get("offset");
1211
- return offset || void 0;
1212
- } catch {
1213
- return void 0;
1214
- }
1215
- }
1216
- function normalizeError(error) {
1217
- if (error instanceof ZapierError) {
1218
- return error;
1219
- }
1220
- const message = error instanceof Error ? error.message : String(error);
1221
- return new ZapierUnknownError(`Unknown error: ${message}`, { cause: error });
1222
- }
1223
- function createFunction(coreFn, schema) {
1224
- const functionName = coreFn.name;
1225
- const namedFunctions = {
1226
- [functionName]: async function(options) {
1227
- try {
1228
- const normalizedOptions = options ?? {};
1229
- if (schema) {
1230
- const validatedOptions = validateOptions(schema, normalizedOptions);
1231
- return await coreFn({
1232
- ...normalizedOptions,
1233
- ...validatedOptions
1234
- });
1235
- }
1236
- return await coreFn(normalizedOptions);
1237
- } catch (error) {
1238
- throw normalizeError(error);
1239
- }
1240
- }
1241
- };
1242
- return namedFunctions[functionName];
1243
- }
1244
- function createPageFunction(coreFn) {
1245
- const functionName = coreFn.name + "Page";
1246
- const namedFunctions = {
1247
- [functionName]: async function(options) {
1248
- try {
1249
- const result = await coreFn(options);
1250
- if (result && typeof result === "object" && "data" in result) {
1251
- const data = result.data;
1252
- return {
1253
- data: Array.isArray(data) ? data : [data],
1254
- nextCursor: result.nextCursor
1255
- };
1256
- }
1257
- if (Array.isArray(result)) {
1258
- return { data: result };
1259
- }
1260
- return { data: [result] };
1261
- } catch (error) {
1262
- throw normalizeError(error);
1263
- }
1264
- }
1265
- };
1266
- return namedFunctions[functionName];
1267
- }
1268
- function createPaginatedFunction(coreFn, schema) {
1269
- const pageFunction = createPageFunction(coreFn);
1270
- const functionName = coreFn.name;
1271
- const validator = schema ? createValidator(schema) : null;
1272
- const namedFunctions = {
1273
- [functionName]: function(options) {
1274
- const normalizedOptions = options ?? {};
1275
- const validatedOptions = {
1276
- ...normalizedOptions,
1277
- ...validator ? validator(normalizedOptions) : normalizedOptions
1278
- };
1279
- const pageSize = validatedOptions.pageSize || 100;
1280
- const optimizedOptions = {
1281
- ...validatedOptions,
1282
- pageSize
1283
- };
1284
- const iterator = paginate(pageFunction, optimizedOptions);
1285
- const firstPagePromise = iterator.next().then((result) => {
1286
- if (result.done) {
1287
- throw new Error("Paginate should always iterate at least once");
1288
- }
1289
- return result.value;
1290
- });
1291
- return Object.assign(firstPagePromise, {
1292
- [Symbol.asyncIterator]: async function* () {
1293
- yield await firstPagePromise;
1294
- for await (const page of iterator) {
1295
- yield page;
1296
- }
1297
- },
1298
- items: function() {
1299
- return {
1300
- [Symbol.asyncIterator]: async function* () {
1301
- const firstPage = await firstPagePromise;
1302
- for (const item of firstPage.data) {
1303
- yield item;
1304
- }
1305
- for await (const page of iterator) {
1306
- for (const item of page.data) {
1307
- yield item;
1308
- }
1309
- }
1310
- }
1311
- };
1312
- }
1313
- });
1314
- }
1315
- };
1316
- return namedFunctions[functionName];
1317
- }
1318
856
  var NeedChoicesSchema = z.object({
1319
857
  key: z.string().optional(),
1320
858
  label: z.string().optional(),
@@ -1649,1223 +1187,1849 @@ z.object({
1649
1187
  previous: z.string().nullable().optional(),
1650
1188
  results: z.array(ImplementationMetaSchema)
1651
1189
  });
1190
+ var NeedChoicesResponseMetaSchema = z.object({
1191
+ page: z.string().nullable().optional()
1192
+ });
1193
+ var NeedChoicesResponseLinksSchema = z.object({
1194
+ next: z.string().nullable().optional(),
1195
+ prev: z.string().nullable().optional()
1196
+ });
1197
+ z.object({
1198
+ selected_api: z.string().optional().describe(
1199
+ "Something like `SlackAPI` (for Python apps) or `SplitwiseCLIAPI@1.0.0` (for CLI apps). Non-public apps are fine as long as the authed user can access them."
1200
+ ),
1201
+ authentication_id: z.number().optional().describe(
1202
+ "If the app needs auth, provide an `authentication_id` that has the `selected_api` of the app you want to run. Can be any auth visible to the user (including shared)."
1203
+ ),
1204
+ params: z.record(z.any()).optional().describe(
1205
+ "Object that matches the input the node would normally get. Has all the same keys/types as the `needs` of the action."
1206
+ ),
1207
+ page: z.number().optional().default(0),
1208
+ prefill: z.string().optional().describe(
1209
+ "The prefill string to indicate what we're fetching choices for. Likely something like `spreadsheet.id.title`. Must be provided alongside `selected_api` if both `action_id` and `input_field_id` are not."
1210
+ ),
1211
+ action_id: z.string().optional().describe(
1212
+ "The id that will be used to lookup the Action for prefill lookup. If provided, `input_field_id` is required, else `prefill` must be provided."
1213
+ ),
1214
+ input_field_id: z.string().optional().describe(
1215
+ "The id (key) of the input field (Need) that dynamic choices are being retrieved for. If provided, `action_id` is required, else `prefill` must be provided."
1216
+ )
1217
+ });
1218
+ z.object({
1219
+ success: z.boolean(),
1220
+ choices: z.array(NeedChoicesSchema).optional(),
1221
+ next_page: z.number().optional(),
1222
+ errors: z.array(z.string()).optional(),
1223
+ meta: NeedChoicesResponseMetaSchema.optional(),
1224
+ links: NeedChoicesResponseLinksSchema.optional()
1225
+ });
1652
1226
 
1653
- // src/schemas/UserProfile.ts
1654
- var UserProfileItemSchema = withFormatter(
1655
- UserProfileSchema.omit({ user_id: true }).extend({
1656
- full_name: z.string()
1657
- // Computed field: first_name + " " + last_name
1227
+ // src/schemas/Action.ts
1228
+ var ActionItemSchema = withFormatter(
1229
+ ActionSchema.omit({ type: true, name: true }).extend({
1230
+ app_key: z.string(),
1231
+ // Mapped from selected_api
1232
+ action_type: ActionSchema.shape.type,
1233
+ // Mapped from original 'type' field
1234
+ title: z.string(),
1235
+ // Mapped from original 'name' field
1236
+ type: z.literal("action")
1237
+ // Fixed type identifier
1658
1238
  }),
1659
1239
  {
1660
1240
  format: (item) => {
1661
1241
  const details = [];
1662
- details.push({ text: item.email, style: "dim" });
1663
- if (item.timezone) {
1242
+ details.push({
1243
+ text: `Type: ${item.action_type}`,
1244
+ style: "accent"
1245
+ });
1246
+ if (item.app_key) {
1664
1247
  details.push({
1665
- text: `Timezone: ${item.timezone}`,
1666
- style: "accent"
1248
+ text: `App: ${item.app_key}`,
1249
+ style: "normal"
1667
1250
  });
1668
1251
  }
1669
- details.push({
1670
- text: `Member since: ${item.since_signup}`,
1671
- style: "dim"
1252
+ if (item.description) {
1253
+ details.push({ text: item.description, style: "dim" });
1254
+ }
1255
+ return {
1256
+ title: item.title || item.name || item.key,
1257
+ subtitle: `(${item.key})`,
1258
+ details
1259
+ };
1260
+ }
1261
+ }
1262
+ );
1263
+
1264
+ // src/plugins/listActions/schemas.ts
1265
+ var ListActionsSchema = withOutputSchema(
1266
+ z.object({
1267
+ appKey: AppKeyPropertySchema.describe(
1268
+ "App key of actions to list (e.g., 'SlackCLIAPI')"
1269
+ ),
1270
+ actionType: ActionTypePropertySchema.optional().describe(
1271
+ "Filter actions by type"
1272
+ ),
1273
+ pageSize: z.number().min(1).optional().describe("Number of actions per page"),
1274
+ maxItems: z.number().min(1).optional().describe("Maximum total items to return across all pages")
1275
+ }).describe("List all actions for a specific app"),
1276
+ ActionItemSchema
1277
+ );
1278
+
1279
+ // src/plugins/listActions/index.ts
1280
+ var listActionsPlugin = ({ context }) => {
1281
+ const listActions = createPaginatedFunction(async function listActionsPage(options) {
1282
+ const { api, getVersionedImplementationId } = context;
1283
+ const selectedApi = await getVersionedImplementationId(options.appKey);
1284
+ if (!selectedApi) {
1285
+ throw new ZapierConfigurationError(
1286
+ "No current_implementation_id found for app",
1287
+ { configType: "current_implementation_id" }
1288
+ );
1289
+ }
1290
+ const searchParams = {
1291
+ global: "true",
1292
+ public_only: "true",
1293
+ selected_apis: selectedApi
1294
+ };
1295
+ const data = await api.get(
1296
+ "/api/v4/implementations/",
1297
+ {
1298
+ searchParams,
1299
+ customErrorHandler: ({ status }) => {
1300
+ if (status === 401) {
1301
+ return new ZapierAuthenticationError(
1302
+ `Authentication failed. Your token may not have permission to access implementations or may be expired. (HTTP ${status})`,
1303
+ { statusCode: status }
1304
+ );
1305
+ }
1306
+ if (status === 403) {
1307
+ return new ZapierAuthenticationError(
1308
+ `Access forbidden. Your token may not have the required scopes to list implementations. (HTTP ${status})`,
1309
+ { statusCode: status }
1310
+ );
1311
+ }
1312
+ return void 0;
1313
+ }
1314
+ }
1315
+ );
1316
+ let allActions = [];
1317
+ for (const implementation of data.results || []) {
1318
+ if (implementation.actions) {
1319
+ for (const action of implementation.actions) {
1320
+ const actionWithContext = {
1321
+ ...action,
1322
+ selected_api: action.selected_api || implementation.selected_api
1323
+ };
1324
+ allActions.push(normalizeActionItem(actionWithContext));
1325
+ }
1326
+ }
1327
+ }
1328
+ if (options.actionType) {
1329
+ allActions = allActions.filter(
1330
+ (action) => action.action_type === options.actionType
1331
+ );
1332
+ }
1333
+ return {
1334
+ data: allActions,
1335
+ nextCursor: void 0
1336
+ };
1337
+ }, ListActionsSchema);
1338
+ return {
1339
+ listActions,
1340
+ context: {
1341
+ meta: {
1342
+ listActions: {
1343
+ categories: ["action"],
1344
+ inputSchema: ListActionsSchema
1345
+ }
1346
+ }
1347
+ }
1348
+ };
1349
+ };
1350
+ var ListInputFieldsSchema = z.object({
1351
+ appKey: AppKeyPropertySchema,
1352
+ actionType: ActionTypePropertySchema,
1353
+ actionKey: ActionKeyPropertySchema,
1354
+ authenticationId: AuthenticationIdPropertySchema.nullable().optional(),
1355
+ inputs: InputsPropertySchema.optional().describe(
1356
+ "Current input values that may affect available fields"
1357
+ ),
1358
+ pageSize: z.number().min(1).optional().describe("Number of input fields per page"),
1359
+ maxItems: z.number().min(1).optional().describe("Maximum total items to return across all pages")
1360
+ }).describe("Get the input fields required for a specific action");
1361
+
1362
+ // src/plugins/listInputFields/index.ts
1363
+ function getInputFieldTypeFromNeed(need) {
1364
+ if (need.list) {
1365
+ return "ARRAY" /* ARRAY */;
1366
+ }
1367
+ const typeMap = {
1368
+ string: "STRING" /* STRING */,
1369
+ decimal: "NUMBER" /* NUMBER */,
1370
+ integer: "INTEGER" /* INTEGER */,
1371
+ boolean: "BOOLEAN" /* BOOLEAN */,
1372
+ dict: "OBJECT" /* OBJECT */
1373
+ };
1374
+ return typeMap[need.type || ""] || "STRING" /* STRING */;
1375
+ }
1376
+ function getInputFieldFormatFromNeed(need) {
1377
+ if (need.prefill || need.choices) {
1378
+ return "SELECT" /* SELECT */;
1379
+ }
1380
+ const formatMap = {
1381
+ text: "MULTILINE" /* MULTILINE */,
1382
+ datetime: "DATETIME" /* DATETIME */,
1383
+ file: "FILE" /* FILE */,
1384
+ password: "PASSWORD" /* PASSWORD */,
1385
+ code: "CODE" /* CODE */
1386
+ };
1387
+ return formatMap[need.type || ""];
1388
+ }
1389
+ function getItemsTypeFromNeed(need) {
1390
+ if (!need.list) {
1391
+ return void 0;
1392
+ }
1393
+ const typeMap = {
1394
+ string: "STRING" /* STRING */,
1395
+ decimal: "NUMBER" /* NUMBER */,
1396
+ integer: "INTEGER" /* INTEGER */,
1397
+ boolean: "BOOLEAN" /* BOOLEAN */,
1398
+ dict: "OBJECT" /* OBJECT */
1399
+ };
1400
+ return typeMap[need.type || ""] || "STRING" /* STRING */;
1401
+ }
1402
+ function transformNeedToInputFieldItem(need) {
1403
+ const itemsType = getItemsTypeFromNeed(need);
1404
+ return {
1405
+ ...need,
1406
+ // Pass through all original Need fields
1407
+ id: need.key,
1408
+ default_value: need.default || "",
1409
+ depends_on: need.depends_on || [],
1410
+ description: need.help_text || "",
1411
+ invalidates_input_fields: need.alters_custom_fields || false,
1412
+ is_required: need.required || false,
1413
+ placeholder: need.placeholder || "",
1414
+ title: need.label || "",
1415
+ value_type: getInputFieldTypeFromNeed(need),
1416
+ format: getInputFieldFormatFromNeed(need),
1417
+ items: itemsType ? { type: itemsType } : void 0
1418
+ };
1419
+ }
1420
+ var listInputFieldsPlugin = ({ context }) => {
1421
+ const listInputFields = createPaginatedFunction(
1422
+ async function listInputFieldsPage(options) {
1423
+ const { api, getVersionedImplementationId } = context;
1424
+ const { appKey, actionKey, actionType, authenticationId, inputs } = options;
1425
+ const selectedApi = await getVersionedImplementationId(appKey);
1426
+ if (!selectedApi) {
1427
+ throw new ZapierConfigurationError(
1428
+ "No current_implementation_id found for app",
1429
+ { configType: "current_implementation_id" }
1430
+ );
1431
+ }
1432
+ const needsRequest = {
1433
+ selected_api: selectedApi,
1434
+ action: actionKey,
1435
+ type_of: actionType,
1436
+ params: inputs || {}
1437
+ };
1438
+ if (authenticationId !== null) {
1439
+ needsRequest.authentication_id = authenticationId;
1440
+ }
1441
+ const needsData = await api.post(
1442
+ "/api/v4/implementations/needs/",
1443
+ needsRequest
1444
+ );
1445
+ if (!needsData.success) {
1446
+ throw new ZapierApiError(
1447
+ `Failed to get action fields: ${needsData.errors?.join(", ") || "Unknown error"}`
1448
+ );
1449
+ }
1450
+ const inputFields = (needsData.needs || []).map(
1451
+ transformNeedToInputFieldItem
1452
+ );
1453
+ return {
1454
+ data: inputFields,
1455
+ nextCursor: void 0
1456
+ // No pagination needed since we return all input fields
1457
+ };
1458
+ },
1459
+ ListInputFieldsSchema
1460
+ );
1461
+ return {
1462
+ listInputFields,
1463
+ context: {
1464
+ meta: {
1465
+ listInputFields: {
1466
+ categories: ["action"],
1467
+ inputSchema: ListInputFieldsSchema
1468
+ }
1469
+ }
1470
+ }
1471
+ };
1472
+ };
1473
+ var ListAuthenticationsSchema = z.object({
1474
+ appKey: AppKeyPropertySchema.optional().describe(
1475
+ "App key of authentications to list (e.g., 'SlackCLIAPI')"
1476
+ ),
1477
+ search: z.string().optional().describe("Search term to filter authentications by title"),
1478
+ title: z.string().optional().describe("Filter authentications by exact title match"),
1479
+ accountId: z.string().optional().describe("Filter by account ID"),
1480
+ owner: z.string().optional().describe("Filter by owner"),
1481
+ pageSize: z.number().min(1).optional().describe("Number of authentications per page"),
1482
+ maxItems: z.number().min(1).optional().describe("Maximum total items to return across all pages")
1483
+ }).describe("List available authentications with optional filtering");
1484
+
1485
+ // src/plugins/listAuthentications/index.ts
1486
+ var listAuthenticationsPlugin = ({ context }) => {
1487
+ const listAuthentications = createPaginatedFunction(
1488
+ async function listAuthenticationsPage(options) {
1489
+ const { api, getVersionedImplementationId } = context;
1490
+ const searchParams = {};
1491
+ if (options.appKey) {
1492
+ const implementationId = await getVersionedImplementationId(
1493
+ options.appKey
1494
+ );
1495
+ if (implementationId) {
1496
+ const [versionlessSelectedApi] = splitVersionedKey(implementationId);
1497
+ searchParams.versionless_selected_api = versionlessSelectedApi;
1498
+ }
1499
+ }
1500
+ if (options.search) {
1501
+ searchParams.search = options.search;
1502
+ } else if (options.title) {
1503
+ searchParams.search = options.title;
1504
+ }
1505
+ if (options.accountId) {
1506
+ searchParams.account_id = options.accountId;
1507
+ }
1508
+ if (options.owner) {
1509
+ searchParams.owner = options.owner;
1510
+ }
1511
+ searchParams.limit = options.pageSize.toString();
1512
+ if (options.cursor) {
1513
+ searchParams.offset = options.cursor;
1514
+ }
1515
+ const data = await api.get(
1516
+ "/api/v4/authentications/",
1517
+ {
1518
+ searchParams,
1519
+ customErrorHandler: ({ status }) => {
1520
+ if (status === 401) {
1521
+ return new ZapierAuthenticationError(
1522
+ `Authentication failed. Your token may not have permission to access authentications or may be expired. (HTTP ${status})`,
1523
+ { statusCode: status }
1524
+ );
1525
+ }
1526
+ if (status === 403) {
1527
+ return new ZapierAuthenticationError(
1528
+ `Access forbidden. Your token may not have the required scopes to list authentications. (HTTP ${status})`,
1529
+ { statusCode: status }
1530
+ );
1531
+ }
1532
+ return void 0;
1533
+ },
1534
+ authRequired: true
1535
+ }
1536
+ );
1537
+ let auths = (data.results || []).map(
1538
+ (auth) => normalizeAuthenticationItem(auth)
1539
+ );
1540
+ if (options.title) {
1541
+ auths = auths.filter((auth) => auth.title === options.title);
1542
+ }
1543
+ return {
1544
+ data: auths,
1545
+ nextCursor: extractCursor(data)
1546
+ };
1547
+ },
1548
+ ListAuthenticationsSchema
1549
+ );
1550
+ return {
1551
+ listAuthentications,
1552
+ context: {
1553
+ meta: {
1554
+ listAuthentications: {
1555
+ categories: ["authentication"],
1556
+ inputSchema: ListAuthenticationsSchema
1557
+ }
1558
+ }
1559
+ }
1560
+ };
1561
+ };
1562
+ var GetAppSchema = withOutputSchema(
1563
+ z.object({
1564
+ appKey: AppKeyPropertySchema.describe(
1565
+ "App key of app to fetch (e.g., 'SlackCLIAPI')"
1566
+ )
1567
+ }).describe("Get detailed information about a specific app"),
1568
+ AppItemSchema
1569
+ );
1570
+
1571
+ // src/plugins/getApp/index.ts
1572
+ var getAppPlugin = ({ context }) => {
1573
+ const getApp = createFunction(async function getApp2(options) {
1574
+ const app = await context.getImplementation(options.appKey);
1575
+ if (!app) {
1576
+ throw new ZapierAppNotFoundError("App not found", {
1577
+ appKey: options.appKey
1578
+ });
1579
+ }
1580
+ return {
1581
+ data: app
1582
+ };
1583
+ }, GetAppSchema);
1584
+ return {
1585
+ getApp,
1586
+ context: {
1587
+ meta: {
1588
+ getApp: {
1589
+ categories: ["app"],
1590
+ inputSchema: GetAppSchema
1591
+ }
1592
+ }
1593
+ }
1594
+ };
1595
+ };
1596
+ var GetActionSchema = z.object({
1597
+ appKey: AppKeyPropertySchema,
1598
+ actionType: ActionTypePropertySchema,
1599
+ actionKey: ActionKeyPropertySchema
1600
+ }).describe("Get detailed information about a specific action");
1601
+
1602
+ // src/plugins/getAction/index.ts
1603
+ var getActionPlugin = ({ sdk }) => {
1604
+ const getAction = createFunction(async function getAction2(options) {
1605
+ const { actionKey, actionType, appKey } = options;
1606
+ const actionsResult = await sdk.listActions({ appKey });
1607
+ for (const action of actionsResult.data) {
1608
+ if (action.key === actionKey && action.action_type === actionType) {
1609
+ return { data: action };
1610
+ }
1611
+ }
1612
+ throw new ZapierResourceNotFoundError(
1613
+ `Action not found: ${actionKey} with type ${actionType}`,
1614
+ { resourceType: "Action", resourceId: `${actionKey} (${actionType})` }
1615
+ );
1616
+ }, GetActionSchema);
1617
+ return {
1618
+ getAction,
1619
+ context: {
1620
+ meta: {
1621
+ getAction: {
1622
+ categories: ["action"],
1623
+ inputSchema: GetActionSchema
1624
+ }
1625
+ }
1626
+ }
1627
+ };
1628
+ };
1629
+ var GetAuthenticationSchema = z.object({
1630
+ authenticationId: z.number().int().positive().describe("Authentication ID to retrieve")
1631
+ }).describe("Get a specific authentication by ID");
1632
+
1633
+ // src/plugins/getAuthentication/index.ts
1634
+ var getAuthenticationPlugin = ({ context }) => {
1635
+ const getAuthentication = createFunction(async function getAuthentication2(options) {
1636
+ const { api } = context;
1637
+ const { authenticationId } = options;
1638
+ const data = await api.get(
1639
+ `/api/v4/authentications/${authenticationId}/`,
1640
+ {
1641
+ customErrorHandler: ({ status }) => {
1642
+ if (status === 401) {
1643
+ return new ZapierAuthenticationError(
1644
+ `Authentication failed. Your token may not have permission to access authentications or may be expired. (HTTP ${status})`,
1645
+ { statusCode: status }
1646
+ );
1647
+ }
1648
+ if (status === 403) {
1649
+ return new ZapierAuthenticationError(
1650
+ `Access forbidden. Your token may not have the required scopes to get authentication ${authenticationId}. (HTTP ${status})`,
1651
+ { statusCode: status }
1652
+ );
1653
+ }
1654
+ if (status === 404) {
1655
+ return new ZapierResourceNotFoundError(
1656
+ `Authentication ${authenticationId} not found. It may not exist or you may not have access to it. (HTTP ${status})`,
1657
+ {
1658
+ resourceType: "Authentication",
1659
+ resourceId: String(authenticationId)
1660
+ }
1661
+ );
1662
+ }
1663
+ return void 0;
1664
+ },
1665
+ authRequired: true
1666
+ }
1667
+ );
1668
+ return {
1669
+ data: normalizeAuthenticationItem(data)
1670
+ };
1671
+ }, GetAuthenticationSchema);
1672
+ return {
1673
+ getAuthentication,
1674
+ context: {
1675
+ meta: {
1676
+ getAuthentication: {
1677
+ categories: ["authentication"],
1678
+ inputSchema: GetAuthenticationSchema
1679
+ }
1680
+ }
1681
+ }
1682
+ };
1683
+ };
1684
+ var FindFirstAuthenticationSchema = z.object({
1685
+ appKey: AppKeyPropertySchema.optional().describe(
1686
+ "App key of authentication to find (e.g., 'SlackCLIAPI')"
1687
+ ),
1688
+ search: z.string().optional().describe("Search term to filter authentications by title"),
1689
+ title: z.string().optional().describe("Filter authentications by exact title match"),
1690
+ accountId: z.string().optional().describe("Filter by account ID"),
1691
+ owner: z.string().optional().describe("Filter by owner")
1692
+ }).describe("Find the first authentication matching the criteria");
1693
+
1694
+ // src/plugins/findFirstAuthentication/index.ts
1695
+ var findFirstAuthenticationPlugin = ({ sdk }) => {
1696
+ const findFirstAuthentication = createFunction(
1697
+ async function findFirstAuthentication2(options = {}) {
1698
+ const authsResponse = await sdk.listAuthentications({
1699
+ ...options,
1700
+ maxItems: 1
1701
+ });
1702
+ return {
1703
+ data: authsResponse.data.length > 0 ? authsResponse.data[0] : null
1704
+ };
1705
+ },
1706
+ FindFirstAuthenticationSchema
1707
+ );
1708
+ return {
1709
+ findFirstAuthentication,
1710
+ context: {
1711
+ meta: {
1712
+ findFirstAuthentication: {
1713
+ categories: ["authentication"],
1714
+ inputSchema: FindFirstAuthenticationSchema
1715
+ }
1716
+ }
1717
+ }
1718
+ };
1719
+ };
1720
+ var FindUniqueAuthenticationSchema = z.object({
1721
+ appKey: AppKeyPropertySchema.optional().describe(
1722
+ "App key of authentication to find (e.g., 'SlackCLIAPI')"
1723
+ ),
1724
+ search: z.string().optional().describe("Search term to filter authentications by title"),
1725
+ title: z.string().optional().describe("Filter authentications by exact title match"),
1726
+ accountId: z.string().optional().describe("Filter by account ID"),
1727
+ owner: z.string().optional().describe("Filter by owner")
1728
+ }).describe("Find a unique authentication matching the criteria");
1729
+
1730
+ // src/plugins/findUniqueAuthentication/index.ts
1731
+ var findUniqueAuthenticationPlugin = ({ sdk }) => {
1732
+ const findUniqueAuthentication = createFunction(
1733
+ async function findUniqueAuthentication2(options = {}) {
1734
+ const authsResponse = await sdk.listAuthentications({
1735
+ ...options,
1736
+ maxItems: 2
1737
+ // Get up to 2 to check for uniqueness
1738
+ });
1739
+ if (authsResponse.data.length === 0) {
1740
+ throw new ZapierResourceNotFoundError(
1741
+ "No authentication found matching the specified criteria",
1742
+ { resourceType: "Authentication" }
1743
+ );
1744
+ }
1745
+ if (authsResponse.data.length > 1) {
1746
+ throw new ZapierValidationError(
1747
+ "Multiple authentications found matching the specified criteria. Expected exactly one."
1748
+ );
1749
+ }
1750
+ return {
1751
+ data: authsResponse.data[0]
1752
+ };
1753
+ },
1754
+ FindUniqueAuthenticationSchema
1755
+ );
1756
+ return {
1757
+ findUniqueAuthentication,
1758
+ context: {
1759
+ meta: {
1760
+ findUniqueAuthentication: {
1761
+ categories: ["authentication"],
1762
+ inputSchema: FindUniqueAuthenticationSchema
1763
+ }
1764
+ }
1765
+ }
1766
+ };
1767
+ };
1768
+ var RunActionSchema = z.object({
1769
+ appKey: AppKeyPropertySchema,
1770
+ actionType: ActionTypePropertySchema,
1771
+ actionKey: ActionKeyPropertySchema,
1772
+ authenticationId: AuthenticationIdPropertySchema.nullable().optional(),
1773
+ inputs: InputsPropertySchema.optional().describe(
1774
+ "Input parameters for the action"
1775
+ ),
1776
+ pageSize: z.number().min(1).optional().describe("Number of results per page"),
1777
+ maxItems: z.number().min(1).optional().describe("Maximum total items to return across all pages")
1778
+ }).describe("Execute an action with the given inputs");
1779
+
1780
+ // src/plugins/runAction/index.ts
1781
+ async function executeAction(actionOptions) {
1782
+ const {
1783
+ api,
1784
+ context,
1785
+ appKey,
1786
+ actionKey,
1787
+ actionType,
1788
+ executionOptions,
1789
+ authenticationId
1790
+ } = actionOptions;
1791
+ const selectedApi = await context.getVersionedImplementationId(appKey);
1792
+ if (!selectedApi) {
1793
+ throw new ZapierConfigurationError(
1794
+ "No current_implementation_id found for app",
1795
+ { configType: "current_implementation_id" }
1796
+ );
1797
+ }
1798
+ const runRequestData = {
1799
+ selected_api: selectedApi,
1800
+ action_key: actionKey,
1801
+ action_type: actionType,
1802
+ inputs: executionOptions.inputs || {}
1803
+ };
1804
+ if (authenticationId !== null && authenticationId !== void 0) {
1805
+ runRequestData.authentication_id = authenticationId;
1806
+ }
1807
+ const runRequest = {
1808
+ data: runRequestData
1809
+ };
1810
+ const runData = await api.post(
1811
+ "/api/actions/v1/runs",
1812
+ runRequest
1813
+ );
1814
+ const runId = runData.data.id;
1815
+ return await api.poll(`/api/actions/v1/runs/${runId}`, {
1816
+ successStatus: 200,
1817
+ pendingStatus: 202,
1818
+ resultExtractor: (result) => result.data
1819
+ });
1820
+ }
1821
+ var runActionPlugin = ({ sdk, context }) => {
1822
+ const runAction = createPaginatedFunction(async function runActionPage(options) {
1823
+ const { api } = context;
1824
+ const {
1825
+ appKey,
1826
+ actionKey,
1827
+ actionType,
1828
+ authenticationId,
1829
+ inputs = {}
1830
+ } = options;
1831
+ const actionData = await sdk.getAction({
1832
+ appKey,
1833
+ actionKey,
1834
+ actionType
1835
+ });
1836
+ if (actionData.data.action_type !== actionType) {
1837
+ throw new ZapierValidationError(
1838
+ `Action type mismatch: expected ${actionType}, got ${actionData.data.action_type}`
1839
+ );
1840
+ }
1841
+ const result = await executeAction({
1842
+ api,
1843
+ context,
1844
+ appKey,
1845
+ actionKey,
1846
+ actionType,
1847
+ executionOptions: { inputs },
1848
+ authenticationId});
1849
+ if (result.errors && result.errors.length > 0) {
1850
+ const errorMessage = result.errors.map(
1851
+ (error) => error.detail || error.title || "Unknown error"
1852
+ ).join("; ");
1853
+ throw new ZapierActionError(`Action execution failed: ${errorMessage}`, {
1854
+ appKey,
1855
+ actionKey
1672
1856
  });
1673
- return {
1674
- title: item.full_name,
1675
- subtitle: `@${item.username}`,
1676
- details
1677
- };
1678
1857
  }
1679
- }
1680
- );
1681
-
1682
- // src/plugins/getProfile/schemas.ts
1683
- var GetProfileSchema = withOutputSchema(
1684
- z.object({}).optional().describe("Get current user's profile information"),
1685
- UserProfileItemSchema
1686
- );
1687
-
1688
- // src/plugins/getProfile/index.ts
1689
- var getProfilePlugin = ({ context }) => {
1690
- const getProfile = createFunction(async function getProfile2() {
1691
- const profile = await context.api.get("/api/v4/profile/", {
1692
- authRequired: true
1693
- });
1694
- const { user_id: _unusedUserId, ...data } = profile;
1695
1858
  return {
1696
- data: {
1697
- ...data,
1698
- // Pass through all API response fields
1699
- full_name: `${profile.first_name} ${profile.last_name}`
1700
- // Computed field
1701
- }
1859
+ data: result.results || [],
1860
+ nextCursor: void 0
1861
+ // No pagination implemented yet
1702
1862
  };
1703
- }, GetProfileSchema);
1863
+ }, RunActionSchema);
1704
1864
  return {
1705
- getProfile,
1865
+ runAction,
1706
1866
  context: {
1707
1867
  meta: {
1708
- getProfile: {
1709
- categories: ["user"],
1710
- inputSchema: GetProfileSchema
1868
+ runAction: {
1869
+ categories: ["action"],
1870
+ inputSchema: RunActionSchema
1711
1871
  }
1712
1872
  }
1713
1873
  }
1714
1874
  };
1715
1875
  };
1716
- var AppItemSchema = withFormatter(
1717
- z.object({
1718
- // Essential properties only
1719
- title: z.string(),
1720
- // Mapped from name
1721
- key: z.string(),
1722
- // Mapped from selected_api
1723
- current_implementation_id: z.string(),
1724
- // From id, keeps the full version
1725
- version: z.string().optional(),
1726
- // Extracted from implementation ID
1727
- description: z.string().optional(),
1728
- slug: z.string().optional()
1729
- }),
1730
- {
1731
- format: (item) => {
1732
- return {
1733
- title: item.title,
1734
- subtitle: `(${item.key})`,
1735
- details: []
1736
- };
1737
- }
1738
- }
1739
- );
1740
-
1741
- // src/plugins/listApps/schemas.ts
1742
- var ListAppsSchema = withOutputSchema(
1743
- z.object({
1744
- appKeys: z.array(z.string()).optional().describe(
1745
- "Filter apps by app keys (e.g., 'SlackCLIAPI' or slug like 'github')"
1746
- ),
1747
- search: z.string().optional().describe("Search for apps by name"),
1748
- pageSize: z.number().min(1).optional().describe("Number of apps per page"),
1749
- maxItems: z.number().min(1).optional().describe("Maximum total items to return across all pages")
1750
- }).describe("List all available apps with optional filtering"),
1751
- AppItemSchema
1752
- );
1876
+ var RelayRequestSchema = z.object({
1877
+ url: z.string().url().describe("The URL to request (will be proxied through Relay)"),
1878
+ method: z.enum(["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]).optional().describe("HTTP method"),
1879
+ body: z.any().optional().describe("Request body as a string"),
1880
+ authenticationId: z.number().int().optional().describe("Zapier authentication ID to use for the request"),
1881
+ callbackUrl: z.string().url().optional().describe("URL to send async response to (makes request async)"),
1882
+ authenticationTemplate: z.string().optional().describe(
1883
+ "Optional JSON string authentication template to bypass Notary lookup"
1884
+ ),
1885
+ headers: z.union([
1886
+ z.record(z.string()),
1887
+ z.instanceof(Headers),
1888
+ z.array(z.tuple([z.string(), z.string()]))
1889
+ ]).optional().describe("Request headers")
1890
+ }).extend({
1891
+ relayBaseUrl: z.string().optional().describe("Base URL for Relay service")
1892
+ }).describe("Make authenticated HTTP requests through Zapier's Relay service");
1893
+ var RelayFetchSchema = RelayRequestSchema;
1753
1894
 
1754
- // src/utils/domain-utils.ts
1755
- function splitVersionedKey(versionedKey) {
1756
- const parts = versionedKey.split("@");
1757
- if (parts.length >= 2) {
1758
- const baseKey = parts[0];
1759
- const version = parts.slice(1).join("@");
1760
- return [baseKey, version];
1761
- }
1762
- return [versionedKey, void 0];
1763
- }
1764
- function normalizeImplementationToAppItem(implementation) {
1765
- const [selectedApi, appVersion] = implementation.selected_api ? splitVersionedKey(implementation.selected_api) : [implementation.selected_api || "", void 0];
1766
- return {
1767
- title: implementation.name || selectedApi,
1768
- key: selectedApi,
1769
- current_implementation_id: implementation.selected_api || "",
1770
- version: appVersion
1771
- // Extract version separately
1772
- };
1773
- }
1774
- function normalizeImplementationMetaToAppItem(implementationMeta) {
1775
- const [selectedApi, appVersion] = splitVersionedKey(implementationMeta.id);
1776
- return {
1777
- title: implementationMeta.name,
1778
- key: selectedApi,
1779
- current_implementation_id: implementationMeta.id,
1780
- // Keep the full versioned ID
1781
- version: appVersion,
1782
- // Extract version separately
1783
- slug: implementationMeta.slug
1784
- };
1895
+ // src/plugins/request/index.ts
1896
+ function transformUrlToRelayPath(url) {
1897
+ const targetUrl = new URL(url);
1898
+ const relayPath = `/relay/${targetUrl.host}${targetUrl.pathname}${targetUrl.search}${targetUrl.hash}`;
1899
+ return relayPath;
1785
1900
  }
1786
- function normalizeAuthenticationItem(auth, options = {}) {
1787
- let appKey = options.app_key;
1788
- let version = options.version;
1789
- if (auth.selected_api) {
1790
- const [extractedAppKey, extractedVersion] = splitVersionedKey(
1791
- auth.selected_api
1792
- );
1793
- if (!appKey) {
1794
- appKey = extractedAppKey;
1901
+ var requestPlugin = ({ context }) => {
1902
+ const request = createFunction(async function request2(options) {
1903
+ const { api } = context;
1904
+ const {
1905
+ url,
1906
+ method = "GET",
1907
+ body,
1908
+ headers: optionsHeaders,
1909
+ authenticationId,
1910
+ callbackUrl,
1911
+ authenticationTemplate
1912
+ } = options;
1913
+ const relayPath = transformUrlToRelayPath(url);
1914
+ const headers = {};
1915
+ if (optionsHeaders) {
1916
+ const headerEntries = optionsHeaders instanceof Headers ? Array.from(optionsHeaders.entries()) : Array.isArray(optionsHeaders) ? optionsHeaders : Object.entries(optionsHeaders);
1917
+ for (const [key, value] of headerEntries) {
1918
+ headers[key] = value;
1919
+ }
1795
1920
  }
1796
- if (!version) {
1797
- version = extractedVersion;
1921
+ if (authenticationId) {
1922
+ headers["X-Relay-Authentication-Id"] = authenticationId.toString();
1798
1923
  }
1799
- }
1800
- const {
1801
- selected_api: selectedApi,
1802
- customuser_id: userId,
1803
- ...restOfAuth
1804
- } = auth;
1805
- return {
1806
- ...restOfAuth,
1807
- // Pass through all other API response fields except selected_api
1808
- implementation_id: selectedApi,
1809
- // Rename selected_api to implementation_id
1810
- title: auth.title || auth.label || void 0,
1811
- // Coerce title from label if missing
1812
- is_expired: auth.is_stale,
1813
- // Map is_stale to is_expired
1814
- expired_at: auth.marked_stale_at,
1815
- // Map marked_stale_at to expired_at
1816
- app_key: appKey,
1817
- // App key from implementations endpoint or parsed from selected_api
1818
- version,
1819
- // Version from selected_api or provided
1820
- user_id: userId
1821
- // Map customuser_id to user_id
1822
- };
1823
- }
1824
- function normalizeActionItem(action) {
1825
- const { name, type, selected_api: appKey, ...restOfAction } = action;
1826
- return {
1827
- ...restOfAction,
1828
- app_key: appKey || "",
1829
- action_type: type,
1830
- title: name,
1831
- // Map name to title
1832
- type: "action"
1833
- };
1834
- }
1835
- function groupVersionedAppKeysByType(appKeys) {
1836
- const result = {
1837
- selectedApi: [],
1838
- slug: []
1839
- };
1840
- const seenSelectedApi = /* @__PURE__ */ new Set();
1841
- const seenSlugs = /* @__PURE__ */ new Set();
1842
- for (const key of appKeys) {
1843
- const [keyWithoutVersion, version] = splitVersionedKey(key);
1844
- const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
1845
- if (uuidRegex.test(keyWithoutVersion)) {
1846
- throw new Error(
1847
- `UUID app keys are not supported. Use app slug or implementation ID instead of: ${key}`
1848
- );
1924
+ if (callbackUrl) {
1925
+ headers["X-Relay-Callback-Url"] = callbackUrl;
1849
1926
  }
1850
- if (isSnakeCasedSlug(keyWithoutVersion)) {
1851
- const dashified = dashifySnakeCasedSlug(keyWithoutVersion);
1852
- const slugWithVersion = version ? `${dashified}@${version}` : dashified;
1853
- if (!seenSlugs.has(slugWithVersion)) {
1854
- seenSlugs.add(slugWithVersion);
1855
- result.slug.push(slugWithVersion);
1927
+ if (authenticationTemplate) {
1928
+ headers["X-Authentication-Template"] = authenticationTemplate;
1929
+ }
1930
+ return await api.fetch(relayPath, {
1931
+ method,
1932
+ body,
1933
+ headers
1934
+ });
1935
+ }, RelayRequestSchema);
1936
+ return {
1937
+ request,
1938
+ context: {
1939
+ meta: {
1940
+ request: {
1941
+ categories: ["http"],
1942
+ inputSchema: RelayRequestSchema
1943
+ }
1856
1944
  }
1857
- continue;
1858
- }
1859
- if (keyWithoutVersion.match(/^[a-z0-9]+(?:-[a-z0-9]+)*$/)) {
1860
- seenSlugs.add(key);
1861
- result.slug.push(key);
1862
- continue;
1863
1945
  }
1864
- if (!seenSelectedApi.has(key)) {
1865
- seenSelectedApi.add(key);
1866
- result.selectedApi.push(key);
1946
+ };
1947
+ };
1948
+ var ManifestSchema = z.object({
1949
+ apps: z.record(
1950
+ z.string(),
1951
+ z.object({
1952
+ implementationName: z.string().describe(
1953
+ "Base implementation name without version (e.g., 'SlackCLIAPI')"
1954
+ ),
1955
+ version: z.string().describe("Version string (e.g., '1.21.1')")
1956
+ })
1957
+ )
1958
+ }).describe("Manifest mapping app keys to version information");
1959
+ z.object({
1960
+ manifestPath: z.string().optional().describe("Path to manifest file"),
1961
+ manifest: z.record(
1962
+ z.string(),
1963
+ z.object({
1964
+ implementationName: z.string(),
1965
+ version: z.string().optional()
1966
+ })
1967
+ ).optional().describe("Direct manifest object")
1968
+ });
1969
+
1970
+ // src/plugins/manifest/index.ts
1971
+ function parseManifestContent(content, source) {
1972
+ try {
1973
+ const parsed = JSON.parse(content);
1974
+ if (parsed?.apps && typeof parsed?.apps === "object") {
1975
+ const result = ManifestSchema.safeParse(parsed);
1976
+ if (result.success) {
1977
+ return result.data;
1978
+ }
1979
+ console.warn(`\u26A0\uFE0F Invalid manifest format in ${source}: ${result.error}`);
1867
1980
  }
1981
+ return null;
1982
+ } catch (error) {
1983
+ console.warn(`\u26A0\uFE0F Failed to parse manifest from ${source}:`, error);
1984
+ return null;
1868
1985
  }
1869
- return result;
1870
- }
1871
- function groupAppKeysByType(appKeys) {
1872
- const grouped = groupVersionedAppKeysByType(appKeys);
1873
- return {
1874
- selectedApi: [
1875
- ...new Set(grouped.selectedApi.map((key) => key.split("@")[0]))
1876
- ],
1877
- slug: [...new Set(grouped.slug.map((key) => key.split("@")[0]))]
1878
- };
1879
1986
  }
1880
- function isSnakeCasedSlug(slug) {
1881
- if (slug.match(/^_[0-9]/)) {
1882
- slug = slug.slice(1);
1987
+ function loadManifestFromFile(filePath) {
1988
+ try {
1989
+ const resolvedPath = resolve(filePath);
1990
+ const content = readFileSync(resolvedPath, "utf8");
1991
+ return parseManifestContent(content, resolvedPath);
1992
+ } catch {
1993
+ console.warn(`\u26A0\uFE0F Failed to load manifest from ${filePath}`);
1994
+ return null;
1883
1995
  }
1884
- return !!slug.match(/^[a-z0-9]+(?:_[a-z0-9]+)*$/);
1885
1996
  }
1886
- function dashifySnakeCasedSlug(slug) {
1887
- if (!isSnakeCasedSlug(slug)) {
1888
- return slug;
1889
- }
1890
- if (slug.startsWith("_")) {
1891
- slug = slug.slice(1);
1997
+ var emitWarning = (appKey) => {
1998
+ console.warn(
1999
+ `
2000
+ ${"\u26A0\uFE0F".padEnd(3)} ${"WARNING".padEnd(8)} No manifest version found for '${appKey}'`
2001
+ );
2002
+ console.warn(
2003
+ ` ${"\u21B3".padEnd(3)} Using a manifest ensures version locking and prevents unexpected behavior due to version changes.`
2004
+ );
2005
+ console.warn(
2006
+ ` ${"\u21B3".padEnd(3)} Generate/update the manifest with: \`zapier-sdk lock-version ${appKey}\`
2007
+ `
2008
+ );
2009
+ };
2010
+ var manifestPlugin = (params) => {
2011
+ const { sdk, context } = params;
2012
+ const { api, options } = context;
2013
+ const { manifestPath = ".zapierrc", manifest } = options || {};
2014
+ let resolvedManifest;
2015
+ function resolveManifest() {
2016
+ if (manifest) {
2017
+ return manifest;
2018
+ }
2019
+ if (manifestPath) {
2020
+ return loadManifestFromFile(manifestPath);
2021
+ }
2022
+ return null;
1892
2023
  }
1893
- return slug.replace(/_/g, "-");
1894
- }
1895
-
1896
- // src/plugins/listApps/index.ts
1897
- var listAppsPlugin = ({ context }) => {
1898
- const listApps = createPaginatedFunction(async function listAppsPage(options) {
1899
- const api = context.api;
1900
- const opts = options;
1901
- const appKeys = [...opts.appKeys ?? []].map(
1902
- (key) => splitVersionedKey(key)[0]
1903
- );
1904
- if (opts.search) {
1905
- const searchParams2 = {};
1906
- searchParams2.term = opts.search;
1907
- const searchEnvelope = await api.get(
1908
- "/api/v4/implementations-meta/search/",
2024
+ const getResolvedManifest = () => {
2025
+ if (typeof resolvedManifest === "undefined") {
2026
+ resolvedManifest = resolveManifest() ?? null;
2027
+ }
2028
+ return resolvedManifest;
2029
+ };
2030
+ const getManifestEntry = (appKey) => {
2031
+ return getResolvedManifest()?.apps?.[appKey] || null;
2032
+ };
2033
+ const getImplementation = async (appKey) => {
2034
+ let selectedApi = null;
2035
+ const manifestImplementation = getResolvedManifest()?.apps?.[appKey];
2036
+ const [versionlessAppKey, version] = splitVersionedKey(appKey);
2037
+ if (version) {
2038
+ selectedApi = `${versionlessAppKey}@${version}`;
2039
+ } else if (manifestImplementation) {
2040
+ selectedApi = `${manifestImplementation.implementationName}@${manifestImplementation.version || "latest"}`;
2041
+ }
2042
+ if (selectedApi) {
2043
+ const searchParams = {
2044
+ selected_apis: selectedApi
2045
+ };
2046
+ const implementationData = await api.get(
2047
+ "/api/v4/implementations/",
1909
2048
  {
1910
- searchParams: searchParams2
2049
+ searchParams
1911
2050
  }
1912
2051
  );
1913
- const implementations = searchEnvelope.results.map(
1914
- normalizeImplementationMetaToAppItem
1915
- );
1916
- const appKeysSet = new Set(appKeys);
1917
- for (const implementation of implementations) {
1918
- if (!appKeysSet.has(implementation.key)) {
1919
- appKeysSet.add(implementation.key);
1920
- appKeys.push(implementation.key);
1921
- }
1922
- }
2052
+ const implementationResults = implementationData.results[0];
2053
+ if (!implementationResults) return null;
2054
+ return normalizeImplementationToAppItem(implementationResults);
1923
2055
  }
1924
- const searchParams = {};
1925
- if (opts.pageSize) {
1926
- searchParams.limit = opts.pageSize.toString();
2056
+ emitWarning(appKey);
2057
+ const appsIterator = sdk.listApps({ appKeys: [appKey] }).items();
2058
+ const apps = [];
2059
+ for await (const app2 of appsIterator) {
2060
+ apps.push(app2);
2061
+ break;
1927
2062
  }
1928
- searchParams.latest_only = "true";
1929
- if (opts.cursor) {
1930
- searchParams.offset = opts.cursor;
2063
+ if (apps.length === 0) {
2064
+ return null;
1931
2065
  }
1932
- if (appKeys.length > 0) {
1933
- const groupedAppKeys = groupAppKeysByType(appKeys);
1934
- if (groupedAppKeys.selectedApi.length > 0) {
1935
- searchParams.selected_apis = groupedAppKeys.selectedApi.join(",");
1936
- }
1937
- if (groupedAppKeys.slug.length > 0) {
1938
- searchParams.slugs = groupedAppKeys.slug.join(",");
1939
- }
2066
+ const app = apps[0];
2067
+ return app;
2068
+ };
2069
+ const getVersionedImplementationId = async (appKey) => {
2070
+ const manifestEntry = getManifestEntry(appKey);
2071
+ if (manifestEntry) {
2072
+ return `${manifestEntry.implementationName}@${manifestEntry.version || "latest"}`;
1940
2073
  }
1941
- const implementationsEnvelope = await api.get(
1942
- "/api/v4/implementations-meta/lookup/",
1943
- {
1944
- searchParams
1945
- }
1946
- );
1947
- return {
1948
- data: implementationsEnvelope.results.map(
1949
- normalizeImplementationMetaToAppItem
1950
- ),
1951
- nextCursor: extractCursor(implementationsEnvelope)
1952
- };
1953
- }, ListAppsSchema);
2074
+ const implementation = await getImplementation(appKey);
2075
+ if (!implementation) return null;
2076
+ return implementation.current_implementation_id;
2077
+ };
1954
2078
  return {
1955
- listApps,
1956
2079
  context: {
1957
- meta: {
1958
- listApps: {
1959
- categories: ["app"],
1960
- inputSchema: ListAppsSchema
1961
- }
1962
- }
2080
+ getVersionedImplementationId,
2081
+ getManifestEntry,
2082
+ getImplementation
1963
2083
  }
1964
2084
  };
1965
2085
  };
1966
- var GetAppSchema = withOutputSchema(
1967
- z.object({
1968
- appKey: AppKeyPropertySchema.describe(
1969
- "App key of app to fetch (e.g., 'SlackCLIAPI')"
1970
- )
1971
- }).describe("Get detailed information about a specific app"),
1972
- AppItemSchema
1973
- );
1974
-
1975
- // src/plugins/getApp/index.ts
1976
- var getAppPlugin = ({ context }) => {
1977
- const getApp = createFunction(async function getApp2(options) {
1978
- const app = await context.getImplementation(options.appKey);
1979
- if (!app) {
1980
- throw new ZapierAppNotFoundError("App not found", {
1981
- appKey: options.appKey
1982
- });
1983
- }
1984
- return {
1985
- data: app
1986
- };
1987
- }, GetAppSchema);
2086
+ var LockVersionSchema = z.object({
2087
+ appKey: z.string().describe("The app key to lock version for (e.g., 'slack', 'gmail')")
2088
+ });
2089
+ var lockVersionPlugin = ({ sdk }) => {
2090
+ const lockVersion = createFunction(
2091
+ async function lockVersion2(options) {
2092
+ const { appKey, configPath = ".zapierrc" } = options;
2093
+ const resolvedPath = resolve(configPath);
2094
+ const appsIterator = sdk.listApps({ appKeys: [appKey] }).items();
2095
+ const apps = [];
2096
+ for await (const app2 of appsIterator) {
2097
+ apps.push(app2);
2098
+ break;
2099
+ }
2100
+ const app = apps[0];
2101
+ const currentImplementationId = app.current_implementation_id;
2102
+ const [implementationName, version] = currentImplementationId.split("@");
2103
+ if (!implementationName || !version) {
2104
+ throw new Error(
2105
+ `Invalid implementation ID format: ${currentImplementationId}. Expected format: <implementationName>@<version>`
2106
+ );
2107
+ }
2108
+ let config = { apps: {} };
2109
+ if (existsSync(resolvedPath)) {
2110
+ try {
2111
+ const configContent = readFileSync(resolvedPath, "utf8");
2112
+ config = JSON.parse(configContent);
2113
+ if (!config.apps) {
2114
+ config.apps = {};
2115
+ }
2116
+ } catch (error) {
2117
+ console.warn(
2118
+ `\u26A0\uFE0F Failed to parse existing config file, creating new one: ${error}`
2119
+ );
2120
+ config = { apps: {} };
2121
+ }
2122
+ }
2123
+ config.apps[appKey] = {
2124
+ implementationName,
2125
+ version
2126
+ };
2127
+ writeFileSync(resolvedPath, JSON.stringify(config, null, 2));
2128
+ return {
2129
+ data: {
2130
+ ...app,
2131
+ implementationName,
2132
+ version
2133
+ },
2134
+ configPath: resolvedPath
2135
+ };
2136
+ },
2137
+ LockVersionSchema.extend({
2138
+ configPath: z.string().optional().describe("Path to .zapierrc file (defaults to '.zapierrc')")
2139
+ })
2140
+ );
1988
2141
  return {
1989
- getApp,
2142
+ lockVersion,
1990
2143
  context: {
1991
2144
  meta: {
1992
- getApp: {
1993
- categories: ["app"],
1994
- inputSchema: GetAppSchema
2145
+ lockVersion: {
2146
+ categories: ["utility"],
2147
+ inputSchema: LockVersionSchema
1995
2148
  }
1996
2149
  }
1997
2150
  }
1998
2151
  };
1999
2152
  };
2000
- var ActionItemSchema = withFormatter(
2001
- ActionSchema.omit({ type: true, name: true }).extend({
2002
- app_key: z.string(),
2003
- // Mapped from selected_api
2004
- action_type: ActionSchema.shape.type,
2005
- // Mapped from original 'type' field
2006
- title: z.string(),
2007
- // Mapped from original 'name' field
2008
- type: z.literal("action")
2009
- // Fixed type identifier
2153
+ var UserProfileItemSchema = withFormatter(
2154
+ UserProfileSchema.omit({ user_id: true }).extend({
2155
+ full_name: z.string()
2156
+ // Computed field: first_name + " " + last_name
2010
2157
  }),
2011
2158
  {
2012
2159
  format: (item) => {
2013
2160
  const details = [];
2014
- details.push({
2015
- text: `Type: ${item.action_type}`,
2016
- style: "accent"
2017
- });
2018
- if (item.app_key) {
2161
+ details.push({ text: item.email, style: "dim" });
2162
+ if (item.timezone) {
2019
2163
  details.push({
2020
- text: `App: ${item.app_key}`,
2021
- style: "normal"
2164
+ text: `Timezone: ${item.timezone}`,
2165
+ style: "accent"
2022
2166
  });
2023
2167
  }
2024
- if (item.description) {
2025
- details.push({ text: item.description, style: "dim" });
2026
- }
2168
+ details.push({
2169
+ text: `Member since: ${item.since_signup}`,
2170
+ style: "dim"
2171
+ });
2027
2172
  return {
2028
- title: item.title || item.name || item.key,
2029
- subtitle: `(${item.key})`,
2173
+ title: item.full_name,
2174
+ subtitle: `@${item.username}`,
2030
2175
  details
2031
2176
  };
2032
2177
  }
2033
2178
  }
2034
2179
  );
2035
2180
 
2036
- // src/plugins/listActions/schemas.ts
2037
- var ListActionsSchema = withOutputSchema(
2038
- z.object({
2039
- appKey: AppKeyPropertySchema.describe(
2040
- "App key of actions to list (e.g., 'SlackCLIAPI')"
2041
- ),
2042
- actionType: ActionTypePropertySchema.optional().describe(
2043
- "Filter actions by type"
2044
- ),
2045
- pageSize: z.number().min(1).optional().describe("Number of actions per page"),
2046
- maxItems: z.number().min(1).optional().describe("Maximum total items to return across all pages")
2047
- }).describe("List all actions for a specific app"),
2048
- ActionItemSchema
2181
+ // src/plugins/getProfile/schemas.ts
2182
+ var GetProfileSchema = withOutputSchema(
2183
+ z.object({}).optional().describe("Get current user's profile information"),
2184
+ UserProfileItemSchema
2049
2185
  );
2050
2186
 
2051
- // src/plugins/listActions/index.ts
2052
- var listActionsPlugin = ({ context }) => {
2053
- const listActions = createPaginatedFunction(async function listActionsPage(options) {
2054
- const { api, getVersionedImplementationId } = context;
2055
- const selectedApi = await getVersionedImplementationId(options.appKey);
2056
- if (!selectedApi) {
2057
- throw new ZapierConfigurationError(
2058
- "No current_implementation_id found for app",
2059
- { configType: "current_implementation_id" }
2060
- );
2061
- }
2062
- const searchParams = {
2063
- global: "true",
2064
- public_only: "true",
2065
- selected_apis: selectedApi
2066
- };
2067
- const data = await api.get(
2068
- "/api/v4/implementations/",
2069
- {
2070
- searchParams,
2071
- customErrorHandler: ({ status }) => {
2072
- if (status === 401) {
2073
- return new ZapierAuthenticationError(
2074
- `Authentication failed. Your token may not have permission to access implementations or may be expired. (HTTP ${status})`,
2075
- { statusCode: status }
2076
- );
2077
- }
2078
- if (status === 403) {
2079
- return new ZapierAuthenticationError(
2080
- `Access forbidden. Your token may not have the required scopes to list implementations. (HTTP ${status})`,
2081
- { statusCode: status }
2082
- );
2083
- }
2084
- return void 0;
2085
- }
2086
- }
2087
- );
2088
- let allActions = [];
2089
- for (const implementation of data.results || []) {
2090
- if (implementation.actions) {
2091
- for (const action of implementation.actions) {
2092
- const actionWithContext = {
2093
- ...action,
2094
- selected_api: action.selected_api || implementation.selected_api
2095
- };
2096
- allActions.push(normalizeActionItem(actionWithContext));
2097
- }
2098
- }
2099
- }
2100
- if (options.actionType) {
2101
- allActions = allActions.filter(
2102
- (action) => action.action_type === options.actionType
2103
- );
2104
- }
2187
+ // src/plugins/getProfile/index.ts
2188
+ var getProfilePlugin = ({ context }) => {
2189
+ const getProfile = createFunction(async function getProfile2() {
2190
+ const profile = await context.api.get("/api/v4/profile/", {
2191
+ authRequired: true
2192
+ });
2193
+ const { user_id: _unusedUserId, ...data } = profile;
2105
2194
  return {
2106
- data: allActions,
2107
- nextCursor: void 0
2195
+ data: {
2196
+ ...data,
2197
+ // Pass through all API response fields
2198
+ full_name: `${profile.first_name} ${profile.last_name}`
2199
+ // Computed field
2200
+ }
2108
2201
  };
2109
- }, ListActionsSchema);
2202
+ }, GetProfileSchema);
2110
2203
  return {
2111
- listActions,
2204
+ getProfile,
2112
2205
  context: {
2113
2206
  meta: {
2114
- listActions: {
2115
- categories: ["action"],
2116
- inputSchema: ListActionsSchema
2207
+ getProfile: {
2208
+ categories: ["account"],
2209
+ inputSchema: GetProfileSchema
2210
+ }
2211
+ }
2212
+ }
2213
+ };
2214
+ };
2215
+
2216
+ // src/api/auth.ts
2217
+ function isJwt(token) {
2218
+ const parts = token.split(".");
2219
+ if (parts.length !== 3) {
2220
+ return false;
2221
+ }
2222
+ const base64UrlPattern = /^[A-Za-z0-9_-]+$/;
2223
+ return parts.every((part) => part.length > 0 && base64UrlPattern.test(part));
2224
+ }
2225
+ function getAuthorizationHeader(token) {
2226
+ if (isJwt(token)) {
2227
+ return `JWT ${token}`;
2228
+ }
2229
+ return `Bearer ${token}`;
2230
+ }
2231
+
2232
+ // src/api/debug.ts
2233
+ function createDebugLogger(enabled) {
2234
+ if (!enabled) {
2235
+ return () => {
2236
+ };
2237
+ }
2238
+ return (message, data) => {
2239
+ console.log(`[Zapier SDK] ${message}`, data || "");
2240
+ };
2241
+ }
2242
+ function createDebugFetch(options) {
2243
+ const { originalFetch, debugLog } = options;
2244
+ return async (input, options2) => {
2245
+ const startTime = Date.now();
2246
+ const url = typeof input === "string" ? input : input.toString();
2247
+ const method = options2?.method || "GET";
2248
+ debugLog(`\u2192 ${method} ${url}`, {
2249
+ headers: options2?.headers,
2250
+ body: options2?.body && typeof options2.body === "string" ? (() => {
2251
+ try {
2252
+ return JSON.parse(options2.body);
2253
+ } catch {
2254
+ return options2.body;
2117
2255
  }
2256
+ })() : options2?.body
2257
+ });
2258
+ try {
2259
+ const response = await originalFetch(input, options2);
2260
+ const duration = Date.now() - startTime;
2261
+ debugLog(`\u2190 ${response.status} ${response.statusText} (${duration}ms)`, {
2262
+ url,
2263
+ method,
2264
+ status: response.status
2265
+ });
2266
+ return response;
2267
+ } catch (error) {
2268
+ const duration = Date.now() - startTime;
2269
+ debugLog(`\u2716 Request failed (${duration}ms)`, {
2270
+ url,
2271
+ method,
2272
+ error: error instanceof Error ? error.message : error
2273
+ });
2274
+ throw error;
2275
+ }
2276
+ };
2277
+ }
2278
+
2279
+ // src/api/polling.ts
2280
+ async function pollUntilComplete(options) {
2281
+ const {
2282
+ fetchPoll,
2283
+ maxAttempts = 30,
2284
+ initialDelay = 50,
2285
+ maxDelay = 1e3,
2286
+ successStatus = 200,
2287
+ pendingStatus = 202,
2288
+ resultExtractor = (response) => response
2289
+ } = options;
2290
+ let delay = initialDelay;
2291
+ let errorCount = 0;
2292
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
2293
+ const response = await fetchPoll();
2294
+ if (response.status === successStatus) {
2295
+ errorCount = 0;
2296
+ const result = await response.json();
2297
+ return resultExtractor(result);
2298
+ } else if (response.status === pendingStatus) {
2299
+ errorCount = 0;
2300
+ if (attempt < maxAttempts - 1) {
2301
+ await new Promise((resolve3) => setTimeout(resolve3, delay));
2302
+ delay = Math.min(delay * 2, maxDelay);
2303
+ continue;
2118
2304
  }
2119
- }
2120
- };
2121
- };
2122
- var GetActionSchema = z.object({
2123
- appKey: AppKeyPropertySchema,
2124
- actionType: ActionTypePropertySchema,
2125
- actionKey: ActionKeyPropertySchema
2126
- }).describe("Get detailed information about a specific action");
2127
-
2128
- // src/plugins/getAction/index.ts
2129
- var getActionPlugin = ({ sdk }) => {
2130
- const getAction = createFunction(async function getAction2(options) {
2131
- const { actionKey, actionType, appKey } = options;
2132
- const actionsResult = await sdk.listActions({ appKey });
2133
- for (const action of actionsResult.data) {
2134
- if (action.key === actionKey && action.action_type === actionType) {
2135
- return { data: action };
2305
+ } else {
2306
+ errorCount++;
2307
+ if (errorCount >= 3) {
2308
+ throw new ZapierApiError(
2309
+ `Poll request failed: ${response.status} ${response.statusText}`,
2310
+ { statusCode: response.status }
2311
+ );
2136
2312
  }
2137
- }
2138
- throw new ZapierResourceNotFoundError(
2139
- `Action not found: ${actionKey} with type ${actionType}`,
2140
- { resourceType: "Action", resourceId: `${actionKey} (${actionType})` }
2141
- );
2142
- }, GetActionSchema);
2143
- return {
2144
- getAction,
2145
- context: {
2146
- meta: {
2147
- getAction: {
2148
- categories: ["action"],
2149
- inputSchema: GetActionSchema
2150
- }
2313
+ if (attempt < maxAttempts - 1) {
2314
+ await new Promise((resolve3) => setTimeout(resolve3, delay));
2315
+ delay = Math.min(delay * 2, maxDelay);
2316
+ continue;
2151
2317
  }
2152
2318
  }
2153
- };
2154
- };
2155
- var RunActionSchema = z.object({
2156
- appKey: AppKeyPropertySchema,
2157
- actionType: ActionTypePropertySchema,
2158
- actionKey: ActionKeyPropertySchema,
2159
- authenticationId: AuthenticationIdPropertySchema.nullable().optional(),
2160
- inputs: InputsPropertySchema.optional().describe(
2161
- "Input parameters for the action"
2162
- ),
2163
- pageSize: z.number().min(1).optional().describe("Number of results per page"),
2164
- maxItems: z.number().min(1).optional().describe("Maximum total items to return across all pages")
2165
- }).describe("Execute an action with the given inputs");
2319
+ }
2320
+ throw new ZapierTimeoutError(
2321
+ `Operation timed out after ${maxAttempts} attempts`,
2322
+ { attempts: maxAttempts, maxAttempts }
2323
+ );
2324
+ }
2166
2325
 
2167
- // src/plugins/runAction/index.ts
2168
- async function executeAction(actionOptions) {
2169
- const {
2170
- api,
2171
- context,
2172
- appKey,
2173
- actionKey,
2174
- actionType,
2175
- executionOptions,
2176
- authenticationId
2177
- } = actionOptions;
2178
- const selectedApi = await context.getVersionedImplementationId(appKey);
2179
- if (!selectedApi) {
2180
- throw new ZapierConfigurationError(
2181
- "No current_implementation_id found for app",
2182
- { configType: "current_implementation_id" }
2183
- );
2326
+ // src/auth.ts
2327
+ function getTokenFromEnv() {
2328
+ return process.env.ZAPIER_TOKEN;
2329
+ }
2330
+ async function getTokenFromCliLogin(options = {}) {
2331
+ try {
2332
+ const { getToken } = await import('@zapier/zapier-sdk-cli-login');
2333
+ return await getToken(options);
2334
+ } catch {
2335
+ return void 0;
2184
2336
  }
2185
- const runRequestData = {
2186
- selected_api: selectedApi,
2187
- action_key: actionKey,
2188
- action_type: actionType,
2189
- inputs: executionOptions.inputs || {}
2190
- };
2191
- if (authenticationId !== null && authenticationId !== void 0) {
2192
- runRequestData.authentication_id = authenticationId;
2337
+ }
2338
+ async function getTokenFromEnvOrConfig(options = {}) {
2339
+ const envToken = getTokenFromEnv();
2340
+ if (envToken) {
2341
+ return envToken;
2193
2342
  }
2194
- const runRequest = {
2195
- data: runRequestData
2196
- };
2197
- const runData = await api.post(
2198
- "/api/actions/v1/runs",
2199
- runRequest
2200
- );
2201
- const runId = runData.data.id;
2202
- return await api.poll(`/api/actions/v1/runs/${runId}`, {
2203
- successStatus: 200,
2204
- pendingStatus: 202,
2205
- resultExtractor: (result) => result.data
2206
- });
2343
+ return getTokenFromCliLogin(options);
2207
2344
  }
2208
- var runActionPlugin = ({ sdk, context }) => {
2209
- const runAction = createPaginatedFunction(async function runActionPage(options) {
2210
- const { api } = context;
2211
- const {
2212
- appKey,
2213
- actionKey,
2214
- actionType,
2215
- authenticationId,
2216
- inputs = {}
2217
- } = options;
2218
- const actionData = await sdk.getAction({
2219
- appKey,
2220
- actionKey,
2221
- actionType
2222
- });
2223
- if (actionData.data.action_type !== actionType) {
2224
- throw new ZapierValidationError(
2225
- `Action type mismatch: expected ${actionType}, got ${actionData.data.action_type}`
2226
- );
2227
- }
2228
- const result = await executeAction({
2229
- api,
2230
- context,
2231
- appKey,
2232
- actionKey,
2233
- actionType,
2234
- executionOptions: { inputs },
2235
- authenticationId});
2236
- if (result.errors && result.errors.length > 0) {
2237
- const errorMessage = result.errors.map(
2238
- (error) => error.detail || error.title || "Unknown error"
2239
- ).join("; ");
2240
- throw new ZapierActionError(`Action execution failed: ${errorMessage}`, {
2241
- appKey,
2242
- actionKey
2345
+
2346
+ // src/api/client.ts
2347
+ var SubdomainConfigMap = {
2348
+ // e.g. https://relay.zapier.com
2349
+ relay: {
2350
+ authHeader: "X-Relay-Authorization"
2351
+ }
2352
+ };
2353
+ var ZapierApiClient = class {
2354
+ constructor(options) {
2355
+ this.options = options;
2356
+ this.fetch = async (path, init) => {
2357
+ return this.plainFetch(path, init);
2358
+ };
2359
+ this.get = async (path, options = {}) => {
2360
+ return this.fetchJson("GET", path, void 0, options);
2361
+ };
2362
+ this.post = async (path, data, options = {}) => {
2363
+ return this.fetchJson("POST", path, data, options);
2364
+ };
2365
+ this.put = async (path, data, options = {}) => {
2366
+ return this.fetchJson("PUT", path, data, options);
2367
+ };
2368
+ this.delete = async (path, options = {}) => {
2369
+ return this.fetchJson("DELETE", path, void 0, options);
2370
+ };
2371
+ this.poll = async (path, options = {}) => {
2372
+ return pollUntilComplete({
2373
+ fetchPoll: () => this.plainFetch(path, {
2374
+ method: "GET",
2375
+ searchParams: options.searchParams,
2376
+ authRequired: options.authRequired
2377
+ }),
2378
+ maxAttempts: options.maxAttempts,
2379
+ initialDelay: options.initialDelay,
2380
+ maxDelay: options.maxDelay,
2381
+ successStatus: options.successStatus,
2382
+ pendingStatus: options.pendingStatus,
2383
+ resultExtractor: options.resultExtractor
2243
2384
  });
2385
+ };
2386
+ }
2387
+ // Helper to parse response data
2388
+ async parseResult(response) {
2389
+ try {
2390
+ return { type: "json", data: await response.json() };
2391
+ } catch {
2392
+ return { type: "text", data: await response.text() };
2244
2393
  }
2245
- return {
2246
- data: result.results || [],
2247
- nextCursor: void 0
2248
- // No pagination implemented yet
2394
+ }
2395
+ // Helper to get a token from the different places it could be gotten
2396
+ async getAuthToken() {
2397
+ if (this.options.token) {
2398
+ return this.options.token;
2399
+ }
2400
+ if (this.options.getToken) {
2401
+ const token = await this.options.getToken();
2402
+ if (token) {
2403
+ return token;
2404
+ }
2405
+ }
2406
+ return getTokenFromEnvOrConfig({
2407
+ onEvent: this.options.onEvent,
2408
+ fetch: this.options.fetch
2409
+ });
2410
+ }
2411
+ // Helper to handle responses
2412
+ async handleResponse(params) {
2413
+ const { response, customErrorHandler, wasMissingAuthToken } = params;
2414
+ const { data: responseData } = await this.parseResult(response);
2415
+ if (response.ok) {
2416
+ return responseData;
2417
+ }
2418
+ const errorInfo = {
2419
+ status: response.status,
2420
+ statusText: response.statusText,
2421
+ data: responseData
2249
2422
  };
2250
- }, RunActionSchema);
2251
- return {
2252
- runAction,
2253
- context: {
2254
- meta: {
2255
- runAction: {
2256
- categories: ["action"],
2257
- inputSchema: RunActionSchema
2423
+ if (customErrorHandler) {
2424
+ const customError = customErrorHandler(errorInfo);
2425
+ if (customError) {
2426
+ if (customError instanceof Error) {
2427
+ throw customError;
2428
+ } else {
2429
+ throw new Error(
2430
+ `customErrorHandler returned a non-Error: ${JSON.stringify(customError)}`
2431
+ );
2258
2432
  }
2259
2433
  }
2260
2434
  }
2261
- };
2262
- };
2263
- var ListAuthenticationsSchema = z.object({
2264
- appKey: AppKeyPropertySchema.optional().describe(
2265
- "App key of authentications to list (e.g., 'SlackCLIAPI')"
2266
- ),
2267
- search: z.string().optional().describe("Search term to filter authentications by title"),
2268
- title: z.string().optional().describe("Filter authentications by exact title match"),
2269
- account_id: z.string().optional().describe("Filter by account ID"),
2270
- owner: z.string().optional().describe("Filter by owner"),
2271
- pageSize: z.number().min(1).optional().describe("Number of authentications per page"),
2272
- maxItems: z.number().min(1).optional().describe("Maximum total items to return across all pages")
2273
- }).describe("List available authentications with optional filtering");
2274
-
2275
- // src/plugins/listAuthentications/index.ts
2276
- var listAuthenticationsPlugin = ({ context }) => {
2277
- const listAuthentications = createPaginatedFunction(
2278
- async function listAuthenticationsPage(options) {
2279
- const { api, getVersionedImplementationId } = context;
2280
- const searchParams = {};
2281
- if (options.appKey) {
2282
- const implementationId = await getVersionedImplementationId(
2283
- options.appKey
2435
+ const { message, errors } = this.parseErrorResponse(errorInfo);
2436
+ const errorOptions = {
2437
+ statusCode: response.status,
2438
+ errors
2439
+ };
2440
+ if (response.status === 404) {
2441
+ throw new ZapierNotFoundError(message, errorOptions);
2442
+ }
2443
+ if (response.status === 401 || response.status === 403) {
2444
+ if (wasMissingAuthToken) {
2445
+ throw new ZapierAuthenticationError(
2446
+ `Authentication required (HTTP ${response.status}). Please provide a token in options or set ZAPIER_TOKEN environment variable.`,
2447
+ errorOptions
2284
2448
  );
2285
- if (implementationId) {
2286
- const [versionlessSelectedApi] = splitVersionedKey(implementationId);
2287
- searchParams.versionless_selected_api = versionlessSelectedApi;
2288
- }
2289
2449
  }
2290
- if (options.search) {
2291
- searchParams.search = options.search;
2292
- } else if (options.title) {
2293
- searchParams.search = options.title;
2450
+ throw new ZapierAuthenticationError(message, errorOptions);
2451
+ }
2452
+ if (response.status === 400) {
2453
+ throw new ZapierValidationError(message, errorOptions);
2454
+ }
2455
+ throw new ZapierApiError(message, errorOptions);
2456
+ }
2457
+ hasErrorArray(data) {
2458
+ return typeof data === "object" && data !== null && "errors" in data && Array.isArray(data.errors);
2459
+ }
2460
+ // Helper to check if data has API errors
2461
+ isApiErrorArray(dataArray) {
2462
+ const data = dataArray[0];
2463
+ return typeof data === "object" && data !== null && "message" in data && "code" in data && "title" in data && "detail" in data;
2464
+ }
2465
+ // Do our best to extract an error message from the response data
2466
+ extractErrorMessage(data) {
2467
+ if (typeof data === "string") {
2468
+ return data;
2469
+ }
2470
+ if (typeof data === "object" && data !== null) {
2471
+ if ("message" in data && typeof data.message === "string") {
2472
+ return data.message;
2294
2473
  }
2295
- if (options.account_id) {
2296
- searchParams.account_id = options.account_id;
2474
+ if ("error" in data) {
2475
+ if (typeof data.error === "string") {
2476
+ return data.error;
2477
+ }
2478
+ if (typeof data.error === "object" && data.error !== null) {
2479
+ if ("message" in data.error && typeof data.error.message === "string") {
2480
+ return data.error.message;
2481
+ }
2482
+ }
2483
+ try {
2484
+ return JSON.stringify(data.error);
2485
+ } catch {
2486
+ }
2297
2487
  }
2298
- if (options.owner) {
2299
- searchParams.owner = options.owner;
2488
+ if ("errors" in data && Array.isArray(data.errors)) {
2489
+ if (this.isApiErrorArray(data.errors)) {
2490
+ return data.errors[0].detail || data.errors[0].title;
2491
+ }
2300
2492
  }
2301
- searchParams.limit = options.pageSize.toString();
2302
- if (options.cursor) {
2303
- searchParams.offset = options.cursor;
2493
+ }
2494
+ return void 0;
2495
+ }
2496
+ // Helper to parse API error response
2497
+ parseErrorResponse(errorInfo) {
2498
+ const fallbackMessage = `HTTP ${errorInfo.status}: ${errorInfo.statusText}`;
2499
+ try {
2500
+ if (typeof errorInfo.data === "string") {
2501
+ return { message: `${fallbackMessage}: ${errorInfo.data}` };
2304
2502
  }
2305
- console.log({ searchParams });
2306
- const data = await api.get(
2307
- "/api/v4/authentications/",
2308
- {
2309
- searchParams,
2310
- customErrorHandler: ({ status }) => {
2311
- if (status === 401) {
2312
- return new ZapierAuthenticationError(
2313
- `Authentication failed. Your token may not have permission to access authentications or may be expired. (HTTP ${status})`,
2314
- { statusCode: status }
2315
- );
2316
- }
2317
- if (status === 403) {
2318
- return new ZapierAuthenticationError(
2319
- `Access forbidden. Your token may not have the required scopes to list authentications. (HTTP ${status})`,
2320
- { statusCode: status }
2321
- );
2322
- }
2323
- return void 0;
2324
- },
2325
- authRequired: true
2503
+ const errorMessage = this.extractErrorMessage(errorInfo.data) || fallbackMessage;
2504
+ if (this.hasErrorArray(errorInfo.data)) {
2505
+ if (this.isApiErrorArray(errorInfo.data.errors)) {
2506
+ return {
2507
+ message: errorMessage,
2508
+ errors: errorInfo.data.errors
2509
+ };
2510
+ } else {
2511
+ return {
2512
+ message: errorMessage,
2513
+ errors: errorInfo.data.errors.map((e) => ({
2514
+ status: errorInfo.status,
2515
+ code: String(errorInfo.status),
2516
+ title: errorInfo.statusText,
2517
+ detail: JSON.stringify(e)
2518
+ }))
2519
+ };
2326
2520
  }
2327
- );
2328
- let auths = (data.results || []).map(
2329
- (auth) => normalizeAuthenticationItem(auth)
2330
- );
2331
- if (options.title) {
2332
- auths = auths.filter((auth) => auth.title === options.title);
2333
2521
  }
2334
- return {
2335
- data: auths,
2336
- nextCursor: extractCursor(data)
2337
- };
2338
- },
2339
- ListAuthenticationsSchema
2340
- );
2341
- return {
2342
- listAuthentications,
2343
- context: {
2344
- meta: {
2345
- listAuthentications: {
2346
- categories: ["authentication"],
2347
- inputSchema: ListAuthenticationsSchema
2348
- }
2522
+ return { message: errorMessage };
2523
+ } catch {
2524
+ return { message: fallbackMessage };
2525
+ }
2526
+ }
2527
+ // Check if this is a path that needs subdomain routing
2528
+ // e.g. /relay/workflows -> relay.zapier.com/workflows
2529
+ applySubdomainBehavior(path) {
2530
+ const pathSegments = path.split("/").filter(Boolean);
2531
+ if (pathSegments.length > 0 && pathSegments[0] in SubdomainConfigMap) {
2532
+ const domainPrefix = pathSegments[0];
2533
+ const subdomainConfig = SubdomainConfigMap[domainPrefix];
2534
+ const originalBaseUrl = new URL(this.options.baseUrl);
2535
+ const finalBaseUrl = `https://${domainPrefix}.${originalBaseUrl.hostname}`;
2536
+ const pathWithoutPrefix = "/" + pathSegments.slice(1).join("/");
2537
+ return { url: new URL(pathWithoutPrefix, finalBaseUrl), subdomainConfig };
2538
+ }
2539
+ return {
2540
+ url: new URL(path, this.options.baseUrl),
2541
+ subdomainConfig: void 0
2542
+ };
2543
+ }
2544
+ // Helper to build full URLs and return routing info
2545
+ buildUrl(path, searchParams) {
2546
+ const { url, subdomainConfig } = this.applySubdomainBehavior(path);
2547
+ if (searchParams) {
2548
+ Object.entries(searchParams).forEach(([key, value]) => {
2549
+ url.searchParams.set(key, value);
2550
+ });
2551
+ }
2552
+ return { url: url.toString(), subdomainConfig };
2553
+ }
2554
+ // Helper to build headers
2555
+ async buildHeaders(options = {}, subdomainConfig) {
2556
+ const headers = new Headers(options.headers ?? {});
2557
+ const authToken = await this.getAuthToken();
2558
+ if (authToken) {
2559
+ const authHeaderName = subdomainConfig?.authHeader || "Authorization";
2560
+ headers.set(authHeaderName, getAuthorizationHeader(authToken));
2561
+ }
2562
+ if (options.authRequired) {
2563
+ if (headers.get("Authorization") == null && authToken == null) {
2564
+ throw new ZapierAuthenticationError(
2565
+ `Authentication required but no token available. Please set ZAPIER_TOKEN, or run the 'login' command with the CLI.`
2566
+ );
2349
2567
  }
2350
2568
  }
2351
- };
2569
+ return headers;
2570
+ }
2571
+ // Helper to perform HTTP requests with JSON handling
2572
+ async fetchJson(method, path, data, options = {}) {
2573
+ const headers = { ...options.headers };
2574
+ if (data && typeof data === "object") {
2575
+ headers["Content-Type"] = "application/json";
2576
+ }
2577
+ const wasMissingAuthToken = options.authRequired && await this.getAuthToken() == null;
2578
+ const response = await this.plainFetch(path, {
2579
+ ...options,
2580
+ method,
2581
+ body: data != null ? JSON.stringify(data) : void 0,
2582
+ headers
2583
+ });
2584
+ const result = await this.handleResponse({
2585
+ response,
2586
+ customErrorHandler: options.customErrorHandler,
2587
+ wasMissingAuthToken
2588
+ });
2589
+ if (typeof result === "string") {
2590
+ throw new ZapierValidationError(
2591
+ `Response could not be parsed as JSON: ${result}`
2592
+ );
2593
+ }
2594
+ return result;
2595
+ }
2596
+ // Plain fetch method for API paths (must start with /)
2597
+ async plainFetch(path, fetchOptions) {
2598
+ if (!path.startsWith("/")) {
2599
+ throw new ZapierValidationError(
2600
+ `plainFetch expects a path starting with '/', got: ${path}`
2601
+ );
2602
+ }
2603
+ if (fetchOptions?.body && typeof fetchOptions.body === "object") {
2604
+ fetchOptions.body = JSON.stringify(fetchOptions.body);
2605
+ }
2606
+ const { url, subdomainConfig } = this.buildUrl(
2607
+ path,
2608
+ fetchOptions?.searchParams
2609
+ );
2610
+ const builtHeaders = await this.buildHeaders(
2611
+ fetchOptions,
2612
+ subdomainConfig
2613
+ );
2614
+ const inputHeaders = new Headers(fetchOptions?.headers ?? {});
2615
+ const mergedHeaders = new Headers();
2616
+ builtHeaders.forEach((value, key) => {
2617
+ mergedHeaders.set(key, value);
2618
+ });
2619
+ inputHeaders.forEach((value, key) => {
2620
+ mergedHeaders.set(key, value);
2621
+ });
2622
+ return await this.options.fetch(url, {
2623
+ ...fetchOptions,
2624
+ headers: mergedHeaders
2625
+ });
2626
+ }
2627
+ };
2628
+ var createZapierApi = (options) => {
2629
+ const {
2630
+ baseUrl,
2631
+ token,
2632
+ getToken,
2633
+ debug = false,
2634
+ fetch: originalFetch = globalThis.fetch,
2635
+ onEvent
2636
+ } = options;
2637
+ const debugLog = createDebugLogger(debug);
2638
+ const debugFetch = createDebugFetch({ originalFetch, debugLog });
2639
+ return new ZapierApiClient({
2640
+ baseUrl,
2641
+ token,
2642
+ getToken,
2643
+ debug,
2644
+ fetch: debugFetch,
2645
+ onEvent
2646
+ });
2352
2647
  };
2353
- var GetAuthenticationSchema = z.object({
2354
- authenticationId: z.number().int().positive().describe("Authentication ID to retrieve")
2355
- }).describe("Get a specific authentication by ID");
2356
2648
 
2357
- // src/plugins/getAuthentication/index.ts
2358
- var getAuthenticationPlugin = ({ context }) => {
2359
- const getAuthentication = createFunction(async function getAuthentication2(options) {
2360
- const { api } = context;
2361
- const { authenticationId } = options;
2362
- const data = await api.get(
2363
- `/api/v4/authentications/${authenticationId}/`,
2364
- {
2365
- customErrorHandler: ({ status }) => {
2366
- if (status === 401) {
2367
- return new ZapierAuthenticationError(
2368
- `Authentication failed. Your token may not have permission to access authentications or may be expired. (HTTP ${status})`,
2369
- { statusCode: status }
2370
- );
2371
- }
2372
- if (status === 403) {
2373
- return new ZapierAuthenticationError(
2374
- `Access forbidden. Your token may not have the required scopes to get authentication ${authenticationId}. (HTTP ${status})`,
2375
- { statusCode: status }
2376
- );
2377
- }
2378
- if (status === 404) {
2379
- return new ZapierResourceNotFoundError(
2380
- `Authentication ${authenticationId} not found. It may not exist or you may not have access to it. (HTTP ${status})`,
2381
- {
2382
- resourceType: "Authentication",
2383
- resourceId: String(authenticationId)
2384
- }
2385
- );
2386
- }
2387
- return void 0;
2388
- },
2389
- authRequired: true
2390
- }
2391
- );
2392
- return {
2393
- data: normalizeAuthenticationItem(data)
2394
- };
2395
- }, GetAuthenticationSchema);
2649
+ // src/plugins/api/index.ts
2650
+ var apiPlugin = (params) => {
2651
+ const {
2652
+ fetch: customFetch = globalThis.fetch,
2653
+ baseUrl = "https://zapier.com",
2654
+ token,
2655
+ getToken,
2656
+ onEvent,
2657
+ debug = false
2658
+ } = params.context.options;
2659
+ const api = createZapierApi({
2660
+ baseUrl,
2661
+ token,
2662
+ getToken,
2663
+ debug,
2664
+ fetch: customFetch,
2665
+ onEvent
2666
+ });
2396
2667
  return {
2397
- getAuthentication,
2398
2668
  context: {
2399
- meta: {
2400
- getAuthentication: {
2401
- categories: ["authentication"],
2402
- inputSchema: GetAuthenticationSchema
2403
- }
2404
- }
2669
+ api
2670
+ // Provide API client in context for other plugins to use
2405
2671
  }
2406
2672
  };
2407
2673
  };
2408
- var FindFirstAuthenticationSchema = z.object({
2409
- appKey: AppKeyPropertySchema.optional().describe(
2410
- "App key of authentication to find (e.g., 'SlackCLIAPI')"
2411
- ),
2412
- search: z.string().optional().describe("Search term to filter authentications by title"),
2413
- title: z.string().optional().describe("Filter authentications by exact title match"),
2414
- account_id: z.string().optional().describe("Filter by account ID"),
2415
- owner: z.string().optional().describe("Filter by owner")
2416
- }).describe("Find the first authentication matching the criteria");
2417
2674
 
2418
- // src/plugins/findFirstAuthentication/index.ts
2419
- var findFirstAuthenticationPlugin = ({ sdk }) => {
2420
- const findFirstAuthentication = createFunction(
2421
- async function findFirstAuthentication2(options = {}) {
2422
- const authsResponse = await sdk.listAuthentications({
2423
- ...options,
2424
- maxItems: 1
2425
- });
2426
- return {
2427
- data: authsResponse.data.length > 0 ? authsResponse.data[0] : null
2428
- };
2429
- },
2430
- FindFirstAuthenticationSchema
2431
- );
2432
- return {
2433
- findFirstAuthentication,
2434
- context: {
2435
- meta: {
2436
- findFirstAuthentication: {
2437
- categories: ["authentication"],
2438
- inputSchema: FindFirstAuthenticationSchema
2439
- }
2440
- }
2441
- }
2442
- };
2675
+ // src/resolvers/appKey.ts
2676
+ var appKeyResolver = {
2677
+ type: "static",
2678
+ inputType: "text",
2679
+ placeholder: "Enter app key (e.g., 'SlackCLIAPI' or slug like 'github')"
2443
2680
  };
2444
- var FindUniqueAuthenticationSchema = z.object({
2445
- appKey: AppKeyPropertySchema.optional().describe(
2446
- "App key of authentication to find (e.g., 'SlackCLIAPI')"
2447
- ),
2448
- search: z.string().optional().describe("Search term to filter authentications by title"),
2449
- title: z.string().optional().describe("Filter authentications by exact title match"),
2450
- account_id: z.string().optional().describe("Filter by account ID"),
2451
- owner: z.string().optional().describe("Filter by owner")
2452
- }).describe("Find a unique authentication matching the criteria");
2453
2681
 
2454
- // src/plugins/findUniqueAuthentication/index.ts
2455
- var findUniqueAuthenticationPlugin = ({ sdk }) => {
2456
- const findUniqueAuthentication = createFunction(
2457
- async function findUniqueAuthentication2(options = {}) {
2458
- const authsResponse = await sdk.listAuthentications({
2459
- ...options,
2460
- maxItems: 2
2461
- // Get up to 2 to check for uniqueness
2462
- });
2463
- if (authsResponse.data.length === 0) {
2464
- throw new ZapierResourceNotFoundError(
2465
- "No authentication found matching the specified criteria",
2466
- { resourceType: "Authentication" }
2467
- );
2468
- }
2469
- if (authsResponse.data.length > 1) {
2470
- throw new ZapierValidationError(
2471
- "Multiple authentications found matching the specified criteria. Expected exactly one."
2472
- );
2473
- }
2474
- return {
2475
- data: authsResponse.data[0]
2476
- };
2477
- },
2478
- FindUniqueAuthenticationSchema
2479
- );
2480
- return {
2481
- findUniqueAuthentication,
2482
- context: {
2483
- meta: {
2484
- findUniqueAuthentication: {
2485
- categories: ["authentication"],
2486
- inputSchema: FindUniqueAuthenticationSchema
2487
- }
2682
+ // src/resolvers/actionType.ts
2683
+ var actionTypeResolver = {
2684
+ type: "dynamic",
2685
+ depends: ["appKey"],
2686
+ fetch: async (sdk, resolvedParams) => {
2687
+ const actionsResponse = await sdk.listActions({
2688
+ appKey: resolvedParams.appKey
2689
+ });
2690
+ const types = [
2691
+ ...new Set(actionsResponse.data.map((action) => action.action_type))
2692
+ ];
2693
+ return types.map((type) => ({ key: type, name: type }));
2694
+ },
2695
+ prompt: (types) => ({
2696
+ type: "list",
2697
+ name: "actionType",
2698
+ message: "Select action type:",
2699
+ choices: types.map((type) => ({
2700
+ name: type.name,
2701
+ value: type.key
2702
+ }))
2703
+ })
2704
+ };
2705
+
2706
+ // src/resolvers/actionKey.ts
2707
+ var actionKeyResolver = {
2708
+ type: "dynamic",
2709
+ depends: ["appKey", "actionType"],
2710
+ fetch: async (sdk, resolvedParams) => {
2711
+ const actionsResponse = await sdk.listActions({
2712
+ appKey: resolvedParams.appKey
2713
+ });
2714
+ return actionsResponse.data.filter(
2715
+ (action) => action.action_type === resolvedParams.actionType
2716
+ );
2717
+ },
2718
+ prompt: (actions) => ({
2719
+ type: "list",
2720
+ name: "actionKey",
2721
+ message: "Select action:",
2722
+ choices: actions.map((action) => ({
2723
+ name: `${action.title || action.name || action.key} - ${action.description || "No description"}`,
2724
+ value: action.key
2725
+ }))
2726
+ })
2727
+ };
2728
+
2729
+ // src/resolvers/authenticationId.ts
2730
+ var authenticationIdResolver = {
2731
+ type: "dynamic",
2732
+ depends: ["appKey"],
2733
+ fetch: async (sdk, resolvedParams) => {
2734
+ const myAuths = await sdk.listAuthentications({
2735
+ appKey: resolvedParams.appKey,
2736
+ maxItems: 1e3,
2737
+ owner: "me"
2738
+ });
2739
+ const allAuths = await sdk.listAuthentications({
2740
+ appKey: resolvedParams.appKey,
2741
+ maxItems: 1e3
2742
+ });
2743
+ const otherAuths = allAuths.data.filter(
2744
+ (auth) => !myAuths.data.some((myAuth) => myAuth.id === auth.id)
2745
+ );
2746
+ return [...myAuths.data, ...otherAuths];
2747
+ },
2748
+ prompt: (auths, params) => ({
2749
+ type: "list",
2750
+ name: "authenticationId",
2751
+ message: `Select authentication for ${params.appKey}:`,
2752
+ choices: [
2753
+ ...auths.map((auth) => ({
2754
+ name: `${auth.title || auth.label || "Authentication"} (ID: ${auth.id})`,
2755
+ value: auth.id
2756
+ })),
2757
+ {
2758
+ name: "\u2197 Skip authentication (may fail)",
2759
+ value: null
2488
2760
  }
2489
- }
2490
- };
2761
+ ]
2762
+ })
2491
2763
  };
2492
- var ListInputFieldsSchema = z.object({
2493
- appKey: AppKeyPropertySchema,
2494
- actionType: ActionTypePropertySchema,
2495
- actionKey: ActionKeyPropertySchema,
2496
- authenticationId: AuthenticationIdPropertySchema.nullable().optional(),
2497
- inputs: InputsPropertySchema.optional().describe(
2498
- "Current input values that may affect available fields"
2499
- ),
2500
- pageSize: z.number().min(1).optional().describe("Number of input fields per page"),
2501
- maxItems: z.number().min(1).optional().describe("Maximum total items to return across all pages")
2502
- }).describe("Get the input fields required for a specific action");
2503
2764
 
2504
- // src/plugins/listInputFields/index.ts
2505
- function getInputFieldTypeFromNeed(need) {
2506
- if (need.list) {
2507
- return "ARRAY" /* ARRAY */;
2765
+ // src/resolvers/inputs.ts
2766
+ var inputsResolver = {
2767
+ type: "fields",
2768
+ depends: ["appKey", "actionKey", "actionType", "authenticationId"],
2769
+ fetch: async (sdk, resolvedParams) => {
2770
+ const fieldsResponse = await sdk.listInputFields({
2771
+ appKey: resolvedParams.appKey,
2772
+ actionKey: resolvedParams.actionKey,
2773
+ actionType: resolvedParams.actionType,
2774
+ authenticationId: resolvedParams.authenticationId,
2775
+ inputs: resolvedParams.inputs
2776
+ // Pass along currently resolved inputs
2777
+ });
2778
+ return fieldsResponse.data;
2508
2779
  }
2509
- const typeMap = {
2510
- string: "STRING" /* STRING */,
2511
- decimal: "NUMBER" /* NUMBER */,
2512
- integer: "INTEGER" /* INTEGER */,
2513
- boolean: "BOOLEAN" /* BOOLEAN */,
2514
- dict: "OBJECT" /* OBJECT */
2515
- };
2516
- return typeMap[need.type || ""] || "STRING" /* STRING */;
2780
+ };
2781
+
2782
+ // src/resolvers/index.ts
2783
+ var resolverRegistry = {
2784
+ appKey: appKeyResolver,
2785
+ actionType: actionTypeResolver,
2786
+ actionKey: actionKeyResolver,
2787
+ authenticationId: authenticationIdResolver,
2788
+ inputs: inputsResolver
2789
+ };
2790
+ function getResolver(name) {
2791
+ return resolverRegistry[name];
2517
2792
  }
2518
- function getInputFieldFormatFromNeed(need) {
2519
- if (need.prefill || need.choices) {
2520
- return "SELECT" /* SELECT */;
2793
+ function getResolversForMissingParams(missingParams) {
2794
+ const resolvers = {};
2795
+ for (const param of missingParams) {
2796
+ const resolver = resolverRegistry[param];
2797
+ if (resolver) {
2798
+ resolvers[param] = resolver;
2799
+ }
2521
2800
  }
2522
- const formatMap = {
2523
- text: "MULTILINE" /* MULTILINE */,
2524
- datetime: "DATETIME" /* DATETIME */,
2525
- file: "FILE" /* FILE */,
2526
- password: "PASSWORD" /* PASSWORD */,
2527
- code: "CODE" /* CODE */
2528
- };
2529
- return formatMap[need.type || ""];
2801
+ return resolvers;
2530
2802
  }
2531
- function getItemsTypeFromNeed(need) {
2532
- if (!need.list) {
2533
- return void 0;
2534
- }
2535
- const typeMap = {
2536
- string: "STRING" /* STRING */,
2537
- decimal: "NUMBER" /* NUMBER */,
2538
- integer: "INTEGER" /* INTEGER */,
2539
- boolean: "BOOLEAN" /* BOOLEAN */,
2540
- dict: "OBJECT" /* OBJECT */
2541
- };
2542
- return typeMap[need.type || ""] || "STRING" /* STRING */;
2803
+ function hasResolver(paramName) {
2804
+ return paramName in resolverRegistry;
2543
2805
  }
2544
- function transformNeedToInputFieldItem(need) {
2545
- const itemsType = getItemsTypeFromNeed(need);
2546
- return {
2547
- ...need,
2548
- // Pass through all original Need fields
2549
- id: need.key,
2550
- default_value: need.default || "",
2551
- depends_on: need.depends_on || [],
2552
- description: need.help_text || "",
2553
- invalidates_input_fields: need.alters_custom_fields || false,
2554
- is_required: need.required || false,
2555
- placeholder: need.placeholder || "",
2556
- title: need.label || "",
2557
- value_type: getInputFieldTypeFromNeed(need),
2558
- format: getInputFieldFormatFromNeed(need),
2559
- items: itemsType ? { type: itemsType } : void 0
2560
- };
2806
+ function getResolvableParams() {
2807
+ return Object.keys(resolverRegistry);
2561
2808
  }
2562
- var listInputFieldsPlugin = ({ context }) => {
2563
- const listInputFields = createPaginatedFunction(
2564
- async function listInputFieldsPage(options) {
2565
- const { api, getVersionedImplementationId } = context;
2566
- const { appKey, actionKey, actionType, authenticationId, inputs } = options;
2567
- const selectedApi = await getVersionedImplementationId(appKey);
2568
- if (!selectedApi) {
2569
- throw new ZapierConfigurationError(
2570
- "No current_implementation_id found for app",
2571
- { configType: "current_implementation_id" }
2572
- );
2573
- }
2574
- const needsRequest = {
2575
- selected_api: selectedApi,
2576
- action: actionKey,
2577
- type_of: actionType,
2578
- params: inputs || {}
2579
- };
2580
- if (authenticationId !== null) {
2581
- needsRequest.authentication_id = authenticationId;
2582
- }
2583
- const needsData = await api.post(
2584
- "/api/v4/implementations/needs/",
2585
- needsRequest
2586
- );
2587
- if (!needsData.success) {
2588
- throw new ZapierApiError(
2589
- `Failed to get action fields: ${needsData.errors?.join(", ") || "Unknown error"}`
2590
- );
2591
- }
2592
- const inputFields = (needsData.needs || []).map(
2593
- transformNeedToInputFieldItem
2594
- );
2595
- return {
2596
- data: inputFields,
2597
- nextCursor: void 0
2598
- // No pagination needed since we return all input fields
2599
- };
2600
- },
2601
- ListInputFieldsSchema
2602
- );
2603
- return {
2604
- listInputFields,
2605
- context: {
2606
- meta: {
2607
- listInputFields: {
2608
- categories: ["action"],
2609
- inputSchema: ListInputFieldsSchema
2610
- }
2809
+ function getResolutionOrder(paramName, resolved = /* @__PURE__ */ new Set()) {
2810
+ const resolver = getResolver(paramName);
2811
+ if (!resolver || resolver.type === "static") {
2812
+ return [paramName];
2813
+ }
2814
+ const order = [];
2815
+ if ("depends" in resolver && resolver.depends) {
2816
+ for (const dependency of resolver.depends) {
2817
+ if (!resolved.has(dependency)) {
2818
+ order.push(...getResolutionOrder(dependency, resolved));
2819
+ resolved.add(dependency);
2611
2820
  }
2612
2821
  }
2613
- };
2614
- };
2615
-
2616
- // src/plugins/request/index.ts
2617
- function transformUrlToRelayPath(url) {
2618
- const targetUrl = new URL(url);
2619
- const relayPath = `/relay/${targetUrl.host}${targetUrl.pathname}${targetUrl.search}${targetUrl.hash}`;
2620
- return relayPath;
2822
+ }
2823
+ if (!resolved.has(paramName)) {
2824
+ order.push(paramName);
2825
+ resolved.add(paramName);
2826
+ }
2827
+ return order;
2621
2828
  }
2622
- var requestPlugin = ({ context }) => {
2623
- const request = createFunction(async function request2(options) {
2624
- const { api } = context;
2625
- const {
2626
- url,
2627
- method = "GET",
2628
- body,
2629
- headers: optionsHeaders,
2630
- authenticationId,
2631
- callbackUrl,
2632
- authenticationTemplate
2633
- } = options;
2634
- const relayPath = transformUrlToRelayPath(url);
2635
- const headers = {};
2636
- if (optionsHeaders) {
2637
- const headerEntries = optionsHeaders instanceof Headers ? Array.from(optionsHeaders.entries()) : Array.isArray(optionsHeaders) ? optionsHeaders : Object.entries(optionsHeaders);
2638
- for (const [key, value] of headerEntries) {
2639
- headers[key] = value;
2640
- }
2641
- }
2642
- if (authenticationId) {
2643
- headers["X-Relay-Authentication-Id"] = authenticationId.toString();
2644
- }
2645
- if (callbackUrl) {
2646
- headers["X-Relay-Callback-Url"] = callbackUrl;
2647
- }
2648
- if (authenticationTemplate) {
2649
- headers["X-Authentication-Template"] = authenticationTemplate;
2650
- }
2651
- return await api.fetch(relayPath, {
2652
- method,
2653
- body,
2654
- headers
2655
- });
2656
- }, RelayRequestSchema);
2657
- return {
2658
- request,
2659
- context: {
2660
- meta: {
2661
- request: {
2662
- categories: ["http"],
2663
- inputSchema: RelayRequestSchema
2664
- }
2665
- }
2666
- }
2667
- };
2668
- };
2669
- var ManifestSchema = z.object({
2670
- apps: z.record(
2671
- z.string(),
2672
- z.object({
2673
- implementationName: z.string().describe(
2674
- "Base implementation name without version (e.g., 'SlackCLIAPI')"
2675
- ),
2676
- version: z.string().describe("Version string (e.g., '1.21.1')")
2677
- })
2678
- )
2679
- }).describe("Manifest mapping app keys to version information");
2680
- z.object({
2681
- manifestPath: z.string().optional().describe("Path to manifest file"),
2682
- manifest: z.record(
2683
- z.string(),
2684
- z.object({
2685
- implementationName: z.string(),
2686
- version: z.string().optional()
2687
- })
2688
- ).optional().describe("Direct manifest object")
2689
- });
2690
-
2691
- // src/plugins/manifest/index.ts
2692
- function parseManifestContent(content, source) {
2693
- try {
2694
- const parsed = JSON.parse(content);
2695
- if (parsed?.apps && typeof parsed?.apps === "object") {
2696
- const result = ManifestSchema.safeParse(parsed);
2697
- if (result.success) {
2698
- return result.data;
2829
+ function getResolutionOrderForParams(paramNames) {
2830
+ const resolved = /* @__PURE__ */ new Set();
2831
+ const order = [];
2832
+ for (const paramName of paramNames) {
2833
+ const paramOrder = getResolutionOrder(paramName, resolved);
2834
+ for (const param of paramOrder) {
2835
+ if (!order.includes(param)) {
2836
+ order.push(param);
2699
2837
  }
2700
- console.warn(`\u26A0\uFE0F Invalid manifest format in ${source}: ${result.error}`);
2701
2838
  }
2702
- return null;
2703
- } catch (error) {
2704
- console.warn(`\u26A0\uFE0F Failed to parse manifest from ${source}:`, error);
2705
- return null;
2706
2839
  }
2840
+ return order;
2707
2841
  }
2708
- function loadManifestFromFile(filePath) {
2709
- try {
2710
- const resolvedPath = resolve(filePath);
2711
- const content = readFileSync(resolvedPath, "utf8");
2712
- return parseManifestContent(content, resolvedPath);
2713
- } catch {
2714
- console.warn(`\u26A0\uFE0F Failed to load manifest from ${filePath}`);
2715
- return null;
2842
+
2843
+ // src/plugins/registry/index.ts
2844
+ var registryPlugin = ({ sdk, context }) => {
2845
+ const metaKeys = Object.keys(context.meta || {});
2846
+ const categoryDefinitions = {
2847
+ account: {
2848
+ title: "Account"
2849
+ },
2850
+ app: {
2851
+ title: "App",
2852
+ titlePlural: "Apps"
2853
+ },
2854
+ authentication: {
2855
+ title: "Authentication"
2856
+ },
2857
+ action: {
2858
+ title: "Action"
2859
+ },
2860
+ http: {
2861
+ title: "HTTP Request"
2862
+ },
2863
+ utility: {
2864
+ title: "Utility",
2865
+ titlePlural: "Utilities"
2866
+ },
2867
+ other: {
2868
+ title: "Other"
2869
+ }
2870
+ };
2871
+ const functions = metaKeys.filter((key) => typeof sdk[key] === "function").map((key) => {
2872
+ return {
2873
+ ...context.meta[key],
2874
+ categories: context.meta[key].categories || [],
2875
+ name: key
2876
+ };
2877
+ }).sort((a, b) => a.name.localeCompare(b.name));
2878
+ const knownCategories = Object.keys(categoryDefinitions);
2879
+ const categories = knownCategories.sort((a, b) => {
2880
+ if (a === "other") return 1;
2881
+ if (b === "other") return -1;
2882
+ const titleA = categoryDefinitions[a].title;
2883
+ const titleB = categoryDefinitions[b].title;
2884
+ return titleA.localeCompare(titleB);
2885
+ }).map((categoryKey) => {
2886
+ const categoryFunctions = functions.filter(
2887
+ (f) => f.categories.includes(categoryKey) || // If the category is "other" and the function is not in any other category, include it
2888
+ categoryKey === "other" && !f.categories.some((c) => knownCategories.includes(c))
2889
+ ).map((f) => f.name).sort();
2890
+ const definition = categoryDefinitions[categoryKey];
2891
+ const title = definition.title;
2892
+ return {
2893
+ key: categoryKey,
2894
+ title,
2895
+ titlePlural: definition.titlePlural ?? `${title}s`,
2896
+ functions: categoryFunctions
2897
+ };
2898
+ });
2899
+ function getRegistry() {
2900
+ return {
2901
+ functions,
2902
+ categories
2903
+ };
2716
2904
  }
2717
- }
2718
- var emitWarning = (appKey) => {
2719
- console.warn(
2720
- `
2721
- ${"\u26A0\uFE0F".padEnd(3)} ${"WARNING".padEnd(8)} No manifest version found for '${appKey}'`
2722
- );
2723
- console.warn(
2724
- ` ${"\u21B3".padEnd(3)} Using a manifest ensures version locking and prevents unexpected behavior due to version changes.`
2725
- );
2726
- console.warn(
2727
- ` ${"\u21B3".padEnd(3)} Generate/update the manifest with: \`zapier-sdk lock-version ${appKey}\`
2728
- `
2729
- );
2905
+ return {
2906
+ getRegistry
2907
+ };
2730
2908
  };
2731
- var manifestPlugin = (params) => {
2732
- const { sdk, context } = params;
2733
- const { api, options } = context;
2734
- const { manifestPath = ".zapierrc", manifest } = options || {};
2735
- let resolvedManifest;
2736
- function resolveManifest() {
2737
- if (manifest) {
2738
- return manifest;
2739
- }
2740
- if (manifestPath) {
2741
- return loadManifestFromFile(manifestPath);
2909
+ var InputFieldChoiceItemSchema = withFormatter(
2910
+ z.object({
2911
+ key: z.string().optional().describe("Unique key/value for the choice"),
2912
+ label: z.string().optional().describe("Human readable label for the choice"),
2913
+ sample: z.string().optional().describe("Sample value for the choice"),
2914
+ value: z.string().optional().describe("Value to be submitted when selected")
2915
+ }),
2916
+ {
2917
+ format: (item) => {
2918
+ const title = item.label || item.key || "Choice";
2919
+ const subtitle = item.label && item.key && item.label !== item.key ? `(${item.key})` : void 0;
2920
+ const details = [];
2921
+ if (item.sample && item.sample !== item.key) {
2922
+ details.push({ text: `Sample: ${item.sample}`, style: "dim" });
2923
+ }
2924
+ if (item.value && item.value !== item.key) {
2925
+ details.push({ text: `Value: ${item.value}`, style: "normal" });
2926
+ }
2927
+ return {
2928
+ title,
2929
+ subtitle,
2930
+ details
2931
+ };
2742
2932
  }
2743
- return null;
2744
2933
  }
2745
- const getResolvedManifest = () => {
2746
- if (typeof resolvedManifest === "undefined") {
2747
- resolvedManifest = resolveManifest() ?? null;
2748
- }
2749
- return resolvedManifest;
2750
- };
2751
- const getManifestEntry = (appKey) => {
2752
- return getResolvedManifest()?.apps?.[appKey] || null;
2934
+ );
2935
+ var ListInputFieldChoicesSchema = withOutputSchema(
2936
+ z.object({
2937
+ // Required action identification
2938
+ appKey: AppKeyPropertySchema,
2939
+ actionType: ActionTypePropertySchema,
2940
+ actionKey: ActionKeyPropertySchema,
2941
+ // Input field specification
2942
+ inputFieldKey: z.string().min(1).describe("Input field key to get choices for."),
2943
+ // Common parameters
2944
+ authenticationId: AuthenticationIdPropertySchema.nullable().optional(),
2945
+ inputs: InputsPropertySchema.optional().describe(
2946
+ "Current input values that may affect available choices"
2947
+ ),
2948
+ page: z.number().int().min(0).optional().describe("Page number for paginated results"),
2949
+ // Pagination options (SDK-level)
2950
+ pageSize: z.number().min(1).optional().describe("Number of choices per page"),
2951
+ maxItems: z.number().min(1).optional().describe("Maximum total items to return across all pages")
2952
+ }).describe("Get the available choices for a dynamic dropdown input field"),
2953
+ InputFieldChoiceItemSchema
2954
+ );
2955
+
2956
+ // src/plugins/listInputFieldChoices/index.ts
2957
+ function transformNeedChoicesToInputFieldChoiceItem(choice) {
2958
+ return {
2959
+ key: choice.key,
2960
+ label: choice.label,
2961
+ sample: choice.sample,
2962
+ value: choice.value
2753
2963
  };
2754
- const getImplementation = async (appKey) => {
2755
- let selectedApi = null;
2756
- const manifestImplementation = getResolvedManifest()?.apps?.[appKey];
2757
- const [versionlessAppKey, version] = splitVersionedKey(appKey);
2758
- if (version) {
2759
- selectedApi = `${versionlessAppKey}@${version}`;
2760
- } else if (manifestImplementation) {
2761
- selectedApi = `${manifestImplementation.implementationName}@${manifestImplementation.version || "latest"}`;
2762
- }
2763
- if (selectedApi) {
2764
- const searchParams = {
2765
- selected_apis: selectedApi
2766
- };
2767
- const implementationData = await api.get(
2768
- "/api/v4/implementations/",
2769
- {
2770
- searchParams
2771
- }
2964
+ }
2965
+ var listInputFieldChoicesPlugin = ({ context, sdk }) => {
2966
+ const listInputFieldChoices = createPaginatedFunction(async function listInputFieldChoicesPage(options) {
2967
+ const { api } = context;
2968
+ const {
2969
+ appKey,
2970
+ actionType,
2971
+ actionKey,
2972
+ inputFieldKey,
2973
+ authenticationId,
2974
+ inputs,
2975
+ page,
2976
+ cursor
2977
+ } = options;
2978
+ const actionResult = await sdk.getAction({ appKey, actionType, actionKey });
2979
+ const actionId = actionResult.data.id;
2980
+ if (!actionId) {
2981
+ throw new ZapierApiError(
2982
+ `Action ${actionKey} does not have an ID - cannot retrieve input field choices`
2772
2983
  );
2773
- const implementationResults = implementationData.results[0];
2774
- if (!implementationResults) return null;
2775
- return normalizeImplementationToAppItem(implementationResults);
2776
- }
2777
- emitWarning(appKey);
2778
- const appsIterator = sdk.listApps({ appKeys: [appKey] }).items();
2779
- const apps = [];
2780
- for await (const app2 of appsIterator) {
2781
- apps.push(app2);
2782
- break;
2783
2984
  }
2784
- if (apps.length === 0) {
2785
- return null;
2786
- }
2787
- const app = apps[0];
2788
- return app;
2789
- };
2790
- const getVersionedImplementationId = async (appKey) => {
2791
- const manifestEntry = getManifestEntry(appKey);
2792
- if (manifestEntry) {
2793
- return `${manifestEntry.implementationName}@${manifestEntry.version || "latest"}`;
2985
+ const requestPage = cursor ? parseInt(cursor, 10) : page ?? 0;
2986
+ const choicesRequest = {
2987
+ action_id: actionId,
2988
+ input_field_id: inputFieldKey,
2989
+ page: requestPage,
2990
+ params: inputs || {}
2991
+ };
2992
+ if (authenticationId !== null) {
2993
+ choicesRequest.authentication_id = authenticationId;
2794
2994
  }
2795
- const implementation = await getImplementation(appKey);
2796
- if (!implementation) return null;
2797
- return implementation.current_implementation_id;
2798
- };
2799
- return {
2800
- context: {
2801
- getVersionedImplementationId,
2802
- getManifestEntry,
2803
- getImplementation
2995
+ const choicesData = await api.post(
2996
+ "/api/v4/implementations/choices/",
2997
+ choicesRequest
2998
+ );
2999
+ if (!choicesData.success) {
3000
+ throw new ZapierApiError(
3001
+ `Failed to get input field choices: ${choicesData.errors?.join(", ") || "Unknown error"}`
3002
+ );
2804
3003
  }
2805
- };
2806
- };
2807
- var LockVersionSchema = z.object({
2808
- appKey: z.string().describe("The app key to lock version for (e.g., 'slack', 'gmail')")
2809
- });
2810
- var lockVersionPlugin = ({ sdk }) => {
2811
- const lockVersion = createFunction(
2812
- async function lockVersion2(options) {
2813
- const { appKey, configPath = ".zapierrc" } = options;
2814
- const resolvedPath = resolve(configPath);
2815
- const appsIterator = sdk.listApps({ appKeys: [appKey] }).items();
2816
- const apps = [];
2817
- for await (const app2 of appsIterator) {
2818
- apps.push(app2);
2819
- break;
2820
- }
2821
- const app = apps[0];
2822
- const currentImplementationId = app.current_implementation_id;
2823
- const [implementationName, version] = currentImplementationId.split("@");
2824
- if (!implementationName || !version) {
2825
- throw new Error(
2826
- `Invalid implementation ID format: ${currentImplementationId}. Expected format: <implementationName>@<version>`
2827
- );
2828
- }
2829
- let config = { apps: {} };
2830
- if (existsSync(resolvedPath)) {
2831
- try {
2832
- const configContent = readFileSync(resolvedPath, "utf8");
2833
- config = JSON.parse(configContent);
2834
- if (!config.apps) {
2835
- config.apps = {};
2836
- }
2837
- } catch (error) {
2838
- console.warn(
2839
- `\u26A0\uFE0F Failed to parse existing config file, creating new one: ${error}`
2840
- );
2841
- config = { apps: {} };
3004
+ const choices = (choicesData.choices || []).map(
3005
+ transformNeedChoicesToInputFieldChoiceItem
3006
+ );
3007
+ let nextCursor;
3008
+ if (choicesData.next_page !== void 0) {
3009
+ nextCursor = choicesData.next_page.toString();
3010
+ } else if (choicesData.links?.next) {
3011
+ try {
3012
+ const nextUrl = new URL(choicesData.links.next);
3013
+ const nextPage = nextUrl.searchParams.get("page");
3014
+ if (nextPage) {
3015
+ nextCursor = nextPage;
2842
3016
  }
3017
+ } catch {
3018
+ nextCursor = void 0;
2843
3019
  }
2844
- config.apps[appKey] = {
2845
- implementationName,
2846
- version
2847
- };
2848
- writeFileSync(resolvedPath, JSON.stringify(config, null, 2));
2849
- return {
2850
- data: {
2851
- ...app,
2852
- implementationName,
2853
- version
2854
- },
2855
- configPath: resolvedPath
2856
- };
2857
- },
2858
- LockVersionSchema.extend({
2859
- configPath: z.string().optional().describe("Path to .zapierrc file (defaults to '.zapierrc')")
2860
- })
2861
- );
3020
+ }
3021
+ return {
3022
+ data: choices,
3023
+ nextCursor
3024
+ };
3025
+ }, ListInputFieldChoicesSchema);
2862
3026
  return {
2863
- lockVersion,
3027
+ listInputFieldChoices,
2864
3028
  context: {
2865
3029
  meta: {
2866
- lockVersion: {
2867
- categories: ["utility"],
2868
- inputSchema: LockVersionSchema
3030
+ listInputFieldChoices: {
3031
+ categories: ["action"],
3032
+ inputSchema: ListInputFieldChoicesSchema
2869
3033
  }
2870
3034
  }
2871
3035
  }
@@ -2920,8 +3084,11 @@ function createSdk(options = {}, initialSdk = {}, initialContext = { meta: {} })
2920
3084
  }
2921
3085
  };
2922
3086
  }
3087
+ function createZapierSdkWithoutRegistry(options = {}) {
3088
+ return createSdk(options).addPlugin(apiPlugin).addPlugin(listAppsPlugin).addPlugin(manifestPlugin).addPlugin(getAppPlugin).addPlugin(listActionsPlugin).addPlugin(getActionPlugin).addPlugin(listInputFieldsPlugin).addPlugin(listInputFieldChoicesPlugin).addPlugin(runActionPlugin).addPlugin(lockVersionPlugin).addPlugin(listAuthenticationsPlugin).addPlugin(getAuthenticationPlugin).addPlugin(findFirstAuthenticationPlugin).addPlugin(findUniqueAuthenticationPlugin).addPlugin(requestPlugin).addPlugin(fetchPlugin).addPlugin(appsPlugin).addPlugin(getProfilePlugin);
3089
+ }
2923
3090
  function createZapierSdk(options = {}) {
2924
- return createSdk(options).addPlugin(apiPlugin).addPlugin(listAppsPlugin).addPlugin(manifestPlugin).addPlugin(getAppPlugin).addPlugin(listActionsPlugin).addPlugin(getActionPlugin).addPlugin(listInputFieldsPlugin).addPlugin(runActionPlugin).addPlugin(lockVersionPlugin).addPlugin(listAuthenticationsPlugin).addPlugin(getAuthenticationPlugin).addPlugin(findFirstAuthenticationPlugin).addPlugin(findUniqueAuthenticationPlugin).addPlugin(requestPlugin).addPlugin(fetchPlugin).addPlugin(appsPlugin).addPlugin(getProfilePlugin).addPlugin(registryPlugin);
3091
+ return createZapierSdkWithoutRegistry(options).addPlugin(registryPlugin);
2925
3092
  }
2926
3093
 
2927
- export { ActionKeyPropertySchema, ActionTypePropertySchema, AppKeyPropertySchema, AuthenticationIdPropertySchema, DebugPropertySchema, InputsPropertySchema, LimitPropertySchema, OffsetPropertySchema, OutputPropertySchema, ParamsPropertySchema, RelayFetchSchema, RelayRequestSchema, ZapierActionError, ZapierApiError, ZapierAppNotFoundError, ZapierAuthenticationError, ZapierBundleError, ZapierConfigurationError, ZapierError, ZapierNotFoundError, ZapierResourceNotFoundError, ZapierTimeoutError, ZapierUnknownError, ZapierValidationError, actionKeyResolver, actionTypeResolver, appKeyResolver, appsPlugin, authenticationIdResolver, createSdk, createZapierSdk, fetchPlugin, formatErrorMessage, getResolutionOrder, getResolutionOrderForParams, getResolvableParams, getResolver, getResolversForMissingParams, getTokenFromCliLogin, getTokenFromEnv, getTokenFromEnvOrConfig, hasResolver, inputsResolver, isPositional, resolverRegistry };
3094
+ export { ActionKeyPropertySchema, ActionTypePropertySchema, AppKeyPropertySchema, AuthenticationIdPropertySchema, DebugPropertySchema, InputsPropertySchema, LimitPropertySchema, OffsetPropertySchema, OutputPropertySchema, ParamsPropertySchema, RelayFetchSchema, RelayRequestSchema, ZapierActionError, ZapierApiError, ZapierAppNotFoundError, ZapierAuthenticationError, ZapierBundleError, ZapierConfigurationError, ZapierError, ZapierNotFoundError, ZapierResourceNotFoundError, ZapierTimeoutError, ZapierUnknownError, ZapierValidationError, actionKeyResolver, actionTypeResolver, apiPlugin, appKeyResolver, appsPlugin, authenticationIdResolver, createFunction, createSdk, createZapierSdk, createZapierSdkWithoutRegistry, fetchPlugin, findFirstAuthenticationPlugin, findUniqueAuthenticationPlugin, formatErrorMessage, getActionPlugin, getAppPlugin, getAuthenticationPlugin, getProfilePlugin, getResolutionOrder, getResolutionOrderForParams, getResolvableParams, getResolver, getResolversForMissingParams, getTokenFromCliLogin, getTokenFromEnv, getTokenFromEnvOrConfig, hasResolver, inputsResolver, isPositional, listActionsPlugin, listAppsPlugin, listAuthenticationsPlugin, listInputFieldsPlugin, loadManifestFromFile, lockVersionPlugin, manifestPlugin, registryPlugin, requestPlugin, resolverRegistry, runActionPlugin };