@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.
Files changed (3) hide show
  1. package/README.md +48 -2
  2. package/dist/index.js +23 -18
  3. 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 new web controller project (Vite + React + TypeScript) configured to work with Couch Kit.
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 when preparing your TV app for release.
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/types.ts
1894
- var init_types = () => {};
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: "^18.2.0",
2160
- "react-dom": "^18.2.0",
2161
- "@couch-kit/client": "^0.4.3"
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": "^18.2.66",
2165
- "@types/react-dom": "^18.2.22",
2166
- "@vitejs/plugin-react": "^4.2.1",
2167
- typescript: "^5.2.2",
2168
- vite: "^5.2.0"
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: { count: 0 },
2251
- reducer: (state, action) => state // Dummy 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: 'BUZZ' })}
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 reducer = reducerModule.default ?? reducerModule.reducer;
2354
- if (typeof reducer !== "function") {
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, reducer);
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, reducer, options) => {
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, reducer, ...reconstructArgs(options)], { from: "user" });
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.4",
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.0",
42
+ "@couch-kit/core": "0.9.1",
43
43
  "commander": "^12.0.0"
44
44
  },
45
45
  "devDependencies": {
46
- "typescript": "^5.4.0"
46
+ "typescript": "^6.0.0"
47
47
  }
48
48
  }