run402 2.39.2 → 2.39.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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Command-line interface for [Run402](https://run402.com) — provision Postgres databases, deploy static sites, run Node 22 serverless functions, host content-addressed CDN assets, send email, sign on-chain. Paid autonomously with x402 USDC on Base. **Prototype tier is free on testnet.**
4
4
 
5
- For the full CLI reference (every flag, every subcommand) see **<https://run402.com/llms-cli.txt>**.
5
+ For the full CLI reference (every flag, every subcommand) see **<https://docs.run402.com/llms-cli.txt>**.
6
6
 
7
7
  ## Install
8
8
 
@@ -243,7 +243,7 @@ run402 functions --help
243
243
 
244
244
  The canonical, comprehensive CLI reference — every flag, every subcommand, edge cases, troubleshooting — lives at:
245
245
 
246
- **<https://run402.com/llms-cli.txt>**
246
+ **<https://docs.run402.com/llms-cli.txt>**
247
247
 
248
248
  Same content also at [`cli/llms-cli.txt`](./llms-cli.txt) in the repo. Treat that file as authoritative; this README is a quick-orientation landing page.
249
249
 
package/lib/ci.mjs CHANGED
@@ -240,7 +240,9 @@ jobs:
240
240
  ${environmentLine} steps:
241
241
  - uses: actions/checkout@v4
242
242
  - name: Deploy to run402
243
- run: npx --yes run402@${RUN402_VERSION} deploy apply --manifest ${shellQuote(manifest)} --project ${shellQuote(projectId)}
243
+ # Redirect stdin from /dev/null: a CI runner's stdin is a FIFO/file that
244
+ # older run402 CLIs counted as a second manifest source alongside --manifest.
245
+ run: npx --yes run402@${RUN402_VERSION} deploy apply --manifest ${shellQuote(manifest)} --project ${shellQuote(projectId)} < /dev/null
244
246
  `;
245
247
  }
246
248
 
package/lib/deploy-v2.mjs CHANGED
@@ -93,7 +93,7 @@ Options:
93
93
  --allow-warnings Continue past plan warnings that require confirmation
94
94
 
95
95
  Output:
96
- stdout: { "status": "ok", "release_id": "rel_...", "operation_id": "op_...", "urls": {...}, "warnings": [...] }
96
+ stdout: { "release_id": "rel_...", "operation_id": "op_...", "urls": {...}, "warnings": [...] }
97
97
  stderr: one JSON event per line (suppressed with --quiet or --final-only)
98
98
 
99
99
  Secrets:
@@ -141,7 +141,7 @@ the pointer-swap activation). The gateway re-runs only the failed phase
141
141
  forward — SQL is never replayed.
142
142
 
143
143
  Output:
144
- stdout: { "status": "ok", "release_id": "...", "operation_id": "...", "urls": {...} }
144
+ stdout: { "release_id": "...", "operation_id": "...", "urls": {...} }
145
145
  stderr: one JSON event per line (suppressed with --quiet)
146
146
  `;
147
147
 
@@ -155,7 +155,7 @@ Options:
155
155
  --limit <n> Maximum number of operations to return
156
156
 
157
157
  Output:
158
- stdout: { "status": "ok", "operations": [...], "cursor": "..." | null }
158
+ stdout: { "operations": [...], "cursor": "..." | null }
159
159
  `;
160
160
 
161
161
  const EVENTS_HELP = `run402 deploy events — Fetch the recorded event stream for a deploy operation
@@ -167,7 +167,7 @@ Options:
167
167
  --project <id> Project ID that owns the operation (default: active project)
168
168
 
169
169
  Output:
170
- stdout: { "status": "ok", "events": [...] }
170
+ stdout: { "events": [...] }
171
171
  `;
172
172
 
173
173
  const RELEASE_HELP = `run402 deploy release — Inspect deploy release inventory and diffs
@@ -183,8 +183,8 @@ Subcommands:
183
183
  diff Diff two release targets
184
184
 
185
185
  Output:
186
- get/active: { "status": "ok", "release": {...} } # includes route inventory and inventory warnings when returned
187
- diff: { "status": "ok", "diff": {...} } # includes route added/removed/changed diff buckets
186
+ get/active: { "release": {...} } # includes route inventory and inventory warnings when returned
187
+ diff: { "diff": {...} } # includes route added/removed/changed diff buckets
188
188
  `;
189
189
 
190
190
  const RELEASE_GET_HELP = `run402 deploy release get — Fetch a release inventory by id
@@ -197,7 +197,7 @@ Options:
197
197
  --site-limit <n> Maximum site path entries to include (gateway default: 5000)
198
198
 
199
199
  Output:
200
- stdout: { "status": "ok", "release": {...} } # preserves full routes inventory and warnings
200
+ stdout: { "release": {...} } # preserves full routes inventory and warnings
201
201
  `;
202
202
 
203
203
  const RELEASE_ACTIVE_HELP = `run402 deploy release active — Fetch the active release inventory
@@ -210,7 +210,7 @@ Options:
210
210
  --site-limit <n> Maximum site path entries to include (gateway default: 5000)
211
211
 
212
212
  Output:
213
- stdout: { "status": "ok", "release": {...} } # preserves full routes inventory and warnings
213
+ stdout: { "release": {...} } # preserves full routes inventory and warnings
214
214
  `;
215
215
 
216
216
  const RELEASE_DIFF_HELP = `run402 deploy release diff — Diff two release targets
@@ -225,7 +225,7 @@ Options:
225
225
  --limit <n> Maximum entries per site diff bucket (gateway default: 1000)
226
226
 
227
227
  Output:
228
- stdout: { "status": "ok", "diff": {...} } # preserves routes.added/removed/changed
228
+ stdout: { "diff": {...} } # preserves routes.added/removed/changed
229
229
  `;
230
230
 
231
231
  const DIAGNOSE_HELP = `run402 deploy diagnose — Diagnose a Run402 public URL
@@ -244,7 +244,7 @@ Options:
244
244
  --method <method> HTTP method to diagnose (default: GET)
245
245
 
246
246
  Output:
247
- stdout: { "status": "ok", "would_serve": true|false, "diagnostic_status": 200|404|..., "match": "...", "summary": "...", "request": {...}, "warnings": [...], "resolution": {...}, "next_steps": [...] }
247
+ stdout: { "would_serve": true|false, "diagnostic_status": 200|404|..., "match": "...", "summary": "...", "request": {...}, "warnings": [...], "resolution": {...}, "next_steps": [...] }
248
248
  `;
249
249
 
250
250
  const RESOLVE_HELP = `run402 deploy resolve — Low-level deploy URL diagnostics
@@ -326,7 +326,6 @@ Options:
326
326
 
327
327
  Output:
328
328
  stdout: {
329
- "status": "ok",
330
329
  "release_id": "rel_old_abc123",
331
330
  "operation_id": "op_...",
332
331
  "previous_release_id": "rel_new_xxx",
@@ -559,11 +558,35 @@ function parseApplyArgs(args) {
559
558
  return opts;
560
559
  }
561
560
 
562
- function applySourceField(opts) {
563
- if (opts.manifest !== null) return "manifest";
564
- if (opts.spec !== null) return "spec";
565
- if (opts.dir !== null && !hasStdinSource()) return "dir";
566
- return "stdin";
561
+ // Resolve the single manifest source from parsed opts + whether stdin actually
562
+ // has data (a pipe/file on fd 0). Explicit --manifest/--spec/--dir take
563
+ // precedence over incidental stdin: a CI runner (e.g. GitHub Actions) hands the
564
+ // step a FIFO/file stdin, which must NOT be mistaken for a piped manifest when a
565
+ // source flag is given. Exported for unit testing. Returns { source } | { error }.
566
+ export function resolveApplySource(opts, stdinPresent) {
567
+ const explicit = [];
568
+ if (opts.manifest !== null) explicit.push("--manifest");
569
+ if (opts.spec !== null) explicit.push("--spec");
570
+ if (explicit.length > 1) {
571
+ return {
572
+ error: {
573
+ code: "BAD_USAGE",
574
+ message: "Only one deploy manifest source may be provided: --manifest or --spec.",
575
+ details: { sources: explicit },
576
+ },
577
+ };
578
+ }
579
+ if (opts.manifest !== null) return { source: "manifest" };
580
+ if (opts.spec !== null) return { source: "spec" };
581
+ if (opts.dir !== null) return { source: "dir" };
582
+ if (stdinPresent) return { source: "stdin" };
583
+ return {
584
+ error: {
585
+ code: "BAD_USAGE",
586
+ message: "No deploy manifest provided. Use --manifest <path>, --spec '<json>', --dir <build>, or pipe a manifest on stdin.",
587
+ details: {},
588
+ },
589
+ };
567
590
  }
568
591
 
569
592
  async function mergeAstroReleaseSlice(spec, dirArg) {
@@ -621,29 +644,16 @@ async function mergeAstroReleaseSlice(spec, dirArg) {
621
644
  spec.functions = { replace: { ...existingFns, ...sliceFns } };
622
645
  }
623
646
 
624
- function validateApplySources(opts) {
625
- const sources = [];
626
- if (opts.manifest !== null) sources.push("--manifest");
627
- if (opts.spec !== null) sources.push("--spec");
628
- if (hasStdinSource()) sources.push("stdin");
629
- if (sources.length > 1) {
630
- fail({
631
- code: "BAD_USAGE",
632
- message: "Only one deploy manifest source may be provided: --spec, --manifest, or stdin.",
633
- details: { sources },
634
- });
635
- }
636
- }
637
-
638
647
  async function applyCmd(args) {
639
648
  const opts = parseApplyArgs(args);
640
- validateApplySources(opts);
649
+ const { source, error: sourceError } = resolveApplySource(opts, hasStdinSource());
650
+ if (sourceError) fail(sourceError);
641
651
 
642
652
  let raw;
643
653
  let manifestPath = null;
644
- if (opts.spec !== null) {
654
+ if (source === "spec") {
645
655
  raw = opts.spec;
646
- } else if (opts.manifest !== null) {
656
+ } else if (source === "manifest") {
647
657
  try {
648
658
  manifestPath = isAbsolute(opts.manifest) ? opts.manifest : resolve(process.cwd(), opts.manifest);
649
659
  raw = readFileSync(manifestPath, "utf-8");
@@ -654,11 +664,12 @@ async function applyCmd(args) {
654
664
  details: { flag: "--manifest", path: opts.manifest },
655
665
  });
656
666
  }
657
- } else if (opts.dir !== null && !hasStdinSource()) {
658
- // --dir without any other source: start from an empty spec and let the
667
+ } else if (source === "dir") {
668
+ // --dir without --manifest/--spec: start from an empty spec and let the
659
669
  // Astro release-slice fill in site/functions/routes below.
660
670
  raw = "{}";
661
671
  } else {
672
+ // source === "stdin": a manifest piped on stdin.
662
673
  raw = await readStdin();
663
674
  }
664
675
 
@@ -669,11 +680,11 @@ async function applyCmd(args) {
669
680
  fail({
670
681
  code: "BAD_USAGE",
671
682
  message: `Manifest is not valid JSON: ${err.message}`,
672
- details: { source: applySourceField(opts), parse_error: err.message },
683
+ details: { source, parse_error: err.message },
673
684
  });
674
685
  }
675
686
  rejectLegacySecretManifest(spec, {
676
- source: applySourceField(opts),
687
+ source,
677
688
  ...(manifestPath ? { path: manifestPath } : {}),
678
689
  });
679
690
 
@@ -720,7 +731,7 @@ async function applyCmd(args) {
720
731
  message: `Manifest contains no deployable sections. Expected at least one of: ${meaningful.join(", ")}`,
721
732
  hint: "Did you mean to write a 'site.replace' or 'database.migrations' block? See https://run402.com/schemas/manifest.v1.json",
722
733
  details: {
723
- field: applySourceField(opts),
734
+ field: source,
724
735
  ...(manifestPath ? { path: manifestPath } : {}),
725
736
  meaningful_keys: meaningful,
726
737
  },
package/lib/image.mjs CHANGED
@@ -20,7 +20,7 @@ Examples:
20
20
  run402 image generate "portrait of a cat CEO" --aspect portrait --output cat.png
21
21
 
22
22
  Output (without --output):
23
- { "status": "ok", "aspect": "square", "content_type": "image/png", "image": "<base64>" }
23
+ { "aspect": "square", "content_type": "image/png", "image": "<base64>" }
24
24
 
25
25
  Notes:
26
26
  - Requires a funded allowance (run402 allowance create && run402 allowance fund)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "run402",
3
- "version": "2.39.2",
3
+ "version": "2.39.4",
4
4
  "description": "CLI for Run402 — provision Postgres databases, deploy static sites, generate images, and manage wallets via x402 and MPP micropayments.",
5
5
  "type": "module",
6
6
  "bin": {