@zapier/zapier-sdk-cli 0.30.0 → 0.31.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 +15 -0
- package/README.md +34 -13
- package/dist/cli.cjs +470 -17
- package/dist/cli.mjs +473 -20
- package/dist/index.cjs +434 -2
- package/dist/index.mjs +437 -4
- package/dist/package.json +1 -1
- package/dist/src/cli.js +3 -2
- package/dist/src/plugins/cliOverrides/index.d.ts +21 -0
- package/dist/src/plugins/cliOverrides/index.js +19 -0
- package/dist/src/plugins/curl/index.d.ts +17 -0
- package/dist/src/plugins/curl/index.js +234 -0
- package/dist/src/plugins/curl/schemas.d.ts +39 -0
- package/dist/src/plugins/curl/schemas.js +101 -0
- package/dist/src/plugins/curl/utils.d.ts +24 -0
- package/dist/src/plugins/curl/utils.js +141 -0
- package/dist/src/plugins/index.d.ts +2 -0
- package/dist/src/plugins/index.js +2 -0
- package/dist/src/sdk.js +4 -1
- package/dist/src/utils/cli-generator.js +39 -12
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @zapier/zapier-sdk-cli
|
|
2
2
|
|
|
3
|
+
## 0.31.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- ad5ee3b: Adds a new curl plugin.
|
|
8
|
+
Switch -v flag to -V for version information.
|
|
9
|
+
Fix CLI to properly handle string and object types.
|
|
10
|
+
Add redirect passthrough to fetch plugin (to support curl plugin).
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- Updated dependencies [ad5ee3b]
|
|
15
|
+
- @zapier/zapier-sdk@0.29.0
|
|
16
|
+
- @zapier/zapier-sdk-mcp@0.9.4
|
|
17
|
+
|
|
3
18
|
## 0.30.0
|
|
4
19
|
|
|
5
20
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
- [`get-connection`](#get-connection)
|
|
31
31
|
- [`list-connections`](#list-connections)
|
|
32
32
|
- [HTTP Requests](#http-requests)
|
|
33
|
-
- [`
|
|
33
|
+
- [`curl`](#curl)
|
|
34
34
|
- [Utilities](#utilities)
|
|
35
35
|
- [`add`](#add)
|
|
36
36
|
- [`build-manifest`](#build-manifest)
|
|
@@ -85,7 +85,7 @@ These options are available for all commands:
|
|
|
85
85
|
|
|
86
86
|
| Option | Short | Description |
|
|
87
87
|
| -------------------------------------- | ----- | -------------------------------------------------- |
|
|
88
|
-
| `--version` | `-
|
|
88
|
+
| `--version` | `-V` | Display version number |
|
|
89
89
|
| `--help` | `-h` | Display help for command |
|
|
90
90
|
| `--debug` | | Enable debug logging |
|
|
91
91
|
| `--json` | | Output raw JSON instead of formatted results |
|
|
@@ -450,25 +450,46 @@ npx zapier-sdk list-connections [--search] [--title] [--owner] [--app-key] [--co
|
|
|
450
450
|
|
|
451
451
|
### HTTP Requests
|
|
452
452
|
|
|
453
|
-
#### `
|
|
453
|
+
#### `curl`
|
|
454
454
|
|
|
455
|
-
Make authenticated HTTP requests to any API through Zapier
|
|
455
|
+
Make authenticated HTTP requests to any API through Zapier. Pass a connection ID to automatically inject the user's stored credentials (OAuth tokens, API keys, etc.) into the outgoing request. Use it in place of the native curl command with additional Zapier-specific options.
|
|
456
456
|
|
|
457
457
|
**Options:**
|
|
458
458
|
|
|
459
|
-
| Option
|
|
460
|
-
|
|
|
461
|
-
| `<url>`
|
|
462
|
-
| `--
|
|
463
|
-
| `--
|
|
464
|
-
| `--
|
|
465
|
-
| `--
|
|
466
|
-
| `--
|
|
459
|
+
| Option | Type | Required | Default | Possible Values | Description |
|
|
460
|
+
| ------------------ | ---------------- | -------- | ------- | ---------------------------------------------------------- | ------------------------------------------------------------ |
|
|
461
|
+
| `<url>` | `string` | ✅ | — | — | Request URL |
|
|
462
|
+
| `--request` | `string` | ❌ | — | `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, `OPTIONS` | HTTP method (defaults to GET, or POST if data is provided) |
|
|
463
|
+
| `--header` | `array` | ❌ | — | — | HTTP headers in 'Key: Value' format (repeatable) |
|
|
464
|
+
| `--data` | `array` | ❌ | — | — | HTTP POST data (repeatable, joined with &) |
|
|
465
|
+
| `--data-raw` | `array` | ❌ | — | — | HTTP POST data without special interpretation (repeatable) |
|
|
466
|
+
| `--data-ascii` | `array` | ❌ | — | — | HTTP POST ASCII data (repeatable) |
|
|
467
|
+
| `--data-binary` | `array` | ❌ | — | — | HTTP POST binary data (repeatable) |
|
|
468
|
+
| `--data-urlencode` | `array` | ❌ | — | — | HTTP POST data, URL-encoded (repeatable) |
|
|
469
|
+
| `--json` | `string` | ❌ | — | — | Send JSON body (sets Content-Type and Accept headers) |
|
|
470
|
+
| `--form` | `array` | ❌ | — | — | Multipart form data as 'name=value' (repeatable) |
|
|
471
|
+
| `--form-string` | `array` | ❌ | — | — | Multipart form string field (repeatable) |
|
|
472
|
+
| `--get` | `boolean` | ❌ | — | — | Force GET method and append data to query string |
|
|
473
|
+
| `--head` | `boolean` | ❌ | — | — | Fetch headers only (HEAD request) |
|
|
474
|
+
| `--location` | `boolean` | ❌ | — | — | Follow redirects |
|
|
475
|
+
| `--include` | `boolean` | ❌ | — | — | Include response headers in output |
|
|
476
|
+
| `--output` | `string` | ❌ | — | — | Write output to file instead of stdout |
|
|
477
|
+
| `--remote-name` | `boolean` | ❌ | — | — | Write output to file named like the remote file |
|
|
478
|
+
| `--verbose` | `boolean` | ❌ | — | — | Verbose output (show request/response headers on stderr) |
|
|
479
|
+
| `--silent` | `boolean` | ❌ | — | — | Silent mode (suppress errors) |
|
|
480
|
+
| `--show-error` | `boolean` | ❌ | — | — | Show errors even when in silent mode |
|
|
481
|
+
| `--fail` | `boolean` | ❌ | — | — | Fail silently on HTTP errors (exit code 22) |
|
|
482
|
+
| `--fail-with-body` | `boolean` | ❌ | — | — | Fail on HTTP errors but still output the body |
|
|
483
|
+
| `--write-out` | `string` | ❌ | — | — | Output format string after completion (e.g., '%{http_code}') |
|
|
484
|
+
| `--max-time` | `number` | ❌ | — | — | Maximum time in seconds for the request |
|
|
485
|
+
| `--user` | `string` | ❌ | — | — | Basic auth credentials as 'user:password' |
|
|
486
|
+
| `--compressed` | `boolean` | ❌ | — | — | Request compressed response (sends Accept-Encoding header) |
|
|
487
|
+
| `--connection-id` | `string, number` | ❌ | — | — | Zapier connection ID for authentication |
|
|
467
488
|
|
|
468
489
|
**Usage:**
|
|
469
490
|
|
|
470
491
|
```bash
|
|
471
|
-
npx zapier-sdk
|
|
492
|
+
npx zapier-sdk curl <url> [--request] [--header] [--data] [--data-raw] [--data-ascii] [--data-binary] [--data-urlencode] [--json] [--form] [--form-string] [--get] [--head] [--location] [--include] [--output] [--remote-name] [--verbose] [--silent] [--show-error] [--fail] [--fail-with-body] [--write-out] [--max-time] [--user] [--compressed] [--connection-id]
|
|
472
493
|
```
|
|
473
494
|
|
|
474
495
|
### Utilities
|
package/dist/cli.cjs
CHANGED
|
@@ -963,7 +963,7 @@ function analyzeZodField(name, schema, functionInfo) {
|
|
|
963
963
|
paramType = "string";
|
|
964
964
|
choices = baseSchema.options;
|
|
965
965
|
} else if (baseSchema instanceof zod.z.ZodRecord) {
|
|
966
|
-
paramType = "
|
|
966
|
+
paramType = "object";
|
|
967
967
|
}
|
|
968
968
|
let paramHasResolver = false;
|
|
969
969
|
if (functionInfo?.resolvers?.[name]) {
|
|
@@ -1278,9 +1278,14 @@ ${confirmMessageAfter}`));
|
|
|
1278
1278
|
description,
|
|
1279
1279
|
parameters,
|
|
1280
1280
|
handler,
|
|
1281
|
-
hidden: functionInfo.categories?.includes("deprecated") ?? false
|
|
1281
|
+
hidden: functionInfo.categories?.includes("deprecated") ?? false,
|
|
1282
|
+
aliases: functionInfo.aliases
|
|
1282
1283
|
};
|
|
1283
1284
|
}
|
|
1285
|
+
function collect(value, previous = []) {
|
|
1286
|
+
previous.push(value);
|
|
1287
|
+
return previous;
|
|
1288
|
+
}
|
|
1284
1289
|
function addCommand(program2, commandName, config2) {
|
|
1285
1290
|
const command = program2.command(commandName, { hidden: config2.hidden ?? false }).description(config2.description);
|
|
1286
1291
|
let hasPositionalArray = false;
|
|
@@ -1299,10 +1304,12 @@ function addCommand(program2, commandName, config2) {
|
|
|
1299
1304
|
);
|
|
1300
1305
|
} else if (param.required && param.type === "array") {
|
|
1301
1306
|
const flags = [`--${kebabName}`];
|
|
1302
|
-
const flagSignature = flags.join(", ") + ` <
|
|
1307
|
+
const flagSignature = flags.join(", ") + ` <value>`;
|
|
1303
1308
|
command.requiredOption(
|
|
1304
1309
|
flagSignature,
|
|
1305
|
-
param.description || `${kebabName} parameter (required)
|
|
1310
|
+
param.description || `${kebabName} parameter (required, repeatable)`,
|
|
1311
|
+
collect,
|
|
1312
|
+
[]
|
|
1306
1313
|
);
|
|
1307
1314
|
} else if (param.required) {
|
|
1308
1315
|
command.argument(
|
|
@@ -1315,16 +1322,17 @@ function addCommand(program2, commandName, config2) {
|
|
|
1315
1322
|
param.description || `${kebabName} parameter`
|
|
1316
1323
|
);
|
|
1317
1324
|
} else {
|
|
1318
|
-
const flags = [
|
|
1325
|
+
const flags = [];
|
|
1326
|
+
const alias = config2.aliases?.[param.name];
|
|
1327
|
+
if (alias && alias.length === 1) {
|
|
1328
|
+
flags.push(`-${alias}`);
|
|
1329
|
+
}
|
|
1330
|
+
flags.push(`--${kebabName}`);
|
|
1319
1331
|
if (param.type === "boolean") {
|
|
1320
1332
|
command.option(flags.join(", "), param.description);
|
|
1321
1333
|
} else if (param.type === "array") {
|
|
1322
|
-
const flagSignature = flags.join(", ") + ` <
|
|
1323
|
-
command.option(
|
|
1324
|
-
flagSignature,
|
|
1325
|
-
param.description,
|
|
1326
|
-
param.default
|
|
1327
|
-
);
|
|
1334
|
+
const flagSignature = flags.join(", ") + ` <value>`;
|
|
1335
|
+
command.option(flagSignature, param.description || "", collect, []);
|
|
1328
1336
|
} else {
|
|
1329
1337
|
const flagSignature = flags.join(", ") + ` <${param.type}>`;
|
|
1330
1338
|
command.option(
|
|
@@ -1335,7 +1343,10 @@ function addCommand(program2, commandName, config2) {
|
|
|
1335
1343
|
}
|
|
1336
1344
|
}
|
|
1337
1345
|
});
|
|
1338
|
-
|
|
1346
|
+
const hasJsonParam = config2.parameters.some((p) => p.name === "json");
|
|
1347
|
+
if (!hasJsonParam) {
|
|
1348
|
+
command.option("--json", "Output raw JSON instead of formatted results");
|
|
1349
|
+
}
|
|
1339
1350
|
command.action(config2.handler);
|
|
1340
1351
|
}
|
|
1341
1352
|
function convertCliArgsToSdkParams(parameters, positionalArgs, options) {
|
|
@@ -1371,6 +1382,16 @@ function convertValue(value, type) {
|
|
|
1371
1382
|
case "array":
|
|
1372
1383
|
return Array.isArray(value) ? value : [value];
|
|
1373
1384
|
case "string":
|
|
1385
|
+
return value;
|
|
1386
|
+
case "object":
|
|
1387
|
+
if (typeof value === "string") {
|
|
1388
|
+
try {
|
|
1389
|
+
return JSON.parse(value);
|
|
1390
|
+
} catch {
|
|
1391
|
+
return value;
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
return value;
|
|
1374
1395
|
default:
|
|
1375
1396
|
if (typeof value === "string" && (value.startsWith("{") || value.startsWith("["))) {
|
|
1376
1397
|
try {
|
|
@@ -1780,7 +1801,7 @@ var LoginSchema = zod.z.object({
|
|
|
1780
1801
|
|
|
1781
1802
|
// package.json
|
|
1782
1803
|
var package_default = {
|
|
1783
|
-
version: "0.
|
|
1804
|
+
version: "0.31.0"};
|
|
1784
1805
|
|
|
1785
1806
|
// src/telemetry/builders.ts
|
|
1786
1807
|
function createCliBaseEvent(context = {}) {
|
|
@@ -3116,18 +3137,450 @@ var feedbackPlugin = ({
|
|
|
3116
3137
|
}
|
|
3117
3138
|
};
|
|
3118
3139
|
};
|
|
3140
|
+
var CurlSchema = zod.z.object({
|
|
3141
|
+
url: zod.z.string().describe("Request URL"),
|
|
3142
|
+
request: zod.z.enum(["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]).optional().describe("HTTP method (defaults to GET, or POST if data is provided)"),
|
|
3143
|
+
header: zod.z.array(zod.z.string()).optional().describe("HTTP headers in 'Key: Value' format (repeatable)"),
|
|
3144
|
+
data: zod.z.array(zod.z.string()).optional().describe("HTTP POST data (repeatable, joined with &)"),
|
|
3145
|
+
dataRaw: zod.z.array(zod.z.string()).optional().describe("HTTP POST data without special interpretation (repeatable)"),
|
|
3146
|
+
dataAscii: zod.z.array(zod.z.string()).optional().describe("HTTP POST ASCII data (repeatable)"),
|
|
3147
|
+
dataBinary: zod.z.array(zod.z.string()).optional().describe("HTTP POST binary data (repeatable)"),
|
|
3148
|
+
dataUrlencode: zod.z.array(zod.z.string()).optional().describe("HTTP POST data, URL-encoded (repeatable)"),
|
|
3149
|
+
json: zod.z.string().optional().describe("Send JSON body (sets Content-Type and Accept headers)"),
|
|
3150
|
+
form: zod.z.array(zod.z.string()).optional().describe("Multipart form data as 'name=value' (repeatable)"),
|
|
3151
|
+
formString: zod.z.array(zod.z.string()).optional().describe("Multipart form string field (repeatable)"),
|
|
3152
|
+
get: zod.z.boolean().optional().describe("Force GET method and append data to query string"),
|
|
3153
|
+
head: zod.z.boolean().optional().describe("Fetch headers only (HEAD request)"),
|
|
3154
|
+
location: zod.z.boolean().optional().describe("Follow redirects"),
|
|
3155
|
+
include: zod.z.boolean().optional().describe("Include response headers in output"),
|
|
3156
|
+
output: zod.z.string().optional().describe("Write output to file instead of stdout"),
|
|
3157
|
+
remoteName: zod.z.boolean().optional().describe("Write output to file named like the remote file"),
|
|
3158
|
+
verbose: zod.z.boolean().optional().describe("Verbose output (show request/response headers on stderr)"),
|
|
3159
|
+
silent: zod.z.boolean().optional().describe("Silent mode (suppress errors)"),
|
|
3160
|
+
showError: zod.z.boolean().optional().describe("Show errors even when in silent mode"),
|
|
3161
|
+
fail: zod.z.boolean().optional().describe("Fail silently on HTTP errors (exit code 22)"),
|
|
3162
|
+
failWithBody: zod.z.boolean().optional().describe("Fail on HTTP errors but still output the body"),
|
|
3163
|
+
writeOut: zod.z.string().optional().describe("Output format string after completion (e.g., '%{http_code}')"),
|
|
3164
|
+
maxTime: zod.z.number().optional().describe("Maximum time in seconds for the request"),
|
|
3165
|
+
user: zod.z.string().optional().describe("Basic auth credentials as 'user:password'"),
|
|
3166
|
+
compressed: zod.z.boolean().optional().describe("Request compressed response (sends Accept-Encoding header)"),
|
|
3167
|
+
connectionId: zod.z.union([zod.z.string(), zod.z.number()]).optional().describe("Zapier connection ID for authentication")
|
|
3168
|
+
}).describe("Make HTTP requests through Zapier Relay with curl-like options");
|
|
3169
|
+
var CurlExitError = class extends Error {
|
|
3170
|
+
constructor(message, exitCode) {
|
|
3171
|
+
super(message);
|
|
3172
|
+
this.exitCode = exitCode;
|
|
3173
|
+
this.name = "CurlExitError";
|
|
3174
|
+
}
|
|
3175
|
+
};
|
|
3176
|
+
function parseHeaderLine(input) {
|
|
3177
|
+
const idx = input.indexOf(":");
|
|
3178
|
+
if (idx === -1) {
|
|
3179
|
+
return null;
|
|
3180
|
+
}
|
|
3181
|
+
const key = input.slice(0, idx).trim();
|
|
3182
|
+
const value = input.slice(idx + 1).trim();
|
|
3183
|
+
if (!key) {
|
|
3184
|
+
return null;
|
|
3185
|
+
}
|
|
3186
|
+
return { key, value };
|
|
3187
|
+
}
|
|
3188
|
+
function basicAuthHeader(userpass) {
|
|
3189
|
+
const idx = userpass.indexOf(":");
|
|
3190
|
+
const user = idx === -1 ? userpass : userpass.slice(0, idx);
|
|
3191
|
+
const pass = idx === -1 ? "" : userpass.slice(idx + 1);
|
|
3192
|
+
const token = Buffer.from(`${user}:${pass}`, "utf8").toString("base64");
|
|
3193
|
+
return `Basic ${token}`;
|
|
3194
|
+
}
|
|
3195
|
+
function deriveRemoteFilename(url) {
|
|
3196
|
+
const path2 = url.pathname;
|
|
3197
|
+
const candidate = path2.endsWith("/") ? "index.html" : path.basename(path2);
|
|
3198
|
+
return candidate || "index.html";
|
|
3199
|
+
}
|
|
3200
|
+
function decodeWriteOutEscapes(input) {
|
|
3201
|
+
return input.replace(/\\n/g, "\n").replace(/\\r/g, "\r").replace(/\\t/g, " ");
|
|
3202
|
+
}
|
|
3203
|
+
function formatWriteOut(params) {
|
|
3204
|
+
const { template } = params;
|
|
3205
|
+
const replacements = {
|
|
3206
|
+
"%{http_code}": String(params.httpCode).padStart(3, "0"),
|
|
3207
|
+
"%{time_total}": params.timeTotalSeconds.toFixed(3),
|
|
3208
|
+
"%{size_download}": String(params.sizeDownloadBytes),
|
|
3209
|
+
"%{url_effective}": params.urlEffective,
|
|
3210
|
+
"%{content_type}": params.contentType ?? ""
|
|
3211
|
+
};
|
|
3212
|
+
let out = template;
|
|
3213
|
+
for (const [token, value] of Object.entries(replacements)) {
|
|
3214
|
+
out = out.split(token).join(value);
|
|
3215
|
+
}
|
|
3216
|
+
return decodeWriteOutEscapes(out);
|
|
3217
|
+
}
|
|
3218
|
+
function appendQueryParams(url, dataParts) {
|
|
3219
|
+
const out = new URL(url.toString());
|
|
3220
|
+
for (const part of dataParts) {
|
|
3221
|
+
const segments = part.split("&");
|
|
3222
|
+
for (const seg of segments) {
|
|
3223
|
+
if (!seg) continue;
|
|
3224
|
+
const idx = seg.indexOf("=");
|
|
3225
|
+
if (idx === -1) {
|
|
3226
|
+
out.searchParams.append(seg, "");
|
|
3227
|
+
} else {
|
|
3228
|
+
out.searchParams.append(seg.slice(0, idx), seg.slice(idx + 1));
|
|
3229
|
+
}
|
|
3230
|
+
}
|
|
3231
|
+
}
|
|
3232
|
+
return out;
|
|
3233
|
+
}
|
|
3234
|
+
async function readAllStdin() {
|
|
3235
|
+
const chunks = [];
|
|
3236
|
+
for await (const chunk of process.stdin) {
|
|
3237
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
3238
|
+
}
|
|
3239
|
+
return Buffer.concat(chunks);
|
|
3240
|
+
}
|
|
3241
|
+
async function resolveDataArgText(raw) {
|
|
3242
|
+
if (!raw.startsWith("@")) {
|
|
3243
|
+
return raw;
|
|
3244
|
+
}
|
|
3245
|
+
const source = raw.slice(1);
|
|
3246
|
+
if (source === "-") {
|
|
3247
|
+
const buf2 = await readAllStdin();
|
|
3248
|
+
return buf2.toString("utf8");
|
|
3249
|
+
}
|
|
3250
|
+
const buf = await fs.promises.readFile(source);
|
|
3251
|
+
return buf.toString("utf8");
|
|
3252
|
+
}
|
|
3253
|
+
async function resolveDataArgBinary(raw) {
|
|
3254
|
+
if (!raw.startsWith("@")) {
|
|
3255
|
+
return Buffer.from(raw, "utf8");
|
|
3256
|
+
}
|
|
3257
|
+
const source = raw.slice(1);
|
|
3258
|
+
if (source === "-") {
|
|
3259
|
+
return await readAllStdin();
|
|
3260
|
+
}
|
|
3261
|
+
return await fs.promises.readFile(source);
|
|
3262
|
+
}
|
|
3263
|
+
async function buildFormData(formArgs, formStringArgs) {
|
|
3264
|
+
if (typeof FormData === "undefined") {
|
|
3265
|
+
throw new CurlExitError(
|
|
3266
|
+
"FormData is not available in this runtime; cannot use --form.",
|
|
3267
|
+
2
|
|
3268
|
+
);
|
|
3269
|
+
}
|
|
3270
|
+
const fd = new FormData();
|
|
3271
|
+
const addField = async (item, forceString) => {
|
|
3272
|
+
const idx = item.indexOf("=");
|
|
3273
|
+
if (idx === -1) {
|
|
3274
|
+
throw new CurlExitError(
|
|
3275
|
+
`Invalid form field: '${item}'. Expected 'name=value' or 'name=@file'.`,
|
|
3276
|
+
2
|
|
3277
|
+
);
|
|
3278
|
+
}
|
|
3279
|
+
const name = item.slice(0, idx);
|
|
3280
|
+
const value = item.slice(idx + 1);
|
|
3281
|
+
if (!name) {
|
|
3282
|
+
throw new CurlExitError(
|
|
3283
|
+
`Invalid form field: '${item}'. Field name cannot be empty.`,
|
|
3284
|
+
2
|
|
3285
|
+
);
|
|
3286
|
+
}
|
|
3287
|
+
if (!forceString && value.startsWith("@")) {
|
|
3288
|
+
const filePath = value.slice(1);
|
|
3289
|
+
const buf = filePath === "-" ? await readAllStdin() : await fs.promises.readFile(filePath);
|
|
3290
|
+
if (typeof Blob === "undefined") {
|
|
3291
|
+
fd.append(name, buf.toString("utf8"));
|
|
3292
|
+
return;
|
|
3293
|
+
}
|
|
3294
|
+
const blob = new Blob([buf]);
|
|
3295
|
+
const filename = filePath === "-" ? `stdin-${crypto.createHash("sha1").update(buf).digest("hex").slice(0, 8)}` : path.basename(filePath);
|
|
3296
|
+
fd.append(name, blob, filename);
|
|
3297
|
+
return;
|
|
3298
|
+
}
|
|
3299
|
+
fd.append(name, value);
|
|
3300
|
+
};
|
|
3301
|
+
for (const item of formArgs) {
|
|
3302
|
+
await addField(item, false);
|
|
3303
|
+
}
|
|
3304
|
+
for (const item of formStringArgs) {
|
|
3305
|
+
await addField(item, true);
|
|
3306
|
+
}
|
|
3307
|
+
return fd;
|
|
3308
|
+
}
|
|
3309
|
+
|
|
3310
|
+
// src/plugins/curl/index.ts
|
|
3311
|
+
var curlPlugin = ({
|
|
3312
|
+
sdk: sdk2
|
|
3313
|
+
}) => {
|
|
3314
|
+
async function curl(options) {
|
|
3315
|
+
const {
|
|
3316
|
+
url: rawUrl,
|
|
3317
|
+
request,
|
|
3318
|
+
header = [],
|
|
3319
|
+
data = [],
|
|
3320
|
+
dataRaw = [],
|
|
3321
|
+
dataAscii = [],
|
|
3322
|
+
dataBinary = [],
|
|
3323
|
+
dataUrlencode = [],
|
|
3324
|
+
json,
|
|
3325
|
+
form = [],
|
|
3326
|
+
formString = [],
|
|
3327
|
+
get: forceGet,
|
|
3328
|
+
head: forceHead,
|
|
3329
|
+
location,
|
|
3330
|
+
include,
|
|
3331
|
+
output,
|
|
3332
|
+
remoteName,
|
|
3333
|
+
verbose,
|
|
3334
|
+
silent,
|
|
3335
|
+
showError,
|
|
3336
|
+
fail,
|
|
3337
|
+
failWithBody,
|
|
3338
|
+
writeOut,
|
|
3339
|
+
maxTime,
|
|
3340
|
+
user,
|
|
3341
|
+
compressed,
|
|
3342
|
+
connectionId
|
|
3343
|
+
} = options;
|
|
3344
|
+
const parsedUrl = new URL(rawUrl);
|
|
3345
|
+
const headers = {};
|
|
3346
|
+
for (const h of header) {
|
|
3347
|
+
const parsed = parseHeaderLine(h);
|
|
3348
|
+
if (parsed) {
|
|
3349
|
+
headers[parsed.key] = parsed.value;
|
|
3350
|
+
}
|
|
3351
|
+
}
|
|
3352
|
+
if (user) {
|
|
3353
|
+
headers["Authorization"] = basicAuthHeader(user);
|
|
3354
|
+
}
|
|
3355
|
+
if (compressed) {
|
|
3356
|
+
headers["Accept-Encoding"] = "gzip, deflate, br";
|
|
3357
|
+
}
|
|
3358
|
+
const rawTextDataArgs = [...data, ...dataRaw, ...dataAscii];
|
|
3359
|
+
const rawBinaryDataArgs = [...dataBinary];
|
|
3360
|
+
const rawUrlencodeArgs = [...dataUrlencode];
|
|
3361
|
+
const hasForm = form.length > 0 || formString.length > 0;
|
|
3362
|
+
const hasJson = json !== void 0;
|
|
3363
|
+
const hasAnyData = hasJson || hasForm || rawTextDataArgs.length > 0 || rawBinaryDataArgs.length > 0 || rawUrlencodeArgs.length > 0;
|
|
3364
|
+
let method = "GET";
|
|
3365
|
+
if (forceHead) {
|
|
3366
|
+
method = "HEAD";
|
|
3367
|
+
} else if (request) {
|
|
3368
|
+
method = request;
|
|
3369
|
+
} else if (forceGet) {
|
|
3370
|
+
method = "GET";
|
|
3371
|
+
} else if (hasAnyData) {
|
|
3372
|
+
method = "POST";
|
|
3373
|
+
}
|
|
3374
|
+
let body;
|
|
3375
|
+
let effectiveUrl = parsedUrl;
|
|
3376
|
+
if (hasJson) {
|
|
3377
|
+
if (!headers["Content-Type"]) {
|
|
3378
|
+
headers["Content-Type"] = "application/json";
|
|
3379
|
+
}
|
|
3380
|
+
if (!headers["Accept"]) {
|
|
3381
|
+
headers["Accept"] = "application/json";
|
|
3382
|
+
}
|
|
3383
|
+
body = json;
|
|
3384
|
+
} else if (hasForm) {
|
|
3385
|
+
body = await buildFormData(form, formString);
|
|
3386
|
+
} else {
|
|
3387
|
+
const resolvedTextParts = [];
|
|
3388
|
+
for (const raw of rawTextDataArgs) {
|
|
3389
|
+
resolvedTextParts.push(await resolveDataArgText(raw));
|
|
3390
|
+
}
|
|
3391
|
+
const resolvedUrlEncodeParts = [];
|
|
3392
|
+
for (const raw of rawUrlencodeArgs) {
|
|
3393
|
+
if (raw.startsWith("@")) {
|
|
3394
|
+
const content = await resolveDataArgText(raw);
|
|
3395
|
+
resolvedUrlEncodeParts.push(encodeURIComponent(content));
|
|
3396
|
+
continue;
|
|
3397
|
+
}
|
|
3398
|
+
const atIdx = raw.indexOf("@");
|
|
3399
|
+
const eqIdx = raw.indexOf("=");
|
|
3400
|
+
if (eqIdx !== -1) {
|
|
3401
|
+
const key = raw.slice(0, eqIdx);
|
|
3402
|
+
const value = raw.slice(eqIdx + 1);
|
|
3403
|
+
resolvedUrlEncodeParts.push(
|
|
3404
|
+
`${encodeURIComponent(key)}=${encodeURIComponent(value)}`
|
|
3405
|
+
);
|
|
3406
|
+
} else if (atIdx !== -1) {
|
|
3407
|
+
const key = raw.slice(0, atIdx);
|
|
3408
|
+
const filePath = raw.slice(atIdx + 1);
|
|
3409
|
+
const buf2 = filePath === "-" ? await readAllStdin() : await fs.promises.readFile(filePath);
|
|
3410
|
+
resolvedUrlEncodeParts.push(
|
|
3411
|
+
`${encodeURIComponent(key)}=${encodeURIComponent(buf2.toString("utf8"))}`
|
|
3412
|
+
);
|
|
3413
|
+
} else {
|
|
3414
|
+
resolvedUrlEncodeParts.push(encodeURIComponent(raw));
|
|
3415
|
+
}
|
|
3416
|
+
}
|
|
3417
|
+
const resolvedBinaryParts = [];
|
|
3418
|
+
for (const raw of rawBinaryDataArgs) {
|
|
3419
|
+
resolvedBinaryParts.push(await resolveDataArgBinary(raw));
|
|
3420
|
+
}
|
|
3421
|
+
const allTextParts = [...resolvedTextParts, ...resolvedUrlEncodeParts];
|
|
3422
|
+
if (forceGet && allTextParts.length > 0) {
|
|
3423
|
+
effectiveUrl = appendQueryParams(parsedUrl, allTextParts);
|
|
3424
|
+
} else if (resolvedBinaryParts.length > 0) {
|
|
3425
|
+
body = Buffer.concat(resolvedBinaryParts);
|
|
3426
|
+
} else if (allTextParts.length > 0) {
|
|
3427
|
+
body = allTextParts.join("&");
|
|
3428
|
+
if (!headers["Content-Type"]) {
|
|
3429
|
+
headers["Content-Type"] = "application/x-www-form-urlencoded";
|
|
3430
|
+
}
|
|
3431
|
+
}
|
|
3432
|
+
}
|
|
3433
|
+
const redirect = location ? "follow" : "manual";
|
|
3434
|
+
if (verbose && !silent) {
|
|
3435
|
+
process.stderr.write(`> ${method} ${effectiveUrl.toString()}
|
|
3436
|
+
`);
|
|
3437
|
+
for (const [k, v] of Object.entries(headers)) {
|
|
3438
|
+
process.stderr.write(`> ${k}: ${v}
|
|
3439
|
+
`);
|
|
3440
|
+
}
|
|
3441
|
+
process.stderr.write(">\n");
|
|
3442
|
+
}
|
|
3443
|
+
const signal = maxTime ? AbortSignal.timeout(maxTime * 1e3) : void 0;
|
|
3444
|
+
const start = performance.now();
|
|
3445
|
+
const response = await sdk2.fetch(effectiveUrl.toString(), {
|
|
3446
|
+
method,
|
|
3447
|
+
headers,
|
|
3448
|
+
body,
|
|
3449
|
+
redirect,
|
|
3450
|
+
signal,
|
|
3451
|
+
connectionId
|
|
3452
|
+
});
|
|
3453
|
+
const timeTotalSeconds = (performance.now() - start) / 1e3;
|
|
3454
|
+
if (verbose && !silent) {
|
|
3455
|
+
process.stderr.write(
|
|
3456
|
+
`< HTTP ${response.status} ${response.statusText}
|
|
3457
|
+
`
|
|
3458
|
+
);
|
|
3459
|
+
response.headers.forEach((value, key) => {
|
|
3460
|
+
process.stderr.write(`< ${key}: ${value}
|
|
3461
|
+
`);
|
|
3462
|
+
});
|
|
3463
|
+
process.stderr.write("<\n");
|
|
3464
|
+
}
|
|
3465
|
+
const isHttpError = response.status >= 400;
|
|
3466
|
+
const shouldFail = (fail || failWithBody) && isHttpError;
|
|
3467
|
+
const shouldOutputBody = !shouldFail || !!failWithBody;
|
|
3468
|
+
const headerText = include ? `HTTP ${response.status} ${response.statusText}
|
|
3469
|
+
${Array.from(
|
|
3470
|
+
response.headers.entries()
|
|
3471
|
+
).map(([k, v]) => `${k}: ${v}`).join("\n")}
|
|
3472
|
+
|
|
3473
|
+
` : "";
|
|
3474
|
+
let bodyBytes = 0;
|
|
3475
|
+
const buf = shouldOutputBody ? Buffer.from(await response.arrayBuffer()) : Buffer.alloc(0);
|
|
3476
|
+
bodyBytes = buf.length;
|
|
3477
|
+
const outputFile = output && output !== "-" ? output : remoteName ? deriveRemoteFilename(parsedUrl) : void 0;
|
|
3478
|
+
if (outputFile) {
|
|
3479
|
+
const dir = path.dirname(outputFile);
|
|
3480
|
+
if (dir !== ".") {
|
|
3481
|
+
await fs.promises.mkdir(dir, { recursive: true });
|
|
3482
|
+
}
|
|
3483
|
+
const ws = fs.createWriteStream(outputFile);
|
|
3484
|
+
if (headerText) {
|
|
3485
|
+
ws.write(headerText);
|
|
3486
|
+
}
|
|
3487
|
+
if (buf.length) {
|
|
3488
|
+
ws.write(buf);
|
|
3489
|
+
}
|
|
3490
|
+
await new Promise((resolve4, reject) => {
|
|
3491
|
+
ws.end(() => resolve4());
|
|
3492
|
+
ws.on("error", reject);
|
|
3493
|
+
});
|
|
3494
|
+
} else {
|
|
3495
|
+
if (headerText) {
|
|
3496
|
+
process.stdout.write(headerText);
|
|
3497
|
+
}
|
|
3498
|
+
if (buf.length) {
|
|
3499
|
+
process.stdout.write(buf);
|
|
3500
|
+
}
|
|
3501
|
+
}
|
|
3502
|
+
if (writeOut) {
|
|
3503
|
+
const formatted = formatWriteOut({
|
|
3504
|
+
template: writeOut,
|
|
3505
|
+
urlEffective: response.url || effectiveUrl.toString(),
|
|
3506
|
+
httpCode: response.status,
|
|
3507
|
+
timeTotalSeconds,
|
|
3508
|
+
sizeDownloadBytes: bodyBytes,
|
|
3509
|
+
contentType: response.headers.get("content-type")
|
|
3510
|
+
});
|
|
3511
|
+
process.stdout.write(formatted);
|
|
3512
|
+
}
|
|
3513
|
+
if (shouldFail) {
|
|
3514
|
+
if (!silent || showError) {
|
|
3515
|
+
process.stderr.write(
|
|
3516
|
+
`curl: (22) The requested URL returned error: ${response.status}
|
|
3517
|
+
`
|
|
3518
|
+
);
|
|
3519
|
+
}
|
|
3520
|
+
throw new CurlExitError("HTTP request failed", 22);
|
|
3521
|
+
}
|
|
3522
|
+
return void 0;
|
|
3523
|
+
}
|
|
3524
|
+
return {
|
|
3525
|
+
curl,
|
|
3526
|
+
context: {
|
|
3527
|
+
meta: {
|
|
3528
|
+
curl: {
|
|
3529
|
+
description: "Make authenticated HTTP requests to any API through Zapier. Pass a connection ID to automatically inject the user's stored credentials (OAuth tokens, API keys, etc.) into the outgoing request. Use it in place of the native curl command with additional Zapier-specific options.",
|
|
3530
|
+
categories: ["http"],
|
|
3531
|
+
inputSchema: CurlSchema,
|
|
3532
|
+
aliases: {
|
|
3533
|
+
request: "X",
|
|
3534
|
+
header: "H",
|
|
3535
|
+
data: "d",
|
|
3536
|
+
form: "F",
|
|
3537
|
+
get: "G",
|
|
3538
|
+
head: "I",
|
|
3539
|
+
location: "L",
|
|
3540
|
+
include: "i",
|
|
3541
|
+
output: "o",
|
|
3542
|
+
remoteName: "O",
|
|
3543
|
+
verbose: "v",
|
|
3544
|
+
silent: "s",
|
|
3545
|
+
showError: "S",
|
|
3546
|
+
writeOut: "w",
|
|
3547
|
+
maxTime: "m",
|
|
3548
|
+
user: "u"
|
|
3549
|
+
}
|
|
3550
|
+
}
|
|
3551
|
+
}
|
|
3552
|
+
}
|
|
3553
|
+
};
|
|
3554
|
+
};
|
|
3555
|
+
|
|
3556
|
+
// src/plugins/cliOverrides/index.ts
|
|
3557
|
+
var cliOverridesPlugin = ({ context }) => {
|
|
3558
|
+
if (!context.meta.fetch) {
|
|
3559
|
+
return { context: { meta: {} } };
|
|
3560
|
+
}
|
|
3561
|
+
return {
|
|
3562
|
+
context: {
|
|
3563
|
+
meta: {
|
|
3564
|
+
fetch: {
|
|
3565
|
+
...context.meta.fetch,
|
|
3566
|
+
categories: [...context.meta.fetch.categories || [], "deprecated"]
|
|
3567
|
+
}
|
|
3568
|
+
}
|
|
3569
|
+
}
|
|
3570
|
+
};
|
|
3571
|
+
};
|
|
3119
3572
|
|
|
3120
3573
|
// src/sdk.ts
|
|
3121
3574
|
function createZapierCliSdk(options = {}) {
|
|
3122
3575
|
return zapierSdk.createZapierSdkWithoutRegistry({
|
|
3123
3576
|
...options
|
|
3124
|
-
}).addPlugin(generateAppTypesPlugin).addPlugin(buildManifestPlugin).addPlugin(bundleCodePlugin).addPlugin(getLoginConfigPathPlugin).addPlugin(addPlugin).addPlugin(feedbackPlugin).addPlugin(mcpPlugin).addPlugin(loginPlugin).addPlugin(logoutPlugin).addPlugin(zapierSdk.registryPlugin);
|
|
3577
|
+
}).addPlugin(generateAppTypesPlugin).addPlugin(buildManifestPlugin).addPlugin(bundleCodePlugin).addPlugin(getLoginConfigPathPlugin).addPlugin(addPlugin).addPlugin(feedbackPlugin).addPlugin(curlPlugin).addPlugin(mcpPlugin).addPlugin(loginPlugin).addPlugin(logoutPlugin).addPlugin(cliOverridesPlugin).addPlugin(zapierSdk.registryPlugin);
|
|
3125
3578
|
}
|
|
3126
3579
|
|
|
3127
3580
|
// package.json with { type: 'json' }
|
|
3128
3581
|
var package_default2 = {
|
|
3129
3582
|
name: "@zapier/zapier-sdk-cli",
|
|
3130
|
-
version: "0.
|
|
3583
|
+
version: "0.31.0"};
|
|
3131
3584
|
function detectPackageManager(cwd = process.cwd()) {
|
|
3132
3585
|
const ua = process.env.npm_config_user_agent;
|
|
3133
3586
|
if (ua) {
|
|
@@ -3330,7 +3783,7 @@ async function checkAndNotifyUpdates({
|
|
|
3330
3783
|
|
|
3331
3784
|
// src/cli.ts
|
|
3332
3785
|
var program = new commander.Command();
|
|
3333
|
-
program.name("zapier-sdk").description("CLI for Zapier SDK").version(package_default2.version,
|
|
3786
|
+
program.name("zapier-sdk").description("CLI for Zapier SDK").version(package_default2.version, void 0, "Display version number").option("--debug", "Enable debug logging").option("--base-url <url>", "Base URL for Zapier API endpoints").option("--credentials <token>", "Authentication token").option("--credentials-client-id <id>", "OAuth client ID for authentication").option(
|
|
3334
3787
|
"--credentials-client-secret <secret>",
|
|
3335
3788
|
"OAuth client secret for authentication"
|
|
3336
3789
|
).option(
|
|
@@ -3342,7 +3795,7 @@ program.name("zapier-sdk").description("CLI for Zapier SDK").version(package_def
|
|
|
3342
3795
|
).option(
|
|
3343
3796
|
"--max-network-retry-delay-ms <ms>",
|
|
3344
3797
|
"Max delay in ms to wait for rate limit retry (default: 60000)"
|
|
3345
|
-
);
|
|
3798
|
+
).helpOption("-h, --help", "Display help for command");
|
|
3346
3799
|
var isDebugMode = process.env.DEBUG === "true" || process.argv.includes("--debug");
|
|
3347
3800
|
function getFlagValue(flagName) {
|
|
3348
3801
|
const index = process.argv.indexOf(flagName);
|