run402 4.8.0 → 4.9.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/cli.mjs +6 -6
- package/lib/admin.mjs +17 -24
- package/lib/apps.mjs +68 -50
- package/lib/argparse.mjs +68 -1
- package/lib/assets.mjs +6 -8
- package/lib/billing.mjs +15 -11
- package/lib/branches.mjs +20 -17
- package/lib/ci.mjs +2 -0
- package/lib/cloud.mjs +25 -18
- package/lib/command-manifest.mjs +352 -0
- package/lib/contracts.mjs +47 -10
- package/lib/deploy-v2.mjs +21 -8
- package/lib/functions.mjs +99 -54
- package/lib/grants.mjs +39 -20
- package/lib/jobs.mjs +15 -9
- package/lib/org.mjs +86 -48
- package/lib/projects.mjs +67 -38
- package/lib/secrets.mjs +98 -40
- package/lib/snapshots.mjs +20 -18
- package/lib/wallets.mjs +4 -3
- package/package.json +1 -1
- package/sdk/dist/namespaces/projects.d.ts +2 -1
- package/sdk/dist/namespaces/projects.d.ts.map +1 -1
- package/sdk/dist/namespaces/projects.js +8 -12
- package/sdk/dist/namespaces/projects.js.map +1 -1
package/lib/org.mjs
CHANGED
|
@@ -16,17 +16,20 @@ Usage:
|
|
|
16
16
|
run402 org create [--name <label>]
|
|
17
17
|
run402 org list
|
|
18
18
|
run402 org get <org_id>
|
|
19
|
-
run402 org rename <org_id> <display_name> (or: --clear to remove the label)
|
|
20
|
-
run402 org payout-wallet <org_id> <wallet_address> (or: --clear to remove the explicit default)
|
|
19
|
+
run402 org rename <org_id> --name <display_name> (or: --clear to remove the label)
|
|
20
|
+
run402 org payout-wallet <org_id> --wallet <wallet_address> (or: --clear to remove the explicit default)
|
|
21
21
|
run402 org whoami
|
|
22
22
|
run402 org audit <org_id> [--limit N] [--after <cursor>] [--before <cursor>]
|
|
23
23
|
run402 org member list <org_id>
|
|
24
|
-
run402 org member add <org_id> <wallet_address> [--role <role>]
|
|
25
|
-
run402 org member role <org_id> <principal_id> <role>
|
|
26
|
-
run402 org member rm <org_id> <principal_id>
|
|
24
|
+
run402 org member add <org_id> --wallet <wallet_address> [--role <role>]
|
|
25
|
+
run402 org member role <org_id> --principal <principal_id> --role <role>
|
|
26
|
+
run402 org member rm <org_id> --principal <principal_id>
|
|
27
27
|
run402 org invite list <org_id>
|
|
28
|
-
run402 org invite create <org_id> <email> [--role <role>] [--ttl-hours N]
|
|
29
|
-
run402 org invite rm <org_id> <principal_id>
|
|
28
|
+
run402 org invite create <org_id> --email <email> [--role <role>] [--ttl-hours N]
|
|
29
|
+
run402 org invite rm <org_id> --principal <principal_id>
|
|
30
|
+
|
|
31
|
+
Legacy (still supported): the second attribute may also be passed positionally,
|
|
32
|
+
e.g. run402 org member add <org_id> <wallet_address>.
|
|
30
33
|
|
|
31
34
|
Subcommands:
|
|
32
35
|
create Create an empty org on the prototype tier (you become owner)
|
|
@@ -87,18 +90,24 @@ non-revealing 403.
|
|
|
87
90
|
rename: `run402 org rename — set or clear an org's display label (owner-only)
|
|
88
91
|
|
|
89
92
|
Usage:
|
|
90
|
-
run402 org rename <org_id> <display_name>
|
|
93
|
+
run402 org rename <org_id> --name <display_name>
|
|
91
94
|
run402 org rename <org_id> --clear
|
|
92
95
|
|
|
96
|
+
Legacy (still supported):
|
|
97
|
+
run402 org rename <org_id> <display_name>
|
|
98
|
+
|
|
93
99
|
Owner-only + step-up gated. Pass --clear (or an empty display_name) to remove
|
|
94
100
|
the label. Output includes the updated tier and lease timestamps.
|
|
95
101
|
`,
|
|
96
102
|
"payout-wallet": `run402 org payout-wallet — set or clear the tenant route payout wallet
|
|
97
103
|
|
|
98
104
|
Usage:
|
|
99
|
-
run402 org payout-wallet <org_id> <wallet_address>
|
|
105
|
+
run402 org payout-wallet <org_id> --wallet <wallet_address>
|
|
100
106
|
run402 org payout-wallet <org_id> --clear
|
|
101
107
|
|
|
108
|
+
Legacy (still supported):
|
|
109
|
+
run402 org payout-wallet <org_id> <wallet_address>
|
|
110
|
+
|
|
102
111
|
Admin/owner-only + step-up gated. The wallet must already be active and linked
|
|
103
112
|
to the same org. This wallet receives x402 settlement for function web routes
|
|
104
113
|
that declare pricing.pay_to = "org_default_payout". Pass --clear to remove the
|
|
@@ -120,9 +129,9 @@ for local wallet/profile state use 'run402 status'.
|
|
|
120
129
|
|
|
121
130
|
Usage:
|
|
122
131
|
run402 org member list <org_id>
|
|
123
|
-
run402 org member add <org_id> <wallet_address> [--role <role>]
|
|
124
|
-
run402 org member role <org_id> <principal_id> <role>
|
|
125
|
-
run402 org member rm <org_id> <principal_id>
|
|
132
|
+
run402 org member add <org_id> --wallet <wallet_address> [--role <role>]
|
|
133
|
+
run402 org member role <org_id> --principal <principal_id> --role <role>
|
|
134
|
+
run402 org member rm <org_id> --principal <principal_id>
|
|
126
135
|
|
|
127
136
|
Roles: ${ROLE_LIST} (add defaults to developer). Mutations require an active owner.
|
|
128
137
|
Demoting/removing the org's only active owner fails with 409 LAST_OWNER.
|
|
@@ -131,8 +140,11 @@ Demoting/removing the org's only active owner fails with 409 LAST_OWNER.
|
|
|
131
140
|
|
|
132
141
|
Usage:
|
|
133
142
|
run402 org invite list <org_id>
|
|
134
|
-
run402 org invite create <org_id> <email> [--role <role>] [--ttl-hours N]
|
|
135
|
-
run402 org invite rm <org_id> <principal_id>
|
|
143
|
+
run402 org invite create <org_id> --email <email> [--role <role>] [--ttl-hours N]
|
|
144
|
+
run402 org invite rm <org_id> --principal <principal_id>
|
|
145
|
+
|
|
146
|
+
Legacy (still supported): the second attribute may also be passed positionally,
|
|
147
|
+
e.g. run402 org member add <org_id> <wallet_address>.
|
|
136
148
|
|
|
137
149
|
An invite is claimed at the recipient's first login. Mutations require an active owner
|
|
138
150
|
(plus step-up when driven by a control-plane session).
|
|
@@ -200,16 +212,18 @@ async function get(args) {
|
|
|
200
212
|
|
|
201
213
|
async function rename(args) {
|
|
202
214
|
const a = normalizeArgv(args);
|
|
203
|
-
assertKnownFlags(a, ["--clear", "--help", "-h"]);
|
|
215
|
+
assertKnownFlags(a, ["--name", "--clear", "--help", "-h"], ["--name"]);
|
|
204
216
|
const clear = a.includes("--clear");
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
217
|
+
const nameFlag = flagValue(a, "--name");
|
|
218
|
+
const single = clear || nameFlag !== null;
|
|
219
|
+
const positionals = requirePositionalCount(a, ["--name"], {
|
|
220
|
+
min: single ? 1 : 2,
|
|
221
|
+
max: single ? 1 : 2,
|
|
222
|
+
command: "run402 org rename <org_id> --name <display_name>",
|
|
223
|
+
missing: single ? "Missing <org_id>." : "Missing <org_id> and/or <display_name> (use --name, or pass --clear).",
|
|
210
224
|
});
|
|
211
225
|
const org = positionals[0];
|
|
212
|
-
const displayName = clear ? null : positionals[1];
|
|
226
|
+
const displayName = clear ? null : (nameFlag ?? positionals[1]);
|
|
213
227
|
try {
|
|
214
228
|
console.log(JSON.stringify(await getSdk().org(org).rename(displayName), null, 2));
|
|
215
229
|
} catch (err) {
|
|
@@ -219,16 +233,18 @@ async function rename(args) {
|
|
|
219
233
|
|
|
220
234
|
async function payoutWallet(args) {
|
|
221
235
|
const a = normalizeArgv(args);
|
|
222
|
-
assertKnownFlags(a, ["--clear", "--help", "-h"]);
|
|
236
|
+
assertKnownFlags(a, ["--wallet", "--clear", "--help", "-h"], ["--wallet"]);
|
|
223
237
|
const clear = a.includes("--clear");
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
238
|
+
const walletFlag = flagValue(a, "--wallet");
|
|
239
|
+
const single = clear || walletFlag !== null;
|
|
240
|
+
const positionals = requirePositionalCount(a, ["--wallet"], {
|
|
241
|
+
min: single ? 1 : 2,
|
|
242
|
+
max: single ? 1 : 2,
|
|
243
|
+
command: "run402 org payout-wallet <org_id> --wallet <wallet_address>",
|
|
244
|
+
missing: single ? "Missing <org_id>." : "Missing <org_id> and/or <wallet_address> (use --wallet, or pass --clear).",
|
|
229
245
|
});
|
|
230
246
|
const org = positionals[0];
|
|
231
|
-
const walletAddress = clear ? null : positionals[1];
|
|
247
|
+
const walletAddress = clear ? null : (walletFlag ?? positionals[1]);
|
|
232
248
|
try {
|
|
233
249
|
console.log(JSON.stringify(await getSdk().org(org).setPayoutWallet({ walletAddress }), null, 2));
|
|
234
250
|
} catch (err) {
|
|
@@ -292,12 +308,16 @@ async function runMember(args) {
|
|
|
292
308
|
|
|
293
309
|
if (memberAction === "add") {
|
|
294
310
|
const a = normalizeArgv(rest);
|
|
295
|
-
assertKnownFlags(a, ["--role", "--help", "-h"], ["--role"]);
|
|
311
|
+
assertKnownFlags(a, ["--role", "--wallet", "--help", "-h"], ["--role", "--wallet"]);
|
|
296
312
|
const role = flagValue(a, "--role");
|
|
297
|
-
const
|
|
298
|
-
|
|
299
|
-
|
|
313
|
+
const walletFlag = flagValue(a, "--wallet");
|
|
314
|
+
const count = walletFlag ? 1 : 2;
|
|
315
|
+
const pos = requirePositionalCount(a, ["--role", "--wallet"], {
|
|
316
|
+
min: count, max: count, command: "run402 org member add <org_id> --wallet <wallet_address> [--role <role>]",
|
|
317
|
+
missing: walletFlag ? "Missing <org_id>." : "Missing <org_id> and/or <wallet_address> (use --wallet).",
|
|
300
318
|
});
|
|
319
|
+
const org = pos[0];
|
|
320
|
+
const wallet = walletFlag ?? pos[1];
|
|
301
321
|
try {
|
|
302
322
|
const res = await getSdk().org(org).members.add({ wallet, role: role || undefined });
|
|
303
323
|
console.log(JSON.stringify(res, null, 2));
|
|
@@ -309,11 +329,17 @@ async function runMember(args) {
|
|
|
309
329
|
|
|
310
330
|
if (memberAction === "role") {
|
|
311
331
|
const a = normalizeArgv(rest);
|
|
312
|
-
assertKnownFlags(a, ["--help", "-h"]);
|
|
313
|
-
const
|
|
314
|
-
|
|
315
|
-
|
|
332
|
+
assertKnownFlags(a, ["--principal", "--role", "--help", "-h"], ["--principal", "--role"]);
|
|
333
|
+
const principalFlag = flagValue(a, "--principal");
|
|
334
|
+
const roleFlag = flagValue(a, "--role");
|
|
335
|
+
const count = 3 - (principalFlag ? 1 : 0) - (roleFlag ? 1 : 0);
|
|
336
|
+
const pos = requirePositionalCount(a, ["--principal", "--role"], {
|
|
337
|
+
min: count, max: count, command: "run402 org member role <org_id> --principal <principal_id> --role <role>",
|
|
338
|
+
missing: "Missing <org_id>, <principal_id> (--principal), and/or <role> (--role).",
|
|
316
339
|
});
|
|
340
|
+
const org = pos[0];
|
|
341
|
+
const principalId = principalFlag ?? pos[1];
|
|
342
|
+
const role = roleFlag ?? (principalFlag ? pos[1] : pos[2]);
|
|
317
343
|
try {
|
|
318
344
|
console.log(JSON.stringify(await getSdk().org(org).members.setRole(principalId, { role }), null, 2));
|
|
319
345
|
} catch (err) {
|
|
@@ -324,11 +350,15 @@ async function runMember(args) {
|
|
|
324
350
|
|
|
325
351
|
if (memberAction === "rm") {
|
|
326
352
|
const a = normalizeArgv(rest);
|
|
327
|
-
assertKnownFlags(a, ["--help", "-h"]);
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
|
|
353
|
+
assertKnownFlags(a, ["--principal", "--help", "-h"], ["--principal"]);
|
|
354
|
+
const principalFlag = flagValue(a, "--principal");
|
|
355
|
+
const count = principalFlag ? 1 : 2;
|
|
356
|
+
const pos = requirePositionalCount(a, ["--principal"], {
|
|
357
|
+
min: count, max: count, command: "run402 org member rm <org_id> --principal <principal_id>",
|
|
358
|
+
missing: principalFlag ? "Missing <org_id>." : "Missing <org_id> and/or <principal_id> (use --principal).",
|
|
331
359
|
});
|
|
360
|
+
const org = pos[0];
|
|
361
|
+
const principalId = principalFlag ?? pos[1];
|
|
332
362
|
try {
|
|
333
363
|
console.log(JSON.stringify(await getSdk().org(org).members.revoke(principalId), null, 2));
|
|
334
364
|
} catch (err) {
|
|
@@ -370,14 +400,18 @@ async function runInvite(args) {
|
|
|
370
400
|
|
|
371
401
|
if (inviteAction === "create") {
|
|
372
402
|
const a = normalizeArgv(rest);
|
|
373
|
-
const valueFlags = ["--role", "--ttl-hours"];
|
|
403
|
+
const valueFlags = ["--role", "--ttl-hours", "--email"];
|
|
374
404
|
assertKnownFlags(a, [...valueFlags, "--help", "-h"], valueFlags);
|
|
375
405
|
const role = flagValue(a, "--role");
|
|
376
406
|
const ttlFlag = flagValue(a, "--ttl-hours");
|
|
377
|
-
const
|
|
378
|
-
|
|
379
|
-
|
|
407
|
+
const emailFlag = flagValue(a, "--email");
|
|
408
|
+
const count = emailFlag ? 1 : 2;
|
|
409
|
+
const pos = requirePositionalCount(a, valueFlags, {
|
|
410
|
+
min: count, max: count, command: "run402 org invite create <org_id> --email <email> [--role <role>]",
|
|
411
|
+
missing: emailFlag ? "Missing <org_id>." : "Missing <org_id> and/or <email> (use --email).",
|
|
380
412
|
});
|
|
413
|
+
const org = pos[0];
|
|
414
|
+
const email = emailFlag ?? pos[1];
|
|
381
415
|
const inviteTtlHours = ttlFlag === null ? undefined : parseIntegerFlag("--ttl-hours", ttlFlag, { min: 1, max: 8760 });
|
|
382
416
|
try {
|
|
383
417
|
const res = await getSdk().org(org).invites.create({ email, role: role || "developer", inviteTtlHours });
|
|
@@ -390,11 +424,15 @@ async function runInvite(args) {
|
|
|
390
424
|
|
|
391
425
|
if (inviteAction === "rm") {
|
|
392
426
|
const a = normalizeArgv(rest);
|
|
393
|
-
assertKnownFlags(a, ["--help", "-h"]);
|
|
394
|
-
const
|
|
395
|
-
|
|
396
|
-
|
|
427
|
+
assertKnownFlags(a, ["--principal", "--help", "-h"], ["--principal"]);
|
|
428
|
+
const principalFlag = flagValue(a, "--principal");
|
|
429
|
+
const count = principalFlag ? 1 : 2;
|
|
430
|
+
const pos = requirePositionalCount(a, ["--principal"], {
|
|
431
|
+
min: count, max: count, command: "run402 org invite rm <org_id> --principal <principal_id>",
|
|
432
|
+
missing: principalFlag ? "Missing <org_id>." : "Missing <org_id> and/or <principal_id> (use --principal).",
|
|
397
433
|
});
|
|
434
|
+
const org = pos[0];
|
|
435
|
+
const principalId = principalFlag ?? pos[1];
|
|
398
436
|
try {
|
|
399
437
|
console.log(JSON.stringify(await getSdk().org(org).invites.revoke(principalId), null, 2));
|
|
400
438
|
} catch (err) {
|
package/lib/projects.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import { loadLiveControlPlaneSession } from "../core-dist/control-plane-session.
|
|
|
5
5
|
import { withAutoApprove } from "./operator.mjs";
|
|
6
6
|
import { getSdk } from "./sdk.mjs";
|
|
7
7
|
import { reportSdkError, fail, parseFlagJson } from "./sdk-errors.mjs";
|
|
8
|
-
import { assertKnownFlags, failBadProjectId, flagValue, hasHelp, normalizeArgv, positionalArgs,
|
|
8
|
+
import { assertKnownFlags, failBadProjectId, flagValue, hasHelp, normalizeArgv, positionalArgs, resolveProjectSelector, validateRegularFile } from "./argparse.mjs";
|
|
9
9
|
|
|
10
10
|
const HELP = `run402 projects — Manage your deployed Run402 projects
|
|
11
11
|
|
|
@@ -21,8 +21,8 @@ Subcommands:
|
|
|
21
21
|
tenant-payments [project_id] [--status <s>] List redacted tenant x402 payments for priced routes
|
|
22
22
|
get [id] Authoritative server read: status, org, tier, active deploy, mailbox, usage vs limits (live; no keys)
|
|
23
23
|
current Show the active project pointer and validation status
|
|
24
|
-
sql
|
|
25
|
-
rest
|
|
24
|
+
sql "<query>" [--project <id>] [--file <path>] [--params '<json>'] Run a SQL query (supports parameterized queries)
|
|
25
|
+
rest <table> [--query "<params>"] [--project <id>] Query a table via the REST API (PostgREST)
|
|
26
26
|
usage [id] Show compute/storage usage for a project
|
|
27
27
|
costs [id] [--window <w>] Show admin-only per-project revenue/cost/margin
|
|
28
28
|
schema [id] Inspect the database schema
|
|
@@ -210,23 +210,25 @@ Examples:
|
|
|
210
210
|
sql: `run402 projects sql — Run a SQL query against a project's database
|
|
211
211
|
|
|
212
212
|
Usage:
|
|
213
|
-
run402 projects sql
|
|
214
|
-
run402 projects sql
|
|
213
|
+
run402 projects sql "<query>" [--project <id>] [options]
|
|
214
|
+
run402 projects sql --file <path> [--project <id>] [options]
|
|
215
|
+
|
|
216
|
+
Legacy (still supported):
|
|
217
|
+
run402 projects sql <prj_id> "<query>" [options]
|
|
215
218
|
|
|
216
219
|
Arguments:
|
|
217
|
-
[id] Project ID (defaults to the active project if omitted;
|
|
218
|
-
must start with 'prj_' — any other first arg is treated
|
|
219
|
-
as the query instead)
|
|
220
220
|
<query> Inline SQL query (quote it to preserve spaces)
|
|
221
221
|
|
|
222
222
|
Options:
|
|
223
|
+
--project <id> Project ID (defaults to the active project; a leading
|
|
224
|
+
prj_... positional is also still accepted)
|
|
223
225
|
--file <path> Read SQL from a file instead of an inline query
|
|
224
226
|
--params '<json>' JSON array of parameters for a parameterized query
|
|
225
227
|
|
|
226
228
|
Examples:
|
|
227
|
-
run402 projects sql
|
|
228
|
-
run402 projects sql
|
|
229
|
-
run402 projects sql
|
|
229
|
+
run402 projects sql "SELECT * FROM users LIMIT 5" --project prj_abc123
|
|
230
|
+
run402 projects sql "SELECT * FROM users WHERE id = $1" --params '[42]'
|
|
231
|
+
run402 projects sql --file setup.sql --project prj_abc123
|
|
230
232
|
`,
|
|
231
233
|
costs: `run402 projects costs — Show admin-only per-project finance
|
|
232
234
|
|
|
@@ -411,6 +413,12 @@ async function applyExpose(projectId, args = []) {
|
|
|
411
413
|
|
|
412
414
|
async function validateExpose(args = []) {
|
|
413
415
|
let projectId = null;
|
|
416
|
+
let projectFlag = null;
|
|
417
|
+
if (args.includes("--project")) {
|
|
418
|
+
projectFlag = flagValue(args, "--project");
|
|
419
|
+
const idx = args.indexOf("--project");
|
|
420
|
+
args = [...args.slice(0, idx), ...args.slice(idx + 2)];
|
|
421
|
+
}
|
|
414
422
|
let file = null;
|
|
415
423
|
let inline = null;
|
|
416
424
|
let migrationFile = null;
|
|
@@ -473,8 +481,15 @@ async function validateExpose(args = []) {
|
|
|
473
481
|
});
|
|
474
482
|
}
|
|
475
483
|
|
|
484
|
+
if (projectFlag !== null && projectId !== null && projectFlag !== projectId) {
|
|
485
|
+
fail({
|
|
486
|
+
code: "BAD_USAGE",
|
|
487
|
+
message: `Conflicting project ids: --project ${projectFlag} vs positional ${projectId}`,
|
|
488
|
+
details: { project_flag: projectFlag, positional: projectId },
|
|
489
|
+
});
|
|
490
|
+
}
|
|
476
491
|
const activeProjectId = getActiveProjectId();
|
|
477
|
-
const project = projectId || activeProjectId || undefined;
|
|
492
|
+
const project = projectFlag || projectId || activeProjectId || undefined;
|
|
478
493
|
if (!project) allowanceAuthHeaders("/projects/v1/expose/validate");
|
|
479
494
|
const migration = migrationFile ? readFileSync(migrationFile, "utf-8") : migrationSql;
|
|
480
495
|
|
|
@@ -697,6 +712,10 @@ function toCliExposeValidationResult(data) {
|
|
|
697
712
|
return { has_errors: hasErrors, ...rest };
|
|
698
713
|
}
|
|
699
714
|
|
|
715
|
+
// The SDK now returns the gateway SQL envelope verbatim (snake_case
|
|
716
|
+
// row_count) — the wire shape is uniform end-to-end. This shim survives one
|
|
717
|
+
// release as belt-and-braces against a stale local SDK build that still
|
|
718
|
+
// camelCases, then can be deleted.
|
|
700
719
|
function toCliSqlResult(data) {
|
|
701
720
|
if (!data || typeof data !== "object" || Array.isArray(data)) return data;
|
|
702
721
|
if ("row_count" in data) return data;
|
|
@@ -705,12 +724,15 @@ function toCliSqlResult(data) {
|
|
|
705
724
|
return { ...rest, row_count: rowCount };
|
|
706
725
|
}
|
|
707
726
|
|
|
708
|
-
async function rest(projectId,
|
|
727
|
+
async function rest(projectId, restArgs = []) {
|
|
728
|
+
const positionals = positionalArgs(restArgs, FLAGS_BY_SUB.rest.values);
|
|
729
|
+
const table = positionals[0];
|
|
730
|
+
const queryParams = flagValue(restArgs, "--query") ?? positionals[1];
|
|
709
731
|
if (!table) {
|
|
710
732
|
fail({
|
|
711
733
|
code: "BAD_USAGE",
|
|
712
|
-
message: "Missing <table> argument. Usage: run402 projects rest
|
|
713
|
-
hint: "Run 'run402 projects schema
|
|
734
|
+
message: "Missing <table> argument. Usage: run402 projects rest <table> [--query \"<query>\"] [--project <id>]",
|
|
735
|
+
hint: "Run 'run402 projects schema' to list tables.",
|
|
714
736
|
});
|
|
715
737
|
}
|
|
716
738
|
try {
|
|
@@ -841,19 +863,26 @@ const FLAGS_BY_SUB = {
|
|
|
841
863
|
values: ["--tier", "--name", "--org", "--idempotency-key"],
|
|
842
864
|
},
|
|
843
865
|
list: { known: ["--org", "--all"], values: ["--org"] },
|
|
844
|
-
rename: { known: ["--name"], values: ["--name"] },
|
|
845
|
-
"tenant-payments": { known: ["--status", "--limit", "--after"], values: ["--status", "--limit", "--after"] },
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
866
|
+
rename: { known: ["--project", "--name"], values: ["--project", "--name"] },
|
|
867
|
+
"tenant-payments": { known: ["--project", "--status", "--limit", "--after"], values: ["--project", "--status", "--limit", "--after"] },
|
|
868
|
+
get: { known: ["--project"], values: ["--project"] },
|
|
869
|
+
rest: { known: ["--project", "--query"], values: ["--project", "--query"] },
|
|
870
|
+
usage: { known: ["--project"], values: ["--project"] },
|
|
871
|
+
schema: { known: ["--project"], values: ["--project"] },
|
|
872
|
+
"get-expose": { known: ["--project"], values: ["--project"] },
|
|
873
|
+
"promote-user": { known: ["--project"], values: ["--project"] },
|
|
874
|
+
"demote-user": { known: ["--project"], values: ["--project"] },
|
|
875
|
+
sql: { known: ["--project", "--file", "--params"], values: ["--project", "--file", "--params"] },
|
|
876
|
+
costs: { known: ["--project", "--window"], values: ["--project", "--window"] },
|
|
877
|
+
"apply-expose": { known: ["--project", "--file"], values: ["--project", "--file"] },
|
|
849
878
|
"validate-expose": {
|
|
850
|
-
known: ["--file", "--migration-file", "--migration-sql"],
|
|
851
|
-
values: ["--file", "--migration-file", "--migration-sql"],
|
|
879
|
+
known: ["--project", "--file", "--migration-file", "--migration-sql"],
|
|
880
|
+
values: ["--project", "--file", "--migration-file", "--migration-sql"],
|
|
852
881
|
},
|
|
853
|
-
delete: { known: ["--confirm"], values: [] },
|
|
882
|
+
delete: { known: ["--project", "--confirm"], values: ["--project"] },
|
|
854
883
|
export: {
|
|
855
|
-
known: ["--scope", "--auth", "--consistency", "--idempotency-key", "--output", "--poll-interval", "--timeout", "--wait", "--json", "--json-stream"],
|
|
856
|
-
values: ["--scope", "--auth", "--consistency", "--idempotency-key", "--output", "--poll-interval", "--timeout"],
|
|
884
|
+
known: ["--project", "--scope", "--auth", "--consistency", "--idempotency-key", "--output", "--poll-interval", "--timeout", "--wait", "--json", "--json-stream"],
|
|
885
|
+
values: ["--project", "--scope", "--auth", "--consistency", "--idempotency-key", "--output", "--poll-interval", "--timeout"],
|
|
857
886
|
},
|
|
858
887
|
};
|
|
859
888
|
|
|
@@ -888,27 +917,27 @@ export async function run(sub, args) {
|
|
|
888
917
|
case "use": await use(args[0]); break;
|
|
889
918
|
case "list": await list(args); break;
|
|
890
919
|
case "current": await current(); break;
|
|
891
|
-
case "rename": { const { projectId, rest } =
|
|
892
|
-
case "tenant-payments": { const { projectId, rest } =
|
|
893
|
-
case "get": { const { projectId } =
|
|
920
|
+
case "rename": { const { projectId, rest } = resolveProjectSelector(args, { rejectBareFirst: true, valueFlags: FLAGS_BY_SUB.rename.values }); await rename(projectId, rest); break; }
|
|
921
|
+
case "tenant-payments": { const { projectId, rest } = resolveProjectSelector(args, { rejectBareFirst: true, valueFlags: FLAGS_BY_SUB["tenant-payments"].values }); await tenantPayments(projectId, rest); break; }
|
|
922
|
+
case "get": { const { projectId } = resolveProjectSelector(args, { rejectBareFirst: true }); await get(projectId); break; }
|
|
894
923
|
case "info": commandMoved("info"); break;
|
|
895
924
|
case "keys": commandMoved("keys"); break;
|
|
896
|
-
case "sql": { const { projectId, rest } =
|
|
897
|
-
case "rest": { const { projectId, rest: restArgs } =
|
|
898
|
-
case "usage": { const { projectId } =
|
|
899
|
-
case "costs": { const { projectId, rest } =
|
|
900
|
-
case "schema": { const { projectId } =
|
|
901
|
-
case "apply-expose": { const { projectId, rest } =
|
|
925
|
+
case "sql": { const { projectId, rest } = resolveProjectSelector(args, { maxBarePositionals: 1, valueFlags: FLAGS_BY_SUB.sql.values, rejectBareFirstWhenFlagPresent: ["--file"] }); await sqlCmd(projectId, rest); break; }
|
|
926
|
+
case "rest": { const { projectId, rest: restArgs } = resolveProjectSelector(args, { valueFlags: FLAGS_BY_SUB.rest.values }); await rest(projectId, restArgs); break; }
|
|
927
|
+
case "usage": { const { projectId } = resolveProjectSelector(args, { rejectBareFirst: true }); await usage(projectId); break; }
|
|
928
|
+
case "costs": { const { projectId, rest } = resolveProjectSelector(args, { rejectBareFirst: true, valueFlags: FLAGS_BY_SUB.costs.values }); await costs(projectId, rest); break; }
|
|
929
|
+
case "schema": { const { projectId } = resolveProjectSelector(args, { rejectBareFirst: true }); await schema(projectId); break; }
|
|
930
|
+
case "apply-expose": { const { projectId, rest } = resolveProjectSelector(args, { maxBarePositionals: 1, valueFlags: FLAGS_BY_SUB["apply-expose"].values, rejectBareFirstWhenFlagPresent: ["--file"] }); await applyExpose(projectId, rest); break; }
|
|
902
931
|
case "validate-expose": await validateExpose(args); break;
|
|
903
|
-
case "get-expose": { const { projectId } =
|
|
904
|
-
case "delete": { const { projectId, rest } =
|
|
932
|
+
case "get-expose": { const { projectId } = resolveProjectSelector(args, { rejectBareFirst: true }); await getExpose(projectId); break; }
|
|
933
|
+
case "delete": { const { projectId, rest } = resolveProjectSelector(args, { rejectBareFirst: true }); await deleteProject(projectId, rest); break; }
|
|
905
934
|
case "export": {
|
|
906
935
|
const { run } = await import("./cloud.mjs");
|
|
907
936
|
await run("archives", ["create", ...args]);
|
|
908
937
|
break;
|
|
909
938
|
}
|
|
910
|
-
case "promote-user": { const { projectId, rest } =
|
|
911
|
-
case "demote-user": { const { projectId, rest } =
|
|
939
|
+
case "promote-user": { const { projectId, rest } = resolveProjectSelector(args); await promoteUser(projectId, rest[0]); break; }
|
|
940
|
+
case "demote-user": { const { projectId, rest } = resolveProjectSelector(args); await demoteUser(projectId, rest[0]); break; }
|
|
912
941
|
default:
|
|
913
942
|
fail({ code: "UNKNOWN_SUBCOMMAND", message: `Unknown projects subcommand: ${sub}`, hint: "Run `run402 projects --help` for usage.", details: { command: "projects", subcommand: sub } });
|
|
914
943
|
}
|