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