run402 1.70.0 → 2.0.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 +5 -5
- package/cli.mjs +4 -4
- package/lib/{blob.mjs → assets.mjs} +51 -51
- package/lib/billing.mjs +18 -2
- package/lib/deploy-v2.mjs +13 -13
- package/lib/sites.mjs +3 -3
- package/lib/tier.mjs +26 -4
- package/package.json +1 -1
- package/sdk/dist/errors.d.ts +23 -0
- package/sdk/dist/errors.d.ts.map +1 -1
- package/sdk/dist/errors.js +30 -0
- package/sdk/dist/errors.js.map +1 -1
- package/sdk/dist/index.d.ts +13 -6
- package/sdk/dist/index.d.ts.map +1 -1
- package/sdk/dist/index.js +13 -6
- package/sdk/dist/index.js.map +1 -1
- package/sdk/dist/namespaces/{blobs.d.ts → assets.d.ts} +3 -3
- package/sdk/dist/namespaces/assets.d.ts.map +1 -0
- package/sdk/dist/namespaces/{blobs.js → assets.js} +2 -2
- package/sdk/dist/namespaces/assets.js.map +1 -0
- package/sdk/dist/namespaces/{blobs.types.d.ts → assets.types.d.ts} +1 -1
- package/sdk/dist/namespaces/assets.types.d.ts.map +1 -0
- package/sdk/dist/namespaces/{blobs.types.js → assets.types.js} +1 -1
- package/sdk/dist/namespaces/assets.types.js.map +1 -0
- package/sdk/dist/namespaces/billing.d.ts +31 -2
- package/sdk/dist/namespaces/billing.d.ts.map +1 -1
- package/sdk/dist/namespaces/billing.js +8 -2
- package/sdk/dist/namespaces/billing.js.map +1 -1
- package/sdk/dist/namespaces/deploy.d.ts +3 -3
- package/sdk/dist/namespaces/deploy.js +20 -20
- package/sdk/dist/namespaces/deploy.js.map +1 -1
- package/sdk/dist/namespaces/deploy.types.d.ts +130 -4
- package/sdk/dist/namespaces/deploy.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/deploy.types.js +1 -1
- package/sdk/dist/namespaces/deploy.types.js.map +1 -1
- package/sdk/dist/node/assets-node.d.ts +205 -0
- package/sdk/dist/node/assets-node.d.ts.map +1 -0
- package/sdk/dist/node/assets-node.js +368 -0
- package/sdk/dist/node/assets-node.js.map +1 -0
- package/sdk/dist/node/canonicalize.d.ts +1 -1
- package/sdk/dist/node/canonicalize.js +1 -1
- package/sdk/dist/node/index.d.ts +9 -2
- package/sdk/dist/node/index.d.ts.map +1 -1
- package/sdk/dist/node/index.js +9 -0
- package/sdk/dist/node/index.js.map +1 -1
- package/sdk/dist/scoped.d.ts +38 -12
- package/sdk/dist/scoped.d.ts.map +1 -1
- package/sdk/dist/scoped.js +52 -35
- package/sdk/dist/scoped.js.map +1 -1
- package/sdk/dist/namespaces/blobs.d.ts.map +0 -1
- package/sdk/dist/namespaces/blobs.js.map +0 -1
- package/sdk/dist/namespaces/blobs.types.d.ts.map +0 -1
- package/sdk/dist/namespaces/blobs.types.js.map +0 -1
package/README.md
CHANGED
|
@@ -100,10 +100,10 @@ CI deploys can ship `site`, `functions`, `database`, and absent/current `base` c
|
|
|
100
100
|
### Storage (paste-and-go CDN assets)
|
|
101
101
|
|
|
102
102
|
```bash
|
|
103
|
-
run402
|
|
104
|
-
run402
|
|
105
|
-
run402
|
|
106
|
-
run402
|
|
103
|
+
run402 assets put ./logo.png # → AssetRef with cdn_url, sri, etag
|
|
104
|
+
run402 assets put ./asset --key assets/logo --content-type image/svg+xml
|
|
105
|
+
run402 assets get <key> --output /tmp/logo.png
|
|
106
|
+
run402 assets diagnose <url> # exit 0 if fresh, 1 if stale
|
|
107
107
|
```
|
|
108
108
|
|
|
109
109
|
The returned `cdn_url` is content-addressed (`pr-<public_id>.run402.com/_blob/<key>-<8hex>.<ext>`) — paste it straight into HTML. SRI is bundled in `sri`.
|
|
@@ -199,7 +199,7 @@ Every command supports `--help` / `-h`:
|
|
|
199
199
|
run402 --help
|
|
200
200
|
run402 projects --help
|
|
201
201
|
run402 sites --help
|
|
202
|
-
run402
|
|
202
|
+
run402 assets --help
|
|
203
203
|
run402 functions --help
|
|
204
204
|
```
|
|
205
205
|
|
package/cli.mjs
CHANGED
|
@@ -29,9 +29,9 @@ Commands:
|
|
|
29
29
|
ci Link GitHub Actions OIDC deploy bindings
|
|
30
30
|
functions Manage serverless functions (deploy, invoke, logs, list, delete)
|
|
31
31
|
secrets Manage project secrets (set, list, delete)
|
|
32
|
-
|
|
32
|
+
assets Direct-to-S3 asset storage (put, get, ls, rm, sign, diagnose) — up to 5 TiB
|
|
33
33
|
sites Deploy static sites
|
|
34
|
-
cdn CloudFront CDN diagnostics (wait-fresh) for public
|
|
34
|
+
cdn CloudFront CDN diagnostics (wait-fresh) for public asset URLs
|
|
35
35
|
subdomains Manage custom subdomains (claim, list, delete)
|
|
36
36
|
domains Manage custom domains (add, list, status, delete)
|
|
37
37
|
apps Browse and manage the app marketplace
|
|
@@ -139,8 +139,8 @@ switch (cmd) {
|
|
|
139
139
|
await run(sub, rest);
|
|
140
140
|
break;
|
|
141
141
|
}
|
|
142
|
-
case "
|
|
143
|
-
const { run } = await import("./lib/
|
|
142
|
+
case "assets": {
|
|
143
|
+
const { run } = await import("./lib/assets.mjs");
|
|
144
144
|
await run(sub, rest);
|
|
145
145
|
break;
|
|
146
146
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* run402
|
|
2
|
+
* run402 assets — direct-to-S3 storage CLI.
|
|
3
3
|
*
|
|
4
4
|
* Usage:
|
|
5
|
-
* run402
|
|
6
|
-
* run402
|
|
7
|
-
* run402
|
|
8
|
-
* run402
|
|
9
|
-
* run402
|
|
5
|
+
* run402 assets put <file> [files...] [--project <id>] [--key <dest>] [--content-type <mime>] [--private] [--immutable] [--concurrency N] [--no-resume]
|
|
6
|
+
* run402 assets get <key> --output <file> [--project <id>]
|
|
7
|
+
* run402 assets ls [--project <id>] [--prefix <p>] [--limit <n>]
|
|
8
|
+
* run402 assets rm <key> [--project <id>]
|
|
9
|
+
* run402 assets sign <key> [--project <id>] [--ttl <seconds>]
|
|
10
10
|
*
|
|
11
11
|
* For any file ≤ 5 GiB a single presigned PUT is used. Larger files use S3
|
|
12
12
|
* multipart uploads with 16 MiB parts (640 parts at 10 GiB; up to 10 000
|
|
@@ -43,12 +43,12 @@ import { assertKnownFlags, hasHelp, normalizeArgv, parseIntegerFlag } from "./ar
|
|
|
43
43
|
const HELP = `run402 blob — Direct-to-S3 blob storage
|
|
44
44
|
|
|
45
45
|
Usage:
|
|
46
|
-
run402
|
|
47
|
-
run402
|
|
48
|
-
run402
|
|
49
|
-
run402
|
|
50
|
-
run402
|
|
51
|
-
run402
|
|
46
|
+
run402 assets put <file> [files...] [options]
|
|
47
|
+
run402 assets get <key> --output <file> [options]
|
|
48
|
+
run402 assets ls [options]
|
|
49
|
+
run402 assets rm <key> [options]
|
|
50
|
+
run402 assets sign <key> [options]
|
|
51
|
+
run402 assets diagnose <url> [options]
|
|
52
52
|
|
|
53
53
|
Options:
|
|
54
54
|
--project <id> Project ID (defaults to active project from 'run402 projects use')
|
|
@@ -65,20 +65,20 @@ Options:
|
|
|
65
65
|
--ttl <seconds> Signed-URL TTL (sign only; default 3600, min 60, max 604800)
|
|
66
66
|
|
|
67
67
|
Examples:
|
|
68
|
-
run402
|
|
69
|
-
run402
|
|
70
|
-
run402
|
|
71
|
-
run402
|
|
72
|
-
run402
|
|
73
|
-
run402
|
|
74
|
-
run402
|
|
68
|
+
run402 assets put ./artifact.tgz --project prj_abc123
|
|
69
|
+
run402 assets put ./dist/**/*.png --project prj_abc123 --key assets/
|
|
70
|
+
run402 assets put huge.bin --project prj_abc123 --immutable
|
|
71
|
+
run402 assets get images/logo.png --output /tmp/logo.png --project prj_abc123
|
|
72
|
+
run402 assets ls --project prj_abc123 --prefix images/
|
|
73
|
+
run402 assets rm images/logo.png --project prj_abc123
|
|
74
|
+
run402 assets sign images/logo.png --project prj_abc123 --ttl 600
|
|
75
75
|
`;
|
|
76
76
|
|
|
77
77
|
const SUB_HELP = {
|
|
78
|
-
put: `run402
|
|
78
|
+
put: `run402 assets put — Upload one or more files to blob storage
|
|
79
79
|
|
|
80
80
|
Usage:
|
|
81
|
-
run402
|
|
81
|
+
run402 assets put <file> [files...] [options]
|
|
82
82
|
|
|
83
83
|
Arguments:
|
|
84
84
|
<file> Path to a file (or glob); pass multiple files to batch-upload
|
|
@@ -94,15 +94,15 @@ Options:
|
|
|
94
94
|
--json Emit NDJSON progress events on stdout (for agent consumption)
|
|
95
95
|
|
|
96
96
|
Examples:
|
|
97
|
-
run402
|
|
98
|
-
run402
|
|
99
|
-
run402
|
|
100
|
-
run402
|
|
97
|
+
run402 assets put ./artifact.tgz --project prj_abc123
|
|
98
|
+
run402 assets put ./dist/**/*.png --project prj_abc123 --key assets/
|
|
99
|
+
run402 assets put ./asset --project prj_abc123 --key assets/logo --content-type image/svg+xml
|
|
100
|
+
run402 assets put huge.bin --project prj_abc123 --immutable --concurrency 8
|
|
101
101
|
`,
|
|
102
|
-
get: `run402
|
|
102
|
+
get: `run402 assets get — Download a blob by key
|
|
103
103
|
|
|
104
104
|
Usage:
|
|
105
|
-
run402
|
|
105
|
+
run402 assets get <key> --output <file> [options]
|
|
106
106
|
|
|
107
107
|
Arguments:
|
|
108
108
|
<key> Blob key to download
|
|
@@ -112,12 +112,12 @@ Options:
|
|
|
112
112
|
--project <id> Project ID (defaults to active project)
|
|
113
113
|
|
|
114
114
|
Examples:
|
|
115
|
-
run402
|
|
115
|
+
run402 assets get images/logo.png --output /tmp/logo.png --project prj_abc123
|
|
116
116
|
`,
|
|
117
|
-
ls: `run402
|
|
117
|
+
ls: `run402 assets ls — List blob keys in a project
|
|
118
118
|
|
|
119
119
|
Usage:
|
|
120
|
-
run402
|
|
120
|
+
run402 assets ls [options]
|
|
121
121
|
|
|
122
122
|
Options:
|
|
123
123
|
--project <id> Project ID (defaults to active project)
|
|
@@ -125,13 +125,13 @@ Options:
|
|
|
125
125
|
--limit <n> Max results (default 100, max 1000)
|
|
126
126
|
|
|
127
127
|
Examples:
|
|
128
|
-
run402
|
|
129
|
-
run402
|
|
128
|
+
run402 assets ls --project prj_abc123
|
|
129
|
+
run402 assets ls --project prj_abc123 --prefix images/ --limit 500
|
|
130
130
|
`,
|
|
131
|
-
rm: `run402
|
|
131
|
+
rm: `run402 assets rm — Delete a blob
|
|
132
132
|
|
|
133
133
|
Usage:
|
|
134
|
-
run402
|
|
134
|
+
run402 assets rm <key> [options]
|
|
135
135
|
|
|
136
136
|
Arguments:
|
|
137
137
|
<key> Blob key to delete
|
|
@@ -140,12 +140,12 @@ Options:
|
|
|
140
140
|
--project <id> Project ID (defaults to active project)
|
|
141
141
|
|
|
142
142
|
Examples:
|
|
143
|
-
run402
|
|
143
|
+
run402 assets rm images/logo.png --project prj_abc123
|
|
144
144
|
`,
|
|
145
|
-
sign: `run402
|
|
145
|
+
sign: `run402 assets sign — Create a presigned download URL for a blob
|
|
146
146
|
|
|
147
147
|
Usage:
|
|
148
|
-
run402
|
|
148
|
+
run402 assets sign <key> [options]
|
|
149
149
|
|
|
150
150
|
Arguments:
|
|
151
151
|
<key> Blob key to sign
|
|
@@ -155,12 +155,12 @@ Options:
|
|
|
155
155
|
--ttl <seconds> Signed-URL TTL (default 3600, min 60, max 604800)
|
|
156
156
|
|
|
157
157
|
Examples:
|
|
158
|
-
run402
|
|
158
|
+
run402 assets sign reports/2025-q4.pdf --project prj_abc123 --ttl 600
|
|
159
159
|
`,
|
|
160
|
-
diagnose: `run402
|
|
160
|
+
diagnose: `run402 assets diagnose — Inspect the live CDN state for a public blob URL
|
|
161
161
|
|
|
162
162
|
Usage:
|
|
163
|
-
run402
|
|
163
|
+
run402 assets diagnose <url> [options]
|
|
164
164
|
|
|
165
165
|
Arguments:
|
|
166
166
|
<url> Full blob URL (e.g. https://app.run402.com/_blob/avatar.png)
|
|
@@ -178,10 +178,10 @@ Exit codes:
|
|
|
178
178
|
1 observed SHA does not match (or probe returned no SHA)
|
|
179
179
|
|
|
180
180
|
Agent loop pattern:
|
|
181
|
-
until run402
|
|
181
|
+
until run402 assets diagnose <url>; do sleep 1; done
|
|
182
182
|
|
|
183
183
|
Examples:
|
|
184
|
-
run402
|
|
184
|
+
run402 assets diagnose https://app.run402.com/_blob/avatar.png
|
|
185
185
|
`,
|
|
186
186
|
};
|
|
187
187
|
|
|
@@ -352,7 +352,7 @@ async function putOne(projectId, filePath, opts) {
|
|
|
352
352
|
let initRes;
|
|
353
353
|
if (state) {
|
|
354
354
|
// Re-poll the session; if it's still active, resume. Otherwise start fresh.
|
|
355
|
-
const poll = await getSdk().
|
|
355
|
+
const poll = await getSdk().assets.getUploadSession(projectId, state.upload_id);
|
|
356
356
|
if (poll.status === "active") {
|
|
357
357
|
log(opts, { event: "resume", upload_id: state.upload_id, key: destKey });
|
|
358
358
|
initRes = {
|
|
@@ -369,7 +369,7 @@ async function putOne(projectId, filePath, opts) {
|
|
|
369
369
|
}
|
|
370
370
|
|
|
371
371
|
if (!state) {
|
|
372
|
-
initRes = await getSdk().
|
|
372
|
+
initRes = await getSdk().assets.initUploadSession(projectId, {
|
|
373
373
|
key: destKey,
|
|
374
374
|
size_bytes: size,
|
|
375
375
|
content_type: opts.contentType ?? guessContentType(destKey),
|
|
@@ -417,7 +417,7 @@ async function putOne(projectId, filePath, opts) {
|
|
|
417
417
|
const body = initRes.mode === "multipart"
|
|
418
418
|
? { parts: etags.map((e, i) => ({ part_number: i + 1, etag: e.etag, sha256: e.sha256 })) }
|
|
419
419
|
: {};
|
|
420
|
-
const result = await getSdk().
|
|
420
|
+
const result = await getSdk().assets.completeUploadSession(projectId, state.upload_id, body, {
|
|
421
421
|
contentType: opts.contentType ?? guessContentType(destKey),
|
|
422
422
|
});
|
|
423
423
|
|
|
@@ -504,7 +504,7 @@ async function get(projectId, argv) {
|
|
|
504
504
|
|
|
505
505
|
let res;
|
|
506
506
|
try {
|
|
507
|
-
res = await getSdk().
|
|
507
|
+
res = await getSdk().assets.get(resolvedId, key);
|
|
508
508
|
} catch (err) {
|
|
509
509
|
reportSdkError(err);
|
|
510
510
|
return;
|
|
@@ -526,7 +526,7 @@ async function ls(projectId, argv) {
|
|
|
526
526
|
const resolvedId = resolveProjectId(opts.project);
|
|
527
527
|
|
|
528
528
|
try {
|
|
529
|
-
const data = await getSdk().
|
|
529
|
+
const data = await getSdk().assets.ls(resolvedId, {
|
|
530
530
|
prefix: opts.prefix ?? undefined,
|
|
531
531
|
limit: opts.limit ?? undefined,
|
|
532
532
|
});
|
|
@@ -549,7 +549,7 @@ async function rm(projectId, argv) {
|
|
|
549
549
|
const key = opts.positional[0];
|
|
550
550
|
|
|
551
551
|
try {
|
|
552
|
-
await getSdk().
|
|
552
|
+
await getSdk().assets.rm(resolvedId, key);
|
|
553
553
|
console.log(JSON.stringify({ status: "ok", key }));
|
|
554
554
|
} catch (err) {
|
|
555
555
|
reportSdkError(err);
|
|
@@ -569,7 +569,7 @@ async function diagnose(projectId, argv) {
|
|
|
569
569
|
const url = opts.positional[0];
|
|
570
570
|
|
|
571
571
|
try {
|
|
572
|
-
const env = await getSdk().
|
|
572
|
+
const env = await getSdk().assets.diagnoseUrl(resolvedId, url);
|
|
573
573
|
// Always print the JSON envelope for agent consumption (parseable).
|
|
574
574
|
console.log(JSON.stringify(env, null, 2));
|
|
575
575
|
// Vantage caveat to stderr so a TTY operator sees it; agent shell loops
|
|
@@ -578,7 +578,7 @@ async function diagnose(projectId, argv) {
|
|
|
578
578
|
`\n# probed once from ${env.vantage}; not a global view\n`,
|
|
579
579
|
);
|
|
580
580
|
// Exit code: 0 if observed === expected, 1 otherwise. Lets agents
|
|
581
|
-
// shell-script `until run402
|
|
581
|
+
// shell-script `until run402 assets diagnose <url>; do sleep 1; done`.
|
|
582
582
|
if (env.observedSha256 && env.observedSha256 === env.expectedSha256) {
|
|
583
583
|
process.exit(0);
|
|
584
584
|
}
|
|
@@ -597,7 +597,7 @@ async function sign(projectId, argv) {
|
|
|
597
597
|
const key = opts.positional[0];
|
|
598
598
|
|
|
599
599
|
try {
|
|
600
|
-
const data = await getSdk().
|
|
600
|
+
const data = await getSdk().assets.sign(resolvedId, key, {
|
|
601
601
|
ttl_seconds: opts.ttl ?? undefined,
|
|
602
602
|
});
|
|
603
603
|
console.log(JSON.stringify(data, null, 2));
|
package/lib/billing.mjs
CHANGED
|
@@ -117,6 +117,16 @@ Arguments:
|
|
|
117
117
|
<account_id> Billing account ID (e.g. acct_abc123)
|
|
118
118
|
<wallet> Wallet address (0x...) to link
|
|
119
119
|
|
|
120
|
+
Notes:
|
|
121
|
+
- Tier and quotas are per-billing-account. Linking a wallet merges its
|
|
122
|
+
spend into the account-wide pool that already includes every project
|
|
123
|
+
on this billing account.
|
|
124
|
+
- The response includes a 'pool_implications' block on v1.46+ gateways:
|
|
125
|
+
tier, projects_in_pool_count, account_api_calls_current,
|
|
126
|
+
account_storage_bytes_current, tier_limits, over_limit. Inspect
|
|
127
|
+
'over_limit' before linking a wallet whose existing usage might push
|
|
128
|
+
the merged pool past the tier cap.
|
|
129
|
+
|
|
120
130
|
Examples:
|
|
121
131
|
run402 billing link-wallet acct_abc123 0x1234abcd...
|
|
122
132
|
`,
|
|
@@ -179,8 +189,14 @@ async function linkWallet(args) {
|
|
|
179
189
|
});
|
|
180
190
|
}
|
|
181
191
|
try {
|
|
182
|
-
await getSdk().billing.linkWallet(accountId, wallet);
|
|
183
|
-
|
|
192
|
+
const data = await getSdk().billing.linkWallet(accountId, wallet);
|
|
193
|
+
const output = {
|
|
194
|
+
status: data?.status ?? "ok",
|
|
195
|
+
billing_account_id: data?.billing_account_id ?? accountId,
|
|
196
|
+
wallet: data?.wallet ?? wallet.toLowerCase(),
|
|
197
|
+
...(data?.pool_implications ? { pool_implications: data.pool_implications } : {}),
|
|
198
|
+
};
|
|
199
|
+
console.log(JSON.stringify(output, null, 2));
|
|
184
200
|
} catch (err) {
|
|
185
201
|
reportSdkError(err);
|
|
186
202
|
}
|
package/lib/deploy-v2.mjs
CHANGED
|
@@ -410,7 +410,7 @@ async function applyCmd(args) {
|
|
|
410
410
|
|
|
411
411
|
// GH-232: Reject empty specs client-side. Without this guard,
|
|
412
412
|
// `run402 deploy apply --spec '{}'` (and `--manifest <empty>`) would silently
|
|
413
|
-
// send an empty ReleaseSpec to /
|
|
413
|
+
// send an empty ReleaseSpec to /apply/v1/plans with no signal that nothing
|
|
414
414
|
// was deployed.
|
|
415
415
|
//
|
|
416
416
|
// `deploy apply` is v2-only — only meaningful keys are the v2 ReleaseSpec
|
|
@@ -488,11 +488,11 @@ async function applyCmd(args) {
|
|
|
488
488
|
};
|
|
489
489
|
} else {
|
|
490
490
|
// Preserve the aggressive early exit when no allowance is configured.
|
|
491
|
-
allowanceAuthHeaders("/
|
|
491
|
+
allowanceAuthHeaders("/apply/v1/plans");
|
|
492
492
|
}
|
|
493
493
|
|
|
494
494
|
try {
|
|
495
|
-
const result = await getSdk(sdkOpts).
|
|
495
|
+
const result = await getSdk(sdkOpts)._applyEngine.apply(releaseSpec, {
|
|
496
496
|
onEvent: makeStderrEventWriter(opts.quiet),
|
|
497
497
|
idempotencyKey,
|
|
498
498
|
allowWarnings: opts.allowWarnings,
|
|
@@ -815,10 +815,10 @@ async function resumeCmd(args) {
|
|
|
815
815
|
});
|
|
816
816
|
const opts = { operationId, quiet: Boolean(parsed.flags["--quiet"]) };
|
|
817
817
|
|
|
818
|
-
allowanceAuthHeaders("/
|
|
818
|
+
allowanceAuthHeaders("/apply/v1/operations");
|
|
819
819
|
|
|
820
820
|
try {
|
|
821
|
-
const result = await getSdk().
|
|
821
|
+
const result = await getSdk()._applyEngine.resume(opts.operationId, {
|
|
822
822
|
onEvent: makeStderrEventWriter(opts.quiet),
|
|
823
823
|
});
|
|
824
824
|
console.log(JSON.stringify({ status: "ok", ...result }, null, 2));
|
|
@@ -843,12 +843,12 @@ async function listCmd(args) {
|
|
|
843
843
|
};
|
|
844
844
|
|
|
845
845
|
const project = resolveProjectId(opts.project);
|
|
846
|
-
allowanceAuthHeaders("/
|
|
846
|
+
allowanceAuthHeaders("/apply/v1/operations");
|
|
847
847
|
|
|
848
848
|
try {
|
|
849
849
|
const sdkOpts = { project };
|
|
850
850
|
if (opts.limit !== null) sdkOpts.limit = opts.limit;
|
|
851
|
-
const result = await getSdk().
|
|
851
|
+
const result = await getSdk()._applyEngine.list(sdkOpts);
|
|
852
852
|
console.log(JSON.stringify({ status: "ok", ...result }, null, 2));
|
|
853
853
|
} catch (err) {
|
|
854
854
|
reportSdkError(err);
|
|
@@ -870,10 +870,10 @@ async function eventsCmd(args) {
|
|
|
870
870
|
const opts = { operationId, project: parsed.flags["--project"] ?? null };
|
|
871
871
|
|
|
872
872
|
const project = resolveProjectId(opts.project);
|
|
873
|
-
allowanceAuthHeaders("/
|
|
873
|
+
allowanceAuthHeaders("/apply/v1/operations");
|
|
874
874
|
|
|
875
875
|
try {
|
|
876
|
-
const result = await getSdk().
|
|
876
|
+
const result = await getSdk()._applyEngine.events(opts.operationId, { project });
|
|
877
877
|
console.log(JSON.stringify({ status: "ok", ...result }, null, 2));
|
|
878
878
|
} catch (err) {
|
|
879
879
|
reportSdkError(err);
|
|
@@ -921,7 +921,7 @@ async function releaseGetCmd(args) {
|
|
|
921
921
|
try {
|
|
922
922
|
const sdkOpts = { project, releaseId: opts.releaseId };
|
|
923
923
|
if (opts.siteLimit !== null) sdkOpts.siteLimit = opts.siteLimit;
|
|
924
|
-
const release = await getSdk().
|
|
924
|
+
const release = await getSdk()._applyEngine.getRelease(sdkOpts);
|
|
925
925
|
console.log(JSON.stringify({ status: "ok", release }, null, 2));
|
|
926
926
|
} catch (err) {
|
|
927
927
|
reportSdkError(err);
|
|
@@ -950,7 +950,7 @@ async function releaseActiveCmd(args) {
|
|
|
950
950
|
try {
|
|
951
951
|
const sdkOpts = { project };
|
|
952
952
|
if (opts.siteLimit !== null) sdkOpts.siteLimit = opts.siteLimit;
|
|
953
|
-
const release = await getSdk().
|
|
953
|
+
const release = await getSdk()._applyEngine.getActiveRelease(sdkOpts);
|
|
954
954
|
console.log(JSON.stringify({ status: "ok", release }, null, 2));
|
|
955
955
|
} catch (err) {
|
|
956
956
|
reportSdkError(err);
|
|
@@ -993,7 +993,7 @@ async function releaseDiffCmd(args) {
|
|
|
993
993
|
try {
|
|
994
994
|
const sdkOpts = { project, from: opts.from, to: opts.to };
|
|
995
995
|
if (opts.limit !== null) sdkOpts.limit = opts.limit;
|
|
996
|
-
const diff = await getSdk().
|
|
996
|
+
const diff = await getSdk()._applyEngine.diff(sdkOpts);
|
|
997
997
|
console.log(JSON.stringify({ status: "ok", diff }, null, 2));
|
|
998
998
|
} catch (err) {
|
|
999
999
|
reportSdkError(err);
|
|
@@ -1092,7 +1092,7 @@ async function printResolveEnvelope(input) {
|
|
|
1092
1092
|
}
|
|
1093
1093
|
|
|
1094
1094
|
try {
|
|
1095
|
-
const resolution = await getSdk().
|
|
1095
|
+
const resolution = await getSdk()._applyEngine.resolve(input);
|
|
1096
1096
|
const summary = buildDeployResolveSummary(resolution, request);
|
|
1097
1097
|
console.log(JSON.stringify({
|
|
1098
1098
|
status: "ok",
|
package/lib/sites.mjs
CHANGED
|
@@ -221,7 +221,7 @@ async function deploy(args) {
|
|
|
221
221
|
if (opts.manifest) resolveFilePathsInManifest(manifest, dirname(resolve(opts.manifest)));
|
|
222
222
|
|
|
223
223
|
// Preserve the aggressive early exit when no allowance is configured.
|
|
224
|
-
allowanceAuthHeaders("/
|
|
224
|
+
allowanceAuthHeaders("/apply/v1/plans");
|
|
225
225
|
|
|
226
226
|
const stage = stageFilesToTempDir(manifest.files || []);
|
|
227
227
|
try {
|
|
@@ -288,7 +288,7 @@ async function deployDir(args) {
|
|
|
288
288
|
if (opts.target !== undefined) failUnsupportedTarget();
|
|
289
289
|
|
|
290
290
|
// Preserve the aggressive early exit when no allowance is configured.
|
|
291
|
-
allowanceAuthHeaders("/
|
|
291
|
+
allowanceAuthHeaders("/apply/v1/plans");
|
|
292
292
|
|
|
293
293
|
let fileSet;
|
|
294
294
|
try {
|
|
@@ -323,7 +323,7 @@ async function deployDir(args) {
|
|
|
323
323
|
|
|
324
324
|
if (opts.dryRun) {
|
|
325
325
|
try {
|
|
326
|
-
const { plan } = await getSdk().
|
|
326
|
+
const { plan } = await getSdk()._applyEngine.plan({
|
|
327
327
|
project: projectId,
|
|
328
328
|
site: { replace: fileSet },
|
|
329
329
|
}, { dryRun: true });
|
package/lib/tier.mjs
CHANGED
|
@@ -8,11 +8,14 @@ Usage:
|
|
|
8
8
|
run402 tier <subcommand> [args...]
|
|
9
9
|
|
|
10
10
|
Subcommands:
|
|
11
|
-
status Show current tier, expiry, usage, and function caps when returned
|
|
11
|
+
status Show current tier, expiry, pool usage, and function caps when returned
|
|
12
12
|
set <tier> Subscribe, renew, or upgrade (pays via x402)
|
|
13
13
|
|
|
14
14
|
Tiers: prototype ($0.10/7d, free with testnet faucet), hobby ($5/30d), team ($20/30d)
|
|
15
15
|
|
|
16
|
+
Tier is per billing account. A single subscription covers every project on
|
|
17
|
+
the account; api_calls and storage_bytes are pooled across all of them.
|
|
18
|
+
|
|
16
19
|
The server auto-detects the action based on your allowance state:
|
|
17
20
|
- No tier or expired → subscribe
|
|
18
21
|
- Same tier, active → renew (extends from expiry)
|
|
@@ -32,7 +35,10 @@ Usage:
|
|
|
32
35
|
run402 tier status
|
|
33
36
|
|
|
34
37
|
Notes:
|
|
35
|
-
-
|
|
38
|
+
- Tier and quotas are per billing account. The 'pool_usage' block sums
|
|
39
|
+
api_calls and storage_bytes across every project on this account
|
|
40
|
+
(across every wallet linked to it), not just the requesting wallet.
|
|
41
|
+
- Returns the current tier name, status, expiry, and pool usage
|
|
36
42
|
- Newer gateways include function authoring caps such as max timeout,
|
|
37
43
|
max memory, max scheduled functions, minimum cron interval, and current
|
|
38
44
|
scheduled-function usage
|
|
@@ -55,6 +61,9 @@ Tiers:
|
|
|
55
61
|
team $20/30d
|
|
56
62
|
|
|
57
63
|
Notes:
|
|
64
|
+
Tier is per billing account, not per project. A successful subscribe,
|
|
65
|
+
renew, or upgrade applies immediately to every project on the account.
|
|
66
|
+
|
|
58
67
|
Server auto-detects action based on current allowance state:
|
|
59
68
|
- No tier or expired -> subscribe
|
|
60
69
|
- Same tier, active -> renew (extends from expiry)
|
|
@@ -62,6 +71,9 @@ Notes:
|
|
|
62
71
|
- Lower tier, active -> rejected (wait for expiry)
|
|
63
72
|
Pays via x402 micropayments.
|
|
64
73
|
|
|
74
|
+
After the call, the CLI refetches /tiers/v1/status and includes the
|
|
75
|
+
refreshed account-pooled usage as 'status_after' in the JSON output.
|
|
76
|
+
|
|
65
77
|
Examples:
|
|
66
78
|
run402 tier set prototype
|
|
67
79
|
run402 tier set hobby
|
|
@@ -107,8 +119,18 @@ async function set(args = []) {
|
|
|
107
119
|
});
|
|
108
120
|
}
|
|
109
121
|
try {
|
|
110
|
-
const
|
|
111
|
-
|
|
122
|
+
const sdk = getSdk();
|
|
123
|
+
const data = await sdk.tier.set(tierName);
|
|
124
|
+
let statusAfter = null;
|
|
125
|
+
try {
|
|
126
|
+
statusAfter = await sdk.tier.status();
|
|
127
|
+
} catch {
|
|
128
|
+
// Refetch failure is non-fatal; the set call already succeeded and
|
|
129
|
+
// the caller has the canonical lease/payment receipt in `data`.
|
|
130
|
+
statusAfter = null;
|
|
131
|
+
}
|
|
132
|
+
const output = statusAfter ? { ...data, status_after: statusAfter } : data;
|
|
133
|
+
console.log(JSON.stringify(output, null, 2));
|
|
112
134
|
} catch (err) {
|
|
113
135
|
reportSdkError(err);
|
|
114
136
|
}
|
package/package.json
CHANGED
package/sdk/dist/errors.d.ts
CHANGED
|
@@ -16,6 +16,14 @@
|
|
|
16
16
|
* and realms — value comparison, no class-identity dependency.
|
|
17
17
|
*/
|
|
18
18
|
export type Run402ErrorKind = "payment_required" | "project_not_found" | "unauthorized" | "api_error" | "network_error" | "local_error" | "deploy_error";
|
|
19
|
+
/**
|
|
20
|
+
* Quota-denial scope discriminator (v1.46+). Indicates whether a quota-related
|
|
21
|
+
* denial was enforced against the pooled billing-account total (`"account"`)
|
|
22
|
+
* or against an orphan project whose billing account row has been purged but
|
|
23
|
+
* cascade has not yet run (`"project"`). Lifted from `details.scope` on the
|
|
24
|
+
* gateway envelope; absent for errors unrelated to quota.
|
|
25
|
+
*/
|
|
26
|
+
export type Run402QuotaScope = "account" | "project";
|
|
19
27
|
export declare abstract class Run402Error extends Error {
|
|
20
28
|
/**
|
|
21
29
|
* Structural brand. Always `true` on any {@link Run402Error} subclass
|
|
@@ -52,6 +60,14 @@ export declare abstract class Run402Error extends Error {
|
|
|
52
60
|
readonly details?: unknown;
|
|
53
61
|
/** Advisory next actions from the gateway. Rendering them must not execute them. */
|
|
54
62
|
readonly nextActions?: unknown[];
|
|
63
|
+
/**
|
|
64
|
+
* Quota-denial scope (v1.46+). `"account"` for pooled billing-account
|
|
65
|
+
* denials; `"project"` for the orphan fallback (project whose billing
|
|
66
|
+
* account row was purged but cascade has not yet run). Lifted from
|
|
67
|
+
* `details.scope` when the gateway returned it. Undefined for errors
|
|
68
|
+
* that are not quota-related.
|
|
69
|
+
*/
|
|
70
|
+
readonly quotaScope?: Run402QuotaScope;
|
|
55
71
|
constructor(message: string, status: number | null, body: unknown, context: string);
|
|
56
72
|
/**
|
|
57
73
|
* Canonical structured envelope for `JSON.stringify`. Without this, an
|
|
@@ -175,6 +191,13 @@ export declare function isNetworkError(e: unknown): e is NetworkError;
|
|
|
175
191
|
export declare function isLocalError(e: unknown): e is LocalError;
|
|
176
192
|
/** True if `e` is a {@link Run402DeployError}. */
|
|
177
193
|
export declare function isDeployError(e: unknown): e is Run402DeployError;
|
|
194
|
+
/**
|
|
195
|
+
* Extract the v1.46+ quota-denial scope from an error. Returns `"account"`
|
|
196
|
+
* for pooled denials, `"project"` for the orphan fallback, or `undefined`
|
|
197
|
+
* when the error is not quota-related (or originated from a pre-v1.46
|
|
198
|
+
* gateway that did not set `details.scope`). Safe to call with `unknown`.
|
|
199
|
+
*/
|
|
200
|
+
export declare function getQuotaScope(e: unknown): Run402QuotaScope | undefined;
|
|
178
201
|
/**
|
|
179
202
|
* Canonical "should I retry this?" policy. Returns true when `e` is a
|
|
180
203
|
* {@link Run402Error} AND any of:
|
package/sdk/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH,MAAM,MAAM,eAAe,GACvB,kBAAkB,GAClB,mBAAmB,GACnB,cAAc,GACd,WAAW,GACX,eAAe,GACf,aAAa,GACb,cAAc,CAAC;AAEnB,8BAAsB,WAAY,SAAQ,KAAK;IAC7C;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,EAAG,IAAI,CAAU;IACvC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IACxC,iFAAiF;IACjF,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,2FAA2F;IAC3F,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,mFAAmF;IACnF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,+DAA+D;IAC/D,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,kDAAkD;IAClD,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,yFAAyF;IACzF,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,sEAAsE;IACtE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,mFAAmF;IACnF,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,oFAAoF;IACpF,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
package/sdk/dist/errors.js
CHANGED
|
@@ -40,6 +40,14 @@ export class Run402Error extends Error {
|
|
|
40
40
|
details;
|
|
41
41
|
/** Advisory next actions from the gateway. Rendering them must not execute them. */
|
|
42
42
|
nextActions;
|
|
43
|
+
/**
|
|
44
|
+
* Quota-denial scope (v1.46+). `"account"` for pooled billing-account
|
|
45
|
+
* denials; `"project"` for the orphan fallback (project whose billing
|
|
46
|
+
* account row was purged but cascade has not yet run). Lifted from
|
|
47
|
+
* `details.scope` when the gateway returned it. Undefined for errors
|
|
48
|
+
* that are not quota-related.
|
|
49
|
+
*/
|
|
50
|
+
quotaScope;
|
|
43
51
|
constructor(message, status, body, context) {
|
|
44
52
|
super(message);
|
|
45
53
|
this.name = this.constructor.name;
|
|
@@ -74,6 +82,9 @@ export class Run402Error extends Error {
|
|
|
74
82
|
}
|
|
75
83
|
if (Array.isArray(envelope?.next_actions))
|
|
76
84
|
this.nextActions = envelope.next_actions;
|
|
85
|
+
const scope = extractQuotaScope(envelope);
|
|
86
|
+
if (scope !== undefined)
|
|
87
|
+
this.quotaScope = scope;
|
|
77
88
|
}
|
|
78
89
|
/**
|
|
79
90
|
* Canonical structured envelope for `JSON.stringify`. Without this, an
|
|
@@ -97,6 +108,7 @@ export class Run402Error extends Error {
|
|
|
97
108
|
context: this.context,
|
|
98
109
|
details: this.details,
|
|
99
110
|
nextActions: this.nextActions,
|
|
111
|
+
quotaScope: this.quotaScope,
|
|
100
112
|
body: this.body,
|
|
101
113
|
};
|
|
102
114
|
}
|
|
@@ -106,6 +118,15 @@ function canonicalEnvelope(body) {
|
|
|
106
118
|
? body
|
|
107
119
|
: null;
|
|
108
120
|
}
|
|
121
|
+
function extractQuotaScope(envelope) {
|
|
122
|
+
if (!envelope)
|
|
123
|
+
return undefined;
|
|
124
|
+
const details = envelope.details;
|
|
125
|
+
if (!details || typeof details !== "object" || Array.isArray(details))
|
|
126
|
+
return undefined;
|
|
127
|
+
const scope = details.scope;
|
|
128
|
+
return scope === "account" || scope === "project" ? scope : undefined;
|
|
129
|
+
}
|
|
109
130
|
/** HTTP 402 — the gateway requires payment (lease expired, insufficient balance, or x402 quote). */
|
|
110
131
|
export class PaymentRequired extends Run402Error {
|
|
111
132
|
static DEFAULT_CODE = "PAYMENT_REQUIRED";
|
|
@@ -254,6 +275,15 @@ export function isLocalError(e) {
|
|
|
254
275
|
export function isDeployError(e) {
|
|
255
276
|
return isRun402Error(e) && e.kind === "deploy_error";
|
|
256
277
|
}
|
|
278
|
+
/**
|
|
279
|
+
* Extract the v1.46+ quota-denial scope from an error. Returns `"account"`
|
|
280
|
+
* for pooled denials, `"project"` for the orphan fallback, or `undefined`
|
|
281
|
+
* when the error is not quota-related (or originated from a pre-v1.46
|
|
282
|
+
* gateway that did not set `details.scope`). Safe to call with `unknown`.
|
|
283
|
+
*/
|
|
284
|
+
export function getQuotaScope(e) {
|
|
285
|
+
return isRun402Error(e) ? e.quotaScope : undefined;
|
|
286
|
+
}
|
|
257
287
|
/**
|
|
258
288
|
* Canonical "should I retry this?" policy. Returns true when `e` is a
|
|
259
289
|
* {@link Run402Error} AND any of:
|