run402 1.52.0 → 1.53.1
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/lib/apps.mjs +1 -1
- package/lib/domains.mjs +13 -4
- package/lib/email.mjs +5 -10
- package/lib/projects.mjs +14 -4
- package/lib/sites.mjs +84 -1
- package/lib/subdomains.mjs +23 -7
- package/package.json +1 -1
- package/sdk/dist/errors.d.ts +73 -0
- package/sdk/dist/errors.d.ts.map +1 -1
- package/sdk/dist/errors.js +128 -0
- package/sdk/dist/errors.js.map +1 -1
- package/sdk/dist/index.d.ts +38 -2
- package/sdk/dist/index.d.ts.map +1 -1
- package/sdk/dist/index.js +55 -1
- package/sdk/dist/index.js.map +1 -1
- package/sdk/dist/namespaces/admin.d.ts +4 -1
- package/sdk/dist/namespaces/admin.d.ts.map +1 -1
- package/sdk/dist/namespaces/admin.js +1 -1
- package/sdk/dist/namespaces/admin.js.map +1 -1
- package/sdk/dist/namespaces/apps.d.ts +27 -30
- package/sdk/dist/namespaces/apps.d.ts.map +1 -1
- package/sdk/dist/namespaces/apps.js.map +1 -1
- package/sdk/dist/namespaces/billing.d.ts +15 -6
- package/sdk/dist/namespaces/billing.d.ts.map +1 -1
- package/sdk/dist/namespaces/billing.js.map +1 -1
- package/sdk/dist/namespaces/contracts.d.ts +67 -15
- package/sdk/dist/namespaces/contracts.d.ts.map +1 -1
- package/sdk/dist/namespaces/contracts.js +32 -8
- package/sdk/dist/namespaces/contracts.js.map +1 -1
- package/sdk/dist/namespaces/domains.d.ts +5 -1
- package/sdk/dist/namespaces/domains.d.ts.map +1 -1
- package/sdk/dist/namespaces/domains.js +1 -1
- package/sdk/dist/namespaces/domains.js.map +1 -1
- package/sdk/dist/namespaces/email.d.ts +21 -13
- package/sdk/dist/namespaces/email.d.ts.map +1 -1
- package/sdk/dist/namespaces/email.js +5 -4
- package/sdk/dist/namespaces/email.js.map +1 -1
- package/sdk/dist/namespaces/functions.d.ts +2 -2
- package/sdk/dist/namespaces/functions.d.ts.map +1 -1
- package/sdk/dist/namespaces/functions.js +1 -1
- package/sdk/dist/namespaces/functions.js.map +1 -1
- package/sdk/dist/namespaces/functions.types.d.ts +4 -0
- package/sdk/dist/namespaces/functions.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/projects.d.ts +12 -0
- package/sdk/dist/namespaces/projects.d.ts.map +1 -1
- package/sdk/dist/namespaces/projects.js +15 -5
- package/sdk/dist/namespaces/projects.js.map +1 -1
- package/sdk/dist/namespaces/projects.types.d.ts +9 -1
- package/sdk/dist/namespaces/projects.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/secrets.d.ts +5 -1
- package/sdk/dist/namespaces/secrets.d.ts.map +1 -1
- package/sdk/dist/namespaces/secrets.js +1 -1
- package/sdk/dist/namespaces/secrets.js.map +1 -1
- package/sdk/dist/namespaces/sender-domain.d.ts +4 -1
- package/sdk/dist/namespaces/sender-domain.d.ts.map +1 -1
- package/sdk/dist/namespaces/sender-domain.js +1 -1
- package/sdk/dist/namespaces/sender-domain.js.map +1 -1
- package/sdk/dist/namespaces/service.d.ts +11 -31
- package/sdk/dist/namespaces/service.d.ts.map +1 -1
- package/sdk/dist/namespaces/service.js.map +1 -1
- package/sdk/dist/namespaces/subdomains.d.ts +10 -1
- package/sdk/dist/namespaces/subdomains.d.ts.map +1 -1
- package/sdk/dist/namespaces/subdomains.js +1 -1
- package/sdk/dist/namespaces/subdomains.js.map +1 -1
- package/sdk/dist/namespaces/tier.d.ts +9 -1
- package/sdk/dist/namespaces/tier.d.ts.map +1 -1
- package/sdk/dist/namespaces/tier.js.map +1 -1
- package/sdk/dist/node/index.d.ts +2 -2
- package/sdk/dist/node/index.d.ts.map +1 -1
- package/sdk/dist/node/index.js +1 -1
- package/sdk/dist/node/index.js.map +1 -1
- package/sdk/dist/retry.d.ts +50 -0
- package/sdk/dist/retry.d.ts.map +1 -0
- package/sdk/dist/retry.js +61 -0
- package/sdk/dist/retry.js.map +1 -0
- package/sdk/dist/scoped.d.ts +248 -0
- package/sdk/dist/scoped.d.ts.map +1 -0
- package/sdk/dist/scoped.js +443 -0
- package/sdk/dist/scoped.js.map +1 -0
package/lib/apps.mjs
CHANGED
|
@@ -72,7 +72,7 @@ Arguments:
|
|
|
72
72
|
Options:
|
|
73
73
|
--description <d> Human-readable description of the app
|
|
74
74
|
--tags <t1,t2> Comma-separated list of tags
|
|
75
|
-
--visibility <v> Visibility: 'public' or 'private'
|
|
75
|
+
--visibility <v> Visibility: 'public', 'unlisted', or 'private'
|
|
76
76
|
--fork-allowed Allow other users to fork this app
|
|
77
77
|
|
|
78
78
|
Examples:
|
package/lib/domains.mjs
CHANGED
|
@@ -11,14 +11,14 @@ Subcommands:
|
|
|
11
11
|
add <domain> <subdomain_name> [--project <id>] Register a custom domain
|
|
12
12
|
list [<id>] List custom domains for a project
|
|
13
13
|
status <domain> [--project <id>] Check domain DNS/SSL status
|
|
14
|
-
delete <domain> [--project <id>]
|
|
14
|
+
delete <domain> --confirm [--project <id>] Release a custom domain. Requires --confirm.
|
|
15
15
|
|
|
16
16
|
Examples:
|
|
17
17
|
run402 domains add example.com myapp
|
|
18
18
|
run402 domains add example.com myapp --project prj_123
|
|
19
19
|
run402 domains list
|
|
20
20
|
run402 domains status example.com
|
|
21
|
-
run402 domains delete example.com
|
|
21
|
+
run402 domains delete example.com --confirm
|
|
22
22
|
|
|
23
23
|
Notes:
|
|
24
24
|
- After adding a domain, configure DNS as shown in the response
|
|
@@ -75,8 +75,17 @@ async function status(args) {
|
|
|
75
75
|
|
|
76
76
|
async function deleteDomain(args) {
|
|
77
77
|
const { project, rest } = parseProjectFlag(args);
|
|
78
|
-
const domain = rest
|
|
79
|
-
if (!domain) { console.error("Usage: run402 domains delete <domain> [--project <id>]"); process.exit(1); }
|
|
78
|
+
const domain = rest.find((a) => !a.startsWith("--"));
|
|
79
|
+
if (!domain) { console.error("Usage: run402 domains delete <domain> --confirm [--project <id>]"); process.exit(1); }
|
|
80
|
+
if (!Array.isArray(args) || !args.includes("--confirm")) {
|
|
81
|
+
console.error(JSON.stringify({
|
|
82
|
+
status: "error",
|
|
83
|
+
code: "CONFIRMATION_REQUIRED",
|
|
84
|
+
message: `Destructive: releasing custom domain '${domain}' detaches it from this project and clears its DNS/SSL configuration. This is irreversible. Re-run with --confirm to proceed.`,
|
|
85
|
+
details: { domain },
|
|
86
|
+
}));
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
80
89
|
const projectId = resolveProjectId(project);
|
|
81
90
|
try {
|
|
82
91
|
await getSdk().domains.remove(domain, { projectId });
|
package/lib/email.mjs
CHANGED
|
@@ -167,12 +167,7 @@ async function create(args) {
|
|
|
167
167
|
|
|
168
168
|
try {
|
|
169
169
|
const data = await getSdk().email.createMailbox(projectId, slug);
|
|
170
|
-
|
|
171
|
-
if (data.slug) {
|
|
172
|
-
console.log(JSON.stringify({ status: "ok", mailbox_id: data.mailbox_id, address: data.address, slug: data.slug }));
|
|
173
|
-
} else {
|
|
174
|
-
console.log(JSON.stringify({ status: "ok", mailbox_id: data.mailbox_id, address: data.address, already_existed: true }));
|
|
175
|
-
}
|
|
170
|
+
console.log(JSON.stringify({ status: "ok", mailbox_id: data.mailbox_id, address: data.address, slug: data.slug }));
|
|
176
171
|
} catch (err) {
|
|
177
172
|
reportSdkError(err);
|
|
178
173
|
}
|
|
@@ -203,7 +198,7 @@ async function send(args) {
|
|
|
203
198
|
text: text ?? undefined,
|
|
204
199
|
from_name: fromName ?? undefined,
|
|
205
200
|
});
|
|
206
|
-
console.log(JSON.stringify({ status: "ok", message_id: data.
|
|
201
|
+
console.log(JSON.stringify({ status: "ok", message_id: data.message_id, to: data.to, template: data.template, subject: data.subject }));
|
|
207
202
|
} catch (err) {
|
|
208
203
|
reportSdkError(err);
|
|
209
204
|
}
|
|
@@ -325,7 +320,7 @@ async function reply(args) {
|
|
|
325
320
|
from_name: fromName ?? undefined,
|
|
326
321
|
in_reply_to: messageId,
|
|
327
322
|
});
|
|
328
|
-
console.log(JSON.stringify({ status: "ok", message_id: data.
|
|
323
|
+
console.log(JSON.stringify({ status: "ok", message_id: data.message_id, to: data.to, subject: replySubject, in_reply_to: messageId }));
|
|
329
324
|
} catch (err) {
|
|
330
325
|
reportSdkError(err);
|
|
331
326
|
}
|
|
@@ -352,8 +347,8 @@ async function deleteMailbox(args) {
|
|
|
352
347
|
}
|
|
353
348
|
|
|
354
349
|
try {
|
|
355
|
-
await getSdk().email.deleteMailbox(projectId, positional ?? undefined);
|
|
356
|
-
console.log(JSON.stringify({ status: "ok", mailbox_id:
|
|
350
|
+
const data = await getSdk().email.deleteMailbox(projectId, positional ?? undefined);
|
|
351
|
+
console.log(JSON.stringify({ status: "ok", mailbox_id: data.mailbox_id, address: data.address, deleted: true }));
|
|
357
352
|
} catch (err) {
|
|
358
353
|
reportSdkError(err);
|
|
359
354
|
}
|
package/lib/projects.mjs
CHANGED
|
@@ -22,7 +22,7 @@ Subcommands:
|
|
|
22
22
|
apply-expose [id] <manifest_json> Apply a declarative authorization manifest
|
|
23
23
|
apply-expose [id] --file <path> Apply a manifest from a JSON file
|
|
24
24
|
get-expose [id] Get the current authorization manifest
|
|
25
|
-
delete [id]
|
|
25
|
+
delete [id] --confirm Immediately and irreversibly delete a project (cascade purge) and remove from local state. Requires --confirm.
|
|
26
26
|
pin [id] Pin a project (admin only; project owners get 403 admin_required)
|
|
27
27
|
promote-user [id] <email> Promote a user to project_admin role
|
|
28
28
|
demote-user [id] <email> Demote a user from project_admin role
|
|
@@ -43,7 +43,7 @@ Examples:
|
|
|
43
43
|
run402 projects apply-expose abc123 --file manifest.json
|
|
44
44
|
run402 projects get-expose abc123
|
|
45
45
|
run402 projects keys abc123
|
|
46
|
-
run402 projects delete abc123
|
|
46
|
+
run402 projects delete abc123 --confirm
|
|
47
47
|
|
|
48
48
|
Notes:
|
|
49
49
|
- <id> is the project_id shown in 'run402 projects list' (prefix: 'prj_')
|
|
@@ -302,7 +302,17 @@ async function demoteUser(projectId, email) {
|
|
|
302
302
|
console.log(JSON.stringify(data, null, 2));
|
|
303
303
|
}
|
|
304
304
|
|
|
305
|
-
async function deleteProject(projectId) {
|
|
305
|
+
async function deleteProject(projectId, args = []) {
|
|
306
|
+
const confirmed = Array.isArray(args) && args.includes("--confirm");
|
|
307
|
+
if (!confirmed) {
|
|
308
|
+
console.error(JSON.stringify({
|
|
309
|
+
status: "error",
|
|
310
|
+
code: "CONFIRMATION_REQUIRED",
|
|
311
|
+
message: `Destructive: deleting project ${projectId} drops all DB schemas, functions, subdomains, mailbox, blobs, and secrets. This is irreversible. Re-run with --confirm to proceed.`,
|
|
312
|
+
details: { project_id: projectId, destroys: ["schemas", "functions", "subdomains", "mailbox", "blobs", "secrets"] },
|
|
313
|
+
}));
|
|
314
|
+
process.exit(1);
|
|
315
|
+
}
|
|
306
316
|
try {
|
|
307
317
|
await getSdk().projects.delete(projectId);
|
|
308
318
|
console.log(JSON.stringify({ status: "ok", message: `Project ${projectId} deleted.` }));
|
|
@@ -346,7 +356,7 @@ export async function run(sub, args) {
|
|
|
346
356
|
case "schema": { const { projectId } = resolvePositionalProject(args); await schema(projectId); break; }
|
|
347
357
|
case "apply-expose": { const { projectId, rest } = resolvePositionalProject(args); await applyExpose(projectId, rest); break; }
|
|
348
358
|
case "get-expose": { const { projectId } = resolvePositionalProject(args); await getExpose(projectId); break; }
|
|
349
|
-
case "delete": { const { projectId } = resolvePositionalProject(args); await deleteProject(projectId); break; }
|
|
359
|
+
case "delete": { const { projectId, rest } = resolvePositionalProject(args); await deleteProject(projectId, rest); break; }
|
|
350
360
|
case "pin": { const { projectId } = resolvePositionalProject(args); await pin(projectId); break; }
|
|
351
361
|
case "promote-user": { const { projectId, rest } = resolvePositionalProject(args); await promoteUser(projectId, rest[0]); break; }
|
|
352
362
|
case "demote-user": { const { projectId, rest } = resolvePositionalProject(args); await demoteUser(projectId, rest[0]); break; }
|
package/lib/sites.mjs
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "fs";
|
|
2
2
|
import { tmpdir } from "os";
|
|
3
3
|
import { dirname, join, resolve } from "path";
|
|
4
|
+
import { fileSetFromDir } from "#sdk/node";
|
|
4
5
|
import { allowanceAuthHeaders, resolveProjectId, updateProject } from "./config.mjs";
|
|
5
6
|
import { resolveFilePathsInManifest } from "./manifest.mjs";
|
|
6
7
|
import { getSdk } from "./sdk.mjs";
|
|
7
8
|
import { reportSdkError } from "./sdk-errors.mjs";
|
|
8
9
|
|
|
10
|
+
const SMALL_DIR_THRESHOLD = 5;
|
|
11
|
+
|
|
9
12
|
const HELP = `run402 sites - Deploy and manage static sites
|
|
10
13
|
|
|
11
14
|
Usage:
|
|
@@ -28,6 +31,9 @@ Options (deploy-dir):
|
|
|
28
31
|
--project <id> Project ID (defaults to active project)
|
|
29
32
|
--target <target> Deployment target (e.g. 'production')
|
|
30
33
|
--quiet Suppress progress events on stderr
|
|
34
|
+
--dry-run Plan-only: print the diff envelope and exit
|
|
35
|
+
--confirm-prune Required when <path> has fewer files than the
|
|
36
|
+
small-dir guardrail threshold
|
|
31
37
|
|
|
32
38
|
Manifest format (JSON):
|
|
33
39
|
{
|
|
@@ -97,6 +103,7 @@ Examples:
|
|
|
97
103
|
|
|
98
104
|
Usage:
|
|
99
105
|
run402 sites deploy-dir <path> [--project <id>] [--target <target>] [--quiet]
|
|
106
|
+
[--dry-run] [--confirm-prune]
|
|
100
107
|
|
|
101
108
|
Arguments:
|
|
102
109
|
<path> Local directory to deploy (positional, required)
|
|
@@ -106,11 +113,23 @@ Options:
|
|
|
106
113
|
--target <target> Deployment target (e.g. 'production')
|
|
107
114
|
--quiet Suppress progress events on stderr (events are on by
|
|
108
115
|
default — see Progress events below)
|
|
116
|
+
--dry-run Plan the deploy and print a JSON envelope describing
|
|
117
|
+
what would happen, then exit. Does NOT upload bytes
|
|
118
|
+
or commit a release.
|
|
119
|
+
--confirm-prune Acknowledge that deploying <path> may remove files
|
|
120
|
+
that exist in the current site but are absent from
|
|
121
|
+
<path>. Required when <path> contains fewer than
|
|
122
|
+
${SMALL_DIR_THRESHOLD} files (the small-dir guardrail).
|
|
109
123
|
|
|
110
124
|
Behavior:
|
|
111
125
|
- Walks <path> recursively, skips .git / node_modules / .DS_Store
|
|
112
126
|
- Computes per-file SHA-256 and uploads only bytes the gateway doesn't
|
|
113
127
|
already have (CAS-backed unified deploy primitive)
|
|
128
|
+
- A static-site deploy REPLACES the live release: any path in the current
|
|
129
|
+
site that is absent from <path> is removed from the new release. To
|
|
130
|
+
avoid accidentally wiping a multi-page site by deploying a single-file
|
|
131
|
+
directory, a small <path> (fewer than ${SMALL_DIR_THRESHOLD} files) requires
|
|
132
|
+
--confirm-prune.
|
|
114
133
|
- Symlinks are rejected (no following)
|
|
115
134
|
- Paths in the manifest are POSIX-style relative to <path>
|
|
116
135
|
|
|
@@ -131,6 +150,8 @@ Examples:
|
|
|
131
150
|
run402 sites deploy-dir ./dist --project prj_abc
|
|
132
151
|
run402 sites deploy-dir ./my-site --project prj_abc --target production
|
|
133
152
|
run402 sites deploy-dir ./dist --project prj_abc --quiet
|
|
153
|
+
run402 sites deploy-dir ./tiny-site --project prj_abc --confirm-prune
|
|
154
|
+
run402 sites deploy-dir ./dist --project prj_abc --dry-run
|
|
134
155
|
`,
|
|
135
156
|
};
|
|
136
157
|
|
|
@@ -207,12 +228,21 @@ async function deploy(args) {
|
|
|
207
228
|
}
|
|
208
229
|
|
|
209
230
|
async function deployDir(args) {
|
|
210
|
-
const opts = {
|
|
231
|
+
const opts = {
|
|
232
|
+
dir: null,
|
|
233
|
+
project: undefined,
|
|
234
|
+
target: undefined,
|
|
235
|
+
quiet: false,
|
|
236
|
+
dryRun: false,
|
|
237
|
+
confirmPrune: false,
|
|
238
|
+
};
|
|
211
239
|
for (let i = 0; i < args.length; i++) {
|
|
212
240
|
if (args[i] === "--help" || args[i] === "-h") { console.log(SUB_HELP["deploy-dir"]); process.exit(0); }
|
|
213
241
|
if (args[i] === "--project" && args[i + 1]) { opts.project = args[++i]; continue; }
|
|
214
242
|
if (args[i] === "--target" && args[i + 1]) { opts.target = args[++i]; continue; }
|
|
215
243
|
if (args[i] === "--quiet") { opts.quiet = true; continue; }
|
|
244
|
+
if (args[i] === "--dry-run") { opts.dryRun = true; continue; }
|
|
245
|
+
if (args[i] === "--confirm-prune") { opts.confirmPrune = true; continue; }
|
|
216
246
|
if (args[i] === "--inherit") {
|
|
217
247
|
console.error(JSON.stringify({
|
|
218
248
|
status: "error",
|
|
@@ -231,6 +261,59 @@ async function deployDir(args) {
|
|
|
231
261
|
// Preserve the aggressive early exit when no allowance is configured.
|
|
232
262
|
allowanceAuthHeaders("/deploy/v2/plans");
|
|
233
263
|
|
|
264
|
+
let fileSet;
|
|
265
|
+
try {
|
|
266
|
+
fileSet = await fileSetFromDir(opts.dir);
|
|
267
|
+
} catch (err) {
|
|
268
|
+
reportSdkError(err);
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
const fileCount = Object.keys(fileSet).length;
|
|
272
|
+
|
|
273
|
+
if (
|
|
274
|
+
fileCount < SMALL_DIR_THRESHOLD &&
|
|
275
|
+
!opts.confirmPrune &&
|
|
276
|
+
!opts.dryRun
|
|
277
|
+
) {
|
|
278
|
+
console.error(JSON.stringify({
|
|
279
|
+
status: "error",
|
|
280
|
+
code: "PRUNE_CONFIRMATION_REQUIRED",
|
|
281
|
+
message:
|
|
282
|
+
`sites deploy-dir would replace the entire site with ${fileCount} ` +
|
|
283
|
+
`file(s) from ${opts.dir}. Any files in the current release that ` +
|
|
284
|
+
`are absent from this directory will be removed. Pass ` +
|
|
285
|
+
`--confirm-prune to proceed, or --dry-run to preview the diff.`,
|
|
286
|
+
details: {
|
|
287
|
+
local_file_count: fileCount,
|
|
288
|
+
threshold: SMALL_DIR_THRESHOLD,
|
|
289
|
+
dir: opts.dir,
|
|
290
|
+
},
|
|
291
|
+
}));
|
|
292
|
+
process.exit(1);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (opts.dryRun) {
|
|
296
|
+
try {
|
|
297
|
+
const { plan } = await getSdk().deploy.plan({
|
|
298
|
+
project: projectId,
|
|
299
|
+
site: { replace: fileSet },
|
|
300
|
+
});
|
|
301
|
+
console.log(JSON.stringify({
|
|
302
|
+
status: "ok",
|
|
303
|
+
dry_run: true,
|
|
304
|
+
local_file_count: fileCount,
|
|
305
|
+
plan_id: plan.plan_id,
|
|
306
|
+
operation_id: plan.operation_id,
|
|
307
|
+
manifest_digest: plan.manifest_digest,
|
|
308
|
+
diff: plan.diff,
|
|
309
|
+
missing_content_count: plan.missing_content.filter((p) => !p.present).length,
|
|
310
|
+
}, null, 2));
|
|
311
|
+
} catch (err) {
|
|
312
|
+
reportSdkError(err);
|
|
313
|
+
}
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
|
|
234
317
|
try {
|
|
235
318
|
const data = await getSdk().sites.deployDir({
|
|
236
319
|
project: projectId,
|
package/lib/subdomains.mjs
CHANGED
|
@@ -9,7 +9,7 @@ Usage:
|
|
|
9
9
|
|
|
10
10
|
Subcommands:
|
|
11
11
|
claim <name> [--project <id>] [--deployment <id>] Claim a subdomain
|
|
12
|
-
delete <name> [--project <id>]
|
|
12
|
+
delete <name> --confirm [--project <id>] Release a subdomain. Requires --confirm.
|
|
13
13
|
list [<id>] List subdomains for a project
|
|
14
14
|
|
|
15
15
|
Options default to the active project and its last deployment when omitted.
|
|
@@ -18,7 +18,7 @@ Legacy syntax 'claim <deployment_id> <name>' is still supported.
|
|
|
18
18
|
Examples:
|
|
19
19
|
run402 subdomains claim myapp
|
|
20
20
|
run402 subdomains claim myapp --deployment dpl_abc123 --project proj123
|
|
21
|
-
run402 subdomains delete myapp
|
|
21
|
+
run402 subdomains delete myapp --confirm
|
|
22
22
|
run402 subdomains list
|
|
23
23
|
|
|
24
24
|
Notes:
|
|
@@ -77,10 +77,26 @@ async function claim(positionalArgs, flagArgs) {
|
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
async function deleteSubdomain(
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
async function deleteSubdomain(allArgs) {
|
|
81
|
+
const argList = Array.isArray(allArgs) ? allArgs : [];
|
|
82
|
+
let opts = { project: null };
|
|
83
|
+
let name = null;
|
|
84
|
+
for (let i = 0; i < argList.length; i++) {
|
|
85
|
+
if (argList[i] === "--project" && argList[i + 1]) { opts.project = argList[++i]; }
|
|
86
|
+
else if (!argList[i].startsWith("--") && !name) { name = argList[i]; }
|
|
87
|
+
}
|
|
88
|
+
if (!name) {
|
|
89
|
+
console.error(JSON.stringify({ status: "error", message: "Usage: run402 subdomains delete <name> --confirm [--project <id>]" }));
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
if (!argList.includes("--confirm")) {
|
|
93
|
+
console.error(JSON.stringify({
|
|
94
|
+
status: "error",
|
|
95
|
+
code: "CONFIRMATION_REQUIRED",
|
|
96
|
+
message: `Destructive: releasing subdomain '${name}' makes it available for any other project to claim. This is irreversible. Re-run with --confirm to proceed.`,
|
|
97
|
+
details: { name },
|
|
98
|
+
}));
|
|
99
|
+
process.exit(1);
|
|
84
100
|
}
|
|
85
101
|
const projectId = resolveProjectId(opts.project);
|
|
86
102
|
try {
|
|
@@ -116,7 +132,7 @@ export async function run(sub, args) {
|
|
|
116
132
|
await claim(positional, flags);
|
|
117
133
|
break;
|
|
118
134
|
}
|
|
119
|
-
case "delete": await deleteSubdomain(args
|
|
135
|
+
case "delete": await deleteSubdomain(args); break;
|
|
120
136
|
case "list": await list(args[0]); break;
|
|
121
137
|
default:
|
|
122
138
|
console.error(`Unknown subcommand: ${sub}\n`);
|
package/package.json
CHANGED
package/sdk/dist/errors.d.ts
CHANGED
|
@@ -2,8 +2,34 @@
|
|
|
2
2
|
* Error hierarchy for the Run402 SDK. Every failure throws a subclass of
|
|
3
3
|
* {@link Run402Error}. Consumers (MCP handlers, CLI commands, user functions)
|
|
4
4
|
* translate these into their native error shapes at the edge.
|
|
5
|
+
*
|
|
6
|
+
* Branch on {@link Run402Error.kind} (or the exported `is*` type guards) rather
|
|
7
|
+
* than `instanceof`. Discriminator-based checks survive duplicate SDK installs,
|
|
8
|
+
* bundler chunk splits, ESM/CJS interop, and V8-isolate realm boundaries —
|
|
9
|
+
* any setting where a class object's identity might differ from the consumer's
|
|
10
|
+
* own class object reference. `instanceof X` continues to work for callers
|
|
11
|
+
* holding a single SDK copy (back-compat); the guards are the recommended path.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Stable string discriminator on every {@link Run402Error} subclass. Use this
|
|
15
|
+
* (or the exported `is*` guards) to branch on errors safely across SDK copies
|
|
16
|
+
* and realms — value comparison, no class-identity dependency.
|
|
5
17
|
*/
|
|
18
|
+
export type Run402ErrorKind = "payment_required" | "project_not_found" | "unauthorized" | "api_error" | "network_error" | "local_error" | "deploy_error";
|
|
6
19
|
export declare abstract class Run402Error extends Error {
|
|
20
|
+
/**
|
|
21
|
+
* Structural brand. Always `true` on any {@link Run402Error} subclass
|
|
22
|
+
* instance, regardless of which SDK copy created it. The exported
|
|
23
|
+
* {@link isRun402Error} guard checks this field instead of `instanceof`,
|
|
24
|
+
* so cross-realm and cross-bundle errors still match.
|
|
25
|
+
*/
|
|
26
|
+
readonly isRun402Error: true;
|
|
27
|
+
/**
|
|
28
|
+
* Stable string discriminator. Branch on `e.kind === "..."` (or the
|
|
29
|
+
* exported subclass guards) rather than `e instanceof X`. Equality on
|
|
30
|
+
* `kind` survives duplicate SDK copies and cross-realm errors.
|
|
31
|
+
*/
|
|
32
|
+
abstract readonly kind: Run402ErrorKind;
|
|
7
33
|
/** HTTP status, or null for local/network failures that produced no response. */
|
|
8
34
|
readonly status: number | null;
|
|
9
35
|
/** Parsed response body, or null when no body was received. */
|
|
@@ -27,28 +53,42 @@ export declare abstract class Run402Error extends Error {
|
|
|
27
53
|
/** Advisory next actions from the gateway. Rendering them must not execute them. */
|
|
28
54
|
readonly nextActions?: unknown[];
|
|
29
55
|
constructor(message: string, status: number | null, body: unknown, context: string);
|
|
56
|
+
/**
|
|
57
|
+
* Canonical structured envelope for `JSON.stringify`. Without this, an
|
|
58
|
+
* `Error` instance serializes as `"{}"` (its built-in fields are
|
|
59
|
+
* non-enumerable), losing every structured detail an agent needs for
|
|
60
|
+
* triage. Subclasses with extra fields (e.g. {@link Run402DeployError})
|
|
61
|
+
* override and spread `super.toJSON()`.
|
|
62
|
+
*/
|
|
63
|
+
toJSON(): Record<string, unknown>;
|
|
30
64
|
}
|
|
31
65
|
/** HTTP 402 — the gateway requires payment (lease expired, insufficient balance, or x402 quote). */
|
|
32
66
|
export declare class PaymentRequired extends Run402Error {
|
|
67
|
+
readonly kind: "payment_required";
|
|
33
68
|
}
|
|
34
69
|
/** Project ID is not present in the credential provider (local miss) or the gateway returned 404. */
|
|
35
70
|
export declare class ProjectNotFound extends Run402Error {
|
|
71
|
+
readonly kind: "project_not_found";
|
|
36
72
|
readonly projectId: string;
|
|
37
73
|
constructor(projectId: string, context: string, status?: number | null, body?: unknown);
|
|
38
74
|
}
|
|
39
75
|
/** HTTP 401 or 403 — authentication missing, invalid, or insufficient for the operation. */
|
|
40
76
|
export declare class Unauthorized extends Run402Error {
|
|
77
|
+
readonly kind: "unauthorized";
|
|
41
78
|
}
|
|
42
79
|
/** Any other non-2xx HTTP response from the gateway. */
|
|
43
80
|
export declare class ApiError extends Run402Error {
|
|
81
|
+
readonly kind: "api_error";
|
|
44
82
|
}
|
|
45
83
|
/** The underlying `fetch` threw before producing a response (DNS, connection reset, offline). */
|
|
46
84
|
export declare class NetworkError extends Run402Error {
|
|
85
|
+
readonly kind: "network_error";
|
|
47
86
|
readonly cause: unknown;
|
|
48
87
|
constructor(message: string, cause: unknown, context: string);
|
|
49
88
|
}
|
|
50
89
|
/** Local/filesystem error — input validation, missing path, unreadable dir. No HTTP involved. */
|
|
51
90
|
export declare class LocalError extends Run402Error {
|
|
91
|
+
readonly kind: "local_error";
|
|
52
92
|
readonly cause?: unknown;
|
|
53
93
|
constructor(message: string, context: string, cause?: unknown);
|
|
54
94
|
}
|
|
@@ -69,6 +109,7 @@ export interface Run402DeployErrorFix {
|
|
|
69
109
|
[key: string]: unknown;
|
|
70
110
|
}
|
|
71
111
|
export declare class Run402DeployError extends Run402Error {
|
|
112
|
+
readonly kind: "deploy_error";
|
|
72
113
|
readonly code: Run402DeployErrorCode;
|
|
73
114
|
readonly phase: string | null;
|
|
74
115
|
readonly resource: string | null;
|
|
@@ -92,5 +133,37 @@ export declare class Run402DeployError extends Run402Error {
|
|
|
92
133
|
body?: unknown;
|
|
93
134
|
context: string;
|
|
94
135
|
});
|
|
136
|
+
toJSON(): Record<string, unknown>;
|
|
95
137
|
}
|
|
138
|
+
/** True if `e` is any {@link Run402Error} subclass instance, regardless of which SDK copy created it. */
|
|
139
|
+
export declare function isRun402Error(e: unknown): e is Run402Error;
|
|
140
|
+
/** True if `e` is a {@link PaymentRequired}. Survives duplicate SDK copies and realms. */
|
|
141
|
+
export declare function isPaymentRequired(e: unknown): e is PaymentRequired;
|
|
142
|
+
/** True if `e` is a {@link ProjectNotFound}. */
|
|
143
|
+
export declare function isProjectNotFound(e: unknown): e is ProjectNotFound;
|
|
144
|
+
/** True if `e` is an {@link Unauthorized}. */
|
|
145
|
+
export declare function isUnauthorized(e: unknown): e is Unauthorized;
|
|
146
|
+
/** True if `e` is an {@link ApiError}. */
|
|
147
|
+
export declare function isApiError(e: unknown): e is ApiError;
|
|
148
|
+
/** True if `e` is a {@link NetworkError}. */
|
|
149
|
+
export declare function isNetworkError(e: unknown): e is NetworkError;
|
|
150
|
+
/** True if `e` is a {@link LocalError}. */
|
|
151
|
+
export declare function isLocalError(e: unknown): e is LocalError;
|
|
152
|
+
/** True if `e` is a {@link Run402DeployError}. */
|
|
153
|
+
export declare function isDeployError(e: unknown): e is Run402DeployError;
|
|
154
|
+
/**
|
|
155
|
+
* Canonical "should I retry this?" policy. Returns true when `e` is a
|
|
156
|
+
* {@link Run402Error} AND any of:
|
|
157
|
+
* - `e.retryable === true` (gateway flagged it)
|
|
158
|
+
* - `e.safeToRetry === true` (gateway flagged it)
|
|
159
|
+
* - `e.kind === "network_error"` (fetch never produced a response)
|
|
160
|
+
* - `e.status` is 408 (Request Timeout), 425 (Too Early), or 429 (Too Many
|
|
161
|
+
* Requests)
|
|
162
|
+
* - `e.status` is a 5xx server error
|
|
163
|
+
*
|
|
164
|
+
* Returns false for non-Run402 errors so it can be safely called with
|
|
165
|
+
* `unknown` from a catch block. Used as the default `retryIf` in
|
|
166
|
+
* {@link withRetry}.
|
|
167
|
+
*/
|
|
168
|
+
export declare function isRetryableRun402Error(e: unknown): boolean;
|
|
96
169
|
//# sourceMappingURL=errors.d.ts.map
|
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;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|