@ratio-app/cli 0.1.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/README.md +504 -0
- package/bin/run.mjs +5 -0
- package/dist/commands/__test__/throw.d.ts +25 -0
- package/dist/commands/__test__/throw.js +238 -0
- package/dist/commands/__test__/throw.js.map +1 -0
- package/dist/commands/app/create.d.ts +55 -0
- package/dist/commands/app/create.js +609 -0
- package/dist/commands/app/create.js.map +1 -0
- package/dist/commands/app/deploy.d.ts +14 -0
- package/dist/commands/app/deploy.js +179 -0
- package/dist/commands/app/deploy.js.map +1 -0
- package/dist/commands/app/dev.d.ts +28 -0
- package/dist/commands/app/dev.js +701 -0
- package/dist/commands/app/dev.js.map +1 -0
- package/dist/commands/app/generate.d.ts +14 -0
- package/dist/commands/app/generate.js +179 -0
- package/dist/commands/app/generate.js.map +1 -0
- package/dist/commands/app/info.d.ts +14 -0
- package/dist/commands/app/info.js +179 -0
- package/dist/commands/app/info.js.map +1 -0
- package/dist/commands/app/link.d.ts +118 -0
- package/dist/commands/app/link.js +1120 -0
- package/dist/commands/app/link.js.map +1 -0
- package/dist/commands/auth/login.d.ts +43 -0
- package/dist/commands/auth/login.js +987 -0
- package/dist/commands/auth/login.js.map +1 -0
- package/dist/commands/auth/logout.d.ts +15 -0
- package/dist/commands/auth/logout.js +486 -0
- package/dist/commands/auth/logout.js.map +1 -0
- package/dist/commands/auth/whoami.d.ts +16 -0
- package/dist/commands/auth/whoami.js +531 -0
- package/dist/commands/auth/whoami.js.map +1 -0
- package/dist/commands/dev/listen.d.ts +84 -0
- package/dist/commands/dev/listen.js +1187 -0
- package/dist/commands/dev/listen.js.map +1 -0
- package/dist/commands/dev/trigger.d.ts +88 -0
- package/dist/commands/dev/trigger.js +729 -0
- package/dist/commands/dev/trigger.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +617 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/auth/authorize-code-exchange.d.ts +50 -0
- package/dist/lib/auth/authorize-code-exchange.js +114 -0
- package/dist/lib/auth/authorize-code-exchange.js.map +1 -0
- package/dist/lib/auth/authorize-url.d.ts +42 -0
- package/dist/lib/auth/authorize-url.js +35 -0
- package/dist/lib/auth/authorize-url.js.map +1 -0
- package/dist/lib/auth/browser.d.ts +16 -0
- package/dist/lib/auth/browser.js +48 -0
- package/dist/lib/auth/browser.js.map +1 -0
- package/dist/lib/auth/config.d.ts +41 -0
- package/dist/lib/auth/config.js +21 -0
- package/dist/lib/auth/config.js.map +1 -0
- package/dist/lib/auth/http-refresher.d.ts +30 -0
- package/dist/lib/auth/http-refresher.js +103 -0
- package/dist/lib/auth/http-refresher.js.map +1 -0
- package/dist/lib/auth/identity.d.ts +26 -0
- package/dist/lib/auth/identity.js +10 -0
- package/dist/lib/auth/identity.js.map +1 -0
- package/dist/lib/auth/index.d.ts +13 -0
- package/dist/lib/auth/index.js +527 -0
- package/dist/lib/auth/index.js.map +1 -0
- package/dist/lib/auth/loopback-server.d.ts +65 -0
- package/dist/lib/auth/loopback-server.js +245 -0
- package/dist/lib/auth/loopback-server.js.map +1 -0
- package/dist/lib/auth/manual-prompt.d.ts +17 -0
- package/dist/lib/auth/manual-prompt.js +20 -0
- package/dist/lib/auth/manual-prompt.js.map +1 -0
- package/dist/lib/auth/pkce.d.ts +24 -0
- package/dist/lib/auth/pkce.js +15 -0
- package/dist/lib/auth/pkce.js.map +1 -0
- package/dist/lib/auth/state.d.ts +20 -0
- package/dist/lib/auth/state.js +19 -0
- package/dist/lib/auth/state.js.map +1 -0
- package/dist/lib/auth/verbose-trace.d.ts +25 -0
- package/dist/lib/auth/verbose-trace.js +17 -0
- package/dist/lib/auth/verbose-trace.js.map +1 -0
- package/dist/lib/credentials/clock.d.ts +18 -0
- package/dist/lib/credentials/clock.js +10 -0
- package/dist/lib/credentials/clock.js.map +1 -0
- package/dist/lib/credentials/index.d.ts +5 -0
- package/dist/lib/credentials/index.js +340 -0
- package/dist/lib/credentials/index.js.map +1 -0
- package/dist/lib/credentials/path.d.ts +26 -0
- package/dist/lib/credentials/path.js +32 -0
- package/dist/lib/credentials/path.js.map +1 -0
- package/dist/lib/credentials/refresher.d.ts +26 -0
- package/dist/lib/credentials/refresher.js +34 -0
- package/dist/lib/credentials/refresher.js.map +1 -0
- package/dist/lib/credentials/schema.d.ts +138 -0
- package/dist/lib/credentials/schema.js +85 -0
- package/dist/lib/credentials/schema.js.map +1 -0
- package/dist/lib/credentials/store.d.ts +102 -0
- package/dist/lib/credentials/store.js +337 -0
- package/dist/lib/credentials/store.js.map +1 -0
- package/dist/lib/credentials/types.d.ts +65 -0
- package/dist/lib/credentials/types.js +1 -0
- package/dist/lib/credentials/types.js.map +1 -0
- package/dist/lib/dev-store-gate.d.ts +66 -0
- package/dist/lib/dev-store-gate.js +15 -0
- package/dist/lib/dev-store-gate.js.map +1 -0
- package/dist/lib/errors.d.ts +60 -0
- package/dist/lib/errors.js +101 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/manifest/index.d.ts +2 -0
- package/dist/lib/manifest/index.js +144 -0
- package/dist/lib/manifest/index.js.map +1 -0
- package/dist/lib/manifest/read-manifest.d.ts +32 -0
- package/dist/lib/manifest/read-manifest.js +87 -0
- package/dist/lib/manifest/read-manifest.js.map +1 -0
- package/dist/lib/manifest/write-client-id.d.ts +33 -0
- package/dist/lib/manifest/write-client-id.js +94 -0
- package/dist/lib/manifest/write-client-id.js.map +1 -0
- package/dist/lib/messages.d.ts +15 -0
- package/dist/lib/messages.js +16 -0
- package/dist/lib/messages.js.map +1 -0
- package/dist/lib/orchestrator/child-runner.d.ts +140 -0
- package/dist/lib/orchestrator/child-runner.js +471 -0
- package/dist/lib/orchestrator/child-runner.js.map +1 -0
- package/dist/lib/preview/index.d.ts +11 -0
- package/dist/lib/preview/index.js +17 -0
- package/dist/lib/preview/index.js.map +1 -0
- package/dist/lib/preview/types.d.ts +16 -0
- package/dist/lib/preview/types.js +11 -0
- package/dist/lib/preview/types.js.map +1 -0
- package/dist/lib/ratio-command.d.ts +52 -0
- package/dist/lib/ratio-command.js +141 -0
- package/dist/lib/ratio-command.js.map +1 -0
- package/dist/lib/relay/index.d.ts +7 -0
- package/dist/lib/relay/index.js +362 -0
- package/dist/lib/relay/index.js.map +1 -0
- package/dist/lib/relay/relay-client.d.ts +91 -0
- package/dist/lib/relay/relay-client.js +362 -0
- package/dist/lib/relay/relay-client.js.map +1 -0
- package/dist/lib/relay/types.d.ts +71 -0
- package/dist/lib/relay/types.js +1 -0
- package/dist/lib/relay/types.js.map +1 -0
- package/dist/lib/render-error.d.ts +35 -0
- package/dist/lib/render-error.js +115 -0
- package/dist/lib/render-error.js.map +1 -0
- package/dist/lib/verbose-flag.d.ts +12 -0
- package/dist/lib/verbose-flag.js +17 -0
- package/dist/lib/verbose-flag.js.map +1 -0
- package/dist/render-CrHGqTPH.d.ts +115 -0
- package/dist/templates/.gitkeep +0 -0
- package/dist/templates/minimal/.env.example.tmpl +4 -0
- package/dist/templates/minimal/README.md.tmpl +26 -0
- package/dist/templates/minimal/gitignore +5 -0
- package/dist/templates/minimal/manifest.json +5 -0
- package/dist/templates/minimal/package.json.tmpl +25 -0
- package/dist/templates/minimal/ratio.config.jsonc.tmpl +17 -0
- package/dist/templates/minimal/src/index.ts.tmpl +26 -0
- package/dist/templates/minimal/src/install.ts.tmpl +37 -0
- package/dist/templates/minimal/src/webhooks.ts.tmpl +57 -0
- package/dist/templates/minimal/tsconfig.json +17 -0
- package/dist/templates/serverless/README.md.tmpl +28 -0
- package/dist/templates/serverless/gitignore +6 -0
- package/dist/templates/serverless/manifest.json +5 -0
- package/dist/templates/serverless/package.json.tmpl +22 -0
- package/dist/templates/serverless/ratio.config.jsonc.tmpl +17 -0
- package/dist/templates/serverless/src/index.ts.tmpl +20 -0
- package/dist/templates/serverless/src/install.ts.tmpl +20 -0
- package/dist/templates/serverless/src/webhooks.ts.tmpl +36 -0
- package/dist/templates/serverless/tsconfig.json +18 -0
- package/dist/templates/serverless/wrangler.toml.tmpl +9 -0
- package/dist/templates/with-admin-ui/.env.example.tmpl +4 -0
- package/dist/templates/with-admin-ui/README.md.tmpl +28 -0
- package/dist/templates/with-admin-ui/gitignore +6 -0
- package/dist/templates/with-admin-ui/manifest.json +5 -0
- package/dist/templates/with-admin-ui/package.json.tmpl +31 -0
- package/dist/templates/with-admin-ui/ratio.config.jsonc.tmpl +17 -0
- package/dist/templates/with-admin-ui/src/admin/app/globals.css +19 -0
- package/dist/templates/with-admin-ui/src/admin/app/layout.tsx.tmpl +13 -0
- package/dist/templates/with-admin-ui/src/admin/app/page.tsx.tmpl +8 -0
- package/dist/templates/with-admin-ui/src/admin/next-env.d.ts.tmpl +5 -0
- package/dist/templates/with-admin-ui/src/admin/next.config.mjs +3 -0
- package/dist/templates/with-admin-ui/src/admin/tsconfig.json +20 -0
- package/dist/templates/with-admin-ui/src/index.ts.tmpl +26 -0
- package/dist/templates/with-admin-ui/src/install.ts.tmpl +37 -0
- package/dist/templates/with-admin-ui/src/webhooks.ts.tmpl +57 -0
- package/dist/templates/with-admin-ui/tsconfig.json +17 -0
- package/package.json +78 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
// src/lib/ratio-command.ts
|
|
2
|
+
import { Command, Errors } from "@oclif/core";
|
|
3
|
+
|
|
4
|
+
// src/lib/errors.ts
|
|
5
|
+
var RatioCLIError = class extends Error {
|
|
6
|
+
code;
|
|
7
|
+
exitCode;
|
|
8
|
+
hint;
|
|
9
|
+
docsUrl;
|
|
10
|
+
constructor(opts) {
|
|
11
|
+
super(opts.message);
|
|
12
|
+
this.name = new.target.name;
|
|
13
|
+
this.code = opts.code;
|
|
14
|
+
this.exitCode = opts.exitCode;
|
|
15
|
+
if (opts.hint !== void 0) this.hint = opts.hint;
|
|
16
|
+
if (opts.docsUrl !== void 0) this.docsUrl = opts.docsUrl;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
var ComingSoonError = class extends RatioCLIError {
|
|
20
|
+
constructor(message) {
|
|
21
|
+
super({ code: "COMING_SOON", exitCode: 0, message });
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
var NotLoggedInError = class extends RatioCLIError {
|
|
25
|
+
constructor(message, hint = "Run 'ratio auth login' to sign in.") {
|
|
26
|
+
super({ code: "NOT_LOGGED_IN", exitCode: 3, message, hint });
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
var TokenExpiredError = class extends RatioCLIError {
|
|
30
|
+
constructor(message, hint = "Run 'ratio auth login' to refresh your session.") {
|
|
31
|
+
super({ code: "TOKEN_EXPIRED", exitCode: 3, message, hint });
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
var ScopeDeniedError = class extends RatioCLIError {
|
|
35
|
+
constructor(message, hint) {
|
|
36
|
+
const opts = {
|
|
37
|
+
code: "SCOPE_DENIED",
|
|
38
|
+
exitCode: 4,
|
|
39
|
+
message
|
|
40
|
+
};
|
|
41
|
+
if (hint !== void 0) opts.hint = hint;
|
|
42
|
+
super(opts);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
var NetworkError = class extends RatioCLIError {
|
|
46
|
+
constructor(message, hint = "Check your network and retry.") {
|
|
47
|
+
super({ code: "NETWORK_ERROR", exitCode: 5, message, hint });
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
var RelayConnectError = class extends RatioCLIError {
|
|
51
|
+
constructor(message, hint = "Verify the tunnel URL and that the auth-server is reachable.") {
|
|
52
|
+
super({ code: "RELAY_CONNECT", exitCode: 6, message, hint });
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
var TemplateExistsError = class extends RatioCLIError {
|
|
56
|
+
constructor(message, hint = "Choose a different name or remove the existing directory.") {
|
|
57
|
+
super({ code: "TEMPLATE_EXISTS", exitCode: 7, message, hint });
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
var ValidationError = class extends RatioCLIError {
|
|
61
|
+
constructor(message, hint) {
|
|
62
|
+
const opts = {
|
|
63
|
+
code: "VALIDATION_ERROR",
|
|
64
|
+
exitCode: 8,
|
|
65
|
+
message
|
|
66
|
+
};
|
|
67
|
+
if (hint !== void 0) opts.hint = hint;
|
|
68
|
+
super(opts);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
var RelayResumeGapError = class extends RatioCLIError {
|
|
72
|
+
constructor(message, hint = "Reconnect from the current cursor; older events are outside the buffer window.") {
|
|
73
|
+
super({ code: "RELAY_RESUME_GAP", exitCode: 9, message, hint });
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
function isRatioCLIError(err) {
|
|
77
|
+
return err instanceof RatioCLIError;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// src/lib/render-error.ts
|
|
81
|
+
function isOclifParserError(err) {
|
|
82
|
+
return err instanceof Error && "parse" in err && err.parse !== null && err.parse !== void 0;
|
|
83
|
+
}
|
|
84
|
+
function buildErrorEnvelope(code, message, hint, docsUrl) {
|
|
85
|
+
const obj = { ok: false, code, message };
|
|
86
|
+
if (hint !== void 0) obj["hint"] = hint;
|
|
87
|
+
if (docsUrl !== void 0) obj["docsUrl"] = docsUrl;
|
|
88
|
+
return JSON.stringify(obj) + "\n";
|
|
89
|
+
}
|
|
90
|
+
function renderError(input) {
|
|
91
|
+
const { err, verbose, json } = input;
|
|
92
|
+
if (isRatioCLIError(err)) {
|
|
93
|
+
const ratioErr = err;
|
|
94
|
+
if (ratioErr.exitCode === 0) {
|
|
95
|
+
if (json) {
|
|
96
|
+
return {
|
|
97
|
+
stdout: JSON.stringify({ ok: true, data: null }) + "\n",
|
|
98
|
+
stderr: "",
|
|
99
|
+
exitCode: 0
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
stdout: ratioErr.message + "\n",
|
|
104
|
+
stderr: "",
|
|
105
|
+
exitCode: 0
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
let stderrLines = `${ratioErr.code}: ${ratioErr.message}
|
|
109
|
+
`;
|
|
110
|
+
if (ratioErr.hint !== void 0) stderrLines += `${ratioErr.hint}
|
|
111
|
+
`;
|
|
112
|
+
if (ratioErr.docsUrl !== void 0) stderrLines += `${ratioErr.docsUrl}
|
|
113
|
+
`;
|
|
114
|
+
if (json) {
|
|
115
|
+
return {
|
|
116
|
+
stdout: buildErrorEnvelope(ratioErr.code, ratioErr.message, ratioErr.hint, ratioErr.docsUrl),
|
|
117
|
+
stderr: verbose && ratioErr.stack ? ratioErr.stack + "\n" : "",
|
|
118
|
+
exitCode: ratioErr.exitCode
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
if (verbose && ratioErr.stack) {
|
|
122
|
+
stderrLines += ratioErr.stack + "\n";
|
|
123
|
+
}
|
|
124
|
+
return { stdout: "", stderr: stderrLines, exitCode: ratioErr.exitCode };
|
|
125
|
+
}
|
|
126
|
+
if (isOclifParserError(err)) {
|
|
127
|
+
const parserErr = err;
|
|
128
|
+
const msg = parserErr.message || "Unknown parse error";
|
|
129
|
+
const coercedErr = new ValidationError(msg);
|
|
130
|
+
let stderrText2 = `${coercedErr.code}: ${msg}
|
|
131
|
+
`;
|
|
132
|
+
if (json) {
|
|
133
|
+
return {
|
|
134
|
+
stdout: buildErrorEnvelope(coercedErr.code, msg),
|
|
135
|
+
stderr: verbose && parserErr.stack ? parserErr.stack + "\n" : "",
|
|
136
|
+
exitCode: 8
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
if (verbose && parserErr.stack) {
|
|
140
|
+
stderrText2 += parserErr.stack + "\n";
|
|
141
|
+
}
|
|
142
|
+
return { stdout: "", stderr: stderrText2, exitCode: 8 };
|
|
143
|
+
}
|
|
144
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
145
|
+
const stack = err instanceof Error ? err.stack : void 0;
|
|
146
|
+
const stderrPrefix = `INTERNAL: ${message}
|
|
147
|
+
`;
|
|
148
|
+
if (json) {
|
|
149
|
+
return {
|
|
150
|
+
stdout: buildErrorEnvelope("INTERNAL", message),
|
|
151
|
+
stderr: verbose && stack ? stack + "\n" : "",
|
|
152
|
+
exitCode: 1
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
let stderrText = stderrPrefix;
|
|
156
|
+
if (verbose && stack) {
|
|
157
|
+
stderrText += stack + "\n";
|
|
158
|
+
}
|
|
159
|
+
return { stdout: "", stderr: stderrText, exitCode: 1 };
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// src/lib/ratio-command.ts
|
|
163
|
+
var RatioCommand = class extends Command {
|
|
164
|
+
_getRenderFlags() {
|
|
165
|
+
const argv = this.argv;
|
|
166
|
+
return {
|
|
167
|
+
verbose: argv.includes("--verbose"),
|
|
168
|
+
json: argv.includes("--json")
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
async catch(err) {
|
|
172
|
+
const { verbose, json } = this._getRenderFlags();
|
|
173
|
+
const output = renderError({ err, verbose, json });
|
|
174
|
+
if (output.stdout) process.stdout.write(output.stdout);
|
|
175
|
+
if (output.stderr) process.stderr.write(output.stderr);
|
|
176
|
+
if (output.exitCode === 0) {
|
|
177
|
+
throw new Errors.ExitError(0);
|
|
178
|
+
}
|
|
179
|
+
err.skipOclifErrorHandling = true;
|
|
180
|
+
err.oclif = { exit: output.exitCode };
|
|
181
|
+
throw err;
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
// src/lib/verbose-flag.ts
|
|
186
|
+
import { Flags } from "@oclif/core";
|
|
187
|
+
var verboseFlag = {
|
|
188
|
+
verbose: Flags.boolean({
|
|
189
|
+
description: "Show diagnostic detail: HTTP status/timing lines for auth requests (stderr) and stack traces for internal errors."
|
|
190
|
+
})
|
|
191
|
+
};
|
|
192
|
+
var jsonFlag = {
|
|
193
|
+
json: Flags.boolean({
|
|
194
|
+
description: "Emit machine-readable JSON on stdout."
|
|
195
|
+
})
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
// src/commands/__test__/throw.ts
|
|
199
|
+
var TestThrow = class _TestThrow extends RatioCommand {
|
|
200
|
+
static description = "Test-only error injection command.";
|
|
201
|
+
static hidden = true;
|
|
202
|
+
static examples = [
|
|
203
|
+
"RATIO_TEST_ERROR_CODE=NOT_LOGGED_IN <%= config.bin %> __test__ throw"
|
|
204
|
+
];
|
|
205
|
+
static flags = {
|
|
206
|
+
...verboseFlag
|
|
207
|
+
};
|
|
208
|
+
async run() {
|
|
209
|
+
await this.parse(_TestThrow);
|
|
210
|
+
const code = process.env["RATIO_TEST_ERROR_CODE"] ?? "";
|
|
211
|
+
switch (code) {
|
|
212
|
+
case "COMING_SOON":
|
|
213
|
+
throw new ComingSoonError("Test coming-soon message.");
|
|
214
|
+
case "NOT_LOGGED_IN":
|
|
215
|
+
throw new NotLoggedInError("Test not-logged-in message.");
|
|
216
|
+
case "TOKEN_EXPIRED":
|
|
217
|
+
throw new TokenExpiredError("Test token-expired message.");
|
|
218
|
+
case "SCOPE_DENIED":
|
|
219
|
+
throw new ScopeDeniedError("Test scope-denied message.");
|
|
220
|
+
case "NETWORK_ERROR":
|
|
221
|
+
throw new NetworkError("Test network-error message.");
|
|
222
|
+
case "RELAY_CONNECT":
|
|
223
|
+
throw new RelayConnectError("Test relay-connect message.");
|
|
224
|
+
case "TEMPLATE_EXISTS":
|
|
225
|
+
throw new TemplateExistsError("Test template-exists message.");
|
|
226
|
+
case "VALIDATION_ERROR":
|
|
227
|
+
throw new ValidationError("Test validation-error message.");
|
|
228
|
+
case "RELAY_RESUME_GAP":
|
|
229
|
+
throw new RelayResumeGapError("Test relay-resume-gap message.");
|
|
230
|
+
default:
|
|
231
|
+
throw new Error(`Unknown RATIO_TEST_ERROR_CODE: ${code}`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
export {
|
|
236
|
+
TestThrow as default
|
|
237
|
+
};
|
|
238
|
+
//# sourceMappingURL=throw.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/ratio-command.ts","../../../src/lib/errors.ts","../../../src/lib/render-error.ts","../../../src/lib/verbose-flag.ts","../../../src/commands/__test__/throw.ts"],"sourcesContent":["import { Command, Errors } from '@oclif/core';\nimport { renderError } from './render-error.js';\n\n/**\n * Base class for all Ratio CLI commands.\n *\n * Overrides catch() to intercept every error thrown from run(), render it\n * per the Ratio CLI error-UX spec (typed hierarchy -> structured stderr/stdout,\n * --verbose for stack traces, --json for machine-readable envelope), and then\n * suppress oclif's own double-render by setting skipOclifErrorHandling on the\n * re-thrown error.\n *\n * Path B: base-class override — no oclif.hooks wiring needed.\n * oclif v4 does not expose a command_error hook; the reliable interception\n * point is Command.catch(), which is called by Command._run() before the\n * error bubbles up to oclif's global handle() function.\n *\n * Double-render prevention:\n * oclif's handle() checks err.skipOclifErrorHandling before printing.\n * After rendering we set skipOclifErrorHandling = true so oclif's\n * pretty-print is skipped. We also set err.oclif.exit = N so handle()\n * calls process.exit(N) with the correct code.\n *\n * Exit-code routing:\n * - exitCode === 0 (ComingSoonError): throw ExitError(0) so oclif calls\n * process.exit(0) cleanly. ExitError has code 'EEXIT' and is treated as\n * a clean exit — shouldPrint is false in handle().\n * - exitCode > 0: mark err.skipOclifErrorHandling = true and set\n * err.oclif = { exit: N }, then re-throw so handle() exits N.\n *\n * Verbose/json detection strategy:\n * We scan this.argv directly. this.argv is set by oclif's Command before\n * run() is called and always contains the raw argument list. This approach\n * works both for:\n * (a) post-parse errors (thrown after this.parse() succeeds) — argv has the\n * flags that were successfully recognised.\n * (b) pre-parse errors (thrown BY this.parse(), e.g. unknown flag) — argv\n * still contains --verbose / --json even though parse() threw.\n * Simple string scan is sufficient since --verbose and --json are boolean\n * flags with no value argument.\n */\nexport abstract class RatioCommand extends Command {\n private _getRenderFlags(): { verbose: boolean; json: boolean } {\n const argv = this.argv as string[];\n return {\n verbose: argv.includes('--verbose'),\n json: argv.includes('--json'),\n };\n }\n\n override async catch(\n err: Error & {\n exitCode?: number;\n oclif?: { exit?: number };\n skipOclifErrorHandling?: boolean;\n },\n ): Promise<never> {\n const { verbose, json } = this._getRenderFlags();\n\n const output = renderError({ err, verbose, json });\n\n // Write rendered output before any exit/throw\n if (output.stdout) process.stdout.write(output.stdout);\n if (output.stderr) process.stderr.write(output.stderr);\n\n if (output.exitCode === 0) {\n // ComingSoonError path — ExitError(0) causes oclif to call process.exit(0)\n // cleanly. ExitError has code 'EEXIT'; handle() treats it as a clean exit\n // (shouldPrint is false) so no additional output is written.\n throw new Errors.ExitError(0);\n }\n\n // For non-zero exits: suppress oclif's pretty-print by marking the error,\n // then route the correct exit code via oclif.exit so handle() calls process.exit(N).\n err.skipOclifErrorHandling = true;\n err.oclif = { exit: output.exitCode };\n throw err;\n }\n}\n","/**\n * Error hierarchy for the Ratio CLI. Every error thrown from a command's\n * run() is expected to be an instance of RatioCLIError so the global\n * render-error handler can map it to a deterministic stderr line and exit\n * code. Uncaught Error subclasses render as \"INTERNAL: <msg>\" with exit 1.\n *\n * No import from @oclif/core — this file is dependency-free so tests\n * can import it without oclif overhead.\n */\n\nexport class RatioCLIError extends Error {\n readonly code: string;\n readonly exitCode: number;\n readonly hint?: string;\n readonly docsUrl?: string;\n\n constructor(opts: {\n code: string;\n exitCode: number;\n message: string;\n hint?: string;\n docsUrl?: string;\n }) {\n super(opts.message);\n this.name = new.target.name;\n this.code = opts.code;\n this.exitCode = opts.exitCode;\n if (opts.hint !== undefined) this.hint = opts.hint;\n if (opts.docsUrl !== undefined) this.docsUrl = opts.docsUrl;\n }\n}\n\n/** Coming-soon stub UX. Renders on stdout with exit 0. */\nexport class ComingSoonError extends RatioCLIError {\n constructor(message: string) {\n super({ code: 'COMING_SOON', exitCode: 0, message });\n }\n}\n\n/** User has no credentials and command requires auth. */\nexport class NotLoggedInError extends RatioCLIError {\n constructor(\n message: string,\n hint: string = \"Run 'ratio auth login' to sign in.\",\n ) {\n super({ code: 'NOT_LOGGED_IN', exitCode: 3, message, hint });\n }\n}\n\nexport class TokenExpiredError extends RatioCLIError {\n constructor(\n message: string,\n hint: string = \"Run 'ratio auth login' to refresh your session.\",\n ) {\n super({ code: 'TOKEN_EXPIRED', exitCode: 3, message, hint });\n }\n}\n\nexport class ScopeDeniedError extends RatioCLIError {\n constructor(message: string, hint?: string) {\n const opts: { code: string; exitCode: number; message: string; hint?: string } = {\n code: 'SCOPE_DENIED',\n exitCode: 4,\n message,\n };\n if (hint !== undefined) opts.hint = hint;\n super(opts);\n }\n}\n\nexport class NetworkError extends RatioCLIError {\n constructor(message: string, hint: string = 'Check your network and retry.') {\n super({ code: 'NETWORK_ERROR', exitCode: 5, message, hint });\n }\n}\n\nexport class RelayConnectError extends RatioCLIError {\n constructor(\n message: string,\n hint: string = 'Verify the tunnel URL and that the auth-server is reachable.',\n ) {\n super({ code: 'RELAY_CONNECT', exitCode: 6, message, hint });\n }\n}\n\nexport class TemplateExistsError extends RatioCLIError {\n constructor(\n message: string,\n hint: string = 'Choose a different name or remove the existing directory.',\n ) {\n super({ code: 'TEMPLATE_EXISTS', exitCode: 7, message, hint });\n }\n}\n\nexport class ValidationError extends RatioCLIError {\n constructor(message: string, hint?: string) {\n const opts: { code: string; exitCode: number; message: string; hint?: string } = {\n code: 'VALIDATION_ERROR',\n exitCode: 8,\n message,\n };\n if (hint !== undefined) opts.hint = hint;\n super(opts);\n }\n}\n\nexport class RelayResumeGapError extends RatioCLIError {\n constructor(\n message: string,\n hint: string = 'Reconnect from the current cursor; older events are outside the buffer window.',\n ) {\n super({ code: 'RELAY_RESUME_GAP', exitCode: 9, message, hint });\n }\n}\n\nexport class OrchestratorSpawnError extends RatioCLIError {\n constructor(\n message: string,\n hint: string = \"Could not start your app's dev command — check that the command in ratio.config.jsonc runs from this directory.\",\n ) {\n super({ code: 'ORCHESTRATOR_SPAWN', exitCode: 10, message, hint });\n }\n}\n\nexport class OrchestratorDrainTimeoutError extends RatioCLIError {\n constructor(\n message: string,\n hint: string = 'Your dev command did not exit cleanly within 5 seconds — it was forcibly terminated.',\n ) {\n super({ code: 'ORCHESTRATOR_DRAIN', exitCode: 11, message, hint });\n }\n}\n\nexport function isRatioCLIError(err: unknown): err is RatioCLIError {\n return err instanceof RatioCLIError;\n}\n","import { isRatioCLIError, RatioCLIError, ValidationError } from './errors.js';\n\nexport interface RenderInput {\n err: unknown;\n verbose: boolean;\n json: boolean;\n}\n\nexport interface RenderOutput {\n /** Text to write to stdout. Empty string means nothing to write. */\n stdout: string;\n /** Text to write to stderr. Empty string means nothing to write. */\n stderr: string;\n exitCode: number;\n}\n\n/**\n * Detects whether an error originates from the oclif argument/flag parser.\n * oclif's CLIParseError subclasses (NonExistentFlagsError, RequiredArgsError,\n * etc.) all carry a `parse` property set by CLIParseErrorOptions. This is the\n * stable structural signal — more reliable than checking the class name string.\n */\nfunction isOclifParserError(err: unknown): err is Error & { parse: unknown } {\n return (\n err instanceof Error &&\n 'parse' in err &&\n err.parse !== null &&\n err.parse !== undefined\n );\n}\n\n/**\n * Builds the JSON error envelope. Fields with undefined values are omitted\n * so the consumer never sees `\"hint\": null` or `\"docsUrl\": null`.\n */\nfunction buildErrorEnvelope(\n code: string,\n message: string,\n hint?: string,\n docsUrl?: string,\n): string {\n const obj: Record<string, unknown> = { ok: false, code, message };\n if (hint !== undefined) obj['hint'] = hint;\n if (docsUrl !== undefined) obj['docsUrl'] = docsUrl;\n return JSON.stringify(obj) + '\\n';\n}\n\n/**\n * Pure rendering function — no side effects, no process.exit, no I/O.\n * The caller (RatioCommand.catch) is responsible for writing output and exiting.\n *\n * Rendering rules (all branches):\n *\n * | Error shape | --json | --verbose | stdout | stderr | exit |\n * |----------------------|--------|-----------|--------------------------------|----------------------------------|------|\n * | ComingSoonError | false | any | err.message + '\\n' | '' | 0 |\n * | ComingSoonError | true | any | '{\"ok\":true,\"data\":null}\\n' | '' | 0 |\n * | RatioCLIError >0 | false | false | '' | code: msg [+ hint] [+ docsUrl] | N |\n * | RatioCLIError >0 | false | true | '' | above + stack | N |\n * | RatioCLIError >0 | true | false | JSON envelope | '' | N |\n * | RatioCLIError >0 | true | true | JSON envelope | stack only | N |\n * | oclif ParserError | false | any | '' | VALIDATION_ERROR: msg [+stack] | 8 |\n * | oclif ParserError | true | any | JSON VALIDATION_ERROR envelope | stack if verbose | 8 |\n * | Plain Error / other | false | false | '' | INTERNAL: msg\\n | 1 |\n * | Plain Error / other | false | true | '' | INTERNAL: msg\\n + stack\\n | 1 |\n * | Plain Error / other | true | any | JSON INTERNAL envelope | stack if verbose | 1 |\n */\nexport function renderError(input: RenderInput): RenderOutput {\n const { err, verbose, json } = input;\n\n // ── Branch 1: our own typed hierarchy ───────────────────────────────────\n if (isRatioCLIError(err)) {\n const ratioErr = err as RatioCLIError;\n\n // exitCode === 0 → coming-soon: render on stdout, no stderr, exit 0\n if (ratioErr.exitCode === 0) {\n if (json) {\n return {\n stdout: JSON.stringify({ ok: true, data: null }) + '\\n',\n stderr: '',\n exitCode: 0,\n };\n }\n return {\n stdout: ratioErr.message + '\\n',\n stderr: '',\n exitCode: 0,\n };\n }\n\n // exitCode > 0 → error render\n let stderrLines = `${ratioErr.code}: ${ratioErr.message}\\n`;\n if (ratioErr.hint !== undefined) stderrLines += `${ratioErr.hint}\\n`;\n if (ratioErr.docsUrl !== undefined) stderrLines += `${ratioErr.docsUrl}\\n`;\n\n if (json) {\n return {\n stdout: buildErrorEnvelope(ratioErr.code, ratioErr.message, ratioErr.hint, ratioErr.docsUrl),\n stderr: verbose && ratioErr.stack ? ratioErr.stack + '\\n' : '',\n exitCode: ratioErr.exitCode,\n };\n }\n\n if (verbose && ratioErr.stack) {\n stderrLines += ratioErr.stack + '\\n';\n }\n\n return { stdout: '', stderr: stderrLines, exitCode: ratioErr.exitCode };\n }\n\n // ── Branch 2: oclif parser error (unknown flag, missing required arg, etc.) ──\n if (isOclifParserError(err)) {\n const parserErr = err as Error & { parse: unknown };\n const msg = parserErr.message || 'Unknown parse error';\n\n // Strip oclif's \"Unexpected argument: --foo\" or similar prefix noise where\n // possible, but keep the core message as-is since it's already human-readable.\n const coercedErr = new ValidationError(msg);\n\n let stderrText = `${coercedErr.code}: ${msg}\\n`;\n\n if (json) {\n return {\n stdout: buildErrorEnvelope(coercedErr.code, msg),\n stderr: verbose && parserErr.stack ? parserErr.stack + '\\n' : '',\n exitCode: 8,\n };\n }\n\n if (verbose && parserErr.stack) {\n stderrText += parserErr.stack + '\\n';\n }\n\n return { stdout: '', stderr: stderrText, exitCode: 8 };\n }\n\n // ── Branch 3: plain Error or non-Error throw ─────────────────────────────\n const message = err instanceof Error ? err.message : String(err);\n const stack = err instanceof Error ? err.stack : undefined;\n const stderrPrefix = `INTERNAL: ${message}\\n`;\n\n if (json) {\n return {\n stdout: buildErrorEnvelope('INTERNAL', message),\n stderr: verbose && stack ? stack + '\\n' : '',\n exitCode: 1,\n };\n }\n\n let stderrText = stderrPrefix;\n if (verbose && stack) {\n stderrText += stack + '\\n';\n }\n\n return { stdout: '', stderr: stderrText, exitCode: 1 };\n}\n","import { Flags } from '@oclif/core';\n\n/** Global verbose flag — every command imports and spreads this. */\nexport const verboseFlag = {\n verbose: Flags.boolean({\n description:\n 'Show diagnostic detail: HTTP status/timing lines for auth requests (stderr) and stack traces for internal errors.',\n }),\n};\n\n/** JSON envelope flag — read-style commands (whoami, dev trigger --list) import. */\nexport const jsonFlag = {\n json: Flags.boolean({\n description: 'Emit machine-readable JSON on stdout.',\n }),\n};\n","import { RatioCommand } from '../../lib/ratio-command.js';\nimport { verboseFlag } from '../../lib/verbose-flag.js';\nimport {\n ComingSoonError,\n NetworkError,\n NotLoggedInError,\n RelayConnectError,\n RelayResumeGapError,\n ScopeDeniedError,\n TemplateExistsError,\n TokenExpiredError,\n ValidationError,\n} from '../../lib/errors.js';\n\n/**\n * Hidden test-only command for error-path e2e testing.\n *\n * Reads the RATIO_TEST_ERROR_CODE environment variable and throws the\n * matching error class. This command is marked hidden: true so it does\n * not appear in --help output.\n *\n * Seam contract: only activated via the RATIO_TEST_ERROR_CODE env var.\n * No production command path calls into this command.\n */\nexport default class TestThrow extends RatioCommand {\n static override description = 'Test-only error injection command.';\n static override hidden = true;\n\n static override examples = [\n 'RATIO_TEST_ERROR_CODE=NOT_LOGGED_IN <%= config.bin %> __test__ throw',\n ];\n\n static override flags = {\n ...verboseFlag,\n };\n\n public async run(): Promise<void> {\n await this.parse(TestThrow);\n const code = process.env['RATIO_TEST_ERROR_CODE'] ?? '';\n\n switch (code) {\n case 'COMING_SOON':\n throw new ComingSoonError('Test coming-soon message.');\n case 'NOT_LOGGED_IN':\n throw new NotLoggedInError('Test not-logged-in message.');\n case 'TOKEN_EXPIRED':\n throw new TokenExpiredError('Test token-expired message.');\n case 'SCOPE_DENIED':\n throw new ScopeDeniedError('Test scope-denied message.');\n case 'NETWORK_ERROR':\n throw new NetworkError('Test network-error message.');\n case 'RELAY_CONNECT':\n throw new RelayConnectError('Test relay-connect message.');\n case 'TEMPLATE_EXISTS':\n throw new TemplateExistsError('Test template-exists message.');\n case 'VALIDATION_ERROR':\n throw new ValidationError('Test validation-error message.');\n case 'RELAY_RESUME_GAP':\n throw new RelayResumeGapError('Test relay-resume-gap message.');\n default:\n throw new Error(`Unknown RATIO_TEST_ERROR_CODE: ${code}`);\n }\n }\n}\n"],"mappings":"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","names":["stderrText"]}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as _oclif_core_interfaces from '@oclif/core/interfaces';
|
|
2
|
+
import { RatioCommand } from '../../lib/ratio-command.js';
|
|
3
|
+
import { R as RenderInput, a as RenderResult } from '../../render-CrHGqTPH.js';
|
|
4
|
+
import '@oclif/core';
|
|
5
|
+
|
|
6
|
+
/** The bundled templates a new app can be scaffolded from. */
|
|
7
|
+
declare const TEMPLATE_OPTIONS: readonly ["minimal", "with-admin-ui", "serverless"];
|
|
8
|
+
type TemplateName = (typeof TEMPLATE_OPTIONS)[number];
|
|
9
|
+
/**
|
|
10
|
+
* Placeholder used in `nextSteps()` output for the app directory name.
|
|
11
|
+
* Callers substitute it via `formatNextSteps()` before display.
|
|
12
|
+
*/
|
|
13
|
+
declare const APP_NAME_PLACEHOLDER = "<APP_NAME>";
|
|
14
|
+
/**
|
|
15
|
+
* The 6-step post-scaffold guidance per template. Hardcoded on purpose
|
|
16
|
+
* (rather than parsed out of the rendered README) so the CLI output stays
|
|
17
|
+
* stable; a regression pin keeps the order in sync with each template's
|
|
18
|
+
* README "Getting started" block.
|
|
19
|
+
*/
|
|
20
|
+
declare function nextSteps(template: TemplateName): readonly string[];
|
|
21
|
+
/** `nextSteps()` with the app-name placeholder substituted for display. */
|
|
22
|
+
declare function formatNextSteps(template: TemplateName, appName: string): readonly string[];
|
|
23
|
+
/**
|
|
24
|
+
* Read the `@ratio-app/sdk` version pin from the CLI's own package.json,
|
|
25
|
+
* discovered by walking up from this module. Works from both the source
|
|
26
|
+
* tree (`src/commands/app/`) and the built layout (`dist/commands/app/`,
|
|
27
|
+
* where package.json lives at the package root, not inside dist/).
|
|
28
|
+
*/
|
|
29
|
+
declare function readOwnSdkVersion(startDir?: string): string;
|
|
30
|
+
/**
|
|
31
|
+
* Locate the bundled templates root by walking up from this module and
|
|
32
|
+
* probing for a sibling `templates/` directory at each level. Resolves to
|
|
33
|
+
* `dist/templates/` when running the built CLI and `src/templates/` when
|
|
34
|
+
* running from source. The walk stops at the first directory that carries
|
|
35
|
+
* a package.json (the package root) so it never escapes the install tree.
|
|
36
|
+
*/
|
|
37
|
+
declare function discoverTemplatesRoot(startDir?: string): string;
|
|
38
|
+
declare class AppCreate extends RatioCommand {
|
|
39
|
+
static description: string;
|
|
40
|
+
static examples: string[];
|
|
41
|
+
static args: {
|
|
42
|
+
name: _oclif_core_interfaces.Arg<string, Record<string, unknown>>;
|
|
43
|
+
};
|
|
44
|
+
static flags: {
|
|
45
|
+
template: _oclif_core_interfaces.OptionFlag<string, _oclif_core_interfaces.CustomOptions>;
|
|
46
|
+
json: _oclif_core_interfaces.BooleanFlag<boolean>;
|
|
47
|
+
verbose: _oclif_core_interfaces.BooleanFlag<boolean>;
|
|
48
|
+
};
|
|
49
|
+
writeOut: (chunk: string) => void;
|
|
50
|
+
writeErr: (chunk: string) => void;
|
|
51
|
+
renderTemplate: (input: RenderInput) => Promise<RenderResult>;
|
|
52
|
+
run(): Promise<void>;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { APP_NAME_PLACEHOLDER, TEMPLATE_OPTIONS, type TemplateName, AppCreate as default, discoverTemplatesRoot, formatNextSteps, nextSteps, readOwnSdkVersion };
|