@couch-kit/client 0.7.1 → 0.8.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/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @couch-kit/client
2
2
 
3
+ ## 0.8.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#27](https://github.com/faluciano/react-native-couch-kit/pull/27) [`4976357`](https://github.com/faluciano/react-native-couch-kit/commit/49763573df502e394d5591b73000f48ee711d7a8) Thanks [@faluciano](https://github.com/faluciano)! - Fix WebSocket connection failure caused by path mismatch: the client connected to `ws://host:8082` (root path `/`) while the server only accepted upgrades on `/ws`. Added shared `DEFAULT_WS_PATH` constant to `@couch-kit/core` and use it in both client URL construction and server handler registration.
8
+
9
+ - Updated dependencies [[`4976357`](https://github.com/faluciano/react-native-couch-kit/commit/49763573df502e394d5591b73000f48ee711d7a8)]:
10
+ - @couch-kit/core@0.8.1
11
+
12
+ ## 0.8.0
13
+
14
+ ### Minor Changes
15
+
16
+ - [#21](https://github.com/faluciano/react-native-couch-kit/pull/21) [`f1e836d`](https://github.com/faluciano/react-native-couch-kit/commit/f1e836d8f17821f0da20db7c3c552552c9b22133) Thanks [@faluciano](https://github.com/faluciano)! - Add `useDebugPanel` hook for capturing debug information (action log, state history, connection status, RTT). Gated behind `debug: true` option.
17
+
18
+ ### Patch Changes
19
+
20
+ - Updated dependencies [[`f1e836d`](https://github.com/faluciano/react-native-couch-kit/commit/f1e836d8f17821f0da20db7c3c552552c9b22133)]:
21
+ - @couch-kit/core@0.8.0
22
+
3
23
  ## 0.7.1
4
24
 
5
25
  ### Patch Changes
package/dist/index.js CHANGED
@@ -4,6 +4,7 @@ import {
4
4
  MessageTypes as MessageTypes2,
5
5
  InternalActionTypes,
6
6
  DEFAULT_WS_PORT_OFFSET,
7
+ DEFAULT_WS_PATH,
7
8
  DEFAULT_MAX_RETRIES,
8
9
  DEFAULT_BASE_DELAY,
9
10
  DEFAULT_MAX_DELAY,
@@ -98,7 +99,7 @@ function useGameClient(config) {
98
99
  const host = window.location.hostname;
99
100
  const httpPort = parseInt(window.location.port, 10) || 80;
100
101
  const wsPort = cfg.wsPort || httpPort + DEFAULT_WS_PORT_OFFSET;
101
- wsUrl = `${protocol}//${host}:${wsPort}`;
102
+ wsUrl = `${protocol}//${host}:${wsPort}${DEFAULT_WS_PATH}`;
102
103
  }
103
104
  if (!wsUrl)
104
105
  return;
@@ -315,9 +316,67 @@ function usePreload(assets, sendMessage) {
315
316
  }, [stableAssets]);
316
317
  return { loaded, progress, failedAssets };
317
318
  }
319
+ // src/debug-panel.ts
320
+ import { useCallback as useCallback3, useEffect as useEffect4, useRef as useRef4, useState as useState4 } from "react";
321
+ function useDebugPanel(options) {
322
+ const { enabled, state, status, rtt, maxEntries = 50 } = options;
323
+ const nextIdRef = useRef4(0);
324
+ const prevStateRef = useRef4(null);
325
+ const [actionLog, setActionLog] = useState4([]);
326
+ const [stateHistory, setStateHistory] = useState4([]);
327
+ const clearHistory = useCallback3(() => {
328
+ setActionLog([]);
329
+ setStateHistory([]);
330
+ nextIdRef.current = 0;
331
+ }, []);
332
+ const logAction = useCallback3((action, source = "local") => {
333
+ if (!enabled)
334
+ return;
335
+ setActionLog((prev) => {
336
+ const entry = {
337
+ id: nextIdRef.current++,
338
+ action,
339
+ timestamp: Date.now(),
340
+ source
341
+ };
342
+ const next = [...prev, entry];
343
+ return next.length > maxEntries ? next.slice(-maxEntries) : next;
344
+ });
345
+ }, [enabled, maxEntries]);
346
+ useEffect4(() => {
347
+ if (!enabled || state === null || state === prevStateRef.current)
348
+ return;
349
+ prevStateRef.current = state;
350
+ setStateHistory((prev) => {
351
+ const entry = {
352
+ id: nextIdRef.current++,
353
+ state,
354
+ timestamp: Date.now()
355
+ };
356
+ const next = [...prev, entry];
357
+ return next.length > maxEntries ? next.slice(-maxEntries) : next;
358
+ });
359
+ }, [enabled, state, maxEntries]);
360
+ useEffect4(() => {
361
+ if (!enabled) {
362
+ clearHistory();
363
+ prevStateRef.current = null;
364
+ }
365
+ }, [enabled, clearHistory]);
366
+ return {
367
+ enabled,
368
+ actionLog,
369
+ stateHistory,
370
+ connectionStatus: status,
371
+ rtt: rtt > 0 ? rtt : null,
372
+ clearHistory,
373
+ logAction
374
+ };
375
+ }
318
376
  export {
319
377
  useServerTime,
320
378
  usePreload,
321
379
  useGameClient,
380
+ useDebugPanel,
322
381
  calculateTimeSync
323
382
  };
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,OAAO,EAUL,KAAK,UAAU,EACf,KAAK,OAAO,EAEb,MAAM,iBAAiB,CAAC;AAGzB,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,UAAU,EAAE,CAAC,SAAS,OAAO;IACnE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC;IACpC,YAAY,EAAE,CAAC,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,UAAU,EAAE,CAAC,SAAS,OAAO,EACnE,MAAM,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC;;;;yBAsNc,CAAC;;IAqBvC,8EAA8E;;IAE9E,0EAA0E;;IAE1E,+EAA+E;;EAGlF"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,OAAO,EAWL,KAAK,UAAU,EACf,KAAK,OAAO,EAEb,MAAM,iBAAiB,CAAC;AAGzB,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,UAAU,EAAE,CAAC,SAAS,OAAO;IACnE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC;IACpC,YAAY,EAAE,CAAC,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,UAAU,EAAE,CAAC,SAAS,OAAO,EACnE,MAAM,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC;;;;yBAsNc,CAAC;;IAqBvC,8EAA8E;;IAE9E,0EAA0E;;IAE1E,+EAA+E;;EAGlF"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * A recorded debug action entry.
3
+ */
4
+ export interface DebugActionEntry {
5
+ id: number;
6
+ action: unknown;
7
+ timestamp: number;
8
+ source: "local" | "remote";
9
+ }
10
+ /**
11
+ * A state history entry for debugging.
12
+ */
13
+ export interface DebugStateEntry<S = unknown> {
14
+ id: number;
15
+ state: S;
16
+ timestamp: number;
17
+ }
18
+ /**
19
+ * Debug panel data returned by useDebugPanel.
20
+ */
21
+ export interface DebugPanelData<S = unknown> {
22
+ /** Whether debug mode is active */
23
+ enabled: boolean;
24
+ /** Log of actions (sent and received) */
25
+ actionLog: DebugActionEntry[];
26
+ /** History of state changes */
27
+ stateHistory: DebugStateEntry<S>[];
28
+ /** Current connection status */
29
+ connectionStatus: string;
30
+ /** Current round-trip time in ms */
31
+ rtt: number | null;
32
+ /** Clear all debug history */
33
+ clearHistory: () => void;
34
+ /** Manually log an action (e.g., from sendAction wrapper) */
35
+ logAction: (action: unknown, source?: "local" | "remote") => void;
36
+ }
37
+ export interface UseDebugPanelOptions<S = unknown> {
38
+ /** Whether debug capture is active */
39
+ enabled: boolean;
40
+ /** Current game state from useGameClient */
41
+ state: S | null;
42
+ /** Connection status from useGameClient */
43
+ status: string;
44
+ /** RTT from useGameClient */
45
+ rtt: number;
46
+ /** Maximum number of entries to keep in logs */
47
+ maxEntries?: number;
48
+ }
49
+ /**
50
+ * Hook that provides debug panel data for development.
51
+ * Tracks state changes, connection status, and action history.
52
+ * Designed to be consumed by DebugOverlay or custom debug UI.
53
+ */
54
+ export declare function useDebugPanel<S = unknown>(options: UseDebugPanelOptions<S>): DebugPanelData<S>;
55
+ //# sourceMappingURL=debug-panel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug-panel.d.ts","sourceRoot":"","sources":["../src/debug-panel.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,OAAO;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,CAAC,CAAC;IACT,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc,CAAC,CAAC,GAAG,OAAO;IACzC,mCAAmC;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,yCAAyC;IACzC,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,+BAA+B;IAC/B,YAAY,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IACnC,gCAAgC;IAChC,gBAAgB,EAAE,MAAM,CAAC;IACzB,oCAAoC;IACpC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,8BAA8B;IAC9B,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,6DAA6D;IAC7D,SAAS,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,KAAK,IAAI,CAAC;CACnE;AAED,MAAM,WAAW,oBAAoB,CAAC,CAAC,GAAG,OAAO;IAC/C,sCAAsC;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,4CAA4C;IAC5C,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;IAChB,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,6BAA6B;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,CAAC,GAAG,OAAO,EACvC,OAAO,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAC/B,cAAc,CAAC,CAAC,CAAC,CAiEnB"}
package/lib/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- export * from './client';
2
- export * from './time-sync';
3
- export * from './assets';
1
+ export * from "./client";
2
+ export * from "./time-sync";
3
+ export * from "./assets";
4
+ export * from "./debug-panel";
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@couch-kit/client",
3
- "version": "0.7.1",
3
+ "version": "0.8.1",
4
4
  "publishConfig": {
5
5
  "access": "public",
6
6
  "provenance": true
@@ -47,7 +47,7 @@
47
47
  "clean": "rm -rf dist lib"
48
48
  },
49
49
  "dependencies": {
50
- "@couch-kit/core": "0.7.0"
50
+ "@couch-kit/core": "0.8.1"
51
51
  },
52
52
  "devDependencies": {
53
53
  "react": "^18.2.0",
package/src/client.ts CHANGED
@@ -3,6 +3,7 @@ import {
3
3
  MessageTypes,
4
4
  InternalActionTypes,
5
5
  DEFAULT_WS_PORT_OFFSET,
6
+ DEFAULT_WS_PATH,
6
7
  DEFAULT_MAX_RETRIES,
7
8
  DEFAULT_BASE_DELAY,
8
9
  DEFAULT_MAX_DELAY,
@@ -106,7 +107,7 @@ export function useGameClient<S extends IGameState, A extends IAction>(
106
107
  const host = window.location.hostname;
107
108
  const httpPort = parseInt(window.location.port, 10) || 80;
108
109
  const wsPort = cfg.wsPort || httpPort + DEFAULT_WS_PORT_OFFSET;
109
- wsUrl = `${protocol}//${host}:${wsPort}`;
110
+ wsUrl = `${protocol}//${host}:${wsPort}${DEFAULT_WS_PATH}`;
110
111
  }
111
112
 
112
113
  if (!wsUrl) return;
@@ -0,0 +1,127 @@
1
+ import { useCallback, useEffect, useRef, useState } from "react";
2
+
3
+ /**
4
+ * A recorded debug action entry.
5
+ */
6
+ export interface DebugActionEntry {
7
+ id: number;
8
+ action: unknown;
9
+ timestamp: number;
10
+ source: "local" | "remote";
11
+ }
12
+
13
+ /**
14
+ * A state history entry for debugging.
15
+ */
16
+ export interface DebugStateEntry<S = unknown> {
17
+ id: number;
18
+ state: S;
19
+ timestamp: number;
20
+ }
21
+
22
+ /**
23
+ * Debug panel data returned by useDebugPanel.
24
+ */
25
+ export interface DebugPanelData<S = unknown> {
26
+ /** Whether debug mode is active */
27
+ enabled: boolean;
28
+ /** Log of actions (sent and received) */
29
+ actionLog: DebugActionEntry[];
30
+ /** History of state changes */
31
+ stateHistory: DebugStateEntry<S>[];
32
+ /** Current connection status */
33
+ connectionStatus: string;
34
+ /** Current round-trip time in ms */
35
+ rtt: number | null;
36
+ /** Clear all debug history */
37
+ clearHistory: () => void;
38
+ /** Manually log an action (e.g., from sendAction wrapper) */
39
+ logAction: (action: unknown, source?: "local" | "remote") => void;
40
+ }
41
+
42
+ export interface UseDebugPanelOptions<S = unknown> {
43
+ /** Whether debug capture is active */
44
+ enabled: boolean;
45
+ /** Current game state from useGameClient */
46
+ state: S | null;
47
+ /** Connection status from useGameClient */
48
+ status: string;
49
+ /** RTT from useGameClient */
50
+ rtt: number;
51
+ /** Maximum number of entries to keep in logs */
52
+ maxEntries?: number;
53
+ }
54
+
55
+ /**
56
+ * Hook that provides debug panel data for development.
57
+ * Tracks state changes, connection status, and action history.
58
+ * Designed to be consumed by DebugOverlay or custom debug UI.
59
+ */
60
+ export function useDebugPanel<S = unknown>(
61
+ options: UseDebugPanelOptions<S>,
62
+ ): DebugPanelData<S> {
63
+ const { enabled, state, status, rtt, maxEntries = 50 } = options;
64
+ const nextIdRef = useRef(0);
65
+ const prevStateRef = useRef<S | null>(null);
66
+
67
+ const [actionLog, setActionLog] = useState<DebugActionEntry[]>([]);
68
+ const [stateHistory, setStateHistory] = useState<DebugStateEntry<S>[]>([]);
69
+
70
+ const clearHistory = useCallback(() => {
71
+ setActionLog([]);
72
+ setStateHistory([]);
73
+ nextIdRef.current = 0;
74
+ }, []);
75
+
76
+ const logAction = useCallback(
77
+ (action: unknown, source: "local" | "remote" = "local") => {
78
+ if (!enabled) return;
79
+
80
+ setActionLog((prev) => {
81
+ const entry: DebugActionEntry = {
82
+ id: nextIdRef.current++,
83
+ action,
84
+ timestamp: Date.now(),
85
+ source,
86
+ };
87
+ const next = [...prev, entry];
88
+ return next.length > maxEntries ? next.slice(-maxEntries) : next;
89
+ });
90
+ },
91
+ [enabled, maxEntries],
92
+ );
93
+
94
+ // Track state changes
95
+ useEffect(() => {
96
+ if (!enabled || state === null || state === prevStateRef.current) return;
97
+ prevStateRef.current = state;
98
+
99
+ setStateHistory((prev) => {
100
+ const entry: DebugStateEntry<S> = {
101
+ id: nextIdRef.current++,
102
+ state,
103
+ timestamp: Date.now(),
104
+ };
105
+ const next = [...prev, entry];
106
+ return next.length > maxEntries ? next.slice(-maxEntries) : next;
107
+ });
108
+ }, [enabled, state, maxEntries]);
109
+
110
+ // Reset when disabled
111
+ useEffect(() => {
112
+ if (!enabled) {
113
+ clearHistory();
114
+ prevStateRef.current = null;
115
+ }
116
+ }, [enabled, clearHistory]);
117
+
118
+ return {
119
+ enabled,
120
+ actionLog,
121
+ stateHistory,
122
+ connectionStatus: status,
123
+ rtt: rtt > 0 ? rtt : null,
124
+ clearHistory,
125
+ logAction,
126
+ };
127
+ }
package/src/index.ts CHANGED
@@ -1,3 +1,4 @@
1
- export * from './client';
2
- export * from './time-sync';
3
- export * from './assets';
1
+ export * from "./client";
2
+ export * from "./time-sync";
3
+ export * from "./assets";
4
+ export * from "./debug-panel";