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 +2 -2
- package/lib/ci.mjs +3 -1
- package/lib/deploy-v2.mjs +49 -38
- package/lib/image.mjs +1 -1
- package/package.json +1 -1
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
|
-
|
|
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: { "
|
|
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: { "
|
|
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: { "
|
|
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: { "
|
|
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: { "
|
|
187
|
-
diff: { "
|
|
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: { "
|
|
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: { "
|
|
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: { "
|
|
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: { "
|
|
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
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
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
|
-
|
|
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 (
|
|
654
|
+
if (source === "spec") {
|
|
645
655
|
raw = opts.spec;
|
|
646
|
-
} else if (
|
|
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 (
|
|
658
|
-
// --dir without
|
|
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
|
|
683
|
+
details: { source, parse_error: err.message },
|
|
673
684
|
});
|
|
674
685
|
}
|
|
675
686
|
rejectLegacySecretManifest(spec, {
|
|
676
|
-
source
|
|
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:
|
|
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
|
-
{ "
|
|
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