@couch-kit/cli 0.3.4 → 0.3.6
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 +48 -2
- package/dist/index.js +23 -18
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ bun add -d @couch-kit/cli
|
|
|
14
14
|
|
|
15
15
|
### `init`
|
|
16
16
|
|
|
17
|
-
Scaffolds a
|
|
17
|
+
Scaffolds a web controller project (Vite + React + TypeScript) to add to an existing host app. This creates only the phone/tablet side — for a full game project (host + client + shared), clone the [Buzz starter](https://github.com/faluciano/buzz-tv-party-game).
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
20
|
bunx couch-kit init web-controller
|
|
@@ -22,7 +22,7 @@ bunx couch-kit init web-controller
|
|
|
22
22
|
|
|
23
23
|
### `bundle`
|
|
24
24
|
|
|
25
|
-
Builds the web controller and copies the assets into your Android project's `assets/www` folder. This is used
|
|
25
|
+
Builds the web controller and copies the assets into your Android project's `assets/www` folder, along with a `manifest.json` listing all files. This manifest is used by `useExtractAssets()` on the host to extract assets at runtime.
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
28
|
# Default (looks for ./web-controller and copies to android/app/src/main/assets/www)
|
|
@@ -32,6 +32,16 @@ bunx couch-kit bundle
|
|
|
32
32
|
bunx couch-kit bundle --source ./my-web-app --output ./android/app/src/main/assets/www
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
+
Output structure:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
android/app/src/main/assets/www/
|
|
39
|
+
├── manifest.json ← import this in your host app
|
|
40
|
+
├── index.html
|
|
41
|
+
├── assets/
|
|
42
|
+
│ └── ...
|
|
43
|
+
```
|
|
44
|
+
|
|
35
45
|
### `simulate`
|
|
36
46
|
|
|
37
47
|
Spawns headless WebSocket bots to simulate players (useful for load testing and quick iteration).
|
|
@@ -46,3 +56,39 @@ bunx couch-kit simulate --url ws://192.168.1.99:8082 --count 8
|
|
|
46
56
|
# Action interval (ms)
|
|
47
57
|
bunx couch-kit simulate --interval 250
|
|
48
58
|
```
|
|
59
|
+
|
|
60
|
+
### `replay`
|
|
61
|
+
|
|
62
|
+
Replays a recorded game session against a reducer, validating state transitions. Useful for debugging, regression testing, and reproducing bugs from recordings captured with `useActionRecorder`.
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
# Replay a recording against your reducer
|
|
66
|
+
bunx couch-kit replay ./session.json ./shared/reducer.ts
|
|
67
|
+
|
|
68
|
+
# With intermediate state snapshots
|
|
69
|
+
bunx couch-kit replay ./session.json ./shared/reducer.ts --snapshots
|
|
70
|
+
|
|
71
|
+
# JSON output (for piping to other tools)
|
|
72
|
+
bunx couch-kit replay ./session.json ./shared/reducer.ts --json
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The reducer module must export a `default` or a named `reducer` function. If your shared file exports `gameReducer`, add a re-export:
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
// shared/reducer.ts (or any entry point for replay)
|
|
79
|
+
export { gameReducer as default } from "./types";
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### `dev`
|
|
83
|
+
|
|
84
|
+
Starts a Vite dev server on the LAN so phones can load the controller from your laptop during development.
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# Default: port 5173, exposed to LAN
|
|
88
|
+
bunx couch-kit dev
|
|
89
|
+
|
|
90
|
+
# Custom port
|
|
91
|
+
bunx couch-kit dev --port 3000
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Prints the LAN URL (e.g., `http://192.168.1.50:5173`) so you can pass it as `devServerUrl` to `GameHostProvider`. Requires `vite` as a dev dependency in your web controller project.
|
package/dist/index.js
CHANGED
|
@@ -1887,11 +1887,14 @@ var init_esm = __esm(() => {
|
|
|
1887
1887
|
} = import__.default);
|
|
1888
1888
|
});
|
|
1889
1889
|
|
|
1890
|
+
// ../core/src/types.ts
|
|
1891
|
+
var init_types = () => {};
|
|
1892
|
+
|
|
1890
1893
|
// ../core/src/middleware.ts
|
|
1891
1894
|
var init_middleware = () => {};
|
|
1892
1895
|
|
|
1893
|
-
// ../core/src/
|
|
1894
|
-
var
|
|
1896
|
+
// ../core/src/reducer.ts
|
|
1897
|
+
var init_reducer = () => {};
|
|
1895
1898
|
|
|
1896
1899
|
// ../core/src/protocol.ts
|
|
1897
1900
|
var MessageTypes;
|
|
@@ -1960,6 +1963,7 @@ function replayActions(recording, reducer) {
|
|
|
1960
1963
|
// ../core/src/index.ts
|
|
1961
1964
|
var init_src = __esm(() => {
|
|
1962
1965
|
init_types();
|
|
1966
|
+
init_reducer();
|
|
1963
1967
|
init_protocol();
|
|
1964
1968
|
init_constants();
|
|
1965
1969
|
init_middleware();
|
|
@@ -2156,16 +2160,16 @@ var init_init = __esm(() => {
|
|
|
2156
2160
|
preview: "vite preview"
|
|
2157
2161
|
},
|
|
2158
2162
|
dependencies: {
|
|
2159
|
-
react: "^
|
|
2160
|
-
"react-dom": "^
|
|
2161
|
-
"@couch-kit/client": "^0.
|
|
2163
|
+
react: "^19.0.0",
|
|
2164
|
+
"react-dom": "^19.0.0",
|
|
2165
|
+
"@couch-kit/client": "^0.8.0"
|
|
2162
2166
|
},
|
|
2163
2167
|
devDependencies: {
|
|
2164
|
-
"@types/react": "^
|
|
2165
|
-
"@types/react-dom": "^
|
|
2166
|
-
"@vitejs/plugin-react": "^
|
|
2167
|
-
typescript: "^5.
|
|
2168
|
-
vite: "^
|
|
2168
|
+
"@types/react": "^19.0.0",
|
|
2169
|
+
"@types/react-dom": "^19.0.0",
|
|
2170
|
+
"@vitejs/plugin-react": "^6.0.0",
|
|
2171
|
+
typescript: "^5.7.0",
|
|
2172
|
+
vite: "^6.0.0"
|
|
2169
2173
|
}
|
|
2170
2174
|
};
|
|
2171
2175
|
fs2.writeFileSync(path2.join(targetDir, "package.json"), JSON.stringify(packageJson, null, 2) + `
|
|
@@ -2244,11 +2248,12 @@ ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
|
2244
2248
|
`);
|
|
2245
2249
|
fs2.writeFileSync(path2.join(targetDir, "src/App.tsx"), `
|
|
2246
2250
|
import { useGameClient } from '@couch-kit/client';
|
|
2251
|
+
import { gameReducer, initialState } from './reducer';
|
|
2247
2252
|
|
|
2248
2253
|
function App() {
|
|
2249
2254
|
const { status, playerId, sendAction } = useGameClient({
|
|
2250
|
-
initialState
|
|
2251
|
-
reducer:
|
|
2255
|
+
initialState,
|
|
2256
|
+
reducer: gameReducer,
|
|
2252
2257
|
});
|
|
2253
2258
|
|
|
2254
2259
|
return (
|
|
@@ -2256,7 +2261,7 @@ function App() {
|
|
|
2256
2261
|
<h1>Controller</h1>
|
|
2257
2262
|
<p>Status: {status}</p>
|
|
2258
2263
|
<p>ID: {playerId || 'Connecting...'}</p>
|
|
2259
|
-
<button onClick={() => sendAction({ type: '
|
|
2264
|
+
<button onClick={() => sendAction({ type: 'SCORE' })}
|
|
2260
2265
|
style={{ fontSize: 24, padding: '20px 40px', width: '100%' }}>
|
|
2261
2266
|
BUZZ!
|
|
2262
2267
|
</button>
|
|
@@ -2350,12 +2355,12 @@ var init_replay = __esm(() => {
|
|
|
2350
2355
|
}
|
|
2351
2356
|
const resolvedReducerPath = resolve(reducerPath);
|
|
2352
2357
|
const reducerModule = await import(resolvedReducerPath);
|
|
2353
|
-
const
|
|
2354
|
-
if (typeof
|
|
2358
|
+
const reducer2 = reducerModule.default ?? reducerModule.reducer;
|
|
2359
|
+
if (typeof reducer2 !== "function") {
|
|
2355
2360
|
console.error("Error: Reducer module must export a default function or named 'reducer' export");
|
|
2356
2361
|
process.exit(1);
|
|
2357
2362
|
}
|
|
2358
|
-
const result = replayActions(recording,
|
|
2363
|
+
const result = replayActions(recording, reducer2);
|
|
2359
2364
|
if (options.json) {
|
|
2360
2365
|
const output = options.snapshots ? result : {
|
|
2361
2366
|
finalState: result.finalState,
|
|
@@ -2472,9 +2477,9 @@ program2.command("init").description("Scaffolds a new web controller project").a
|
|
|
2472
2477
|
const { initCommand: initCommand2 } = await Promise.resolve().then(() => (init_init(), exports_init));
|
|
2473
2478
|
await initCommand2.parseAsync(["init", name], { from: "user" });
|
|
2474
2479
|
});
|
|
2475
|
-
program2.command("replay").description("Replay a recorded game session against a reducer").argument("<recording>", "Path to recording JSON file").argument("<reducer>", "Path to reducer module").option("--snapshots", "Output intermediate state snapshots").option("--json", "Output as formatted JSON").action(async (recording,
|
|
2480
|
+
program2.command("replay").description("Replay a recorded game session against a reducer").argument("<recording>", "Path to recording JSON file").argument("<reducer>", "Path to reducer module").option("--snapshots", "Output intermediate state snapshots").option("--json", "Output as formatted JSON").action(async (recording, reducer2, options) => {
|
|
2476
2481
|
const { replay: replay3 } = await Promise.resolve().then(() => (init_replay(), exports_replay));
|
|
2477
|
-
await replay3.parseAsync(["replay", recording,
|
|
2482
|
+
await replay3.parseAsync(["replay", recording, reducer2, ...reconstructArgs(options)], { from: "user" });
|
|
2478
2483
|
});
|
|
2479
2484
|
program2.command("dev").description("Start development server with LAN access").option("-p, --port <port>", "Port number", "5173").option("--host", "Expose to LAN").option("--open", "Open browser automatically").action(async (options) => {
|
|
2480
2485
|
const { dev: dev2 } = await Promise.resolve().then(() => (init_dev(), exports_dev));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@couch-kit/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.6",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"provenance": true
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
"clean": "rm -rf dist"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@couch-kit/core": "0.9.
|
|
42
|
+
"@couch-kit/core": "0.9.1",
|
|
43
43
|
"commander": "^12.0.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"typescript": "^
|
|
46
|
+
"typescript": "^6.0.0"
|
|
47
47
|
}
|
|
48
48
|
}
|