@withone/cli 1.35.0 → 1.36.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/README.md CHANGED
@@ -255,6 +255,7 @@ one actions execute stripe <actionId> <connectionKey> \
255
255
  | `--dry-run` | Show the request without executing it |
256
256
  | `--mock` | Return example response without making an API call |
257
257
  | `--skip-validation` | Skip input validation against the action schema |
258
+ | `--output <path>` | Save response to a file (for binary downloads) |
258
259
 
259
260
  The CLI validates required parameters (path variables, query params, body fields) against the action schema before executing. Missing params return a clear error with the flag name and description. Pass `--skip-validation` to bypass.
260
261
 
@@ -11,6 +11,10 @@ import { exec, spawn } from "child_process";
11
11
  import { promisify } from "util";
12
12
 
13
13
  // src/lib/api.ts
14
+ import { createWriteStream } from "fs";
15
+ import { resolve } from "path";
16
+ import { pipeline } from "stream/promises";
17
+ import { Readable } from "stream";
14
18
  var ApiError = class extends Error {
15
19
  constructor(status, message, retryAfterSeconds) {
16
20
  super(message);
@@ -328,12 +332,45 @@ var OneApi = class {
328
332
  const text = await response.text();
329
333
  throw new ApiError(response.status, text || `HTTP ${response.status}`);
330
334
  }
335
+ const responseContentType = response.headers.get("content-type") || "";
336
+ const isExplicitJson = responseContentType.includes("application/json") || responseContentType.includes("text/");
337
+ if (isExplicitJson || !responseContentType) {
338
+ const responseText2 = await response.text();
339
+ const responseData = responseText2 ? JSON.parse(responseText2) : {};
340
+ return { requestConfig: sanitizedConfig, responseData };
341
+ }
342
+ if (args.output) {
343
+ const outputPath = resolve(args.output);
344
+ const body = response.body;
345
+ if (!body) {
346
+ throw new ApiError(0, "Response body is null \u2014 cannot save to file");
347
+ }
348
+ const nodeReadable = Readable.fromWeb(body);
349
+ await pipeline(nodeReadable, createWriteStream(outputPath));
350
+ const contentLength = response.headers.get("content-length");
351
+ const size = contentLength ? parseInt(contentLength, 10) : void 0;
352
+ return {
353
+ requestConfig: sanitizedConfig,
354
+ responseData: { saved: true, path: outputPath, size, contentType: responseContentType }
355
+ };
356
+ }
331
357
  const responseText = await response.text();
332
- const responseData = responseText ? JSON.parse(responseText) : {};
333
- return {
334
- requestConfig: sanitizedConfig,
335
- responseData
336
- };
358
+ try {
359
+ const responseData = responseText ? JSON.parse(responseText) : {};
360
+ return { requestConfig: sanitizedConfig, responseData };
361
+ } catch {
362
+ const contentLength = response.headers.get("content-length");
363
+ const size = contentLength ? parseInt(contentLength, 10) : responseText.length;
364
+ return {
365
+ requestConfig: sanitizedConfig,
366
+ responseData: {
367
+ binary: true,
368
+ size,
369
+ contentType: responseContentType,
370
+ message: "Binary response received. Use --output <path> to save to a file."
371
+ }
372
+ };
373
+ }
337
374
  }
338
375
  // Webhook Relay methods
339
376
  async createRelayEndpoint(body) {
@@ -394,7 +431,7 @@ var TimeoutError = class extends Error {
394
431
  }
395
432
  };
396
433
  function sleep(ms) {
397
- return new Promise((resolve) => setTimeout(resolve, ms));
434
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
398
435
  }
399
436
  function replacePathVariables(path3, variables) {
400
437
  if (!path3) return path3;
@@ -532,7 +569,7 @@ function setByDotPath(obj, dotPath, value) {
532
569
  // src/lib/flow-engine.ts
533
570
  var execAsync = promisify(exec);
534
571
  function sleep2(ms) {
535
- return new Promise((resolve) => setTimeout(resolve, ms));
572
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
536
573
  }
537
574
  var StepTimeoutError = class extends Error {
538
575
  errorCode = "TIMEOUT";
@@ -843,7 +880,7 @@ async function executeCodeModule(stepId, modulePath, context, options) {
843
880
  const { env: _omitEnv, ...safeContext } = context;
844
881
  void _omitEnv;
845
882
  const stdinPayload = JSON.stringify(safeContext);
846
- return await new Promise((resolve, reject) => {
883
+ return await new Promise((resolve2, reject) => {
847
884
  const child = spawn(process.execPath, [absPath], {
848
885
  cwd: rootDir,
849
886
  stdio: ["pipe", "pipe", "pipe"]
@@ -862,11 +899,11 @@ async function executeCodeModule(stepId, modulePath, context, options) {
862
899
  }
863
900
  const trimmed = stdout.trim();
864
901
  if (trimmed === "") {
865
- resolve(void 0);
902
+ resolve2(void 0);
866
903
  return;
867
904
  }
868
905
  try {
869
- resolve(JSON.parse(stripCodeFences(trimmed)));
906
+ resolve2(JSON.parse(stripCodeFences(trimmed)));
870
907
  } catch (err) {
871
908
  reject(new Error(`Code module "${modulePath}" did not print valid JSON to stdout: ${err.message}`));
872
909
  }
@@ -1042,7 +1079,7 @@ async function executeSubflowStep(step, context, api, permissions, allowedAction
1042
1079
  if (flowStack.includes(resolvedKey)) {
1043
1080
  throw new Error(`Circular flow detected: ${[...flowStack, resolvedKey].join(" \u2192 ")}`);
1044
1081
  }
1045
- const { loadFlowWithMeta: loadFlowWithMeta2 } = await import("./flow-runner-TNI7YWVY.js");
1082
+ const { loadFlowWithMeta: loadFlowWithMeta2 } = await import("./flow-runner-OVOGDXNR.js");
1046
1083
  const { flow: subFlow, rootDir: subRootDir } = loadFlowWithMeta2(resolvedKey);
1047
1084
  const subContext = await executeFlow(
1048
1085
  subFlow,
@@ -11,7 +11,7 @@ import {
11
11
  saveFlow,
12
12
  summarizeFlowInputs,
13
13
  walkSteps
14
- } from "./chunk-HZP7NT4K.js";
14
+ } from "./chunk-MNJJE4PJ.js";
15
15
  export {
16
16
  FlowRunner,
17
17
  collectStepTypes,
package/dist/index.js CHANGED
@@ -19,7 +19,7 @@ import {
19
19
  resolveFlowPath,
20
20
  saveFlow,
21
21
  validateActionInput
22
- } from "./chunk-HZP7NT4K.js";
22
+ } from "./chunk-MNJJE4PJ.js";
23
23
 
24
24
  // src/index.ts
25
25
  import { createRequire as createRequire2 } from "module";
@@ -2771,7 +2771,8 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
2771
2771
  headers,
2772
2772
  isFormData: options.formData,
2773
2773
  isFormUrlEncoded: options.formUrlEncoded,
2774
- dryRun: options.dryRun
2774
+ dryRun: options.dryRun,
2775
+ output: options.output
2775
2776
  },
2776
2777
  actionDetails
2777
2778
  );
@@ -8006,6 +8007,7 @@ one --agent actions execute <platform> <actionId> <key> -d '{}' # Execute it
8006
8007
  - \`--dry-run\` \u2014 Preview request without executing
8007
8008
  - \`--mock\` \u2014 Return example response without making an API call (useful for building UI against a response shape)
8008
8009
  - \`--skip-validation\` \u2014 Skip input validation against the action schema
8010
+ - \`--output <path>\` \u2014 Save response to a file (for binary downloads like PDFs, images, documents)
8009
8011
 
8010
8012
  The CLI validates required parameters against the action schema before executing. If you're missing a required path variable, query param, or body field, you'll get a clear error listing what's missing and which flag to use. Pass \`--skip-validation\` to bypass.
8011
8013
 
@@ -8129,6 +8131,7 @@ one --agent actions execute <platform> <actionId> <connectionKey> [options]
8129
8131
  - \`--dry-run\` \u2014 Preview without executing
8130
8132
  - \`--mock\` \u2014 Return example response without making an API call
8131
8133
  - \`--skip-validation\` \u2014 Skip input validation against the action schema
8134
+ - \`--output <path>\` \u2014 Save response to a file (for binary downloads like PDFs, images, documents)
8132
8135
 
8133
8136
  **Do NOT** pass path or query parameters in \`-d\`. Use the correct flags.
8134
8137
 
@@ -9369,7 +9372,7 @@ actions.command("search <platform> <query>").description('Search for actions on
9369
9372
  actions.command("knowledge <platform> <actionId>").alias("k").description("Get full docs for an action \u2014 MUST call before execute to know required params").option("--no-cache", "Skip cache, fetch fresh from API").option("--cache-status", "Print cache metadata without fetching").action(async (platform, actionId, options) => {
9370
9373
  await actionsKnowledgeCommand(platform, actionId, options);
9371
9374
  });
9372
- actions.command("execute [platform] [actionId] [connectionKey]").alias("x").allowUnknownOption(true).allowExcessArguments(true).description("Execute an action (or multiple with --parallel, separated by --)").option("-d, --data <json>", "Request body as JSON").option("--path-vars <json>", "Path variables as JSON").option("--query-params <json>", "Query parameters as JSON").option("--headers <json>", "Additional headers as JSON").option("--form-data", "Send as multipart/form-data").option("--form-url-encoded", "Send as application/x-www-form-urlencoded").option("--dry-run", "Show request that would be sent without executing").option("--mock", "Return example response without making an API call").option("--skip-validation", "Skip input validation against the action schema").option("--parallel", "Execute multiple actions concurrently (separate actions with --)").option("--max-concurrency <n>", "Max concurrent actions when using --parallel (default: 5)", "5").action(async (platform, actionId, connectionKey, options) => {
9375
+ actions.command("execute [platform] [actionId] [connectionKey]").alias("x").allowUnknownOption(true).allowExcessArguments(true).description("Execute an action (or multiple with --parallel, separated by --)").option("-d, --data <json>", "Request body as JSON").option("--path-vars <json>", "Path variables as JSON").option("--query-params <json>", "Query parameters as JSON").option("--headers <json>", "Additional headers as JSON").option("--form-data", "Send as multipart/form-data").option("--form-url-encoded", "Send as application/x-www-form-urlencoded").option("--dry-run", "Show request that would be sent without executing").option("--mock", "Return example response without making an API call").option("--skip-validation", "Skip input validation against the action schema").option("--output <path>", "Save binary response to a file (for non-JSON responses like file downloads)").option("--parallel", "Execute multiple actions concurrently (separate actions with --)").option("--max-concurrency <n>", "Max concurrent actions when using --parallel (default: 5)", "5").action(async (platform, actionId, connectionKey, options) => {
9373
9376
  if (options.parallel) {
9374
9377
  await actionsExecuteParallelCommand();
9375
9378
  return;
@@ -9386,7 +9389,8 @@ actions.command("execute [platform] [actionId] [connectionKey]").alias("x").allo
9386
9389
  formUrlEncoded: options.formUrlEncoded,
9387
9390
  dryRun: options.dryRun,
9388
9391
  mock: options.mock,
9389
- skipValidation: options.skipValidation
9392
+ skipValidation: options.skipValidation,
9393
+ output: options.output
9390
9394
  });
9391
9395
  });
9392
9396
  var flow = program.command("flow").alias("f").description("Create, execute, and manage multi-step workflows");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@withone/cli",
3
- "version": "1.35.0",
3
+ "version": "1.36.0",
4
4
  "description": "CLI for managing One",
5
5
  "type": "module",
6
6
  "files": [
@@ -87,6 +87,7 @@ Options:
87
87
  - `--dry-run` — Preview the request without executing
88
88
  - `--mock` — Return example response without making an API call (useful for building UI)
89
89
  - `--skip-validation` — Skip input validation against the action schema
90
+ - `--output <path>` — Save response to a file (for binary downloads like PDFs, images, documents)
90
91
 
91
92
  The CLI validates required parameters before executing. Missing params return a structured error with the flag name, parameter name, and description. Pass `--skip-validation` to bypass.
92
93