@couch-kit/devtools 3.0.1 → 3.0.3

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,32 @@
1
1
  # @couch-kit/devtools
2
2
 
3
+ ## 3.0.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#206](https://github.com/faluciano/react-native-couch-kit/pull/206) [`cfe5bbb`](https://github.com/faluciano/react-native-couch-kit/commit/cfe5bbb1ac46eca0cb006b07473fbfab32e0182b) Thanks [@faluciano](https://github.com/faluciano)! - Publish a bundle that actually contains `DebugOverlay`.
8
+
9
+ Every previous release shipped a 27-byte `dist/index.js` that exported `DebugOverlay` without defining it: with `sideEffects: false`, the bundler tree-shook the named re-export of the package's only value. The build also targeted React's development JSX runtime, which does not work in a production build. The entry point now uses `export *`, the bundle is built against `react/jsx-runtime`, and the build fails if either regresses.
10
+
11
+ ## 3.0.2
12
+
13
+ ### Patch Changes
14
+
15
+ - [#151](https://github.com/faluciano/react-native-couch-kit/pull/151) [`ff839a6`](https://github.com/faluciano/react-native-couch-kit/commit/ff839a67c54aaf1f042b598d59d7918f03814c92) Thanks [@faluciano](https://github.com/faluciano)! - Fix an over-strict peer dependency that pinned devtools to one exact client
16
+ release.
17
+
18
+ The peer range was `workspace:*`, which publishing rewrites to the current
19
+ version — so `@couch-kit/devtools@3.0.0` demanded _exactly_
20
+ `@couch-kit/client@0.11.0`, and any client patch would conflict. devtools uses
21
+ one type-only import from client and nothing at runtime, so the peer is now a
22
+ wide, optional range (`>=0.9.0 <1.0.0`).
23
+
24
+ This also stops the runaway majors: because a peerDependency range change is
25
+ treated as breaking, every client release majored devtools — 0.2.10 → 1.0.0 →
26
+ 2.0.0 → 3.0.0 in a day, each changelog reading "Patch Changes". Changesets is
27
+ now configured to bump peer dependents only when a release actually leaves
28
+ their range.
29
+
3
30
  ## 3.0.1
4
31
 
5
32
  ### Patch Changes
package/dist/index.js CHANGED
@@ -1,3 +1,372 @@
1
+ // src/DebugOverlay.tsx
2
+ import { useState, useCallback, useRef } from "react";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ var STATUS_COLORS = {
5
+ connected: "#4ade80",
6
+ connecting: "#facc15",
7
+ reconnecting: "#facc15",
8
+ disconnected: "#f87171",
9
+ error: "#f87171"
10
+ };
11
+ function formatTimestamp(ts) {
12
+ const date = new Date(ts);
13
+ return date.toLocaleTimeString("en-US", {
14
+ hour12: false,
15
+ hour: "2-digit",
16
+ minute: "2-digit",
17
+ second: "2-digit"
18
+ }) + "." + String(date.getMilliseconds()).padStart(3, "0");
19
+ }
20
+ function JsonTree({ data, depth = 0 }) {
21
+ if (data === null || data === undefined) {
22
+ return /* @__PURE__ */ jsx("span", {
23
+ style: { color: "#9ca3af" },
24
+ children: String(data)
25
+ });
26
+ }
27
+ if (typeof data === "boolean") {
28
+ return /* @__PURE__ */ jsx("span", {
29
+ style: { color: "#c084fc" },
30
+ children: String(data)
31
+ });
32
+ }
33
+ if (typeof data === "number") {
34
+ return /* @__PURE__ */ jsx("span", {
35
+ style: { color: "#60a5fa" },
36
+ children: data
37
+ });
38
+ }
39
+ if (typeof data === "string") {
40
+ return /* @__PURE__ */ jsxs("span", {
41
+ style: { color: "#4ade80" },
42
+ children: [
43
+ '"',
44
+ data,
45
+ '"'
46
+ ]
47
+ });
48
+ }
49
+ if (Array.isArray(data)) {
50
+ if (data.length === 0)
51
+ return /* @__PURE__ */ jsx("span", {
52
+ children: "[]"
53
+ });
54
+ return /* @__PURE__ */ jsxs("span", {
55
+ children: [
56
+ `[
57
+ `,
58
+ data.map((item, i) => /* @__PURE__ */ jsxs("span", {
59
+ children: [
60
+ " ".repeat(depth + 1),
61
+ /* @__PURE__ */ jsx(JsonTree, {
62
+ data: item,
63
+ depth: depth + 1
64
+ }),
65
+ i < data.length - 1 ? "," : "",
66
+ `
67
+ `
68
+ ]
69
+ }, i)),
70
+ " ".repeat(depth),
71
+ "]"
72
+ ]
73
+ });
74
+ }
75
+ if (typeof data === "object") {
76
+ const entries = Object.entries(data);
77
+ if (entries.length === 0)
78
+ return /* @__PURE__ */ jsx("span", {
79
+ children: "{}"
80
+ });
81
+ return /* @__PURE__ */ jsxs("span", {
82
+ children: [
83
+ `{
84
+ `,
85
+ entries.map(([key, value], i) => /* @__PURE__ */ jsxs("span", {
86
+ children: [
87
+ " ".repeat(depth + 1),
88
+ /* @__PURE__ */ jsx("span", {
89
+ style: { color: "#93c5fd" },
90
+ children: key
91
+ }),
92
+ ": ",
93
+ /* @__PURE__ */ jsx(JsonTree, {
94
+ data: value,
95
+ depth: depth + 1
96
+ }),
97
+ i < entries.length - 1 ? "," : "",
98
+ `
99
+ `
100
+ ]
101
+ }, key)),
102
+ " ".repeat(depth),
103
+ "}"
104
+ ]
105
+ });
106
+ }
107
+ return /* @__PURE__ */ jsx("span", {
108
+ children: String(data)
109
+ });
110
+ }
111
+ function DebugOverlay({
112
+ data,
113
+ defaultCollapsed = true,
114
+ position = "bottom-right",
115
+ maxHeight = 400
116
+ }) {
117
+ const [collapsed, setCollapsed] = useState(defaultCollapsed);
118
+ const [activeTab, setActiveTab] = useState("actions");
119
+ const tapCountRef = useRef(0);
120
+ const tapTimerRef = useRef(null);
121
+ const handleToggle = useCallback(() => {
122
+ tapCountRef.current++;
123
+ if (tapTimerRef.current) {
124
+ clearTimeout(tapTimerRef.current);
125
+ }
126
+ tapTimerRef.current = setTimeout(() => {
127
+ tapCountRef.current = 0;
128
+ }, 300);
129
+ setCollapsed((prev) => !prev);
130
+ }, []);
131
+ if (!data.enabled)
132
+ return null;
133
+ const positionStyles = {
134
+ position: "fixed",
135
+ zIndex: 99999,
136
+ ...position.includes("top") ? { top: 8 } : { bottom: 8 },
137
+ ...position.includes("left") ? { left: 8 } : { right: 8 }
138
+ };
139
+ const statusColor = STATUS_COLORS[data.connectionStatus] ?? "#9ca3af";
140
+ const panelStyle = {
141
+ ...positionStyles,
142
+ fontFamily: "'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, monospace",
143
+ fontSize: 11,
144
+ lineHeight: 1.4,
145
+ color: "#e5e7eb",
146
+ backgroundColor: "rgba(17, 24, 39, 0.95)",
147
+ border: "1px solid rgba(75, 85, 99, 0.6)",
148
+ borderRadius: 8,
149
+ overflow: "hidden",
150
+ width: collapsed ? "auto" : 360,
151
+ backdropFilter: "blur(8px)",
152
+ boxShadow: "0 4px 24px rgba(0, 0, 0, 0.4)"
153
+ };
154
+ const buttonStyle = {
155
+ background: "none",
156
+ border: "none",
157
+ color: "#e5e7eb",
158
+ cursor: "pointer",
159
+ padding: "6px 10px",
160
+ fontSize: 11,
161
+ fontFamily: "inherit"
162
+ };
163
+ const tabStyle = (isActive) => ({
164
+ ...buttonStyle,
165
+ borderBottom: isActive ? "2px solid #60a5fa" : "2px solid transparent",
166
+ color: isActive ? "#60a5fa" : "#9ca3af",
167
+ paddingBottom: 4
168
+ });
169
+ if (collapsed) {
170
+ return /* @__PURE__ */ jsx("div", {
171
+ style: positionStyles,
172
+ children: /* @__PURE__ */ jsxs("button", {
173
+ onClick: handleToggle,
174
+ style: {
175
+ ...buttonStyle,
176
+ backgroundColor: "rgba(17, 24, 39, 0.95)",
177
+ border: "1px solid rgba(75, 85, 99, 0.6)",
178
+ borderRadius: 8,
179
+ display: "flex",
180
+ alignItems: "center",
181
+ gap: 6,
182
+ padding: "6px 12px",
183
+ backdropFilter: "blur(8px)",
184
+ boxShadow: "0 2px 12px rgba(0, 0, 0, 0.3)"
185
+ },
186
+ children: [
187
+ /* @__PURE__ */ jsx("span", {
188
+ style: {
189
+ width: 8,
190
+ height: 8,
191
+ borderRadius: "50%",
192
+ backgroundColor: statusColor,
193
+ display: "inline-block"
194
+ }
195
+ }),
196
+ /* @__PURE__ */ jsx("span", {
197
+ children: "Debug"
198
+ }),
199
+ data.rtt !== null && /* @__PURE__ */ jsxs("span", {
200
+ style: { color: "#9ca3af" },
201
+ children: [
202
+ data.rtt,
203
+ "ms"
204
+ ]
205
+ })
206
+ ]
207
+ })
208
+ });
209
+ }
210
+ const latestState = data.stateHistory.length > 0 ? data.stateHistory[data.stateHistory.length - 1]?.state : null;
211
+ return /* @__PURE__ */ jsxs("div", {
212
+ style: panelStyle,
213
+ children: [
214
+ /* @__PURE__ */ jsxs("div", {
215
+ style: {
216
+ display: "flex",
217
+ alignItems: "center",
218
+ justifyContent: "space-between",
219
+ padding: "6px 10px",
220
+ borderBottom: "1px solid rgba(75, 85, 99, 0.4)"
221
+ },
222
+ children: [
223
+ /* @__PURE__ */ jsxs("div", {
224
+ style: { display: "flex", alignItems: "center", gap: 6 },
225
+ children: [
226
+ /* @__PURE__ */ jsx("span", {
227
+ style: {
228
+ width: 8,
229
+ height: 8,
230
+ borderRadius: "50%",
231
+ backgroundColor: statusColor,
232
+ display: "inline-block"
233
+ }
234
+ }),
235
+ /* @__PURE__ */ jsx("span", {
236
+ style: { fontWeight: 600 },
237
+ children: "Debug"
238
+ }),
239
+ /* @__PURE__ */ jsxs("span", {
240
+ style: { color: "#9ca3af" },
241
+ children: [
242
+ data.connectionStatus,
243
+ data.rtt !== null ? ` · ${data.rtt}ms` : ""
244
+ ]
245
+ })
246
+ ]
247
+ }),
248
+ /* @__PURE__ */ jsxs("div", {
249
+ style: { display: "flex", gap: 4 },
250
+ children: [
251
+ /* @__PURE__ */ jsx("button", {
252
+ onClick: data.clearHistory,
253
+ style: buttonStyle,
254
+ title: "Clear",
255
+ children: "✕"
256
+ }),
257
+ /* @__PURE__ */ jsx("button", {
258
+ onClick: handleToggle,
259
+ style: buttonStyle,
260
+ title: "Collapse",
261
+ children: "▾"
262
+ })
263
+ ]
264
+ })
265
+ ]
266
+ }),
267
+ /* @__PURE__ */ jsxs("div", {
268
+ style: {
269
+ display: "flex",
270
+ gap: 0,
271
+ borderBottom: "1px solid rgba(75, 85, 99, 0.4)",
272
+ padding: "0 6px"
273
+ },
274
+ children: [
275
+ /* @__PURE__ */ jsxs("button", {
276
+ onClick: () => setActiveTab("actions"),
277
+ style: tabStyle(activeTab === "actions"),
278
+ children: [
279
+ "Actions (",
280
+ data.actionLog.length,
281
+ ")"
282
+ ]
283
+ }),
284
+ /* @__PURE__ */ jsx("button", {
285
+ onClick: () => setActiveTab("state"),
286
+ style: tabStyle(activeTab === "state"),
287
+ children: "State"
288
+ })
289
+ ]
290
+ }),
291
+ /* @__PURE__ */ jsxs("div", {
292
+ style: {
293
+ maxHeight,
294
+ overflowY: "auto",
295
+ padding: 8
296
+ },
297
+ children: [
298
+ activeTab === "actions" && /* @__PURE__ */ jsx("div", {
299
+ children: data.actionLog.length === 0 ? /* @__PURE__ */ jsx("div", {
300
+ style: {
301
+ color: "#6b7280",
302
+ textAlign: "center",
303
+ padding: 16
304
+ },
305
+ children: "No actions recorded"
306
+ }) : data.actionLog.slice().reverse().map((entry) => /* @__PURE__ */ jsxs("div", {
307
+ style: {
308
+ padding: "4px 6px",
309
+ borderBottom: "1px solid rgba(75, 85, 99, 0.2)",
310
+ display: "flex",
311
+ flexDirection: "column",
312
+ gap: 2
313
+ },
314
+ children: [
315
+ /* @__PURE__ */ jsxs("div", {
316
+ style: {
317
+ display: "flex",
318
+ justifyContent: "space-between",
319
+ alignItems: "center"
320
+ },
321
+ children: [
322
+ /* @__PURE__ */ jsx("span", {
323
+ style: {
324
+ color: entry.source === "local" ? "#60a5fa" : "#4ade80",
325
+ fontSize: 10,
326
+ textTransform: "uppercase"
327
+ },
328
+ children: entry.source
329
+ }),
330
+ /* @__PURE__ */ jsx("span", {
331
+ style: { color: "#6b7280", fontSize: 10 },
332
+ children: formatTimestamp(entry.timestamp)
333
+ })
334
+ ]
335
+ }),
336
+ /* @__PURE__ */ jsx("pre", {
337
+ style: {
338
+ margin: 0,
339
+ fontSize: 10,
340
+ color: "#d1d5db",
341
+ whiteSpace: "pre-wrap",
342
+ wordBreak: "break-all"
343
+ },
344
+ children: /* @__PURE__ */ jsx(JsonTree, {
345
+ data: entry.action
346
+ })
347
+ })
348
+ ]
349
+ }, entry.id))
350
+ }),
351
+ activeTab === "state" && /* @__PURE__ */ jsx("pre", {
352
+ style: {
353
+ margin: 0,
354
+ fontSize: 10,
355
+ whiteSpace: "pre-wrap",
356
+ wordBreak: "break-all"
357
+ },
358
+ children: latestState !== null ? /* @__PURE__ */ jsx(JsonTree, {
359
+ data: latestState
360
+ }) : /* @__PURE__ */ jsx("span", {
361
+ style: { color: "#6b7280" },
362
+ children: "No state captured"
363
+ })
364
+ })
365
+ ]
366
+ })
367
+ ]
368
+ });
369
+ }
1
370
  export {
2
371
  DebugOverlay
3
372
  };
package/lib/index.d.ts CHANGED
@@ -1,3 +1,2 @@
1
- export { DebugOverlay } from "./DebugOverlay";
2
- export type { DebugOverlayProps } from "./DebugOverlay";
1
+ export * from "./DebugOverlay";
3
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,cAAc,gBAAgB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@couch-kit/devtools",
3
- "version": "3.0.1",
3
+ "version": "3.0.3",
4
4
  "description": "Developer tooling and debug overlay for Couch Kit games",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./lib/index.d.ts",
@@ -13,7 +13,9 @@
13
13
  },
