@zapier/zapier-sdk 0.23.2 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/README.md +11 -40
- package/dist/index.cjs +123 -104
- package/dist/index.d.mts +50 -30
- package/dist/index.mjs +123 -104
- package/dist/plugins/fetch/index.d.ts +13 -5
- package/dist/plugins/fetch/index.d.ts.map +1 -1
- package/dist/plugins/fetch/index.js +85 -33
- package/dist/plugins/fetch/index.test.d.ts +2 -0
- package/dist/plugins/fetch/index.test.d.ts.map +1 -0
- package/dist/plugins/fetch/index.test.js +296 -0
- package/dist/plugins/fetch/schemas.d.ts.map +1 -1
- package/dist/plugins/fetch/schemas.js +10 -5
- package/dist/plugins/registry/index.d.ts.map +1 -1
- package/dist/plugins/registry/index.js +1 -0
- package/dist/plugins/request/index.d.ts +8 -7
- package/dist/plugins/request/index.d.ts.map +1 -1
- package/dist/plugins/request/index.js +15 -55
- package/dist/plugins/request/index.test.js +106 -2
- package/dist/plugins/request/schemas.d.ts +0 -2
- package/dist/plugins/request/schemas.d.ts.map +1 -1
- package/dist/plugins/request/schemas.js +0 -3
- package/dist/schemas/Action.d.ts +1 -1
- package/dist/sdk.d.ts +8 -7
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +2 -2
- package/dist/types/plugin.d.ts +6 -0
- package/dist/types/plugin.d.ts.map +1 -1
- package/dist/types/sdk.d.ts +6 -0
- package/dist/types/sdk.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -362,71 +362,136 @@ var appsPlugin = ({ sdk }) => {
|
|
|
362
362
|
}
|
|
363
363
|
};
|
|
364
364
|
};
|
|
365
|
-
var FetchUrlSchema = z.union([z.string(), z.instanceof(URL)]).describe(
|
|
365
|
+
var FetchUrlSchema = z.union([z.string(), z.instanceof(URL)]).describe(
|
|
366
|
+
"The full URL of the API endpoint to call (proxied through Zapier's Relay service)"
|
|
367
|
+
);
|
|
366
368
|
var FetchInitSchema = z.object({
|
|
367
|
-
method: z.enum(["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]).optional(),
|
|
368
|
-
headers: z.record(z.string(), z.string()).optional(),
|
|
369
|
+
method: z.enum(["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]).optional().describe("HTTP method for the request (defaults to GET)"),
|
|
370
|
+
headers: z.record(z.string(), z.string()).optional().describe("HTTP headers to include in the request"),
|
|
369
371
|
body: z.union([
|
|
370
372
|
z.string(),
|
|
371
373
|
z.instanceof(FormData),
|
|
372
374
|
z.instanceof(URLSearchParams)
|
|
373
|
-
]).optional()
|
|
375
|
+
]).optional().describe(
|
|
376
|
+
"Request body \u2014 JSON strings are auto-detected and Content-Type is set accordingly"
|
|
377
|
+
),
|
|
374
378
|
authenticationId: AuthenticationIdPropertySchema.optional(),
|
|
375
379
|
callbackUrl: z.string().optional().describe("URL to send async response to (makes request async)"),
|
|
376
380
|
authenticationTemplate: z.string().optional().describe(
|
|
377
381
|
"Optional JSON string authentication template to bypass Notary lookup"
|
|
378
382
|
)
|
|
379
|
-
}).optional().describe(
|
|
383
|
+
}).optional().describe(
|
|
384
|
+
"Request options including method, headers, body, and authentication"
|
|
385
|
+
);
|
|
386
|
+
|
|
387
|
+
// src/utils/id-utils.ts
|
|
388
|
+
function coerceToNumericId(fieldName, value) {
|
|
389
|
+
if (value === "") {
|
|
390
|
+
throw new ZapierValidationError(`The ${fieldName} cannot be empty`);
|
|
391
|
+
}
|
|
392
|
+
const numericValue = typeof value === "number" ? value : Number(value);
|
|
393
|
+
if (!Number.isFinite(numericValue)) {
|
|
394
|
+
throw new ZapierValidationError(
|
|
395
|
+
`The ${fieldName} "${value}" could not be converted to a number`
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
return numericValue;
|
|
399
|
+
}
|
|
380
400
|
|
|
381
401
|
// src/plugins/fetch/index.ts
|
|
382
|
-
|
|
402
|
+
function transformUrlToRelayPath(url) {
|
|
403
|
+
const targetUrl = new URL(url);
|
|
404
|
+
return `/relay/${targetUrl.host}${targetUrl.pathname}${targetUrl.search}${targetUrl.hash}`;
|
|
405
|
+
}
|
|
406
|
+
function normalizeHeaders(optionsHeaders) {
|
|
407
|
+
const headers = {};
|
|
408
|
+
if (!optionsHeaders) {
|
|
409
|
+
return headers;
|
|
410
|
+
}
|
|
411
|
+
const headerEntries = optionsHeaders instanceof Headers ? Array.from(optionsHeaders.entries()) : Array.isArray(optionsHeaders) ? optionsHeaders : Object.entries(optionsHeaders);
|
|
412
|
+
for (const [key, value] of headerEntries) {
|
|
413
|
+
headers[key] = value;
|
|
414
|
+
}
|
|
415
|
+
return headers;
|
|
416
|
+
}
|
|
417
|
+
var fetchPlugin = ({ context }) => {
|
|
383
418
|
return {
|
|
384
419
|
fetch: async function fetch2(url, init) {
|
|
420
|
+
const { api } = context;
|
|
385
421
|
const startTime = Date.now();
|
|
422
|
+
const isNested = init?._telemetry?.isNested === true;
|
|
386
423
|
try {
|
|
387
424
|
const {
|
|
388
425
|
authenticationId,
|
|
389
426
|
callbackUrl,
|
|
390
427
|
authenticationTemplate,
|
|
428
|
+
_telemetry,
|
|
391
429
|
...fetchInit
|
|
392
430
|
} = init || {};
|
|
393
|
-
const
|
|
394
|
-
|
|
395
|
-
|
|
431
|
+
const relayPath = transformUrlToRelayPath(url);
|
|
432
|
+
const headers = normalizeHeaders(
|
|
433
|
+
fetchInit.headers
|
|
434
|
+
);
|
|
435
|
+
const hasContentType = Object.keys(headers).some(
|
|
436
|
+
(k) => k.toLowerCase() === "content-type"
|
|
437
|
+
);
|
|
438
|
+
if (fetchInit.body && !hasContentType) {
|
|
439
|
+
const bodyStr = typeof fetchInit.body === "string" ? fetchInit.body : JSON.stringify(fetchInit.body);
|
|
440
|
+
const trimmed = bodyStr.trimStart();
|
|
441
|
+
if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
|
|
442
|
+
headers["Content-Type"] = "application/json; charset=utf-8";
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
if (authenticationId) {
|
|
446
|
+
headers["X-Relay-Authentication-Id"] = coerceToNumericId(
|
|
447
|
+
"authenticationId",
|
|
448
|
+
authenticationId
|
|
449
|
+
).toString();
|
|
450
|
+
}
|
|
451
|
+
if (callbackUrl) {
|
|
452
|
+
headers["X-Relay-Callback-Url"] = callbackUrl;
|
|
453
|
+
}
|
|
454
|
+
if (authenticationTemplate) {
|
|
455
|
+
headers["X-Authentication-Template"] = authenticationTemplate;
|
|
456
|
+
}
|
|
457
|
+
const result = await api.fetch(relayPath, {
|
|
458
|
+
method: fetchInit.method ?? "GET",
|
|
396
459
|
body: fetchInit.body,
|
|
397
|
-
headers
|
|
398
|
-
|
|
399
|
-
callbackUrl,
|
|
400
|
-
authenticationTemplate,
|
|
401
|
-
_telemetry: { isNested: true }
|
|
402
|
-
});
|
|
403
|
-
context.eventEmission.emitMethodCalled({
|
|
404
|
-
method_name: "fetch",
|
|
405
|
-
execution_duration_ms: Date.now() - startTime,
|
|
406
|
-
success_flag: true,
|
|
407
|
-
error_message: null,
|
|
408
|
-
error_type: null,
|
|
409
|
-
argument_count: init ? 2 : 1,
|
|
410
|
-
is_paginated: false
|
|
460
|
+
headers,
|
|
461
|
+
authRequired: true
|
|
411
462
|
});
|
|
463
|
+
if (!isNested) {
|
|
464
|
+
context.eventEmission.emitMethodCalled({
|
|
465
|
+
method_name: "fetch",
|
|
466
|
+
execution_duration_ms: Date.now() - startTime,
|
|
467
|
+
success_flag: true,
|
|
468
|
+
error_message: null,
|
|
469
|
+
error_type: null,
|
|
470
|
+
argument_count: init ? 2 : 1,
|
|
471
|
+
is_paginated: false
|
|
472
|
+
});
|
|
473
|
+
}
|
|
412
474
|
return result;
|
|
413
475
|
} catch (error) {
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
476
|
+
if (!isNested) {
|
|
477
|
+
context.eventEmission.emitMethodCalled({
|
|
478
|
+
method_name: "fetch",
|
|
479
|
+
execution_duration_ms: Date.now() - startTime,
|
|
480
|
+
success_flag: false,
|
|
481
|
+
error_message: error instanceof Error ? error.message : String(error),
|
|
482
|
+
error_type: error instanceof Error ? error.constructor.name : "Unknown",
|
|
483
|
+
argument_count: init ? 2 : 1,
|
|
484
|
+
is_paginated: false
|
|
485
|
+
});
|
|
486
|
+
}
|
|
423
487
|
throw error;
|
|
424
488
|
}
|
|
425
489
|
},
|
|
426
490
|
context: {
|
|
427
491
|
meta: {
|
|
428
492
|
fetch: {
|
|
429
|
-
|
|
493
|
+
description: "Make authenticated HTTP requests to any API through Zapier's Relay service. Pass an authenticationId to automatically inject the user's stored credentials (OAuth tokens, API keys, etc.) into the outgoing request. Mirrors the native fetch(url, init?) signature with additional Zapier-specific options.",
|
|
494
|
+
packages: ["sdk", "cli", "mcp"],
|
|
430
495
|
categories: ["http"],
|
|
431
496
|
returnType: "Response",
|
|
432
497
|
inputParameters: [
|
|
@@ -1805,20 +1870,6 @@ var RootFieldItemSchema = z.union([
|
|
|
1805
1870
|
FieldsetItemSchema
|
|
1806
1871
|
]);
|
|
1807
1872
|
|
|
1808
|
-
// src/utils/id-utils.ts
|
|
1809
|
-
function coerceToNumericId(fieldName, value) {
|
|
1810
|
-
if (value === "") {
|
|
1811
|
-
throw new ZapierValidationError(`The ${fieldName} cannot be empty`);
|
|
1812
|
-
}
|
|
1813
|
-
const numericValue = typeof value === "number" ? value : Number(value);
|
|
1814
|
-
if (!Number.isFinite(numericValue)) {
|
|
1815
|
-
throw new ZapierValidationError(
|
|
1816
|
-
`The ${fieldName} "${value}" could not be converted to a number`
|
|
1817
|
-
);
|
|
1818
|
-
}
|
|
1819
|
-
return numericValue;
|
|
1820
|
-
}
|
|
1821
|
-
|
|
1822
1873
|
// src/services/implementations.ts
|
|
1823
1874
|
async function fetchImplementationNeeds({
|
|
1824
1875
|
api,
|
|
@@ -2801,64 +2852,41 @@ var RelayRequestSchema = z.object({
|
|
|
2801
2852
|
z.instanceof(Headers),
|
|
2802
2853
|
z.array(z.tuple([z.string(), z.string()]))
|
|
2803
2854
|
]).optional().describe("Request headers")
|
|
2804
|
-
}).extend({
|
|
2805
|
-
relayBaseUrl: z.string().optional().describe("Base URL for Relay service")
|
|
2806
2855
|
}).merge(TelemetryMarkerSchema).describe("Make authenticated HTTP requests through Zapier's Relay service");
|
|
2807
2856
|
var RelayFetchSchema = RelayRequestSchema;
|
|
2808
2857
|
|
|
2809
|
-
// src/
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2858
|
+
// src/utils/logging.ts
|
|
2859
|
+
var loggedDeprecations = /* @__PURE__ */ new Set();
|
|
2860
|
+
function logDeprecation(message) {
|
|
2861
|
+
if (loggedDeprecations.has(message)) return;
|
|
2862
|
+
loggedDeprecations.add(message);
|
|
2863
|
+
console.warn(`[zapier-sdk] Deprecation: ${message}`);
|
|
2864
|
+
}
|
|
2865
|
+
function resetDeprecationWarnings() {
|
|
2866
|
+
loggedDeprecations.clear();
|
|
2814
2867
|
}
|
|
2815
|
-
|
|
2868
|
+
|
|
2869
|
+
// src/plugins/request/index.ts
|
|
2870
|
+
var requestPlugin = ({ sdk, context }) => {
|
|
2816
2871
|
async function request(options) {
|
|
2817
|
-
|
|
2872
|
+
logDeprecation("request() is deprecated. Use fetch() instead.");
|
|
2818
2873
|
const {
|
|
2819
2874
|
url,
|
|
2820
|
-
method
|
|
2875
|
+
method,
|
|
2821
2876
|
body,
|
|
2822
|
-
headers
|
|
2877
|
+
headers,
|
|
2823
2878
|
authenticationId,
|
|
2824
2879
|
callbackUrl,
|
|
2825
2880
|
authenticationTemplate
|
|
2826
2881
|
} = options;
|
|
2827
|
-
|
|
2828
|
-
const headers = {};
|
|
2829
|
-
if (optionsHeaders) {
|
|
2830
|
-
const headerEntries = optionsHeaders instanceof Headers ? Array.from(optionsHeaders.entries()) : Array.isArray(optionsHeaders) ? optionsHeaders : Object.entries(optionsHeaders);
|
|
2831
|
-
for (const [key, value] of headerEntries) {
|
|
2832
|
-
headers[key] = value;
|
|
2833
|
-
}
|
|
2834
|
-
}
|
|
2835
|
-
const hasContentType = Object.keys(headers).some(
|
|
2836
|
-
(k) => k.toLowerCase() === "content-type"
|
|
2837
|
-
);
|
|
2838
|
-
if (body && !hasContentType) {
|
|
2839
|
-
const bodyStr = typeof body === "string" ? body : JSON.stringify(body);
|
|
2840
|
-
const trimmed = bodyStr.trimStart();
|
|
2841
|
-
if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
|
|
2842
|
-
headers["Content-Type"] = "application/json; charset=utf-8";
|
|
2843
|
-
}
|
|
2844
|
-
}
|
|
2845
|
-
if (authenticationId) {
|
|
2846
|
-
headers["X-Relay-Authentication-Id"] = coerceToNumericId(
|
|
2847
|
-
"authenticationId",
|
|
2848
|
-
authenticationId
|
|
2849
|
-
).toString();
|
|
2850
|
-
}
|
|
2851
|
-
if (callbackUrl) {
|
|
2852
|
-
headers["X-Relay-Callback-Url"] = callbackUrl;
|
|
2853
|
-
}
|
|
2854
|
-
if (authenticationTemplate) {
|
|
2855
|
-
headers["X-Authentication-Template"] = authenticationTemplate;
|
|
2856
|
-
}
|
|
2857
|
-
return await api.fetch(relayPath, {
|
|
2882
|
+
return sdk.fetch(url, {
|
|
2858
2883
|
method,
|
|
2859
2884
|
body,
|
|
2860
2885
|
headers,
|
|
2861
|
-
|
|
2886
|
+
authenticationId,
|
|
2887
|
+
callbackUrl,
|
|
2888
|
+
authenticationTemplate,
|
|
2889
|
+
_telemetry: { isNested: true }
|
|
2862
2890
|
});
|
|
2863
2891
|
}
|
|
2864
2892
|
const requestDefinition = createFunction(
|
|
@@ -2874,7 +2902,8 @@ var requestPlugin = ({ context }) => {
|
|
|
2874
2902
|
context: {
|
|
2875
2903
|
meta: {
|
|
2876
2904
|
request: {
|
|
2877
|
-
|
|
2905
|
+
packages: ["cli", "mcp"],
|
|
2906
|
+
categories: ["http", "deprecated"],
|
|
2878
2907
|
returnType: "Response",
|
|
2879
2908
|
inputSchema: RelayRequestSchema
|
|
2880
2909
|
}
|
|
@@ -3747,17 +3776,6 @@ function isCredentialsFunction(credentials) {
|
|
|
3747
3776
|
return typeof credentials === "function";
|
|
3748
3777
|
}
|
|
3749
3778
|
|
|
3750
|
-
// src/utils/logging.ts
|
|
3751
|
-
var loggedDeprecations = /* @__PURE__ */ new Set();
|
|
3752
|
-
function logDeprecation(message) {
|
|
3753
|
-
if (loggedDeprecations.has(message)) return;
|
|
3754
|
-
loggedDeprecations.add(message);
|
|
3755
|
-
console.warn(`[zapier-sdk] Deprecation: ${message}`);
|
|
3756
|
-
}
|
|
3757
|
-
function resetDeprecationWarnings() {
|
|
3758
|
-
loggedDeprecations.clear();
|
|
3759
|
-
}
|
|
3760
|
-
|
|
3761
3779
|
// src/utils/url-utils.ts
|
|
3762
3780
|
function getZapierBaseUrl(baseUrl) {
|
|
3763
3781
|
if (!baseUrl) {
|
|
@@ -4615,6 +4633,7 @@ var registryPlugin = ({ sdk, context }) => {
|
|
|
4615
4633
|
const meta = context.meta[key];
|
|
4616
4634
|
return {
|
|
4617
4635
|
name: key,
|
|
4636
|
+
description: meta.description,
|
|
4618
4637
|
type: meta.type,
|
|
4619
4638
|
itemType: meta.itemType,
|
|
4620
4639
|
returnType: meta.returnType,
|
|
@@ -5075,7 +5094,7 @@ function getCpuTime() {
|
|
|
5075
5094
|
|
|
5076
5095
|
// package.json
|
|
5077
5096
|
var package_default = {
|
|
5078
|
-
version: "0.
|
|
5097
|
+
version: "0.24.0"};
|
|
5079
5098
|
|
|
5080
5099
|
// src/plugins/eventEmission/builders.ts
|
|
5081
5100
|
function createBaseEvent(context = {}) {
|
|
@@ -5529,7 +5548,7 @@ function createSdk(options = {}, initialSdk = {}, initialContext = { meta: {} })
|
|
|
5529
5548
|
};
|
|
5530
5549
|
}
|
|
5531
5550
|
function createZapierSdkWithoutRegistry(options = {}) {
|
|
5532
|
-
return createSdk(options).addPlugin(eventEmissionPlugin).addPlugin(apiPlugin).addPlugin(manifestPlugin).addPlugin(listAppsPlugin).addPlugin(getAppPlugin).addPlugin(listActionsPlugin).addPlugin(getActionPlugin).addPlugin(listInputFieldsPlugin).addPlugin(getInputFieldsSchemaPlugin).addPlugin(listInputFieldChoicesPlugin).addPlugin(runActionPlugin).addPlugin(listAuthenticationsPlugin).addPlugin(getAuthenticationPlugin).addPlugin(findFirstAuthenticationPlugin).addPlugin(findUniqueAuthenticationPlugin).addPlugin(listClientCredentialsPlugin).addPlugin(createClientCredentialsPlugin).addPlugin(deleteClientCredentialsPlugin).addPlugin(
|
|
5551
|
+
return createSdk(options).addPlugin(eventEmissionPlugin).addPlugin(apiPlugin).addPlugin(manifestPlugin).addPlugin(listAppsPlugin).addPlugin(getAppPlugin).addPlugin(listActionsPlugin).addPlugin(getActionPlugin).addPlugin(listInputFieldsPlugin).addPlugin(getInputFieldsSchemaPlugin).addPlugin(listInputFieldChoicesPlugin).addPlugin(runActionPlugin).addPlugin(listAuthenticationsPlugin).addPlugin(getAuthenticationPlugin).addPlugin(findFirstAuthenticationPlugin).addPlugin(findUniqueAuthenticationPlugin).addPlugin(listClientCredentialsPlugin).addPlugin(createClientCredentialsPlugin).addPlugin(deleteClientCredentialsPlugin).addPlugin(fetchPlugin).addPlugin(requestPlugin).addPlugin(appsPlugin).addPlugin(getProfilePlugin);
|
|
5533
5552
|
}
|
|
5534
5553
|
function createZapierSdk(options = {}) {
|
|
5535
5554
|
return createZapierSdkWithoutRegistry(options).addPlugin(registryPlugin);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Plugin
|
|
2
|
-
import type {
|
|
1
|
+
import type { Plugin } from "../../types/plugin";
|
|
2
|
+
import type { ApiClient } from "../../api";
|
|
3
3
|
import type { z } from "zod";
|
|
4
4
|
import type { EventEmissionContext } from "../eventEmission";
|
|
5
5
|
export interface FetchPluginProvides {
|
|
@@ -7,10 +7,14 @@ export interface FetchPluginProvides {
|
|
|
7
7
|
authenticationId?: string | number;
|
|
8
8
|
callbackUrl?: string;
|
|
9
9
|
authenticationTemplate?: string;
|
|
10
|
+
_telemetry?: {
|
|
11
|
+
isNested?: boolean;
|
|
12
|
+
};
|
|
10
13
|
}) => Promise<Response>;
|
|
11
14
|
context: {
|
|
12
15
|
meta: {
|
|
13
16
|
fetch: {
|
|
17
|
+
description: string;
|
|
14
18
|
packages: string[];
|
|
15
19
|
categories: string[];
|
|
16
20
|
returnType: string;
|
|
@@ -23,10 +27,14 @@ export interface FetchPluginProvides {
|
|
|
23
27
|
};
|
|
24
28
|
}
|
|
25
29
|
/**
|
|
26
|
-
*
|
|
30
|
+
* Fetch plugin — the primary way to make authenticated HTTP requests through Zapier's Relay service.
|
|
31
|
+
* Mirrors the native fetch(url, init?) signature with additional Zapier-specific options.
|
|
27
32
|
*/
|
|
28
|
-
export declare const fetchPlugin: Plugin<
|
|
29
|
-
|
|
33
|
+
export declare const fetchPlugin: Plugin<{}, // no SDK dependencies
|
|
34
|
+
// no SDK dependencies
|
|
35
|
+
{
|
|
36
|
+
api: ApiClient;
|
|
37
|
+
} & EventEmissionContext, // requires api + eventEmission in context
|
|
30
38
|
FetchPluginProvides>;
|
|
31
39
|
export type ZapierFetchInitOptions = RequestInit & {
|
|
32
40
|
authenticationId?: string | number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/fetch/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/fetch/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE3C,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAoC7D,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,CACL,GAAG,EAAE,MAAM,GAAG,GAAG,EACjB,IAAI,CAAC,EAAE,WAAW,GAAG;QACnB,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QACnC,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,sBAAsB,CAAC,EAAE,MAAM,CAAC;QAChC,UAAU,CAAC,EAAE;YAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;SAAE,CAAC;KACrC,KACE,OAAO,CAAC,QAAQ,CAAC,CAAC;IACvB,OAAO,EAAE;QACP,IAAI,EAAE;YACJ,KAAK,EAAE;gBACL,WAAW,EAAE,MAAM,CAAC;gBACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;gBACnB,UAAU,EAAE,MAAM,EAAE,CAAC;gBACrB,UAAU,EAAE,MAAM,CAAC;gBACnB,eAAe,EAAE,KAAK,CAAC;oBAAE,IAAI,EAAE,MAAM,CAAC;oBAAC,MAAM,EAAE,CAAC,CAAC,SAAS,CAAA;iBAAE,CAAC,CAAC;aAC/D,CAAC;SACH,CAAC;KACH,CAAC;CACH;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,MAAM,CAC9B,EAAE,EAAE,sBAAsB;AAC1B,AADI,sBAAsB;AAC1B;IAAE,GAAG,EAAE,SAAS,CAAA;CAAE,GAAG,oBAAoB,EAAE,0CAA0C;AACrF,mBAAmB,CAsHpB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,WAAW,GAAG;IACjD,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC,CAAC"}
|
|
@@ -1,54 +1,106 @@
|
|
|
1
1
|
import { FetchUrlSchema, FetchInitSchema } from "./schemas";
|
|
2
|
+
import { coerceToNumericId } from "../../utils/id-utils";
|
|
2
3
|
/**
|
|
3
|
-
*
|
|
4
|
+
* Transforms full URLs into Relay format: /relay/{domain}/{path}
|
|
4
5
|
*/
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
function transformUrlToRelayPath(url) {
|
|
7
|
+
const targetUrl = new URL(url);
|
|
8
|
+
return `/relay/${targetUrl.host}${targetUrl.pathname}${targetUrl.search}${targetUrl.hash}`;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Normalizes various header formats into a plain Record<string, string>.
|
|
12
|
+
*/
|
|
13
|
+
function normalizeHeaders(optionsHeaders) {
|
|
14
|
+
const headers = {};
|
|
15
|
+
if (!optionsHeaders) {
|
|
16
|
+
return headers;
|
|
17
|
+
}
|
|
18
|
+
const headerEntries = optionsHeaders instanceof Headers
|
|
19
|
+
? Array.from(optionsHeaders.entries())
|
|
20
|
+
: Array.isArray(optionsHeaders)
|
|
21
|
+
? optionsHeaders
|
|
22
|
+
: Object.entries(optionsHeaders);
|
|
23
|
+
for (const [key, value] of headerEntries) {
|
|
24
|
+
headers[key] = value;
|
|
25
|
+
}
|
|
26
|
+
return headers;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Fetch plugin — the primary way to make authenticated HTTP requests through Zapier's Relay service.
|
|
30
|
+
* Mirrors the native fetch(url, init?) signature with additional Zapier-specific options.
|
|
31
|
+
*/
|
|
32
|
+
export const fetchPlugin = ({ context }) => {
|
|
7
33
|
return {
|
|
8
34
|
fetch: async function fetch(url, init) {
|
|
35
|
+
const { api } = context;
|
|
9
36
|
const startTime = Date.now();
|
|
37
|
+
const isNested = init?._telemetry?.isNested === true;
|
|
10
38
|
try {
|
|
11
|
-
const { authenticationId, callbackUrl, authenticationTemplate, ...fetchInit } = init || {};
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
39
|
+
const { authenticationId, callbackUrl, authenticationTemplate, _telemetry, ...fetchInit } = init || {};
|
|
40
|
+
const relayPath = transformUrlToRelayPath(url);
|
|
41
|
+
const headers = normalizeHeaders(fetchInit.headers);
|
|
42
|
+
// Auto-set Content-Type for JSON bodies if not already specified
|
|
43
|
+
const hasContentType = Object.keys(headers).some((k) => k.toLowerCase() === "content-type");
|
|
44
|
+
if (fetchInit.body && !hasContentType) {
|
|
45
|
+
const bodyStr = typeof fetchInit.body === "string"
|
|
46
|
+
? fetchInit.body
|
|
47
|
+
: JSON.stringify(fetchInit.body);
|
|
48
|
+
const trimmed = bodyStr.trimStart();
|
|
49
|
+
if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
|
|
50
|
+
headers["Content-Type"] = "application/json; charset=utf-8";
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (authenticationId) {
|
|
54
|
+
headers["X-Relay-Authentication-Id"] = coerceToNumericId("authenticationId", authenticationId).toString();
|
|
55
|
+
}
|
|
56
|
+
if (callbackUrl) {
|
|
57
|
+
headers["X-Relay-Callback-Url"] = callbackUrl;
|
|
58
|
+
}
|
|
59
|
+
if (authenticationTemplate) {
|
|
60
|
+
headers["X-Authentication-Template"] = authenticationTemplate;
|
|
61
|
+
}
|
|
62
|
+
const result = await api.fetch(relayPath, {
|
|
63
|
+
method: fetchInit.method ?? "GET",
|
|
15
64
|
body: fetchInit.body,
|
|
16
|
-
headers
|
|
17
|
-
|
|
18
|
-
callbackUrl,
|
|
19
|
-
authenticationTemplate,
|
|
20
|
-
_telemetry: { isNested: true },
|
|
21
|
-
});
|
|
22
|
-
// Emit success telemetry
|
|
23
|
-
context.eventEmission.emitMethodCalled({
|
|
24
|
-
method_name: "fetch",
|
|
25
|
-
execution_duration_ms: Date.now() - startTime,
|
|
26
|
-
success_flag: true,
|
|
27
|
-
error_message: null,
|
|
28
|
-
error_type: null,
|
|
29
|
-
argument_count: init ? 2 : 1,
|
|
30
|
-
is_paginated: false,
|
|
65
|
+
headers,
|
|
66
|
+
authRequired: true,
|
|
31
67
|
});
|
|
68
|
+
if (!isNested) {
|
|
69
|
+
context.eventEmission.emitMethodCalled({
|
|
70
|
+
method_name: "fetch",
|
|
71
|
+
execution_duration_ms: Date.now() - startTime,
|
|
72
|
+
success_flag: true,
|
|
73
|
+
error_message: null,
|
|
74
|
+
error_type: null,
|
|
75
|
+
argument_count: init ? 2 : 1,
|
|
76
|
+
is_paginated: false,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
32
79
|
return result;
|
|
33
80
|
}
|
|
34
81
|
catch (error) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
82
|
+
if (!isNested) {
|
|
83
|
+
context.eventEmission.emitMethodCalled({
|
|
84
|
+
method_name: "fetch",
|
|
85
|
+
execution_duration_ms: Date.now() - startTime,
|
|
86
|
+
success_flag: false,
|
|
87
|
+
error_message: error instanceof Error ? error.message : String(error),
|
|
88
|
+
error_type: error instanceof Error ? error.constructor.name : "Unknown",
|
|
89
|
+
argument_count: init ? 2 : 1,
|
|
90
|
+
is_paginated: false,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
45
93
|
throw error;
|
|
46
94
|
}
|
|
47
95
|
},
|
|
48
96
|
context: {
|
|
49
97
|
meta: {
|
|
50
98
|
fetch: {
|
|
51
|
-
|
|
99
|
+
description: "Make authenticated HTTP requests to any API through Zapier's Relay service. " +
|
|
100
|
+
"Pass an authenticationId to automatically inject the user's stored credentials " +
|
|
101
|
+
"(OAuth tokens, API keys, etc.) into the outgoing request. " +
|
|
102
|
+
"Mirrors the native fetch(url, init?) signature with additional Zapier-specific options.",
|
|
103
|
+
packages: ["sdk", "cli", "mcp"],
|
|
52
104
|
categories: ["http"],
|
|
53
105
|
returnType: "Response",
|
|
54
106
|
inputParameters: [
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../src/plugins/fetch/index.test.ts"],"names":[],"mappings":""}
|