@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
package/README.md
ADDED
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
# @ratio-app/cli
|
|
2
|
+
|
|
3
|
+
The official Ratio developer CLI — scaffold, link, run, and develop apps on the Ratio platform.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g @ratio-app/cli
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Homebrew:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
brew tap imran-primathon/ratio
|
|
17
|
+
brew install ratio
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Requirements:** Node.js >= 18. Works on macOS, Linux, and Windows (WSL recommended for Windows users).
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Quickstart
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# 1. Sign in
|
|
28
|
+
ratio auth login
|
|
29
|
+
|
|
30
|
+
# 2. Scaffold a new app
|
|
31
|
+
ratio app create hello-app --template minimal
|
|
32
|
+
|
|
33
|
+
# 3. Link it to your Ratio developer account
|
|
34
|
+
cd hello-app && ratio app link
|
|
35
|
+
|
|
36
|
+
# 4. Start local development (runs your dev command + webhook listener)
|
|
37
|
+
ratio app dev
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## What you get with the Ratio CLI
|
|
43
|
+
|
|
44
|
+
| Command | Status | What it gives you |
|
|
45
|
+
|---|---|---|
|
|
46
|
+
| `ratio auth login` | GA | One-command sign-in to your Ratio developer account — browser PKCE flow, `--manual` copy-paste fallback for headless machines |
|
|
47
|
+
| `ratio auth logout` | GA | Signs out and securely clears stored credentials |
|
|
48
|
+
| `ratio auth whoami` | GA | Shows the signed-in identity, scopes, and profile; `--json` supported |
|
|
49
|
+
| `ratio app create <name>` | GA | Scaffolds a fully-wired Ratio app in seconds — three templates: `minimal`, `with-admin-ui`, `serverless` |
|
|
50
|
+
| `ratio app link` | GA | Connects your local code to a Ratio app registration — interactive or flag-driven; writes `clientId` to `ratio.config.jsonc` |
|
|
51
|
+
| `ratio app dev` | GA | One command for local development: runs your dev server and a live webhook listener side by side |
|
|
52
|
+
| `ratio dev listen` | GA | Streams real platform webhook events to your localhost server over a WebSocket relay — no tunnels to set up |
|
|
53
|
+
| `ratio dev trigger [topic]` | GA | Fires synthetic webhook events (`cod`, `prepaid`, `cancelled` scenarios) so you can test handlers without real orders |
|
|
54
|
+
| `ratio version` | GA | Prints the CLI version |
|
|
55
|
+
| `ratio help [command]` | GA | Command help |
|
|
56
|
+
| `ratio app deploy` | Coming soon | Deploy your app to the Ratio platform (prints guidance in this release) |
|
|
57
|
+
| `ratio app info` | Coming soon | Show details of the linked app (prints guidance in this release) |
|
|
58
|
+
| `ratio app generate` | Coming soon | Generate code inside your app (prints guidance in this release) |
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Per-command examples
|
|
63
|
+
|
|
64
|
+
### `ratio auth login`
|
|
65
|
+
|
|
66
|
+
Sign in to Ratio using a browser-based PKCE flow. The browser opens automatically and the CLI waits for the callback.
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
ratio auth login
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Use `--manual` for headless environments where a browser cannot be opened. The CLI prints a URL; you visit it, copy the authorization code, and paste it back.
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
ratio auth login --manual
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Flags:**
|
|
79
|
+
|
|
80
|
+
| Flag | Description |
|
|
81
|
+
|---|---|
|
|
82
|
+
| `--manual` | Use manual copy-paste flow instead of a browser |
|
|
83
|
+
| `--verbose` | Write structured diagnostic lines to stderr |
|
|
84
|
+
| `--profile <name>` | Credential profile name to write into (default: `default`) |
|
|
85
|
+
|
|
86
|
+
**`--json` is not supported for `auth login`** — the command has no machine-readable output.
|
|
87
|
+
|
|
88
|
+
**`RATIO_API_TOKEN` bypass:** If the environment variable `RATIO_API_TOKEN` is set to a non-empty value, `ratio auth login` exits immediately ("Using RATIO_API_TOKEN — no login needed."). This lets CI pipelines skip interactive sign-in. Because the token bypasses the stored credential file, `ratio auth whoami` cannot report identity while it is set. Store `RATIO_API_TOKEN` as a CI repository secret and never echo it in logs.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
### `ratio auth logout`
|
|
93
|
+
|
|
94
|
+
Sign out and clear stored credentials.
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
ratio auth logout
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Flags:**
|
|
101
|
+
|
|
102
|
+
| Flag | Description |
|
|
103
|
+
|---|---|
|
|
104
|
+
| `--verbose` | Write structured diagnostic lines to stderr |
|
|
105
|
+
|
|
106
|
+
**`--json` is intentionally not supported for `auth logout`** — there is no machine-readable output to emit.
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
### `ratio auth whoami`
|
|
111
|
+
|
|
112
|
+
Show the currently signed-in Ratio user.
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
ratio auth whoami
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Machine-readable output:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
ratio auth whoami --json
|
|
122
|
+
# stdout: {"ok":true,"data":{"source":"file","clientId":"...","merchantId":"...","scopes":[...],"expiresAt":"...","profile":"default"}}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**Flags:**
|
|
126
|
+
|
|
127
|
+
| Flag | Description |
|
|
128
|
+
|---|---|
|
|
129
|
+
| `--verbose` | Write structured diagnostic lines to stderr |
|
|
130
|
+
| `--json` | Write a single JSON envelope to stdout |
|
|
131
|
+
| `--profile <name>` | Credential profile name to read (default: `default`) |
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
### `ratio app create <name>`
|
|
136
|
+
|
|
137
|
+
Scaffold a new Ratio app from a template into a new directory named `<name>`.
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
# Minimal Node.js app (default)
|
|
141
|
+
ratio app create my-app
|
|
142
|
+
|
|
143
|
+
# Node.js app with an admin UI panel
|
|
144
|
+
ratio app create my-app --template=with-admin-ui
|
|
145
|
+
|
|
146
|
+
# Cloudflare Workers serverless app
|
|
147
|
+
ratio app create my-app --template=serverless
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**Flags:**
|
|
151
|
+
|
|
152
|
+
| Flag | Description |
|
|
153
|
+
|---|---|
|
|
154
|
+
| `--template=<name>` | Template to scaffold from: `minimal` (default), `with-admin-ui`, `serverless` |
|
|
155
|
+
| `--verbose` | Write structured diagnostic lines to stderr |
|
|
156
|
+
| `--json` | Write a single JSON envelope to stdout: `{"ok":true,"data":{"template":"...","path":"...","filesWritten":N,"next":[...]}}` |
|
|
157
|
+
|
|
158
|
+
**Templates at a glance:**
|
|
159
|
+
|
|
160
|
+
- `minimal` — plain Node.js Express-style server with OAuth callback and webhook handler. Starts on port 3000 (`npm run dev`).
|
|
161
|
+
- `with-admin-ui` — API server (port 3000) plus a React admin panel (port 3001, `npm run admin:dev`).
|
|
162
|
+
- `serverless` — Cloudflare Workers entry point; deploy with `wrangler`.
|
|
163
|
+
|
|
164
|
+
After scaffolding, run `ratio app link` to write the `clientId` into `ratio.config.jsonc`.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
### `ratio app link`
|
|
169
|
+
|
|
170
|
+
Link the app in the current directory to a Ratio app registration. Signs you in (if needed), lets you pick or create an app, then writes its `clientId` into `ratio.config.jsonc`.
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
# Interactive: prompts for credentials, lists your apps, lets you pick or create
|
|
174
|
+
ratio app link
|
|
175
|
+
|
|
176
|
+
# Pre-fill the developer email to skip that prompt
|
|
177
|
+
ratio app link --email dev@example.com
|
|
178
|
+
|
|
179
|
+
# Attach to an existing app by its id (non-interactive)
|
|
180
|
+
ratio app link --app-id 4f9d2c31-8a6b-4f2e-9c1d-3e5a7b9d0f12 --json
|
|
181
|
+
|
|
182
|
+
# Write a known clientId directly without contacting the server
|
|
183
|
+
ratio app link --client-id ratio_ci_1234
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
**Flags:**
|
|
187
|
+
|
|
188
|
+
| Flag | Description |
|
|
189
|
+
|---|---|
|
|
190
|
+
| `--email <address>` | Developer email for sign-in (prompted when omitted) |
|
|
191
|
+
| `--client-id <id>` | Write this clientId directly into `ratio.config.jsonc` without contacting the server |
|
|
192
|
+
| `--app-id <uuid>` | Attach to an existing app by id; its clientId is fetched and written |
|
|
193
|
+
| `--category <slug>` | Category slug used when creating a new app (default: `general`) |
|
|
194
|
+
| `--verbose` | Write structured diagnostic lines to stderr |
|
|
195
|
+
| `--json` | Write a single JSON envelope to stdout |
|
|
196
|
+
|
|
197
|
+
**Environment variables:**
|
|
198
|
+
|
|
199
|
+
- `RATIO_DEVELOPER_TOKEN` — skip interactive sign-in entirely by providing a developer bearer token. Intended for CI pipelines. This is separate from `RATIO_API_TOKEN` (used by other commands). Store it as a CI repository secret and never echo it in logs.
|
|
200
|
+
- `RATIO_SERVER` — override the server base URL (default: `https://api.ratio.app`).
|
|
201
|
+
|
|
202
|
+
**Manifest file:** `ratio.config.jsonc` must exist in the current directory before running `ratio app link`. The command reads `appName` and rewrites the `clientId` field in-place, preserving all comments and whitespace.
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
### `ratio app dev`
|
|
207
|
+
|
|
208
|
+
Run the current app locally. Reads `ratio.config.jsonc` from the current directory and starts two side-by-side processes:
|
|
209
|
+
|
|
210
|
+
1. Your own dev command (the `devCommand` field in `ratio.config.jsonc`).
|
|
211
|
+
2. A webhook listener that forwards platform events to your local server.
|
|
212
|
+
|
|
213
|
+
Output from both processes is multiplexed to stdout with per-child line prefixes. If either process stops, the other is shut down and the failing exit code is propagated. `Ctrl+C` stops both cleanly.
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
ratio app dev
|
|
217
|
+
ratio app dev --verbose
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
**Flags:**
|
|
221
|
+
|
|
222
|
+
| Flag | Description |
|
|
223
|
+
|---|---|
|
|
224
|
+
| `--verbose` | Write structured diagnostic lines to stderr |
|
|
225
|
+
|
|
226
|
+
**`--json` is not supported for `ratio app dev`** — the command is a long-running process that streams interleaved child output.
|
|
227
|
+
|
|
228
|
+
**Manifest fields read:**
|
|
229
|
+
|
|
230
|
+
| Field | Required | Description |
|
|
231
|
+
|---|---|---|
|
|
232
|
+
| `devCommand` | Yes | Command string to start your app (e.g. `npm run dev`). Tokenized by the CLI and spawned without a shell. |
|
|
233
|
+
| `devServerPort` | No | Port your dev server listens on. When set, passed to your dev command as `PORT` env var. |
|
|
234
|
+
|
|
235
|
+
**Exit codes:** the codes you are most likely to see from `ratio app dev` are `10` (a child process could not be started), `11` (a child had to be forcibly terminated during shutdown), `130` (Ctrl+C), and `143` (SIGTERM). These are part of the CLI-wide taxonomy — see [Exit codes and troubleshooting](#exit-codes-and-troubleshooting) for the full table.
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
### `ratio dev listen`
|
|
240
|
+
|
|
241
|
+
Stream webhook events from your Ratio dev session and forward them to a local HTTP server. Requires an active sign-in.
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
# Forward all events
|
|
245
|
+
ratio dev listen --forward-to localhost:3000/webhooks
|
|
246
|
+
|
|
247
|
+
# Filter to specific topics
|
|
248
|
+
ratio dev listen --forward-to http://127.0.0.1:3000/webhooks --events=orders.created,orders.updated
|
|
249
|
+
|
|
250
|
+
# Machine-readable event log on stdout (NDJSON)
|
|
251
|
+
ratio dev listen --forward-to localhost:3000/webhooks --json
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
**Flags:**
|
|
255
|
+
|
|
256
|
+
| Flag | Description |
|
|
257
|
+
|---|---|
|
|
258
|
+
| `--forward-to <url>` | Local URL to forward events to (localhost only, explicit port required). **Required.** |
|
|
259
|
+
| `--events <topics>` | Comma-separated event topics to forward (default: all topics forwarded) |
|
|
260
|
+
| `--verbose` | Write structured diagnostic lines to stderr |
|
|
261
|
+
| `--json` | Write one NDJSON object per event to stdout instead of key=value lines to stderr |
|
|
262
|
+
|
|
263
|
+
**Event log line shapes:**
|
|
264
|
+
|
|
265
|
+
- Key-value mode (default): `seq=N t=<timestamp> topic=<topic> forward-status=ok:200`
|
|
266
|
+
- JSON mode (`--json`): `{"seq":N,"t":"<timestamp>","topic":"<topic>","forward-status":"ok:200"}`
|
|
267
|
+
|
|
268
|
+
Forward status tokens: `ok:<http-status>`, `err:timeout`, `err:network`, `err:http-<status>`, `filtered`, `dropped:control`.
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
### `ratio dev trigger [topic]`
|
|
273
|
+
|
|
274
|
+
Fire a synthetic Ratio webhook event for local testing. The platform delivers it to your registered webhook endpoint.
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
# List available topics and their scenarios
|
|
278
|
+
ratio dev trigger --list
|
|
279
|
+
|
|
280
|
+
# Fire an event
|
|
281
|
+
ratio dev trigger orders.created --scenario=cod --app-id=4f9d2c31-8a6b-4f2e-9c1d-3e5a7b9d0f12
|
|
282
|
+
|
|
283
|
+
# List in JSON
|
|
284
|
+
ratio dev trigger --list --json
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
**Flags:**
|
|
288
|
+
|
|
289
|
+
| Flag | Description |
|
|
290
|
+
|---|---|
|
|
291
|
+
| `--scenario <name>` | Payload scenario: `cod`, `prepaid`, `cancelled` |
|
|
292
|
+
| `--list` | List available topics and scenarios |
|
|
293
|
+
| `--app-id <uuid>` | App id whose synthetic delivery to trigger (UUID). Required when a topic is given. |
|
|
294
|
+
| `--verbose` | Write structured diagnostic lines to stderr |
|
|
295
|
+
| `--json` | Write a single JSON envelope to stdout |
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
### `ratio version`
|
|
300
|
+
|
|
301
|
+
Print the CLI version.
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
ratio version
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
### `ratio help`
|
|
310
|
+
|
|
311
|
+
Show help for any command.
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
ratio help
|
|
315
|
+
ratio help auth login
|
|
316
|
+
ratio help app create
|
|
317
|
+
ratio help dev listen
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
### Coming-soon commands
|
|
323
|
+
|
|
324
|
+
The following commands are registered and will print a guidance message, then exit. No destructive action is taken.
|
|
325
|
+
|
|
326
|
+
- `ratio app deploy` — deployment to the Ratio platform (coming in a future release).
|
|
327
|
+
- `ratio app info` — show details about the current linked app (coming in a future release).
|
|
328
|
+
- `ratio app generate` — generate code inside the current app (coming in a future release).
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
## Configuration
|
|
333
|
+
|
|
334
|
+
### Environment variables
|
|
335
|
+
|
|
336
|
+
| Variable | Used by | Description |
|
|
337
|
+
|---|---|---|
|
|
338
|
+
| `RATIO_API_TOKEN` | All commands | OAuth token override. When set, bypasses the stored credential file, so `ratio auth whoami` cannot report identity while it is set. Store it as a CI repository secret; never echo it in logs. |
|
|
339
|
+
| `RATIO_DEVELOPER_TOKEN` | `app link` only | Developer bearer for unattended sign-in. Strictly separate from `RATIO_API_TOKEN`. Store it as a CI repository secret; never echo it in logs. |
|
|
340
|
+
| `RATIO_SERVER` | `app link` | Server base URL override (default: `https://api.ratio.app`). |
|
|
341
|
+
|
|
342
|
+
### Credential file
|
|
343
|
+
|
|
344
|
+
Stored credentials are written to:
|
|
345
|
+
|
|
346
|
+
- POSIX: `~/.config/ratio/credentials` (mode `0600`)
|
|
347
|
+
- Windows: `%APPDATA%\ratio\credentials`
|
|
348
|
+
|
|
349
|
+
### Manifest file: `ratio.config.jsonc`
|
|
350
|
+
|
|
351
|
+
Created by `ratio app create` in the app directory. Fields:
|
|
352
|
+
|
|
353
|
+
| Field | Required | Description |
|
|
354
|
+
|---|---|---|
|
|
355
|
+
| `appName` | Yes | Human-readable name for the app |
|
|
356
|
+
| `clientId` | Yes | Written by `ratio app link`; identifies the app to the platform |
|
|
357
|
+
| `devCommand` | Yes (for `app dev`) | Command string to start your app (tokenized and spawned without a shell) |
|
|
358
|
+
| `devServerPort` | No | Port your dev server listens on; passed as `PORT` env var to your dev command |
|
|
359
|
+
|
|
360
|
+
---
|
|
361
|
+
|
|
362
|
+
## Exit codes and troubleshooting
|
|
363
|
+
|
|
364
|
+
### Exit codes
|
|
365
|
+
|
|
366
|
+
Every command maps its typed errors to a deterministic exit code. This table applies CLI-wide — any command can return the codes whose condition it can hit.
|
|
367
|
+
|
|
368
|
+
| Code | Condition | What to try |
|
|
369
|
+
|---|---|---|
|
|
370
|
+
| `0` | Success (also used by the coming-soon stubs, which print guidance and exit) | — |
|
|
371
|
+
| `3` | Not signed in, or the stored session expired and could not be refreshed | Run `ratio auth login` |
|
|
372
|
+
| `4` | Scope denied — the signed-in identity lacks a required scope | Re-authorize with the needed scopes |
|
|
373
|
+
| `5` | Network failure reaching the Ratio server | Check your network and retry |
|
|
374
|
+
| `6` | Relay connect failure (`dev listen` could not reach the event relay) | Verify the server URL and that the relay is reachable |
|
|
375
|
+
| `7` | Template destination already exists (`app create` into a non-empty directory) | Choose a different name or remove the existing directory |
|
|
376
|
+
| `8` | Invalid configuration or arguments (validation error) | Fix the flag/manifest value named in the error message |
|
|
377
|
+
| `9` | Relay resume gap (`dev listen` reconnected past the event buffer window) | Reconnect; events outside the buffer window are not replayed |
|
|
378
|
+
| `10` | `app dev`: a child process could not be started | Check that `devCommand` in `ratio.config.jsonc` runs from the app directory |
|
|
379
|
+
| `11` | `app dev`: a child had to be forcibly terminated during shutdown | Make your dev command exit promptly on SIGTERM |
|
|
380
|
+
| `130` | Interrupted (Ctrl+C / SIGINT) | — |
|
|
381
|
+
| `143` | Terminated (SIGTERM) | — |
|
|
382
|
+
|
|
383
|
+
Unexpected internal errors render as `INTERNAL: <message>` and exit with code `1`.
|
|
384
|
+
|
|
385
|
+
### `ratio app dev` shutdown behaviour
|
|
386
|
+
|
|
387
|
+
- **Drain window:** when `ratio app dev` shuts down (Ctrl+C, SIGTERM, or one child exiting), the orchestrator sends SIGTERM to the children and allows them up to **5 seconds** to exit on their own. A child that appears to "hang" briefly during shutdown is usually just inside this drain window. A child that does not exit within it is force-killed, and the run exits with code `11`.
|
|
388
|
+
- **Second Ctrl+C forces exit:** pressing Ctrl+C a second time within **2 seconds** of the first skips the remaining drain and exits immediately with code `130`. Use this when a child is stuck and you don't want to wait out the drain window.
|
|
389
|
+
|
|
390
|
+
### Reporting bugs
|
|
391
|
+
|
|
392
|
+
When reporting a bug, re-run the failing command with `--verbose` and include the diagnostic lines in your report. Diagnostics go to **stderr** (capture with `2>diagnostics.txt` if needed) and never contain tokens or other secret material — see [`--verbose` output conventions](#--verbose-output-conventions).
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
|
|
396
|
+
## Architecture
|
|
397
|
+
|
|
398
|
+
The CLI is organised as reusable library modules (`src/lib/`) that command entry points (`src/commands/`) compose. Some library modules are deliberately pure — the dev-store gate module, for example, carries a per-module no-I/O invariant. Others own their I/O directly: credential storage reads and writes the credentials file, the auth loopback server binds a local HTTP listener for the PKCE callback, the manifest readers parse `ratio.config.jsonc`, and the dev-command orchestrator spawns and supervises child processes. Commands stay thin — they parse flags, compose library modules, and map typed errors to exit codes.
|
|
399
|
+
|
|
400
|
+
### Dev-store gating seam
|
|
401
|
+
|
|
402
|
+
`src/lib/dev-store-gate.ts` defines the `DevStoreGate` interface and a `NoopDevStoreGate` class (permissive by default). A process-lifetime singleton is exposed via `getDevStoreGate()`. When the entitlement service is ready, a real implementation will replace the noop without any callers changing — they already depend on the interface, not the concrete type.
|
|
403
|
+
|
|
404
|
+
**Interface:**
|
|
405
|
+
|
|
406
|
+
```typescript
|
|
407
|
+
interface DevStoreGateContext {
|
|
408
|
+
readonly command: string; // e.g. "app link" — always required
|
|
409
|
+
readonly appId?: string; // present for authenticated flows
|
|
410
|
+
readonly developerId?: string;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
interface DevStoreGate {
|
|
414
|
+
assertAllowed(context: DevStoreGateContext): void;
|
|
415
|
+
}
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
The method signature is `void`-returning — a caller cannot silently proceed after a denial. The only signalling channel is an exception, so a missed `try/catch` surfaces immediately in tests and logs.
|
|
419
|
+
|
|
420
|
+
**v1 behaviour:** `NoopDevStoreGate.assertAllowed()` is a no-op. Every operation is permitted regardless of store type. A future single-class swap in `getDevStoreGate()` activates enforcement without touching any consumer.
|
|
421
|
+
|
|
422
|
+
### Preview seam
|
|
423
|
+
|
|
424
|
+
`src/lib/preview/types.ts` defines the `PreviewController` interface and the `NullPreviewController` class (no-op by default). The factory `createPreviewController()` (in `src/lib/preview/index.ts`) always returns a `NullPreviewController` in v1.
|
|
425
|
+
|
|
426
|
+
**Interface:**
|
|
427
|
+
|
|
428
|
+
```typescript
|
|
429
|
+
interface PreviewController {
|
|
430
|
+
onDevServerReady(port: number): Promise<void>;
|
|
431
|
+
onShutdown(): Promise<void>;
|
|
432
|
+
}
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
**v1 behaviour:** Both methods of `NullPreviewController` are async no-ops. `ratio app dev` v1 does NOT do preview injection — there is no admin iframe, no storefront override, and no preview activation API. The seam exists so that a future release can bind an active implementation without editing the orchestrator.
|
|
436
|
+
|
|
437
|
+
### `--verbose` output conventions
|
|
438
|
+
|
|
439
|
+
`--verbose` writes diagnostic lines to **stderr** only — one line per boundary crossing (an HTTP request, a spawn, a callback, a shutdown step) — so a failing run can be diagnosed from the terminal transcript alone. The exact lines differ per subsystem. Placeholders below are shown in angle brackets (e.g. `<port>`); the real output contains the concrete value.
|
|
440
|
+
|
|
441
|
+
**Auth (`auth login`, token refresh)** — lines are prefixed with `[verbose]`:
|
|
442
|
+
|
|
443
|
+
```text
|
|
444
|
+
[verbose] refresh: fired (access token expired or expiring)
|
|
445
|
+
[verbose] POST /oauth/token → <status> (<elapsed>ms)
|
|
446
|
+
[verbose] POST /oauth/token → network error (<elapsed>ms)
|
|
447
|
+
[verbose] loopback: bound 127.0.0.1:<port>
|
|
448
|
+
[verbose] callback: received on port <port> (state ok)
|
|
449
|
+
[verbose] callback: timeout fired after <timeout>ms
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
**`app dev` orchestrator** — lines are prefixed with `[verbose]`:
|
|
453
|
+
|
|
454
|
+
```text
|
|
455
|
+
[verbose] spawn app: <command> (<pid>)
|
|
456
|
+
[verbose] spawn listen: (<pid>)
|
|
457
|
+
[verbose] app exited: code=<code> signal=<signal>
|
|
458
|
+
[verbose] listen exited: code=<code> signal=<signal>
|
|
459
|
+
[verbose] signal received: <signal>
|
|
460
|
+
[verbose] drain elapsed: <elapsed>ms
|
|
461
|
+
[verbose] preview: onDevServerReady(<port>)
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
**`app create`** — plain diagnostic lines on stderr:
|
|
465
|
+
|
|
466
|
+
```text
|
|
467
|
+
template: <name>
|
|
468
|
+
destination: <path>
|
|
469
|
+
wrote <relative-path>
|
|
470
|
+
rendered in <elapsed>ms
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
**`dev trigger`** — plain diagnostic lines on stderr:
|
|
474
|
+
|
|
475
|
+
```text
|
|
476
|
+
server: <url>
|
|
477
|
+
trigger: topic=<topic> scenario=<scenario>
|
|
478
|
+
trigger accepted in <elapsed>ms
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
**`dev listen`** — plain diagnostic lines on stderr:
|
|
482
|
+
|
|
483
|
+
```text
|
|
484
|
+
session created: <session-id> (expires <timestamp>)
|
|
485
|
+
target probe: responded with status <status>
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
Verbose lines never interpolate environment-variable values or secret material — no access or refresh tokens, no authorization codes, no state values. Only method, path, HTTP status, port numbers, pids, exit codes, signal names, durations, and the user's own declared dev command appear in diagnostic output.
|
|
489
|
+
|
|
490
|
+
### `--json` output conventions
|
|
491
|
+
|
|
492
|
+
When `--json` is supported (see per-command tables above), the command writes a single JSON envelope to **stdout**:
|
|
493
|
+
|
|
494
|
+
```json
|
|
495
|
+
{"ok":true,"data":{...}}
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
Errors are not written to stdout in `--json` mode; they surface as non-zero exit codes with a typed error message on stderr.
|
|
499
|
+
|
|
500
|
+
---
|
|
501
|
+
|
|
502
|
+
## Contributing
|
|
503
|
+
|
|
504
|
+
See [LICENSE](./LICENSE) for the project license. To report issues or propose improvements, open an issue or pull request in this repository.
|
package/bin/run.mjs
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as _oclif_core_interfaces from '@oclif/core/interfaces';
|
|
2
|
+
import { RatioCommand } from '../../lib/ratio-command.js';
|
|
3
|
+
import '@oclif/core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Hidden test-only command for error-path e2e testing.
|
|
7
|
+
*
|
|
8
|
+
* Reads the RATIO_TEST_ERROR_CODE environment variable and throws the
|
|
9
|
+
* matching error class. This command is marked hidden: true so it does
|
|
10
|
+
* not appear in --help output.
|
|
11
|
+
*
|
|
12
|
+
* Seam contract: only activated via the RATIO_TEST_ERROR_CODE env var.
|
|
13
|
+
* No production command path calls into this command.
|
|
14
|
+
*/
|
|
15
|
+
declare class TestThrow extends RatioCommand {
|
|
16
|
+
static description: string;
|
|
17
|
+
static hidden: boolean;
|
|
18
|
+
static examples: string[];
|
|
19
|
+
static flags: {
|
|
20
|
+
verbose: _oclif_core_interfaces.BooleanFlag<boolean>;
|
|
21
|
+
};
|
|
22
|
+
run(): Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export { TestThrow as default };
|