14
14
  "sideEffects": false,
15
15
  "scripts": {
16
- "build": "bun build ./src/index.ts --outdir ./dist --target browser --external react --external @couch-kit/client --external @couch-kit/core && tsc -p tsconfig.build.json",
16
+ "build": "NODE_ENV=production bun build ./src/index.ts --outdir ./dist --target browser --external react --external @couch-kit/client --external @couch-kit/core && tsc -p tsconfig.build.json && bun run verify-build",
17
+ "verify-build": "node -e \"const s=require('fs').readFileSync('./dist/index.js','utf8');if(!s.includes('function DebugOverlay'))throw new Error('dist/index.js is missing DebugOverlay — empty bundle');if(s.includes('jsx-dev-runtime'))throw new Error('dist/index.js uses react/jsx-dev-runtime — build with NODE_ENV=production');\"",
18
+ "prepublishOnly": "bun run build",
17
19
  "test": "bun test",
18
20
  "typecheck": "tsc --noEmit",
19
21
  "clean": "rm -rf dist lib"
@@ -27,8 +29,8 @@
27
29
  ],
28
30
  "dependencies": {},
29
31
  "devDependencies": {
30
- "@couch-kit/client": "0.11.0",
31
- "@couch-kit/core": "0.9.3",
32
+ "@couch-kit/client": "0.15.0",
33
+ "@couch-kit/core": "0.10.0",
32
34
  "@happy-dom/global-registrator": "^20.10.6",
33
35
  "@testing-library/dom": "^10.4.1",
34
36
  "@testing-library/react": "^16.3.2",
package/src/index.ts CHANGED
@@ -1,2 +1,5 @@
1
- export { DebugOverlay } from "./DebugOverlay";
2
- export type { DebugOverlayProps } from "./DebugOverlay";
1
+ // `export *`, not `export { DebugOverlay } from`: with `sideEffects: false`,
2
+ // bun tree-shakes a named re-export of the package's only value out of the
3
+ // bundle, publishing a `dist/index.js` that exports a binding it never defines.
4
+ // The build's `verify-build` step fails if that ever happens again.
5
+ export * from "./DebugOverlay";