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