@irtio/cli 0.5.1 → 0.5.2
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/dist/chunk-32QTPKVT.js +93 -0
- package/dist/{static-deploy-BP3MDXCP.js → chunk-GBNHBWES.js} +86 -49
- package/dist/chunk-TV66QHFP.js +167 -0
- package/dist/{deploy-YVCVDVMS.js → deploy-3SABPL3T.js} +104 -55
- package/dist/{dev-7UZZGE4U.js → dev-QJOGXLKM.js} +164 -89
- package/dist/index.js +29 -16
- package/dist/init.d.ts +2 -1
- package/dist/init.js +25 -0
- package/dist/{keys-KEKO3EJ6.js → keys-XBORZAPI.js} +47 -20
- package/dist/{login-OV2EFNTJ.js → login-3EXB4CGX.js} +18 -1
- package/dist/{logs-5OUDPAIX.js → logs-2EOXLNWF.js} +40 -19
- package/dist/{migrate-UD245ULI.js → migrate-WUO2GBMX.js} +41 -20
- package/dist/{rollback-CLQVYFHW.js → rollback-GA6UY772.js} +39 -19
- package/dist/{rooms-OJ3JLYHD.js → rooms-B66LQIIF.js} +46 -19
- package/dist/simulate.d.ts +71 -2
- package/dist/simulate.js +196 -22
- package/dist/static-deploy-5TBH4VNA.js +17 -0
- package/dist/{whoami-S73O6KJF.js → whoami-CI5D5RCC.js} +19 -4
- package/package.json +8 -7
- package/dist/chunk-D7CDJRFF.js +0 -24
- package/dist/chunk-I37DLT7K.js +0 -85
- package/dist/chunk-NVUKSP5U.js +0 -61
package/dist/index.js
CHANGED
|
@@ -20,7 +20,9 @@ commands:
|
|
|
20
20
|
[--misprediction-max <units>] fail the run if one correction snaps a
|
|
21
21
|
[--snaps-max <n>] prediction further than this, if more than
|
|
22
22
|
[--corrections-max <perSec>] <n> corrections fall outside the resim
|
|
23
|
-
|
|
23
|
+
[--overruns-max <n>] window, above this correction rate/bot, or
|
|
24
|
+
above this many server tick overruns.
|
|
25
|
+
exits 0 clean, 1 violation, 2 not performed
|
|
24
26
|
|
|
25
27
|
login [--url <control>] sign in to a control plane via the browser
|
|
26
28
|
whoami [--url <control>] print the identity the stored credential
|
|
@@ -28,13 +30,17 @@ commands:
|
|
|
28
30
|
deploy [--allow-breaking] [--project <id>] bundle, classify the schema change against the
|
|
29
31
|
[--url <control>] [--room <file>] last deployment, and upload \u2014 refuses breaking
|
|
30
32
|
[--strategy drain|migrate] changes unless a migration covers them;
|
|
31
|
-
[--name <name>]
|
|
33
|
+
[--name <name>] [--no-static] migrate moves LIVE rooms onto the new version
|
|
32
34
|
now (drain, the default, lets them finish).
|
|
33
35
|
A project that does not exist yet is created
|
|
34
|
-
as --name, else irtio.json's "name"
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
as --name, else irtio.json's "name".
|
|
37
|
+
With "static" in the project file the client
|
|
38
|
+
directory ships too; --no-static skips it
|
|
39
|
+
deploy --static [<dir>] [--project <id>] upload a BUILT client directory to the project's
|
|
40
|
+
[--label <label>] [--url <control>] static site and print the playable link, and
|
|
41
|
+
[--name <name>] nothing else (<label>.irt-serve.com; no build
|
|
42
|
+
step). Directory and label default to the
|
|
43
|
+
project file's "static"
|
|
38
44
|
migrate create <name> scaffold irtio/migrations/<n>_<name>.ts with the
|
|
39
45
|
live breaking changes quoted in its header
|
|
40
46
|
rollback <version> [--project <id>] re-promote deployment <version> and bring rooms
|
|
@@ -54,6 +60,13 @@ commands:
|
|
|
54
60
|
rooms saves <room> list a room's save generations, newest first
|
|
55
61
|
rooms restore <room> --save <id> bring a room back from a save \u2014 DISCARDS its
|
|
56
62
|
current state; stops the tenant if it is live
|
|
63
|
+
|
|
64
|
+
every command takes --help (or -h) and prints its own usage, which is the authority: the lines
|
|
65
|
+
above are a map, and the command's own help is generated next to the code that parses it.
|
|
66
|
+
|
|
67
|
+
every command that reads the project file takes -c/--config <file> to read a different one
|
|
68
|
+
(dev, deploy, deploy --static, migrate create, rollback, logs, rooms, keys). Default irtio.json;
|
|
69
|
+
the named file must exist. That is the test.irtio.json / prod.irtio.json pattern.
|
|
57
70
|
`;
|
|
58
71
|
switch (command) {
|
|
59
72
|
case "init": {
|
|
@@ -62,7 +75,7 @@ switch (command) {
|
|
|
62
75
|
break;
|
|
63
76
|
}
|
|
64
77
|
case "dev": {
|
|
65
|
-
const { dev } = await import("./dev-
|
|
78
|
+
const { dev } = await import("./dev-QJOGXLKM.js");
|
|
66
79
|
await dev(args);
|
|
67
80
|
break;
|
|
68
81
|
}
|
|
@@ -72,47 +85,47 @@ switch (command) {
|
|
|
72
85
|
break;
|
|
73
86
|
}
|
|
74
87
|
case "login": {
|
|
75
|
-
const { login } = await import("./login-
|
|
88
|
+
const { login } = await import("./login-3EXB4CGX.js");
|
|
76
89
|
await login(args);
|
|
77
90
|
break;
|
|
78
91
|
}
|
|
79
92
|
case "whoami": {
|
|
80
|
-
const { whoami } = await import("./whoami-
|
|
93
|
+
const { whoami } = await import("./whoami-CI5D5RCC.js");
|
|
81
94
|
await whoami(args);
|
|
82
95
|
break;
|
|
83
96
|
}
|
|
84
97
|
case "deploy": {
|
|
85
98
|
if (args.includes("--static")) {
|
|
86
|
-
const { staticDeploy } = await import("./static-deploy-
|
|
99
|
+
const { staticDeploy } = await import("./static-deploy-5TBH4VNA.js");
|
|
87
100
|
await staticDeploy(args);
|
|
88
101
|
break;
|
|
89
102
|
}
|
|
90
|
-
const { deploy } = await import("./deploy-
|
|
103
|
+
const { deploy } = await import("./deploy-3SABPL3T.js");
|
|
91
104
|
await deploy(args);
|
|
92
105
|
break;
|
|
93
106
|
}
|
|
94
107
|
case "migrate": {
|
|
95
|
-
const { migrate } = await import("./migrate-
|
|
108
|
+
const { migrate } = await import("./migrate-WUO2GBMX.js");
|
|
96
109
|
await migrate(args);
|
|
97
110
|
break;
|
|
98
111
|
}
|
|
99
112
|
case "rollback": {
|
|
100
|
-
const { rollback } = await import("./rollback-
|
|
113
|
+
const { rollback } = await import("./rollback-GA6UY772.js");
|
|
101
114
|
await rollback(args);
|
|
102
115
|
break;
|
|
103
116
|
}
|
|
104
117
|
case "keys": {
|
|
105
|
-
const { keys } = await import("./keys-
|
|
118
|
+
const { keys } = await import("./keys-XBORZAPI.js");
|
|
106
119
|
await keys(args);
|
|
107
120
|
break;
|
|
108
121
|
}
|
|
109
122
|
case "logs": {
|
|
110
|
-
const { logs } = await import("./logs-
|
|
123
|
+
const { logs } = await import("./logs-2EOXLNWF.js");
|
|
111
124
|
await logs(args);
|
|
112
125
|
break;
|
|
113
126
|
}
|
|
114
127
|
case "rooms": {
|
|
115
|
-
const { rooms } = await import("./rooms-
|
|
128
|
+
const { rooms } = await import("./rooms-B66LQIIF.js");
|
|
116
129
|
await rooms(args);
|
|
117
130
|
break;
|
|
118
131
|
}
|
package/dist/init.d.ts
CHANGED
|
@@ -59,6 +59,7 @@ interface InitResult {
|
|
|
59
59
|
* `irtio init [dir] [--tick|--event]`. Hand-rolled like `parseDevArgs`: the CLI has no
|
|
60
60
|
* argument-parsing dependency and four flags do not earn one.
|
|
61
61
|
*/
|
|
62
|
+
declare const USAGE = "usage: irtio init [dir] [options]\n\nScaffolds irtio/schema.ts, irtio/rpc.ts, irtio/room.ts, irtio/room.test.ts and irtio.json.\nNothing that already exists is ever overwritten.\n\noptions:\n [dir] where to scaffold (default: here)\n --tick a tick room, without asking\n --event an event room, without asking\n --physics scaffold a physics room and its shared world builder\n --name <name> the project name a first deploy registers (default: the directory)\n -h, --help print this\n";
|
|
62
63
|
declare function parseInitArgs(args: readonly string[]): InitArgs;
|
|
63
64
|
/** `p_` + 16 hex characters: the project id *is* the public key, so it is not a secret. */
|
|
64
65
|
declare function generateProjectId(): string;
|
|
@@ -70,4 +71,4 @@ declare function runInit(options?: RunInitOptions): Promise<InitResult>;
|
|
|
70
71
|
/** Thin on purpose: parse, run, and turn a thrown message into an exit code. */
|
|
71
72
|
declare function init(args: readonly string[]): Promise<void>;
|
|
72
73
|
|
|
73
|
-
export { INIT_DEPENDENCIES, type InitArgs, type InitResult, type RoomMode, type RunInitOptions, generateProjectId, init, parseInitArgs, runInit };
|
|
74
|
+
export { INIT_DEPENDENCIES, type InitArgs, type InitResult, type RoomMode, type RunInitOptions, USAGE, generateProjectId, init, parseInitArgs, runInit };
|
package/dist/init.js
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
HelpRequested,
|
|
3
|
+
helpFor,
|
|
4
|
+
helpRequested
|
|
5
|
+
} from "./chunk-TV66QHFP.js";
|
|
6
|
+
|
|
1
7
|
// src/init.ts
|
|
2
8
|
import { randomBytes } from "crypto";
|
|
3
9
|
import { existsSync } from "fs";
|
|
@@ -13,7 +19,21 @@ var INIT_DEPENDENCIES = [
|
|
|
13
19
|
];
|
|
14
20
|
var DEFAULT_TICK_RATE = 20;
|
|
15
21
|
var DEFAULT_IDLE_MS = 3e4;
|
|
22
|
+
var USAGE = `usage: irtio init [dir] [options]
|
|
23
|
+
|
|
24
|
+
Scaffolds irtio/schema.ts, irtio/rpc.ts, irtio/room.ts, irtio/room.test.ts and irtio.json.
|
|
25
|
+
Nothing that already exists is ever overwritten.
|
|
26
|
+
|
|
27
|
+
options:
|
|
28
|
+
[dir] where to scaffold (default: here)
|
|
29
|
+
--tick a tick room, without asking
|
|
30
|
+
--event an event room, without asking
|
|
31
|
+
--physics scaffold a physics room and its shared world builder
|
|
32
|
+
--name <name> the project name a first deploy registers (default: the directory)
|
|
33
|
+
-h, --help print this
|
|
34
|
+
`;
|
|
16
35
|
function parseInitArgs(args) {
|
|
36
|
+
if (helpRequested(args)) throw helpFor(USAGE);
|
|
17
37
|
const parsed = {};
|
|
18
38
|
for (let i = 0; i < args.length; i++) {
|
|
19
39
|
const arg = args[i];
|
|
@@ -534,12 +554,17 @@ async function init(args) {
|
|
|
534
554
|
...parsed.name !== void 0 ? { name: parsed.name } : {}
|
|
535
555
|
});
|
|
536
556
|
} catch (err) {
|
|
557
|
+
if (err instanceof HelpRequested) {
|
|
558
|
+
console.log(err.usage);
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
537
561
|
console.error(pc.red(err instanceof Error ? err.message : String(err)));
|
|
538
562
|
process.exitCode = 1;
|
|
539
563
|
}
|
|
540
564
|
}
|
|
541
565
|
export {
|
|
542
566
|
INIT_DEPENDENCIES,
|
|
567
|
+
USAGE,
|
|
543
568
|
generateProjectId,
|
|
544
569
|
init,
|
|
545
570
|
parseInitArgs,
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
} from "./chunk-I37DLT7K.js";
|
|
2
|
+
readProjectConfig
|
|
3
|
+
} from "./chunk-32QTPKVT.js";
|
|
5
4
|
import {
|
|
5
|
+
createApiClient,
|
|
6
|
+
helpRequested,
|
|
7
|
+
isLoginRequired,
|
|
6
8
|
resolveControlUrlForUser
|
|
7
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-TV66QHFP.js";
|
|
8
10
|
|
|
9
11
|
// src/keys.ts
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
+
import "fs";
|
|
13
|
+
import "fs/promises";
|
|
12
14
|
import * as path from "path";
|
|
13
15
|
import pc from "picocolors";
|
|
14
16
|
|
|
@@ -22,17 +24,6 @@ function signJwt(secret, claims) {
|
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
// src/keys.ts
|
|
25
|
-
async function readIrtioJsonProject(cwd) {
|
|
26
|
-
const file = path.join(cwd, "irtio.json");
|
|
27
|
-
if (!existsSync(file)) return void 0;
|
|
28
|
-
let parsed;
|
|
29
|
-
try {
|
|
30
|
-
parsed = JSON.parse(await readFile(file, "utf8"));
|
|
31
|
-
} catch {
|
|
32
|
-
throw new Error(`irtio keys: ${file} is not valid JSON`);
|
|
33
|
-
}
|
|
34
|
-
return typeof parsed.project === "string" && parsed.project.length > 0 ? parsed.project : void 0;
|
|
35
|
-
}
|
|
36
27
|
function flagValue(args, flag) {
|
|
37
28
|
const i = args.indexOf(flag);
|
|
38
29
|
if (i === -1) return void 0;
|
|
@@ -40,11 +31,15 @@ function flagValue(args, flag) {
|
|
|
40
31
|
if (value === void 0) throw new Error(`irtio keys: ${flag} needs a value`);
|
|
41
32
|
return value;
|
|
42
33
|
}
|
|
34
|
+
function configFlag(args) {
|
|
35
|
+
return flagValue(args, "--config") ?? flagValue(args, "-c");
|
|
36
|
+
}
|
|
43
37
|
async function resolveProject(args) {
|
|
44
|
-
const
|
|
38
|
+
const config = await readProjectConfig(process.cwd(), "irtio keys", configFlag(args));
|
|
39
|
+
const project = flagValue(args, "--project") ?? config.project;
|
|
45
40
|
if (project === void 0) {
|
|
46
41
|
throw new Error(
|
|
47
|
-
|
|
42
|
+
`irtio keys: no project id \u2014 pass --project or run this from a project with ${path.basename(config.file)}`
|
|
48
43
|
);
|
|
49
44
|
}
|
|
50
45
|
return project;
|
|
@@ -88,9 +83,40 @@ async function runJwtSecretRetire(options) {
|
|
|
88
83
|
log(pc.green(`retired the oldest active secret; ${result.active} remain(s) active`));
|
|
89
84
|
log(pc.dim("tokens signed with the retired secret stop verifying at the next placement"));
|
|
90
85
|
}
|
|
86
|
+
var USAGE = `usage: irtio keys jwt-secret [retire] [options]
|
|
87
|
+
irtio keys jwt-mint --secret <s> --sub <playerId> [options]
|
|
88
|
+
|
|
89
|
+
jwt-secret mints a signing secret for the project. It is printed ONCE and never again. Running it
|
|
90
|
+
a second time starts a rotation, where both secrets verify; retire finishes one by dropping the
|
|
91
|
+
oldest.
|
|
92
|
+
|
|
93
|
+
jwt-mint signs a test token locally, with the documented recipe. The secret you pass never leaves
|
|
94
|
+
this machine.
|
|
95
|
+
|
|
96
|
+
jwt-secret options:
|
|
97
|
+
retire retire the oldest active secret for this issuer
|
|
98
|
+
--issuer <label> the issuer to mint or retire under
|
|
99
|
+
--project <id> project id (default: the project file)
|
|
100
|
+
-c, --config <f> the project file to read (default irtio.json)
|
|
101
|
+
--url <control> control plane (default: your stored login)
|
|
102
|
+
|
|
103
|
+
jwt-mint options:
|
|
104
|
+
--secret <s> the signing secret (required)
|
|
105
|
+
--sub <playerId> the player the token is for (required)
|
|
106
|
+
--iss <label> the issuer claim
|
|
107
|
+
--room <id> restrict the token to one room
|
|
108
|
+
--role <r> the role to join as
|
|
109
|
+
--ttl <sec> lifetime in seconds (default 3600)
|
|
110
|
+
|
|
111
|
+
-h, --help print this
|
|
112
|
+
`;
|
|
91
113
|
async function keys(args, deps = {}) {
|
|
92
114
|
const log = deps.log ?? ((line) => console.log(line));
|
|
93
115
|
const errorLog = deps.errorLog ?? ((line) => console.error(line));
|
|
116
|
+
if (helpRequested(args)) {
|
|
117
|
+
log(USAGE);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
94
120
|
try {
|
|
95
121
|
const sub = args[0];
|
|
96
122
|
const rest = args.slice(1);
|
|
@@ -133,7 +159,7 @@ async function keys(args, deps = {}) {
|
|
|
133
159
|
const room = flagValue(rest, "--room");
|
|
134
160
|
const role = flagValue(rest, "--role");
|
|
135
161
|
const iss = flagValue(rest, "--iss") ?? DEFAULT_ISSUER;
|
|
136
|
-
const project = flagValue(rest, "--project") ?? await
|
|
162
|
+
const project = flagValue(rest, "--project") ?? (await readProjectConfig(process.cwd(), "irtio keys", configFlag(rest))).project;
|
|
137
163
|
if (project === void 0) {
|
|
138
164
|
throw new Error(
|
|
139
165
|
"irtio keys jwt-mint: --project is required (aud must name the project the token is for)"
|
|
@@ -168,6 +194,7 @@ async function keys(args, deps = {}) {
|
|
|
168
194
|
}
|
|
169
195
|
export {
|
|
170
196
|
DEFAULT_ISSUER,
|
|
197
|
+
USAGE,
|
|
171
198
|
keys,
|
|
172
199
|
runJwtSecret,
|
|
173
200
|
runJwtSecretRetire
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
|
+
HelpRequested,
|
|
2
3
|
credentialsPath,
|
|
4
|
+
helpFor,
|
|
5
|
+
helpRequested,
|
|
3
6
|
resolveControlUrl,
|
|
4
7
|
writeCredential
|
|
5
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-TV66QHFP.js";
|
|
6
9
|
|
|
7
10
|
// src/login.ts
|
|
8
11
|
import { spawn } from "child_process";
|
|
@@ -10,7 +13,16 @@ import { randomBytes } from "crypto";
|
|
|
10
13
|
import { createServer } from "http";
|
|
11
14
|
import pc from "picocolors";
|
|
12
15
|
var LOGIN_TIMEOUT_MS = 3 * 60 * 1e3;
|
|
16
|
+
var USAGE = `usage: irtio login [--url <control>]
|
|
17
|
+
|
|
18
|
+
Signs in to a control plane through your browser and stores the credential it hands back.
|
|
19
|
+
|
|
20
|
+
options:
|
|
21
|
+
--url <control> the control plane to sign in to (default: the last one you used)
|
|
22
|
+
-h, --help print this
|
|
23
|
+
`;
|
|
13
24
|
function parseLoginArgs(args) {
|
|
25
|
+
if (helpRequested(args)) throw helpFor(USAGE);
|
|
14
26
|
const parsed = {};
|
|
15
27
|
for (let i = 0; i < args.length; i++) {
|
|
16
28
|
const arg = args[i];
|
|
@@ -145,11 +157,16 @@ async function login(args) {
|
|
|
145
157
|
console.log(pc.dim(`control plane: ${result.controlUrl}`));
|
|
146
158
|
console.log(pc.dim(`credentials stored at ${result.file ?? credentialsPath()}`));
|
|
147
159
|
} catch (err) {
|
|
160
|
+
if (err instanceof HelpRequested) {
|
|
161
|
+
console.log(err.usage);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
148
164
|
console.error(pc.red(err instanceof Error ? err.message : String(err)));
|
|
149
165
|
process.exitCode = 1;
|
|
150
166
|
}
|
|
151
167
|
}
|
|
152
168
|
export {
|
|
169
|
+
USAGE,
|
|
153
170
|
defaultOpenBrowser,
|
|
154
171
|
login,
|
|
155
172
|
parseLoginArgs,
|
|
@@ -1,18 +1,36 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
} from "./chunk-I37DLT7K.js";
|
|
2
|
+
readProjectConfig
|
|
3
|
+
} from "./chunk-32QTPKVT.js";
|
|
5
4
|
import {
|
|
5
|
+
HelpRequested,
|
|
6
|
+
createApiClient,
|
|
7
|
+
helpFor,
|
|
8
|
+
helpRequested,
|
|
9
|
+
isLoginRequired,
|
|
6
10
|
resolveControlUrlForUser
|
|
7
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-TV66QHFP.js";
|
|
8
12
|
|
|
9
13
|
// src/logs.ts
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
14
|
+
import "fs";
|
|
15
|
+
import "fs/promises";
|
|
16
|
+
import "path";
|
|
13
17
|
import pc from "picocolors";
|
|
14
18
|
var POLL_MS = 2e3;
|
|
19
|
+
var USAGE = `usage: irtio logs [options]
|
|
20
|
+
|
|
21
|
+
Tails a project's logs, oldest line first.
|
|
22
|
+
|
|
23
|
+
options:
|
|
24
|
+
--follow poll every 2s, threading the cursor so nothing repeats
|
|
25
|
+
--since <cursor> start after this cursor (a previous row's timestamp)
|
|
26
|
+
--room <id> narrow to one room's stream. __tenant is the tenant's own events
|
|
27
|
+
--project <id> project id (default: the project file)
|
|
28
|
+
-c, --config <f> the project file to read (default irtio.json)
|
|
29
|
+
--url <control> control plane (default: your stored login)
|
|
30
|
+
-h, --help print this
|
|
31
|
+
`;
|
|
15
32
|
function parseLogsArgs(args) {
|
|
33
|
+
if (helpRequested(args)) throw helpFor(USAGE);
|
|
16
34
|
const parsed = {
|
|
17
35
|
follow: false
|
|
18
36
|
};
|
|
@@ -40,6 +58,14 @@ function parseLogsArgs(args) {
|
|
|
40
58
|
parsed.project = value;
|
|
41
59
|
break;
|
|
42
60
|
}
|
|
61
|
+
case "-c":
|
|
62
|
+
case "--config": {
|
|
63
|
+
const value = args[++i];
|
|
64
|
+
if (value === void 0 || value === "")
|
|
65
|
+
throw new Error("irtio logs: --config needs a value");
|
|
66
|
+
parsed.config = value;
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
43
69
|
case "--url": {
|
|
44
70
|
const value = args[++i];
|
|
45
71
|
if (value === void 0) throw new Error("irtio logs: --url needs a value");
|
|
@@ -81,23 +107,13 @@ async function runLogs(options) {
|
|
|
81
107
|
await new Promise((resolve) => setTimeout(resolve, options.pollMs ?? POLL_MS));
|
|
82
108
|
}
|
|
83
109
|
}
|
|
84
|
-
async function readIrtioJsonProject(cwd) {
|
|
85
|
-
const file = path.join(cwd, "irtio.json");
|
|
86
|
-
if (!existsSync(file)) return void 0;
|
|
87
|
-
let parsed;
|
|
88
|
-
try {
|
|
89
|
-
parsed = JSON.parse(await readFile(file, "utf8"));
|
|
90
|
-
} catch {
|
|
91
|
-
throw new Error(`irtio logs: ${file} is not valid JSON`);
|
|
92
|
-
}
|
|
93
|
-
return typeof parsed.project === "string" && parsed.project.length > 0 ? parsed.project : void 0;
|
|
94
|
-
}
|
|
95
110
|
async function logs(args, deps = {}) {
|
|
96
111
|
const log = deps.log ?? ((line) => console.log(line));
|
|
97
112
|
const errorLog = deps.errorLog ?? ((line) => console.error(line));
|
|
98
113
|
try {
|
|
99
114
|
const parsed = parseLogsArgs(args);
|
|
100
|
-
const
|
|
115
|
+
const config = await readProjectConfig(process.cwd(), "irtio logs", parsed.config);
|
|
116
|
+
const project = parsed.project ?? config.project;
|
|
101
117
|
if (project === void 0) {
|
|
102
118
|
throw new Error(
|
|
103
119
|
"irtio logs: no project id \u2014 pass --project or run this from a project with irtio.json"
|
|
@@ -113,6 +129,10 @@ async function logs(args, deps = {}) {
|
|
|
113
129
|
...deps.client !== void 0 ? { client: deps.client } : {}
|
|
114
130
|
});
|
|
115
131
|
} catch (err) {
|
|
132
|
+
if (err instanceof HelpRequested) {
|
|
133
|
+
log(err.usage);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
116
136
|
if (isLoginRequired(err)) {
|
|
117
137
|
errorLog(pc.red("not logged in"));
|
|
118
138
|
errorLog("run: irtio login");
|
|
@@ -124,6 +144,7 @@ async function logs(args, deps = {}) {
|
|
|
124
144
|
}
|
|
125
145
|
}
|
|
126
146
|
export {
|
|
147
|
+
USAGE,
|
|
127
148
|
logs,
|
|
128
149
|
parseLogsArgs,
|
|
129
150
|
runLogs
|
|
@@ -2,16 +2,20 @@ import {
|
|
|
2
2
|
bundleRoom
|
|
3
3
|
} from "./chunk-KRQUAEN2.js";
|
|
4
4
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
} from "./chunk-I37DLT7K.js";
|
|
5
|
+
readProjectConfig
|
|
6
|
+
} from "./chunk-32QTPKVT.js";
|
|
8
7
|
import {
|
|
8
|
+
HelpRequested,
|
|
9
|
+
createApiClient,
|
|
10
|
+
helpFor,
|
|
11
|
+
helpRequested,
|
|
12
|
+
isLoginRequired,
|
|
9
13
|
resolveControlUrlForUser
|
|
10
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-TV66QHFP.js";
|
|
11
15
|
|
|
12
16
|
// src/migrate.ts
|
|
13
17
|
import { existsSync } from "fs";
|
|
14
|
-
import { mkdir, mkdtemp,
|
|
18
|
+
import { mkdir, mkdtemp, readdir, writeFile } from "fs/promises";
|
|
15
19
|
import { tmpdir } from "os";
|
|
16
20
|
import * as path from "path";
|
|
17
21
|
import { pathToFileURL } from "url";
|
|
@@ -23,7 +27,18 @@ import {
|
|
|
23
27
|
import pc from "picocolors";
|
|
24
28
|
var MIGRATIONS_DIR = "irtio/migrations";
|
|
25
29
|
var ROOM_CANDIDATES = ["irtio/room.ts", "irtio/room.js", "room.ts"];
|
|
30
|
+
var USAGE = `usage: irtio migrate create <name> [-c <file>]
|
|
31
|
+
|
|
32
|
+
Scaffolds irtio/migrations/<n>_<name>.ts, with the breaking changes against the live deployment
|
|
33
|
+
quoted in its header so the transform has something to answer.
|
|
34
|
+
|
|
35
|
+
options:
|
|
36
|
+
<name> a short name for the migration, e.g. rename-hp
|
|
37
|
+
-c, --config <f> the project file to read (default irtio.json)
|
|
38
|
+
-h, --help print this
|
|
39
|
+
`;
|
|
26
40
|
function parseMigrateArgs(args) {
|
|
41
|
+
if (helpRequested(args)) throw helpFor(USAGE);
|
|
27
42
|
const [sub, name, ...rest] = args;
|
|
28
43
|
if (sub !== "create") {
|
|
29
44
|
throw new Error(
|
|
@@ -35,9 +50,20 @@ function parseMigrateArgs(args) {
|
|
|
35
50
|
"irtio migrate create: a name is required, e.g. irtio migrate create rename-hp"
|
|
36
51
|
);
|
|
37
52
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
53
|
+
let config;
|
|
54
|
+
for (let i = 0; i < rest.length; i++) {
|
|
55
|
+
const arg = rest[i];
|
|
56
|
+
if (arg === "-c" || arg === "--config") {
|
|
57
|
+
const value = rest[++i];
|
|
58
|
+
if (value === void 0 || value === "") {
|
|
59
|
+
throw new Error("irtio migrate create: --config needs a value");
|
|
60
|
+
}
|
|
61
|
+
config = value;
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
throw new Error(`irtio migrate create: unexpected extra argument ${JSON.stringify(arg)}`);
|
|
65
|
+
}
|
|
66
|
+
return { command: "create", args: config === void 0 ? { name } : { name, config } };
|
|
41
67
|
}
|
|
42
68
|
function resolveEntry(cwd, room) {
|
|
43
69
|
if (room !== void 0) {
|
|
@@ -53,17 +79,6 @@ function resolveEntry(cwd, room) {
|
|
|
53
79
|
`irtio migrate create: no room file found in ${cwd} (looked for: ${ROOM_CANDIDATES.join(", ")})`
|
|
54
80
|
);
|
|
55
81
|
}
|
|
56
|
-
async function readIrtioJsonProject(cwd) {
|
|
57
|
-
const file = path.join(cwd, "irtio.json");
|
|
58
|
-
if (!existsSync(file)) return void 0;
|
|
59
|
-
let parsed;
|
|
60
|
-
try {
|
|
61
|
-
parsed = JSON.parse(await readFile(file, "utf8"));
|
|
62
|
-
} catch {
|
|
63
|
-
throw new Error(`irtio migrate: ${file} is not valid JSON`);
|
|
64
|
-
}
|
|
65
|
-
return typeof parsed.project === "string" && parsed.project.length > 0 ? parsed.project : void 0;
|
|
66
|
-
}
|
|
67
82
|
async function scanDirectoryVersion(cwd) {
|
|
68
83
|
const dir = path.join(cwd, MIGRATIONS_DIR);
|
|
69
84
|
if (!existsSync(dir)) return 1;
|
|
@@ -120,7 +135,8 @@ async function runMigrateCreate(options) {
|
|
|
120
135
|
const cwd = path.resolve(options.cwd ?? process.cwd());
|
|
121
136
|
const log = options.log ?? ((line) => console.log(line));
|
|
122
137
|
const controlUrl = await resolveControlUrlForUser(options.controlUrl);
|
|
123
|
-
const
|
|
138
|
+
const config = await readProjectConfig(cwd, "irtio migrate", options.config);
|
|
139
|
+
const projectId = options.project ?? config.project;
|
|
124
140
|
let version;
|
|
125
141
|
let versionSource;
|
|
126
142
|
let previousSchemaJson;
|
|
@@ -196,6 +212,10 @@ async function migrate(args, deps = {}) {
|
|
|
196
212
|
...deps.client !== void 0 ? { client: deps.client } : {}
|
|
197
213
|
});
|
|
198
214
|
} catch (err) {
|
|
215
|
+
if (err instanceof HelpRequested) {
|
|
216
|
+
log(err.usage);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
199
219
|
if (isLoginRequired(err)) {
|
|
200
220
|
errorLog(pc.red("not logged in"));
|
|
201
221
|
errorLog("run: irtio login");
|
|
@@ -207,6 +227,7 @@ async function migrate(args, deps = {}) {
|
|
|
207
227
|
}
|
|
208
228
|
}
|
|
209
229
|
export {
|
|
230
|
+
USAGE,
|
|
210
231
|
migrate,
|
|
211
232
|
parseMigrateArgs,
|
|
212
233
|
runMigrateCreate
|
|
@@ -1,17 +1,34 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
} from "./chunk-I37DLT7K.js";
|
|
2
|
+
readProjectConfig
|
|
3
|
+
} from "./chunk-32QTPKVT.js";
|
|
5
4
|
import {
|
|
5
|
+
HelpRequested,
|
|
6
|
+
createApiClient,
|
|
7
|
+
helpFor,
|
|
8
|
+
helpRequested,
|
|
9
|
+
isLoginRequired,
|
|
6
10
|
resolveControlUrlForUser
|
|
7
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-TV66QHFP.js";
|
|
8
12
|
|
|
9
13
|
// src/rollback.ts
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
14
|
+
import "fs";
|
|
15
|
+
import "fs/promises";
|
|
16
|
+
import "path";
|
|
13
17
|
import pc from "picocolors";
|
|
18
|
+
var USAGE = `usage: irtio rollback <version> [options]
|
|
19
|
+
|
|
20
|
+
Re-promotes deployment <version> and brings rooms that migrated past it back to their
|
|
21
|
+
pre-migration state. This DISCARDS whatever those rooms wrote since their migration.
|
|
22
|
+
|
|
23
|
+
options:
|
|
24
|
+
<version> the deployment version to go back to
|
|
25
|
+
--project <id> project id (default: the project file)
|
|
26
|
+
-c, --config <f> the project file to read (default irtio.json)
|
|
27
|
+
--url <control> control plane (default: your stored login)
|
|
28
|
+
-h, --help print this
|
|
29
|
+
`;
|
|
14
30
|
function parseRollbackArgs(args) {
|
|
31
|
+
if (helpRequested(args)) throw helpFor(USAGE);
|
|
15
32
|
const parsed = {};
|
|
16
33
|
for (let i = 0; i < args.length; i++) {
|
|
17
34
|
const arg = args[i];
|
|
@@ -22,6 +39,14 @@ function parseRollbackArgs(args) {
|
|
|
22
39
|
parsed.project = value;
|
|
23
40
|
break;
|
|
24
41
|
}
|
|
42
|
+
case "-c":
|
|
43
|
+
case "--config": {
|
|
44
|
+
const value = args[++i];
|
|
45
|
+
if (value === void 0 || value === "")
|
|
46
|
+
throw new Error("irtio rollback: --config needs a value");
|
|
47
|
+
parsed.config = value;
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
25
50
|
case "--url": {
|
|
26
51
|
const value = args[++i];
|
|
27
52
|
if (value === void 0) throw new Error("irtio rollback: --url needs a value");
|
|
@@ -75,23 +100,13 @@ async function runRollback(options) {
|
|
|
75
100
|
}
|
|
76
101
|
return result;
|
|
77
102
|
}
|
|
78
|
-
async function readIrtioJsonProject(cwd) {
|
|
79
|
-
const file = path.join(cwd, "irtio.json");
|
|
80
|
-
if (!existsSync(file)) return void 0;
|
|
81
|
-
let parsed;
|
|
82
|
-
try {
|
|
83
|
-
parsed = JSON.parse(await readFile(file, "utf8"));
|
|
84
|
-
} catch {
|
|
85
|
-
throw new Error(`irtio rollback: ${file} is not valid JSON`);
|
|
86
|
-
}
|
|
87
|
-
return typeof parsed.project === "string" && parsed.project.length > 0 ? parsed.project : void 0;
|
|
88
|
-
}
|
|
89
103
|
async function rollback(args, deps = {}) {
|
|
90
104
|
const log = deps.log ?? ((line) => console.log(line));
|
|
91
105
|
const errorLog = deps.errorLog ?? ((line) => console.error(line));
|
|
92
106
|
try {
|
|
93
107
|
const parsed = parseRollbackArgs(args);
|
|
94
|
-
const
|
|
108
|
+
const config = await readProjectConfig(process.cwd(), "irtio rollback", parsed.config);
|
|
109
|
+
const project = parsed.project ?? config.project;
|
|
95
110
|
if (project === void 0) {
|
|
96
111
|
throw new Error(
|
|
97
112
|
"irtio rollback: no project id \u2014 pass --project or run this from a project with irtio.json"
|
|
@@ -105,6 +120,10 @@ async function rollback(args, deps = {}) {
|
|
|
105
120
|
...deps.client !== void 0 ? { client: deps.client } : {}
|
|
106
121
|
});
|
|
107
122
|
} catch (err) {
|
|
123
|
+
if (err instanceof HelpRequested) {
|
|
124
|
+
log(err.usage);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
108
127
|
if (isLoginRequired(err)) {
|
|
109
128
|
errorLog(pc.red("not logged in"));
|
|
110
129
|
errorLog("run: irtio login");
|
|
@@ -116,6 +135,7 @@ async function rollback(args, deps = {}) {
|
|
|
116
135
|
}
|
|
117
136
|
}
|
|
118
137
|
export {
|
|
138
|
+
USAGE,
|
|
119
139
|
parseRollbackArgs,
|
|
120
140
|
rollback,
|
|
121
141
|
runRollback
|