@sqlite-sync/devtools 0.8.1 → 0.9.0

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/dist/index.js CHANGED
@@ -1,2258 +1,2534 @@
1
- // src/devtools.tsx
2
1
  import { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
3
-
4
- // src/devtools-registry.ts
5
- var devtoolsRegistrySymbol = Symbol.for("@sqlite-sync/devtools");
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ //#region src/devtools-registry.ts
4
+ const devtoolsRegistrySymbol = Symbol.for("@sqlite-sync/devtools");
6
5
  function createSQLiteSyncDevtoolsRegistry() {
7
- const instances = /* @__PURE__ */ new Map();
8
- const listeners = /* @__PURE__ */ new Set();
9
- let snapshot = {
10
- instances: []
11
- };
12
- const notify = () => {
13
- for (const listener of listeners) {
14
- listener();
15
- }
16
- };
17
- const updateSnapshot = () => {
18
- snapshot = {
19
- instances: Array.from(instances.values())
20
- };
21
- notify();
22
- };
23
- return {
24
- version: 1,
25
- instances,
26
- subscribe(listener) {
27
- listeners.add(listener);
28
- return () => {
29
- listeners.delete(listener);
30
- };
31
- },
32
- getSnapshot() {
33
- return snapshot;
34
- },
35
- register(instance) {
36
- instances.set(instance.instanceId, instance);
37
- updateSnapshot();
38
- let isUnregistered = false;
39
- return () => {
40
- if (isUnregistered) return;
41
- isUnregistered = true;
42
- if (!instances.delete(instance.instanceId)) return;
43
- updateSnapshot();
44
- };
45
- }
46
- };
6
+ const instances = /* @__PURE__ */ new Map();
7
+ const listeners = /* @__PURE__ */ new Set();
8
+ let snapshot = { instances: [] };
9
+ const notify = () => {
10
+ for (const listener of listeners) listener();
11
+ };
12
+ const updateSnapshot = () => {
13
+ snapshot = { instances: Array.from(instances.values()) };
14
+ notify();
15
+ };
16
+ return {
17
+ version: 1,
18
+ instances,
19
+ subscribe(listener) {
20
+ listeners.add(listener);
21
+ return () => {
22
+ listeners.delete(listener);
23
+ };
24
+ },
25
+ getSnapshot() {
26
+ return snapshot;
27
+ },
28
+ register(instance) {
29
+ instances.set(instance.instanceId, instance);
30
+ updateSnapshot();
31
+ let isUnregistered = false;
32
+ return () => {
33
+ if (isUnregistered) return;
34
+ isUnregistered = true;
35
+ if (!instances.delete(instance.instanceId)) return;
36
+ updateSnapshot();
37
+ };
38
+ }
39
+ };
47
40
  }
48
41
  function getOrCreateSQLiteSyncDevtoolsRegistry() {
49
- const registryGlobal = globalThis;
50
- registryGlobal[devtoolsRegistrySymbol] ??= createSQLiteSyncDevtoolsRegistry();
51
- return registryGlobal[devtoolsRegistrySymbol];
42
+ const registryGlobal = globalThis;
43
+ registryGlobal[devtoolsRegistrySymbol] ??= createSQLiteSyncDevtoolsRegistry();
44
+ return registryGlobal[devtoolsRegistrySymbol];
52
45
  }
53
-
54
- // src/devtools.tsx
55
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
56
- var TRIGGER_POSITION_STORAGE_KEY = "sqlite-sync-devtools.trigger-position";
57
- var DRAG_THRESHOLD_PX = 4;
58
- var VIEWPORT_MARGIN_PX = 8;
46
+ //#endregion
47
+ //#region src/devtools.tsx
48
+ const TRIGGER_POSITION_STORAGE_KEY = "sqlite-sync-devtools.trigger-position";
49
+ const DRAG_THRESHOLD_PX = 4;
50
+ const VIEWPORT_MARGIN_PX = 8;
59
51
  function readStoredTriggerPosition() {
60
- if (typeof window === "undefined") return null;
61
- try {
62
- const raw = window.localStorage.getItem(TRIGGER_POSITION_STORAGE_KEY);
63
- if (!raw) return null;
64
- const parsed = JSON.parse(raw);
65
- if (typeof parsed.x === "number" && typeof parsed.y === "number") {
66
- return { x: parsed.x, y: parsed.y };
67
- }
68
- } catch {
69
- }
70
- return null;
52
+ if (typeof window === "undefined") return null;
53
+ try {
54
+ const raw = window.localStorage.getItem(TRIGGER_POSITION_STORAGE_KEY);
55
+ if (!raw) return null;
56
+ const parsed = JSON.parse(raw);
57
+ if (typeof parsed.x === "number" && typeof parsed.y === "number") return {
58
+ x: parsed.x,
59
+ y: parsed.y
60
+ };
61
+ } catch {}
62
+ return null;
71
63
  }
72
64
  function useDraggableTrigger() {
73
- const buttonRef = useRef(null);
74
- const [position, setPosition] = useState(readStoredTriggerPosition);
75
- const dragRef = useRef(null);
76
- const suppressClickRef = useRef(false);
77
- const onPointerDown = useCallback((event) => {
78
- const button = buttonRef.current;
79
- if (!button || event.button !== 0) return;
80
- suppressClickRef.current = false;
81
- const rect = button.getBoundingClientRect();
82
- dragRef.current = {
83
- pointerId: event.pointerId,
84
- startX: event.clientX,
85
- startY: event.clientY,
86
- offsetX: event.clientX - rect.left,
87
- offsetY: event.clientY - rect.top,
88
- moved: false
89
- };
90
- button.setPointerCapture(event.pointerId);
91
- }, []);
92
- const onPointerMove = useCallback((event) => {
93
- const drag = dragRef.current;
94
- const button = buttonRef.current;
95
- if (!drag || !button || drag.pointerId !== event.pointerId) return;
96
- if (!drag.moved && Math.hypot(event.clientX - drag.startX, event.clientY - drag.startY) < DRAG_THRESHOLD_PX) {
97
- return;
98
- }
99
- drag.moved = true;
100
- const maxX = window.innerWidth - button.offsetWidth - VIEWPORT_MARGIN_PX;
101
- const maxY = window.innerHeight - button.offsetHeight - VIEWPORT_MARGIN_PX;
102
- setPosition({
103
- x: Math.max(VIEWPORT_MARGIN_PX, Math.min(event.clientX - drag.offsetX, maxX)),
104
- y: Math.max(VIEWPORT_MARGIN_PX, Math.min(event.clientY - drag.offsetY, maxY))
105
- });
106
- }, []);
107
- const endDrag = useCallback((event) => {
108
- const drag = dragRef.current;
109
- if (!drag || drag.pointerId !== event.pointerId) return;
110
- dragRef.current = null;
111
- buttonRef.current?.releasePointerCapture(event.pointerId);
112
- if (!drag.moved) return;
113
- suppressClickRef.current = true;
114
- setPosition((current) => {
115
- if (current && typeof window !== "undefined") {
116
- try {
117
- window.localStorage.setItem(TRIGGER_POSITION_STORAGE_KEY, JSON.stringify(current));
118
- } catch {
119
- }
120
- }
121
- return current;
122
- });
123
- }, []);
124
- const consumeDragClick = useCallback(() => {
125
- if (!suppressClickRef.current) return false;
126
- suppressClickRef.current = false;
127
- return true;
128
- }, []);
129
- const positionStyle = position ? { left: position.x, top: position.y, right: "auto", bottom: "auto" } : {};
130
- return {
131
- buttonRef,
132
- positionStyle,
133
- triggerHandlers: { onPointerDown, onPointerMove, onPointerUp: endDrag, onPointerCancel: endDrag },
134
- consumeDragClick
135
- };
65
+ const buttonRef = useRef(null);
66
+ const [position, setPosition] = useState(readStoredTriggerPosition);
67
+ const dragRef = useRef(null);
68
+ const suppressClickRef = useRef(false);
69
+ const onPointerDown = useCallback((event) => {
70
+ const button = buttonRef.current;
71
+ if (!button || event.button !== 0) return;
72
+ suppressClickRef.current = false;
73
+ const rect = button.getBoundingClientRect();
74
+ dragRef.current = {
75
+ pointerId: event.pointerId,
76
+ startX: event.clientX,
77
+ startY: event.clientY,
78
+ offsetX: event.clientX - rect.left,
79
+ offsetY: event.clientY - rect.top,
80
+ moved: false
81
+ };
82
+ button.setPointerCapture(event.pointerId);
83
+ }, []);
84
+ const onPointerMove = useCallback((event) => {
85
+ const drag = dragRef.current;
86
+ const button = buttonRef.current;
87
+ if (!drag || !button || drag.pointerId !== event.pointerId) return;
88
+ if (!drag.moved && Math.hypot(event.clientX - drag.startX, event.clientY - drag.startY) < DRAG_THRESHOLD_PX) return;
89
+ drag.moved = true;
90
+ const maxX = window.innerWidth - button.offsetWidth - VIEWPORT_MARGIN_PX;
91
+ const maxY = window.innerHeight - button.offsetHeight - VIEWPORT_MARGIN_PX;
92
+ setPosition({
93
+ x: Math.max(VIEWPORT_MARGIN_PX, Math.min(event.clientX - drag.offsetX, maxX)),
94
+ y: Math.max(VIEWPORT_MARGIN_PX, Math.min(event.clientY - drag.offsetY, maxY))
95
+ });
96
+ }, []);
97
+ const endDrag = useCallback((event) => {
98
+ const drag = dragRef.current;
99
+ if (!drag || drag.pointerId !== event.pointerId) return;
100
+ dragRef.current = null;
101
+ buttonRef.current?.releasePointerCapture(event.pointerId);
102
+ if (!drag.moved) return;
103
+ suppressClickRef.current = true;
104
+ setPosition((current) => {
105
+ if (current && typeof window !== "undefined") try {
106
+ window.localStorage.setItem(TRIGGER_POSITION_STORAGE_KEY, JSON.stringify(current));
107
+ } catch {}
108
+ return current;
109
+ });
110
+ }, []);
111
+ const consumeDragClick = useCallback(() => {
112
+ if (!suppressClickRef.current) return false;
113
+ suppressClickRef.current = false;
114
+ return true;
115
+ }, []);
116
+ return {
117
+ buttonRef,
118
+ positionStyle: position ? {
119
+ left: position.x,
120
+ top: position.y,
121
+ right: "auto",
122
+ bottom: "auto"
123
+ } : {},
124
+ triggerHandlers: {
125
+ onPointerDown,
126
+ onPointerMove,
127
+ onPointerUp: endDrag,
128
+ onPointerCancel: endDrag
129
+ },
130
+ consumeDragClick
131
+ };
136
132
  }
137
133
  function SQLiteSyncDevtools({ className }) {
138
- const registry = getOrCreateSQLiteSyncDevtoolsRegistry();
139
- const snapshot = useSyncExternalStore(registry.subscribe, registry.getSnapshot, getEmptySnapshot);
140
- const instances = snapshot.instances;
141
- const { buttonRef, positionStyle, triggerHandlers, consumeDragClick } = useDraggableTrigger();
142
- const [isOpen, setIsOpen] = useState(false);
143
- const [activeTab, setActiveTab] = useState("overview");
144
- const [selectedInstanceId, setSelectedInstanceId] = useState("");
145
- const [queryTarget, setQueryTarget] = useState("memory");
146
- const [query, setQuery] = useState("");
147
- const [queryState, setQueryState] = useState({
148
- status: "idle"
149
- });
150
- useEffect(() => {
151
- if (!isOpen) return;
152
- const onKeyDown = (event) => {
153
- if (event.key === "Escape") {
154
- setIsOpen(false);
155
- }
156
- };
157
- window.addEventListener("keydown", onKeyDown);
158
- return () => {
159
- window.removeEventListener("keydown", onKeyDown);
160
- };
161
- }, [isOpen]);
162
- useEffect(() => {
163
- if (instances.length === 0) {
164
- setSelectedInstanceId("");
165
- return;
166
- }
167
- if (instances.some((instance) => instance.instanceId === selectedInstanceId)) {
168
- return;
169
- }
170
- setSelectedInstanceId(instances[0]?.instanceId ?? "");
171
- }, [instances, selectedInstanceId]);
172
- const dbIdCounts = useMemo(() => {
173
- const counts = /* @__PURE__ */ new Map();
174
- for (const instance of instances) {
175
- counts.set(instance.dbId, (counts.get(instance.dbId) ?? 0) + 1);
176
- }
177
- return counts;
178
- }, [instances]);
179
- const selectedInstance = useMemo(() => {
180
- return instances.find((instance) => instance.instanceId === selectedInstanceId) ?? null;
181
- }, [instances, selectedInstanceId]);
182
- const canRunQuery = selectedInstance !== null && query.trim().length > 0 && queryState.status !== "running";
183
- const runQuery = async () => {
184
- if (!selectedInstance) return;
185
- let normalizedQuery = query.trim();
186
- try {
187
- normalizedQuery = normalizeSingleStatement(query);
188
- const statementKind = getStatementKind(normalizedQuery);
189
- if (queryTarget === "worker") {
190
- if (!isWorkerReadOnlyStatement(statementKind)) {
191
- throw new Error("Worker DB devtools only allows read-only SQL: SELECT, PRAGMA.");
192
- }
193
- } else {
194
- const touchedTables = selectedInstance.instance._internal.getMemoryQueryTables(normalizedQuery);
195
- const writtenTables = touchedTables.filter((table) => table.isWrite).map((table) => table.name);
196
- const allowedTables = new Set(selectedInstance.instance._internal.crdtTableNames);
197
- const invalidTables = writtenTables.filter((table) => !allowedTables.has(table));
198
- if (invalidTables.length > 0) {
199
- throw new Error(
200
- `Memory DB writes are only allowed for CRDT tables. Rejected tables: ${invalidTables.join(", ")}`
201
- );
202
- }
203
- }
204
- setQueryState({ status: "running" });
205
- const startedAt = performance.now();
206
- const result = queryTarget === "memory" ? selectedInstance.instance.db.execute(normalizedQuery) : await selectedInstance.instance._internal.executeAsync({
207
- sql: normalizedQuery,
208
- parameters: []
209
- });
210
- setQueryState({
211
- status: "success",
212
- output: {
213
- target: queryTarget,
214
- sql: normalizedQuery,
215
- rowCount: result.rows.length,
216
- durationMs: Number((performance.now() - startedAt).toFixed(2)),
217
- rows: result.rows
218
- }
219
- });
220
- } catch (error) {
221
- setQueryState({
222
- status: "error",
223
- error: {
224
- target: queryTarget,
225
- sql: normalizedQuery,
226
- message: error instanceof Error ? error.message : String(error)
227
- }
228
- });
229
- }
230
- };
231
- return /* @__PURE__ */ jsxs(Fragment, { children: [
232
- /* @__PURE__ */ jsx("div", { style: floatingRootStyles, children: /* @__PURE__ */ jsxs(
233
- "button",
234
- {
235
- ref: buttonRef,
236
- type: "button",
237
- style: { ...triggerButtonStyles, ...positionStyle },
238
- onClick: () => {
239
- if (consumeDragClick()) return;
240
- setIsOpen(true);
241
- },
242
- title: "SQLite Sync Devtools",
243
- ...triggerHandlers,
244
- children: [
245
- /* @__PURE__ */ jsx("span", { style: triggerIconStyles, children: "\u25C8" }),
246
- /* @__PURE__ */ jsx("span", { style: triggerCountStyles, children: instances.length })
247
- ]
248
- }
249
- ) }),
250
- isOpen ? /* @__PURE__ */ jsx("div", { style: overlayStyles, onClick: () => setIsOpen(false), children: /* @__PURE__ */ jsxs(
251
- "section",
252
- {
253
- className,
254
- role: "dialog",
255
- "aria-modal": "true",
256
- "aria-label": "SQLite Sync devtools",
257
- style: dialogStyles,
258
- onClick: (event) => event.stopPropagation(),
259
- children: [
260
- /* @__PURE__ */ jsxs("div", { style: headerStyles, children: [
261
- /* @__PURE__ */ jsxs("div", { style: headerLeftStyles, children: [
262
- /* @__PURE__ */ jsx("span", { style: headerLogoStyles, children: "\u25C8" }),
263
- /* @__PURE__ */ jsxs("div", { children: [
264
- /* @__PURE__ */ jsx("div", { style: eyebrowStyles, children: "sqlite-sync" }),
265
- /* @__PURE__ */ jsx("h2", { style: titleStyles, children: "Devtools" })
266
- ] })
267
- ] }),
268
- /* @__PURE__ */ jsxs("div", { style: headerRightStyles, children: [
269
- instances.length > 0 && /* @__PURE__ */ jsxs("label", { style: instancePickerLabelStyles, children: [
270
- /* @__PURE__ */ jsx("span", { style: instancePickerTextStyles, children: "DB" }),
271
- /* @__PURE__ */ jsx(
272
- "select",
273
- {
274
- value: selectedInstanceId,
275
- onChange: (event) => setSelectedInstanceId(event.target.value),
276
- style: instancePickerSelectStyles,
277
- children: instances.map((instance) => /* @__PURE__ */ jsx("option", { value: instance.instanceId, children: formatInstanceLabel(instance.dbId, instance.instanceId, dbIdCounts.get(instance.dbId) ?? 0) }, instance.instanceId))
278
- }
279
- )
280
- ] }),
281
- /* @__PURE__ */ jsxs("span", { style: instanceCountBadgeStyles, children: [
282
- instances.length,
283
- " instance",
284
- instances.length !== 1 ? "s" : ""
285
- ] }),
286
- /* @__PURE__ */ jsx("button", { type: "button", style: closeButtonStyles, onClick: () => setIsOpen(false), "aria-label": "Close", children: "\u2715" })
287
- ] })
288
- ] }),
289
- instances.length === 0 ? /* @__PURE__ */ jsxs("div", { style: emptyStateStyles, children: [
290
- /* @__PURE__ */ jsx("div", { style: emptyStateIconStyles, children: "\u25C8" }),
291
- /* @__PURE__ */ jsx("p", { style: emptyStateTextStyles, children: "No SQLite Sync database instances registered." }),
292
- /* @__PURE__ */ jsxs("p", { style: emptyStateSubtextStyles, children: [
293
- "Call ",
294
- /* @__PURE__ */ jsx("code", { style: inlineCodeStyles, children: "registerDevtools(db)" }),
295
- " in your app to get started."
296
- ] })
297
- ] }) : /* @__PURE__ */ jsxs("div", { style: contentLayoutStyles, children: [
298
- /* @__PURE__ */ jsxs("aside", { style: sidebarStyles, children: [
299
- /* @__PURE__ */ jsxs("nav", { style: navStyles, children: [
300
- /* @__PURE__ */ jsxs(
301
- "button",
302
- {
303
- type: "button",
304
- style: getTabButtonStyles(activeTab === "overview"),
305
- onClick: () => setActiveTab("overview"),
306
- children: [
307
- /* @__PURE__ */ jsx("span", { style: navIconStyles, children: "\u25A6" }),
308
- "Overview"
309
- ]
310
- }
311
- ),
312
- /* @__PURE__ */ jsxs(
313
- "button",
314
- {
315
- type: "button",
316
- style: getTabButtonStyles(activeTab === "schema"),
317
- onClick: () => setActiveTab("schema"),
318
- children: [
319
- /* @__PURE__ */ jsx("span", { style: navIconStyles, children: "\u2B21" }),
320
- "Schema"
321
- ]
322
- }
323
- ),
324
- /* @__PURE__ */ jsxs(
325
- "button",
326
- {
327
- type: "button",
328
- style: getTabButtonStyles(activeTab === "live-queries"),
329
- onClick: () => setActiveTab("live-queries"),
330
- children: [
331
- /* @__PURE__ */ jsx("span", { style: navIconStyles, children: "\u25C9" }),
332
- "Live Queries"
333
- ]
334
- }
335
- ),
336
- /* @__PURE__ */ jsxs(
337
- "button",
338
- {
339
- type: "button",
340
- style: getTabButtonStyles(activeTab === "event-log"),
341
- onClick: () => setActiveTab("event-log"),
342
- children: [
343
- /* @__PURE__ */ jsx("span", { style: navIconStyles, children: "\u2261" }),
344
- "Event Log"
345
- ]
346
- }
347
- ),
348
- /* @__PURE__ */ jsxs(
349
- "button",
350
- {
351
- type: "button",
352
- style: getTabButtonStyles(activeTab === "query-runner"),
353
- onClick: () => setActiveTab("query-runner"),
354
- children: [
355
- /* @__PURE__ */ jsx("span", { style: navIconStyles, children: "\u25B6" }),
356
- "Query Runner"
357
- ]
358
- }
359
- )
360
- ] }),
361
- selectedInstance && /* @__PURE__ */ jsxs("div", { style: sidebarInfoStyles, children: [
362
- /* @__PURE__ */ jsx("div", { style: sidebarInfoLabelStyles, children: "Active instance" }),
363
- /* @__PURE__ */ jsx("div", { style: sidebarInfoValueStyles, children: formatInstanceLabel(
364
- selectedInstance.dbId,
365
- selectedInstance.instanceId,
366
- dbIdCounts.get(selectedInstance.dbId) ?? 0
367
- ) }),
368
- /* @__PURE__ */ jsxs("div", { style: sidebarInfoSubStyles, children: [
369
- "id: ",
370
- selectedInstance.instanceId.slice(0, 12),
371
- "\u2026"
372
- ] })
373
- ] })
374
- ] }),
375
- /* @__PURE__ */ jsx("div", { style: mainPaneStyles, children: activeTab === "overview" ? /* @__PURE__ */ jsx(OverviewTab, { selectedInstance, dbIdCounts }) : activeTab === "schema" ? /* @__PURE__ */ jsx(SchemaTab, { selectedInstance }) : activeTab === "live-queries" ? /* @__PURE__ */ jsx(LiveQueriesTab, { selectedInstance }) : activeTab === "event-log" ? /* @__PURE__ */ jsx(EventLogTab, { selectedInstance }) : /* @__PURE__ */ jsx(
376
- QueryRunnerTab,
377
- {
378
- selectedInstance,
379
- queryTarget,
380
- setQueryTarget,
381
- query,
382
- setQuery,
383
- queryState,
384
- canRunQuery,
385
- runQuery
386
- }
387
- ) })
388
- ] })
389
- ]
390
- }
391
- ) }) : null
392
- ] });
134
+ const registry = getOrCreateSQLiteSyncDevtoolsRegistry();
135
+ const instances = useSyncExternalStore(registry.subscribe, registry.getSnapshot, getEmptySnapshot).instances;
136
+ const { buttonRef, positionStyle, triggerHandlers, consumeDragClick } = useDraggableTrigger();
137
+ const [isOpen, setIsOpen] = useState(false);
138
+ const [activeTab, setActiveTab] = useState("overview");
139
+ const [selectedInstanceId, setSelectedInstanceId] = useState("");
140
+ const [queryTarget, setQueryTarget] = useState("memory");
141
+ const [query, setQuery] = useState("");
142
+ const [queryState, setQueryState] = useState({ status: "idle" });
143
+ useEffect(() => {
144
+ if (!isOpen) return;
145
+ const onKeyDown = (event) => {
146
+ if (event.key === "Escape") setIsOpen(false);
147
+ };
148
+ window.addEventListener("keydown", onKeyDown);
149
+ return () => {
150
+ window.removeEventListener("keydown", onKeyDown);
151
+ };
152
+ }, [isOpen]);
153
+ useEffect(() => {
154
+ if (instances.length === 0) {
155
+ setSelectedInstanceId("");
156
+ return;
157
+ }
158
+ if (instances.some((instance) => instance.instanceId === selectedInstanceId)) return;
159
+ setSelectedInstanceId(instances[0]?.instanceId ?? "");
160
+ }, [instances, selectedInstanceId]);
161
+ const dbIdCounts = useMemo(() => {
162
+ const counts = /* @__PURE__ */ new Map();
163
+ for (const instance of instances) counts.set(instance.dbId, (counts.get(instance.dbId) ?? 0) + 1);
164
+ return counts;
165
+ }, [instances]);
166
+ const selectedInstance = useMemo(() => {
167
+ return instances.find((instance) => instance.instanceId === selectedInstanceId) ?? null;
168
+ }, [instances, selectedInstanceId]);
169
+ const canRunQuery = selectedInstance !== null && query.trim().length > 0 && queryState.status !== "running";
170
+ const runQuery = async () => {
171
+ if (!selectedInstance) return;
172
+ let normalizedQuery = query.trim();
173
+ try {
174
+ normalizedQuery = normalizeSingleStatement(query);
175
+ const statementKind = getStatementKind(normalizedQuery);
176
+ if (queryTarget === "worker") {
177
+ if (!isWorkerReadOnlyStatement(statementKind)) throw new Error("Worker DB devtools only allows read-only SQL: SELECT, PRAGMA.");
178
+ } else {
179
+ const writtenTables = selectedInstance.instance._internal.getMemoryQueryTables(normalizedQuery).filter((table) => table.isWrite).map((table) => table.name);
180
+ const allowedTables = new Set(selectedInstance.instance._internal.crdtTableNames);
181
+ const invalidTables = writtenTables.filter((table) => !allowedTables.has(table));
182
+ if (invalidTables.length > 0) throw new Error(`Memory DB writes are only allowed for CRDT tables. Rejected tables: ${invalidTables.join(", ")}`);
183
+ }
184
+ setQueryState({ status: "running" });
185
+ const startedAt = performance.now();
186
+ const result = queryTarget === "memory" ? selectedInstance.instance.db.execute(normalizedQuery) : await selectedInstance.instance._internal.executeAsync({
187
+ sql: normalizedQuery,
188
+ parameters: []
189
+ });
190
+ setQueryState({
191
+ status: "success",
192
+ output: {
193
+ target: queryTarget,
194
+ sql: normalizedQuery,
195
+ rowCount: result.rows.length,
196
+ durationMs: Number((performance.now() - startedAt).toFixed(2)),
197
+ rows: result.rows
198
+ }
199
+ });
200
+ } catch (error) {
201
+ setQueryState({
202
+ status: "error",
203
+ error: {
204
+ target: queryTarget,
205
+ sql: normalizedQuery,
206
+ message: error instanceof Error ? error.message : String(error)
207
+ }
208
+ });
209
+ }
210
+ };
211
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
212
+ style: floatingRootStyles,
213
+ children: /* @__PURE__ */ jsxs("button", {
214
+ ref: buttonRef,
215
+ type: "button",
216
+ style: {
217
+ ...triggerButtonStyles,
218
+ ...positionStyle
219
+ },
220
+ onClick: () => {
221
+ if (consumeDragClick()) return;
222
+ setIsOpen(true);
223
+ },
224
+ title: "SQLite Sync Devtools",
225
+ ...triggerHandlers,
226
+ children: [/* @__PURE__ */ jsx("span", {
227
+ style: triggerIconStyles,
228
+ children: "◈"
229
+ }), /* @__PURE__ */ jsx("span", {
230
+ style: triggerCountStyles,
231
+ children: instances.length
232
+ })]
233
+ })
234
+ }), isOpen ? /* @__PURE__ */ jsx("div", {
235
+ style: overlayStyles,
236
+ onClick: () => setIsOpen(false),
237
+ children: /* @__PURE__ */ jsxs("section", {
238
+ className,
239
+ role: "dialog",
240
+ "aria-modal": "true",
241
+ "aria-label": "SQLite Sync devtools",
242
+ style: dialogStyles,
243
+ onClick: (event) => event.stopPropagation(),
244
+ children: [/* @__PURE__ */ jsxs("div", {
245
+ style: headerStyles,
246
+ children: [/* @__PURE__ */ jsxs("div", {
247
+ style: headerLeftStyles,
248
+ children: [/* @__PURE__ */ jsx("span", {
249
+ style: headerLogoStyles,
250
+ children: "◈"
251
+ }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
252
+ style: eyebrowStyles,
253
+ children: "sqlite-sync"
254
+ }), /* @__PURE__ */ jsx("h2", {
255
+ style: titleStyles,
256
+ children: "Devtools"
257
+ })] })]
258
+ }), /* @__PURE__ */ jsxs("div", {
259
+ style: headerRightStyles,
260
+ children: [
261
+ instances.length > 0 && /* @__PURE__ */ jsxs("label", {
262
+ style: instancePickerLabelStyles,
263
+ children: [/* @__PURE__ */ jsx("span", {
264
+ style: instancePickerTextStyles,
265
+ children: "DB"
266
+ }), /* @__PURE__ */ jsx("select", {
267
+ value: selectedInstanceId,
268
+ onChange: (event) => setSelectedInstanceId(event.target.value),
269
+ style: instancePickerSelectStyles,
270
+ children: instances.map((instance) => /* @__PURE__ */ jsx("option", {
271
+ value: instance.instanceId,
272
+ children: formatInstanceLabel(instance.dbId, instance.instanceId, dbIdCounts.get(instance.dbId) ?? 0)
273
+ }, instance.instanceId))
274
+ })]
275
+ }),
276
+ /* @__PURE__ */ jsxs("span", {
277
+ style: instanceCountBadgeStyles,
278
+ children: [
279
+ instances.length,
280
+ " instance",
281
+ instances.length !== 1 ? "s" : ""
282
+ ]
283
+ }),
284
+ /* @__PURE__ */ jsx("button", {
285
+ type: "button",
286
+ style: closeButtonStyles,
287
+ onClick: () => setIsOpen(false),
288
+ "aria-label": "Close",
289
+ children: "✕"
290
+ })
291
+ ]
292
+ })]
293
+ }), instances.length === 0 ? /* @__PURE__ */ jsxs("div", {
294
+ style: emptyStateStyles,
295
+ children: [
296
+ /* @__PURE__ */ jsx("div", {
297
+ style: emptyStateIconStyles,
298
+ children: "◈"
299
+ }),
300
+ /* @__PURE__ */ jsx("p", {
301
+ style: emptyStateTextStyles,
302
+ children: "No SQLite Sync database instances registered."
303
+ }),
304
+ /* @__PURE__ */ jsxs("p", {
305
+ style: emptyStateSubtextStyles,
306
+ children: [
307
+ "Call ",
308
+ /* @__PURE__ */ jsx("code", {
309
+ style: inlineCodeStyles,
310
+ children: "registerDevtools(db)"
311
+ }),
312
+ " in your app to get started."
313
+ ]
314
+ })
315
+ ]
316
+ }) : /* @__PURE__ */ jsxs("div", {
317
+ style: contentLayoutStyles,
318
+ children: [/* @__PURE__ */ jsxs("aside", {
319
+ style: sidebarStyles,
320
+ children: [/* @__PURE__ */ jsxs("nav", {
321
+ style: navStyles,
322
+ children: [
323
+ /* @__PURE__ */ jsxs("button", {
324
+ type: "button",
325
+ style: getTabButtonStyles(activeTab === "overview"),
326
+ onClick: () => setActiveTab("overview"),
327
+ children: [/* @__PURE__ */ jsx("span", {
328
+ style: navIconStyles,
329
+ children: "▦"
330
+ }), "Overview"]
331
+ }),
332
+ /* @__PURE__ */ jsxs("button", {
333
+ type: "button",
334
+ style: getTabButtonStyles(activeTab === "schema"),
335
+ onClick: () => setActiveTab("schema"),
336
+ children: [/* @__PURE__ */ jsx("span", {
337
+ style: navIconStyles,
338
+ children: "⬡"
339
+ }), "Schema"]
340
+ }),
341
+ /* @__PURE__ */ jsxs("button", {
342
+ type: "button",
343
+ style: getTabButtonStyles(activeTab === "live-queries"),
344
+ onClick: () => setActiveTab("live-queries"),
345
+ children: [/* @__PURE__ */ jsx("span", {
346
+ style: navIconStyles,
347
+ children: "◉"
348
+ }), "Live Queries"]
349
+ }),
350
+ /* @__PURE__ */ jsxs("button", {
351
+ type: "button",
352
+ style: getTabButtonStyles(activeTab === "event-log"),
353
+ onClick: () => setActiveTab("event-log"),
354
+ children: [/* @__PURE__ */ jsx("span", {
355
+ style: navIconStyles,
356
+ children: "≡"
357
+ }), "Event Log"]
358
+ }),
359
+ /* @__PURE__ */ jsxs("button", {
360
+ type: "button",
361
+ style: getTabButtonStyles(activeTab === "query-runner"),
362
+ onClick: () => setActiveTab("query-runner"),
363
+ children: [/* @__PURE__ */ jsx("span", {
364
+ style: navIconStyles,
365
+ children: "▶"
366
+ }), "Query Runner"]
367
+ })
368
+ ]
369
+ }), selectedInstance && /* @__PURE__ */ jsxs("div", {
370
+ style: sidebarInfoStyles,
371
+ children: [
372
+ /* @__PURE__ */ jsx("div", {
373
+ style: sidebarInfoLabelStyles,
374
+ children: "Active instance"
375
+ }),
376
+ /* @__PURE__ */ jsx("div", {
377
+ style: sidebarInfoValueStyles,
378
+ children: formatInstanceLabel(selectedInstance.dbId, selectedInstance.instanceId, dbIdCounts.get(selectedInstance.dbId) ?? 0)
379
+ }),
380
+ /* @__PURE__ */ jsxs("div", {
381
+ style: sidebarInfoSubStyles,
382
+ children: [
383
+ "id: ",
384
+ selectedInstance.instanceId.slice(0, 12),
385
+ "…"
386
+ ]
387
+ })
388
+ ]
389
+ })]
390
+ }), /* @__PURE__ */ jsx("div", {
391
+ style: mainPaneStyles,
392
+ children: activeTab === "overview" ? /* @__PURE__ */ jsx(OverviewTab, {
393
+ selectedInstance,
394
+ dbIdCounts
395
+ }) : activeTab === "schema" ? /* @__PURE__ */ jsx(SchemaTab, { selectedInstance }) : activeTab === "live-queries" ? /* @__PURE__ */ jsx(LiveQueriesTab, { selectedInstance }) : activeTab === "event-log" ? /* @__PURE__ */ jsx(EventLogTab, { selectedInstance }) : /* @__PURE__ */ jsx(QueryRunnerTab, {
396
+ selectedInstance,
397
+ queryTarget,
398
+ setQueryTarget,
399
+ query,
400
+ setQuery,
401
+ queryState,
402
+ canRunQuery,
403
+ runQuery
404
+ })
405
+ })]
406
+ })]
407
+ })
408
+ }) : null] });
393
409
  }
394
- var EVENT_HLC_ACCUMULATOR_KV_KEY = "crdt.consistency.event_hlc_sum.v2";
395
- var EVENT_HLC_ACCUMULATOR_QUERY = `SELECT value FROM "worker"."kv" WHERE key = '${EVENT_HLC_ACCUMULATOR_KV_KEY}'`;
396
- function OverviewTab({
397
- selectedInstance,
398
- dbIdCounts
399
- }) {
400
- const [eventHlcAccumulator, setEventHlcAccumulator] = useState(null);
401
- const [accumulatorError, setAccumulatorError] = useState(null);
402
- const [isAccumulatorLoading, setIsAccumulatorLoading] = useState(false);
403
- const refreshEventHlcAccumulator = useCallback(async () => {
404
- if (!selectedInstance) return;
405
- setIsAccumulatorLoading(true);
406
- setAccumulatorError(null);
407
- try {
408
- const result = await selectedInstance.instance._internal.executeAsync({
409
- sql: EVENT_HLC_ACCUMULATOR_QUERY,
410
- parameters: []
411
- });
412
- const row = result.rows[0];
413
- setEventHlcAccumulator(row?.value ?? "");
414
- } catch (error) {
415
- setAccumulatorError(error instanceof Error ? error.message : String(error));
416
- setEventHlcAccumulator(null);
417
- } finally {
418
- setIsAccumulatorLoading(false);
419
- }
420
- }, [selectedInstance]);
421
- useEffect(() => {
422
- setEventHlcAccumulator(null);
423
- setAccumulatorError(null);
424
- void refreshEventHlcAccumulator();
425
- }, [refreshEventHlcAccumulator]);
426
- if (!selectedInstance) return null;
427
- const label = formatInstanceLabel(
428
- selectedInstance.dbId,
429
- selectedInstance.instanceId,
430
- dbIdCounts.get(selectedInstance.dbId) ?? 0
431
- );
432
- const crdtTables = selectedInstance.instance._internal.crdtTableNames;
433
- return /* @__PURE__ */ jsxs("div", { style: overviewLayoutStyles, children: [
434
- /* @__PURE__ */ jsxs("div", { style: overviewCardsRowStyles, children: [
435
- /* @__PURE__ */ jsxs("div", { style: overviewCardStyles, children: [
436
- /* @__PURE__ */ jsx("div", { style: overviewCardLabelStyles, children: "Database" }),
437
- /* @__PURE__ */ jsx("div", { style: overviewCardValueStyles, children: label })
438
- ] }),
439
- /* @__PURE__ */ jsxs("div", { style: overviewCardStyles, children: [
440
- /* @__PURE__ */ jsx("div", { style: overviewCardLabelStyles, children: "Instance ID" }),
441
- /* @__PURE__ */ jsxs("div", { style: { ...overviewCardValueStyles, fontFamily: "ui-monospace, monospace", fontSize: "0.78rem" }, children: [
442
- selectedInstance.instanceId.slice(0, 16),
443
- "\u2026"
444
- ] })
445
- ] }),
446
- /* @__PURE__ */ jsxs("div", { style: overviewCardStyles, children: [
447
- /* @__PURE__ */ jsx("div", { style: overviewCardLabelStyles, children: "CRDT Tables" }),
448
- /* @__PURE__ */ jsx("div", { style: overviewCardValueStyles, children: crdtTables.length })
449
- ] })
450
- ] }),
451
- /* @__PURE__ */ jsxs("div", { style: overviewSectionStyles, children: [
452
- /* @__PURE__ */ jsx("div", { style: overviewSectionTitleStyles, children: "CRDT Tables" }),
453
- crdtTables.length === 0 ? /* @__PURE__ */ jsx("div", { style: overviewEmptyStyles, children: "No CRDT tables registered." }) : /* @__PURE__ */ jsx("div", { style: crdtTableListStyles, children: [...crdtTables].map((name) => /* @__PURE__ */ jsxs("div", { style: crdtTableRowStyles, children: [
454
- /* @__PURE__ */ jsx("span", { style: crdtTableIconStyles, children: "\u25A6" }),
455
- /* @__PURE__ */ jsx("span", { style: crdtTableNameStyles, children: name })
456
- ] }, name)) })
457
- ] }),
458
- /* @__PURE__ */ jsxs("div", { style: overviewSectionStyles, children: [
459
- /* @__PURE__ */ jsxs("div", { style: overviewSectionHeaderStyles, children: [
460
- /* @__PURE__ */ jsx("div", { style: overviewSectionTitleStyles, children: "Event HLC accumulator" }),
461
- /* @__PURE__ */ jsxs(
462
- "button",
463
- {
464
- type: "button",
465
- style: overviewRefreshButtonStyles,
466
- disabled: isAccumulatorLoading,
467
- onClick: () => void refreshEventHlcAccumulator(),
468
- children: [
469
- isAccumulatorLoading ? "\u2026" : "\u21BB",
470
- " Refresh"
471
- ]
472
- }
473
- )
474
- ] }),
475
- /* @__PURE__ */ jsx("div", { style: overviewAccumulatorValueStyles, children: accumulatorError ? /* @__PURE__ */ jsx("span", { style: overviewAccumulatorErrorStyles, children: accumulatorError }) : isAccumulatorLoading && eventHlcAccumulator === null ? "Loading\u2026" : eventHlcAccumulator === "" ? /* @__PURE__ */ jsx("span", { style: overviewAccumulatorEmptyStyles, children: "(empty)" }) : eventHlcAccumulator })
476
- ] }),
477
- /* @__PURE__ */ jsxs("div", { style: overviewSectionStyles, children: [
478
- /* @__PURE__ */ jsx("div", { style: overviewSectionTitleStyles, children: "Write Permissions" }),
479
- /* @__PURE__ */ jsxs("div", { style: permissionRowStyles, children: [
480
- /* @__PURE__ */ jsx("span", { style: permissionIconStyles, children: "\u2713" }),
481
- /* @__PURE__ */ jsx("span", { style: permissionTextStyles, children: "Memory DB \u2014 CRDT tables only" })
482
- ] }),
483
- /* @__PURE__ */ jsxs("div", { style: permissionRowStyles, children: [
484
- /* @__PURE__ */ jsx("span", { style: { ...permissionIconStyles, color: "#f59e0b" }, children: "\u2298" }),
485
- /* @__PURE__ */ jsx("span", { style: permissionTextStyles, children: "Worker DB \u2014 read-only (SELECT, PRAGMA, EXPLAIN)" })
486
- ] })
487
- ] }),
488
- /* @__PURE__ */ jsx(
489
- DataSection,
490
- {
491
- dbId: selectedInstance.dbId,
492
- instance: selectedInstance.instance
493
- },
494
- selectedInstance.instanceId
495
- ),
496
- /* @__PURE__ */ jsx(ResetSection, { dbId: selectedInstance.dbId, instance: selectedInstance.instance })
497
- ] });
410
+ const EVENT_HLC_ACCUMULATOR_QUERY = `SELECT value FROM "worker"."kv" WHERE key = 'crdt.consistency.event_hlc_sum.v2'`;
411
+ function OverviewTab({ selectedInstance, dbIdCounts }) {
412
+ const [eventHlcAccumulator, setEventHlcAccumulator] = useState(null);
413
+ const [accumulatorError, setAccumulatorError] = useState(null);
414
+ const [isAccumulatorLoading, setIsAccumulatorLoading] = useState(false);
415
+ const refreshEventHlcAccumulator = useCallback(async () => {
416
+ if (!selectedInstance) return;
417
+ setIsAccumulatorLoading(true);
418
+ setAccumulatorError(null);
419
+ try {
420
+ const row = (await selectedInstance.instance._internal.executeAsync({
421
+ sql: EVENT_HLC_ACCUMULATOR_QUERY,
422
+ parameters: []
423
+ })).rows[0];
424
+ setEventHlcAccumulator(row?.value ?? "");
425
+ } catch (error) {
426
+ setAccumulatorError(error instanceof Error ? error.message : String(error));
427
+ setEventHlcAccumulator(null);
428
+ } finally {
429
+ setIsAccumulatorLoading(false);
430
+ }
431
+ }, [selectedInstance]);
432
+ useEffect(() => {
433
+ setEventHlcAccumulator(null);
434
+ setAccumulatorError(null);
435
+ refreshEventHlcAccumulator();
436
+ }, [refreshEventHlcAccumulator]);
437
+ if (!selectedInstance) return null;
438
+ const label = formatInstanceLabel(selectedInstance.dbId, selectedInstance.instanceId, dbIdCounts.get(selectedInstance.dbId) ?? 0);
439
+ const crdtTables = selectedInstance.instance._internal.crdtTableNames;
440
+ return /* @__PURE__ */ jsxs("div", {
441
+ style: overviewLayoutStyles,
442
+ children: [
443
+ /* @__PURE__ */ jsxs("div", {
444
+ style: overviewCardsRowStyles,
445
+ children: [
446
+ /* @__PURE__ */ jsxs("div", {
447
+ style: overviewCardStyles,
448
+ children: [/* @__PURE__ */ jsx("div", {
449
+ style: overviewCardLabelStyles,
450
+ children: "Database"
451
+ }), /* @__PURE__ */ jsx("div", {
452
+ style: overviewCardValueStyles,
453
+ children: label
454
+ })]
455
+ }),
456
+ /* @__PURE__ */ jsxs("div", {
457
+ style: overviewCardStyles,
458
+ children: [/* @__PURE__ */ jsx("div", {
459
+ style: overviewCardLabelStyles,
460
+ children: "Instance ID"
461
+ }), /* @__PURE__ */ jsxs("div", {
462
+ style: {
463
+ ...overviewCardValueStyles,
464
+ fontFamily: "ui-monospace, monospace",
465
+ fontSize: "0.78rem"
466
+ },
467
+ children: [selectedInstance.instanceId.slice(0, 16), "…"]
468
+ })]
469
+ }),
470
+ /* @__PURE__ */ jsxs("div", {
471
+ style: overviewCardStyles,
472
+ children: [/* @__PURE__ */ jsx("div", {
473
+ style: overviewCardLabelStyles,
474
+ children: "CRDT Tables"
475
+ }), /* @__PURE__ */ jsx("div", {
476
+ style: overviewCardValueStyles,
477
+ children: crdtTables.length
478
+ })]
479
+ })
480
+ ]
481
+ }),
482
+ /* @__PURE__ */ jsxs("div", {
483
+ style: overviewSectionStyles,
484
+ children: [/* @__PURE__ */ jsx("div", {
485
+ style: overviewSectionTitleStyles,
486
+ children: "CRDT Tables"
487
+ }), crdtTables.length === 0 ? /* @__PURE__ */ jsx("div", {
488
+ style: overviewEmptyStyles,
489
+ children: "No CRDT tables registered."
490
+ }) : /* @__PURE__ */ jsx("div", {
491
+ style: crdtTableListStyles,
492
+ children: [...crdtTables].map((name) => /* @__PURE__ */ jsxs("div", {
493
+ style: crdtTableRowStyles,
494
+ children: [/* @__PURE__ */ jsx("span", {
495
+ style: crdtTableIconStyles,
496
+ children: "▦"
497
+ }), /* @__PURE__ */ jsx("span", {
498
+ style: crdtTableNameStyles,
499
+ children: name
500
+ })]
501
+ }, name))
502
+ })]
503
+ }),
504
+ /* @__PURE__ */ jsxs("div", {
505
+ style: overviewSectionStyles,
506
+ children: [/* @__PURE__ */ jsxs("div", {
507
+ style: overviewSectionHeaderStyles,
508
+ children: [/* @__PURE__ */ jsx("div", {
509
+ style: overviewSectionTitleStyles,
510
+ children: "Event HLC accumulator"
511
+ }), /* @__PURE__ */ jsxs("button", {
512
+ type: "button",
513
+ style: overviewRefreshButtonStyles,
514
+ disabled: isAccumulatorLoading,
515
+ onClick: () => void refreshEventHlcAccumulator(),
516
+ children: [isAccumulatorLoading ? "…" : "↻", " Refresh"]
517
+ })]
518
+ }), /* @__PURE__ */ jsx("div", {
519
+ style: overviewAccumulatorValueStyles,
520
+ children: accumulatorError ? /* @__PURE__ */ jsx("span", {
521
+ style: overviewAccumulatorErrorStyles,
522
+ children: accumulatorError
523
+ }) : isAccumulatorLoading && eventHlcAccumulator === null ? "Loading…" : eventHlcAccumulator === "" ? /* @__PURE__ */ jsx("span", {
524
+ style: overviewAccumulatorEmptyStyles,
525
+ children: "(empty)"
526
+ }) : eventHlcAccumulator
527
+ })]
528
+ }),
529
+ /* @__PURE__ */ jsxs("div", {
530
+ style: overviewSectionStyles,
531
+ children: [
532
+ /* @__PURE__ */ jsx("div", {
533
+ style: overviewSectionTitleStyles,
534
+ children: "Write Permissions"
535
+ }),
536
+ /* @__PURE__ */ jsxs("div", {
537
+ style: permissionRowStyles,
538
+ children: [/* @__PURE__ */ jsx("span", {
539
+ style: permissionIconStyles,
540
+ children: "✓"
541
+ }), /* @__PURE__ */ jsx("span", {
542
+ style: permissionTextStyles,
543
+ children: "Memory DB — CRDT tables only"
544
+ })]
545
+ }),
546
+ /* @__PURE__ */ jsxs("div", {
547
+ style: permissionRowStyles,
548
+ children: [/* @__PURE__ */ jsx("span", {
549
+ style: {
550
+ ...permissionIconStyles,
551
+ color: "#f59e0b"
552
+ },
553
+ children: "⊘"
554
+ }), /* @__PURE__ */ jsx("span", {
555
+ style: permissionTextStyles,
556
+ children: "Worker DB — read-only (SELECT, PRAGMA, EXPLAIN)"
557
+ })]
558
+ })
559
+ ]
560
+ }),
561
+ /* @__PURE__ */ jsx(DataSection, {
562
+ dbId: selectedInstance.dbId,
563
+ instance: selectedInstance.instance
564
+ }, selectedInstance.instanceId),
565
+ /* @__PURE__ */ jsx(ResetSection, {
566
+ dbId: selectedInstance.dbId,
567
+ instance: selectedInstance.instance
568
+ })
569
+ ]
570
+ });
498
571
  }
499
572
  function DataSection({ dbId, instance }) {
500
- const fileInputRef = useRef(null);
501
- const [isImporting, setIsImporting] = useState(false);
502
- const [status, setStatus] = useState(null);
503
- const handleExport = () => {
504
- try {
505
- const data = instance.exportData();
506
- const json = JSON.stringify(data, null, 2);
507
- const blob = new Blob([json], { type: "application/json" });
508
- const url = URL.createObjectURL(blob);
509
- const anchor = document.createElement("a");
510
- anchor.href = url;
511
- anchor.download = `${dbId}-${data.exportedAt.replace(/[:.]/g, "-")}.json`;
512
- anchor.click();
513
- URL.revokeObjectURL(url);
514
- const rowCount = Object.values(data.tables).reduce((sum, rows) => sum + rows.length, 0);
515
- setStatus({ kind: "success", message: `Exported ${rowCount} row${rowCount === 1 ? "" : "s"}.` });
516
- } catch (error) {
517
- setStatus({ kind: "error", message: error instanceof Error ? error.message : String(error) });
518
- }
519
- };
520
- const handleImportFile = async (file) => {
521
- setIsImporting(true);
522
- setStatus(null);
523
- try {
524
- const data = JSON.parse(await file.text());
525
- const result = await instance.importData(data);
526
- setStatus({ kind: "success", message: `Imported ${result.imported} row${result.imported === 1 ? "" : "s"}.` });
527
- } catch (error) {
528
- setStatus({ kind: "error", message: error instanceof Error ? error.message : String(error) });
529
- } finally {
530
- setIsImporting(false);
531
- }
532
- };
533
- return /* @__PURE__ */ jsxs("div", { style: overviewSectionStyles, children: [
534
- /* @__PURE__ */ jsx("div", { style: overviewSectionTitleStyles, children: "Backup & Restore" }),
535
- /* @__PURE__ */ jsx("div", { style: dangerZoneDescStyles, children: "Export the active rows of every CRDT table as JSON, or import a dump to seed/restore. Import overwrites rows with matching ids and is propagated to the server." }),
536
- /* @__PURE__ */ jsxs("div", { style: dataActionsStyles, children: [
537
- /* @__PURE__ */ jsx("button", { type: "button", style: dataButtonStyles, onClick: handleExport, children: "\u2193 Export JSON" }),
538
- /* @__PURE__ */ jsx(
539
- "button",
540
- {
541
- type: "button",
542
- style: dataButtonStyles,
543
- disabled: isImporting,
544
- onClick: () => fileInputRef.current?.click(),
545
- children: isImporting ? "Importing\u2026" : "\u2191 Import JSON"
546
- }
547
- ),
548
- /* @__PURE__ */ jsx(
549
- "input",
550
- {
551
- ref: fileInputRef,
552
- type: "file",
553
- accept: "application/json,.json",
554
- style: { display: "none" },
555
- onChange: (event) => {
556
- const file = event.target.files?.[0];
557
- event.target.value = "";
558
- if (file) void handleImportFile(file);
559
- }
560
- }
561
- )
562
- ] }),
563
- status && /* @__PURE__ */ jsx("div", { style: status.kind === "error" ? dataStatusErrorStyles : dataStatusSuccessStyles, children: status.message })
564
- ] });
573
+ const fileInputRef = useRef(null);
574
+ const [isImporting, setIsImporting] = useState(false);
575
+ const [status, setStatus] = useState(null);
576
+ const handleExport = () => {
577
+ try {
578
+ const data = instance.exportData();
579
+ const json = JSON.stringify(data, null, 2);
580
+ const blob = new Blob([json], { type: "application/json" });
581
+ const url = URL.createObjectURL(blob);
582
+ const anchor = document.createElement("a");
583
+ anchor.href = url;
584
+ anchor.download = `${dbId}-${data.exportedAt.replace(/[:.]/g, "-")}.json`;
585
+ anchor.click();
586
+ URL.revokeObjectURL(url);
587
+ const rowCount = Object.values(data.tables).reduce((sum, rows) => sum + rows.length, 0);
588
+ setStatus({
589
+ kind: "success",
590
+ message: `Exported ${rowCount} row${rowCount === 1 ? "" : "s"}.`
591
+ });
592
+ } catch (error) {
593
+ setStatus({
594
+ kind: "error",
595
+ message: error instanceof Error ? error.message : String(error)
596
+ });
597
+ }
598
+ };
599
+ const handleImportFile = async (file) => {
600
+ setIsImporting(true);
601
+ setStatus(null);
602
+ try {
603
+ const data = JSON.parse(await file.text());
604
+ const result = await instance.importData(data);
605
+ setStatus({
606
+ kind: "success",
607
+ message: `Imported ${result.imported} row${result.imported === 1 ? "" : "s"}.`
608
+ });
609
+ } catch (error) {
610
+ setStatus({
611
+ kind: "error",
612
+ message: error instanceof Error ? error.message : String(error)
613
+ });
614
+ } finally {
615
+ setIsImporting(false);
616
+ }
617
+ };
618
+ return /* @__PURE__ */ jsxs("div", {
619
+ style: overviewSectionStyles,
620
+ children: [
621
+ /* @__PURE__ */ jsx("div", {
622
+ style: overviewSectionTitleStyles,
623
+ children: "Backup & Restore"
624
+ }),
625
+ /* @__PURE__ */ jsx("div", {
626
+ style: dangerZoneDescStyles,
627
+ children: "Export the active rows of every CRDT table as JSON, or import a dump to seed/restore. Import overwrites rows with matching ids and is propagated to the server."
628
+ }),
629
+ /* @__PURE__ */ jsxs("div", {
630
+ style: dataActionsStyles,
631
+ children: [
632
+ /* @__PURE__ */ jsx("button", {
633
+ type: "button",
634
+ style: dataButtonStyles,
635
+ onClick: handleExport,
636
+ children: "↓ Export JSON"
637
+ }),
638
+ /* @__PURE__ */ jsx("button", {
639
+ type: "button",
640
+ style: dataButtonStyles,
641
+ disabled: isImporting,
642
+ onClick: () => fileInputRef.current?.click(),
643
+ children: isImporting ? "Importing…" : "↑ Import JSON"
644
+ }),
645
+ /* @__PURE__ */ jsx("input", {
646
+ ref: fileInputRef,
647
+ type: "file",
648
+ accept: "application/json,.json",
649
+ style: { display: "none" },
650
+ onChange: (event) => {
651
+ const file = event.target.files?.[0];
652
+ event.target.value = "";
653
+ if (file) handleImportFile(file);
654
+ }
655
+ })
656
+ ]
657
+ }),
658
+ status && /* @__PURE__ */ jsx("div", {
659
+ style: status.kind === "error" ? dataStatusErrorStyles : dataStatusSuccessStyles,
660
+ children: status.message
661
+ })
662
+ ]
663
+ });
565
664
  }
566
665
  function ResetSection({ dbId, instance }) {
567
- const [confirming, setConfirming] = useState(false);
568
- const [isResetting, setIsResetting] = useState(false);
569
- const handleReset = () => {
570
- setIsResetting(true);
571
- void instance.requestReload({ clean: true });
572
- };
573
- return /* @__PURE__ */ jsxs("div", { style: dangerZoneStyles, children: [
574
- /* @__PURE__ */ jsx("div", { style: dangerZoneTitleStyles, children: "Danger Zone" }),
575
- /* @__PURE__ */ jsxs("div", { style: dangerZoneRowStyles, children: [
576
- /* @__PURE__ */ jsxs("div", { style: dangerZoneDescStyles, children: [
577
- "Requests a clean reload, so ",
578
- /* @__PURE__ */ jsx("code", { style: inlineCodeStyles, children: dbId }),
579
- " is wiped on next load via",
580
- " ",
581
- /* @__PURE__ */ jsx("code", { style: inlineCodeStyles, children: "clearOnInit" }),
582
- ", then reloads all tabs."
583
- ] }),
584
- confirming ? /* @__PURE__ */ jsxs("div", { style: dangerZoneActionsStyles, children: [
585
- /* @__PURE__ */ jsx(
586
- "button",
587
- {
588
- type: "button",
589
- style: resetCancelButtonStyles,
590
- disabled: isResetting,
591
- onClick: () => setConfirming(false),
592
- children: "Cancel"
593
- }
594
- ),
595
- /* @__PURE__ */ jsx("button", { type: "button", style: resetConfirmButtonStyles, disabled: isResetting, onClick: handleReset, children: isResetting ? "Resetting\u2026" : "Confirm reset" })
596
- ] }) : /* @__PURE__ */ jsx("button", { type: "button", style: resetButtonStyles, onClick: () => setConfirming(true), children: "Reset DB" })
597
- ] })
598
- ] });
666
+ const [confirming, setConfirming] = useState(false);
667
+ const [isResetting, setIsResetting] = useState(false);
668
+ const handleReset = () => {
669
+ setIsResetting(true);
670
+ instance.requestReload({ clean: true });
671
+ };
672
+ return /* @__PURE__ */ jsxs("div", {
673
+ style: dangerZoneStyles,
674
+ children: [/* @__PURE__ */ jsx("div", {
675
+ style: dangerZoneTitleStyles,
676
+ children: "Danger Zone"
677
+ }), /* @__PURE__ */ jsxs("div", {
678
+ style: dangerZoneRowStyles,
679
+ children: [/* @__PURE__ */ jsxs("div", {
680
+ style: dangerZoneDescStyles,
681
+ children: [
682
+ "Requests a clean reload, so ",
683
+ /* @__PURE__ */ jsx("code", {
684
+ style: inlineCodeStyles,
685
+ children: dbId
686
+ }),
687
+ " is wiped on next load via",
688
+ " ",
689
+ /* @__PURE__ */ jsx("code", {
690
+ style: inlineCodeStyles,
691
+ children: "clearOnInit"
692
+ }),
693
+ ", then reloads all tabs."
694
+ ]
695
+ }), confirming ? /* @__PURE__ */ jsxs("div", {
696
+ style: dangerZoneActionsStyles,
697
+ children: [/* @__PURE__ */ jsx("button", {
698
+ type: "button",
699
+ style: resetCancelButtonStyles,
700
+ disabled: isResetting,
701
+ onClick: () => setConfirming(false),
702
+ children: "Cancel"
703
+ }), /* @__PURE__ */ jsx("button", {
704
+ type: "button",
705
+ style: resetConfirmButtonStyles,
706
+ disabled: isResetting,
707
+ onClick: handleReset,
708
+ children: isResetting ? "Resetting…" : "Confirm reset"
709
+ })]
710
+ }) : /* @__PURE__ */ jsx("button", {
711
+ type: "button",
712
+ style: resetButtonStyles,
713
+ onClick: () => setConfirming(true),
714
+ children: "Reset DB"
715
+ })]
716
+ })]
717
+ });
599
718
  }
600
- function SchemaTab({
601
- selectedInstance
602
- }) {
603
- if (!selectedInstance) return null;
604
- const { crdtTablesConfig, schemaVersion, migrationVersions } = selectedInstance.instance._internal;
605
- const latestVersion = migrationVersions.at(-1) ?? 0;
606
- return /* @__PURE__ */ jsxs("div", { style: schemaLayoutStyles, children: [
607
- /* @__PURE__ */ jsxs("div", { style: schemaSectionStyles, children: [
608
- /* @__PURE__ */ jsxs("div", { style: schemaSectionHeaderStyles, children: [
609
- /* @__PURE__ */ jsx("div", { style: schemaSectionTitleStyles, children: "CRDT Tables" }),
610
- /* @__PURE__ */ jsx("span", { style: schemaBadgeStyles, children: crdtTablesConfig.length })
611
- ] }),
612
- /* @__PURE__ */ jsxs("div", { style: schemaTableGridStyles, children: [
613
- /* @__PURE__ */ jsxs("div", { style: schemaTableHeaderRowStyles, children: [
614
- /* @__PURE__ */ jsx("div", { style: schemaColHeaderStyles, children: "Base Table" }),
615
- /* @__PURE__ */ jsx("div", { style: schemaColHeaderStyles, children: "CRDT Table" }),
616
- /* @__PURE__ */ jsx("div", { style: { ...schemaColHeaderStyles, textAlign: "center" }, children: "Status" })
617
- ] }),
618
- crdtTablesConfig.map((table) => /* @__PURE__ */ jsxs("div", { style: schemaTableRowStyles, children: [
619
- /* @__PURE__ */ jsxs("div", { style: schemaTableNameStyles, children: [
620
- /* @__PURE__ */ jsx("span", { style: schemaTableIconStyles, children: "\u25A6" }),
621
- table.baseTableName
622
- ] }),
623
- /* @__PURE__ */ jsx("div", { style: schemaCrdtNameStyles, children: table.crdtTableName }),
624
- /* @__PURE__ */ jsx("div", { style: schemaStatusCellStyles, children: /* @__PURE__ */ jsx("span", { style: schemaActiveTagStyles, children: "active" }) })
625
- ] }, table.crdtTableName))
626
- ] })
627
- ] }),
628
- /* @__PURE__ */ jsxs("div", { style: schemaSectionStyles, children: [
629
- /* @__PURE__ */ jsxs("div", { style: schemaSectionHeaderStyles, children: [
630
- /* @__PURE__ */ jsx("div", { style: schemaSectionTitleStyles, children: "Migrations" }),
631
- /* @__PURE__ */ jsxs("div", { style: schemaMigrationsMetaStyles, children: [
632
- /* @__PURE__ */ jsxs("span", { style: schemaBadgeStyles, children: [
633
- migrationVersions.length,
634
- " total"
635
- ] }),
636
- /* @__PURE__ */ jsxs("span", { style: schemaVersionChipStyles, children: [
637
- "current: v",
638
- schemaVersion,
639
- " / latest: v",
640
- latestVersion
641
- ] })
642
- ] })
643
- ] }),
644
- migrationVersions.length === 0 ? /* @__PURE__ */ jsx("div", { style: schemaEmptyStyles, children: "No migrations defined." }) : /* @__PURE__ */ jsx("div", { style: migrationListStyles, children: migrationVersions.map((version) => {
645
- const applied = version <= schemaVersion;
646
- const isCurrent = version === schemaVersion;
647
- return /* @__PURE__ */ jsxs("div", { style: getMigrationRowStyles(applied), children: [
648
- /* @__PURE__ */ jsxs("div", { style: migrationVersionStyles, children: [
649
- "v",
650
- version
651
- ] }),
652
- /* @__PURE__ */ jsx("div", { style: migrationBarTrackStyles, children: /* @__PURE__ */ jsx("div", { style: getMigrationBarFillStyles(applied) }) }),
653
- /* @__PURE__ */ jsx("div", { style: getMigrationTagStyles(applied, isCurrent), children: isCurrent ? "current" : applied ? "applied" : "pending" })
654
- ] }, version);
655
- }) })
656
- ] })
657
- ] });
719
+ function SchemaTab({ selectedInstance }) {
720
+ if (!selectedInstance) return null;
721
+ const { crdtTablesConfig, schemaVersion, migrationVersions } = selectedInstance.instance._internal;
722
+ const latestVersion = migrationVersions.at(-1) ?? 0;
723
+ return /* @__PURE__ */ jsxs("div", {
724
+ style: schemaLayoutStyles,
725
+ children: [/* @__PURE__ */ jsxs("div", {
726
+ style: schemaSectionStyles,
727
+ children: [/* @__PURE__ */ jsxs("div", {
728
+ style: schemaSectionHeaderStyles,
729
+ children: [/* @__PURE__ */ jsx("div", {
730
+ style: schemaSectionTitleStyles,
731
+ children: "CRDT Tables"
732
+ }), /* @__PURE__ */ jsx("span", {
733
+ style: schemaBadgeStyles,
734
+ children: crdtTablesConfig.length
735
+ })]
736
+ }), /* @__PURE__ */ jsxs("div", {
737
+ style: schemaTableGridStyles,
738
+ children: [/* @__PURE__ */ jsxs("div", {
739
+ style: schemaTableHeaderRowStyles,
740
+ children: [
741
+ /* @__PURE__ */ jsx("div", {
742
+ style: schemaColHeaderStyles,
743
+ children: "Base Table"
744
+ }),
745
+ /* @__PURE__ */ jsx("div", {
746
+ style: schemaColHeaderStyles,
747
+ children: "CRDT Table"
748
+ }),
749
+ /* @__PURE__ */ jsx("div", {
750
+ style: {
751
+ ...schemaColHeaderStyles,
752
+ textAlign: "center"
753
+ },
754
+ children: "Status"
755
+ })
756
+ ]
757
+ }), crdtTablesConfig.map((table) => /* @__PURE__ */ jsxs("div", {
758
+ style: schemaTableRowStyles,
759
+ children: [
760
+ /* @__PURE__ */ jsxs("div", {
761
+ style: schemaTableNameStyles,
762
+ children: [/* @__PURE__ */ jsx("span", {
763
+ style: schemaTableIconStyles,
764
+ children: "▦"
765
+ }), table.baseTableName]
766
+ }),
767
+ /* @__PURE__ */ jsx("div", {
768
+ style: schemaCrdtNameStyles,
769
+ children: table.crdtTableName
770
+ }),
771
+ /* @__PURE__ */ jsx("div", {
772
+ style: schemaStatusCellStyles,
773
+ children: /* @__PURE__ */ jsx("span", {
774
+ style: schemaActiveTagStyles,
775
+ children: "active"
776
+ })
777
+ })
778
+ ]
779
+ }, table.crdtTableName))]
780
+ })]
781
+ }), /* @__PURE__ */ jsxs("div", {
782
+ style: schemaSectionStyles,
783
+ children: [/* @__PURE__ */ jsxs("div", {
784
+ style: schemaSectionHeaderStyles,
785
+ children: [/* @__PURE__ */ jsx("div", {
786
+ style: schemaSectionTitleStyles,
787
+ children: "Migrations"
788
+ }), /* @__PURE__ */ jsxs("div", {
789
+ style: schemaMigrationsMetaStyles,
790
+ children: [/* @__PURE__ */ jsxs("span", {
791
+ style: schemaBadgeStyles,
792
+ children: [migrationVersions.length, " total"]
793
+ }), /* @__PURE__ */ jsxs("span", {
794
+ style: schemaVersionChipStyles,
795
+ children: [
796
+ "current: v",
797
+ schemaVersion,
798
+ " / latest: v",
799
+ latestVersion
800
+ ]
801
+ })]
802
+ })]
803
+ }), migrationVersions.length === 0 ? /* @__PURE__ */ jsx("div", {
804
+ style: schemaEmptyStyles,
805
+ children: "No migrations defined."
806
+ }) : /* @__PURE__ */ jsx("div", {
807
+ style: migrationListStyles,
808
+ children: migrationVersions.map((version) => {
809
+ const applied = version <= schemaVersion;
810
+ const isCurrent = version === schemaVersion;
811
+ return /* @__PURE__ */ jsxs("div", {
812
+ style: getMigrationRowStyles(applied),
813
+ children: [
814
+ /* @__PURE__ */ jsxs("div", {
815
+ style: migrationVersionStyles,
816
+ children: ["v", version]
817
+ }),
818
+ /* @__PURE__ */ jsx("div", {
819
+ style: migrationBarTrackStyles,
820
+ children: /* @__PURE__ */ jsx("div", { style: getMigrationBarFillStyles(applied) })
821
+ }),
822
+ /* @__PURE__ */ jsx("div", {
823
+ style: getMigrationTagStyles(applied, isCurrent),
824
+ children: isCurrent ? "current" : applied ? "applied" : "pending"
825
+ })
826
+ ]
827
+ }, version);
828
+ })
829
+ })]
830
+ })]
831
+ });
658
832
  }
659
833
  function LiveQueriesTab({ selectedInstance }) {
660
- const [queries, setQueries] = useState([]);
661
- const refresh = useCallback(() => {
662
- if (!selectedInstance) {
663
- setQueries([]);
664
- return;
665
- }
666
- setQueries(
667
- selectedInstance.instance._internal.getSharedLiveQueriesSnapshot().sort(
668
- (a, b) => a.sql.localeCompare(b.sql) || formatLiveQueryParameters(a.parameters).localeCompare(formatLiveQueryParameters(b.parameters))
669
- )
670
- );
671
- }, [selectedInstance]);
672
- useEffect(() => {
673
- refresh();
674
- }, [refresh]);
675
- const totalSubscribers = queries.reduce((total, query) => total + query.subscriberCount, 0);
676
- return /* @__PURE__ */ jsx("div", { style: schemaLayoutStyles, children: /* @__PURE__ */ jsxs("div", { style: schemaSectionStyles, children: [
677
- /* @__PURE__ */ jsxs("div", { style: schemaSectionHeaderStyles, children: [
678
- /* @__PURE__ */ jsx("div", { style: schemaSectionTitleStyles, children: "Shared Live Queries" }),
679
- /* @__PURE__ */ jsx("span", { style: schemaBadgeStyles, children: queries.length }),
680
- /* @__PURE__ */ jsxs("span", { style: schemaVersionChipStyles, children: [
681
- totalSubscribers,
682
- " subscriber",
683
- totalSubscribers !== 1 ? "s" : ""
684
- ] }),
685
- /* @__PURE__ */ jsx(
686
- "button",
687
- {
688
- type: "button",
689
- style: { ...eventLogRefreshButtonStyles, marginLeft: "auto" },
690
- onClick: refresh,
691
- disabled: !selectedInstance,
692
- children: "\u21BB Refresh"
693
- }
694
- )
695
- ] }),
696
- queries.length === 0 ? /* @__PURE__ */ jsxs("div", { style: schemaEmptyStyles, children: [
697
- "No active live queries. Queries created via ",
698
- /* @__PURE__ */ jsx("code", { style: inlineCodeStyles, children: "useDbQuery" }),
699
- " appear here while components are subscribed."
700
- ] }) : /* @__PURE__ */ jsxs("div", { style: schemaTableGridStyles, children: [
701
- /* @__PURE__ */ jsxs("div", { style: liveQueryHeaderRowStyles, children: [
702
- /* @__PURE__ */ jsx("div", { style: schemaColHeaderStyles, children: "SQL" }),
703
- /* @__PURE__ */ jsx("div", { style: schemaColHeaderStyles, children: "Parameters" }),
704
- /* @__PURE__ */ jsx("div", { style: { ...schemaColHeaderStyles, textAlign: "center" }, children: "Subscribers" })
705
- ] }),
706
- queries.map((query) => {
707
- const parameters = formatLiveQueryParameters(query.parameters);
708
- return /* @__PURE__ */ jsxs("div", { style: liveQueryRowStyles, children: [
709
- /* @__PURE__ */ jsx("div", { style: liveQuerySqlStyles, children: query.sql }),
710
- /* @__PURE__ */ jsx("div", { style: liveQueryParametersStyles, children: parameters }),
711
- /* @__PURE__ */ jsx("div", { style: schemaStatusCellStyles, children: /* @__PURE__ */ jsx("span", { style: query.subscriberCount > 0 ? schemaActiveTagStyles : liveQueryIdleTagStyles, children: query.subscriberCount }) })
712
- ] }, `${query.sql}|${parameters}`);
713
- })
714
- ] })
715
- ] }) });
834
+ const [queries, setQueries] = useState([]);
835
+ const refresh = useCallback(() => {
836
+ if (!selectedInstance) {
837
+ setQueries([]);
838
+ return;
839
+ }
840
+ setQueries(selectedInstance.instance._internal.getSharedLiveQueriesSnapshot().sort((a, b) => a.sql.localeCompare(b.sql) || formatLiveQueryParameters(a.parameters).localeCompare(formatLiveQueryParameters(b.parameters))));
841
+ }, [selectedInstance]);
842
+ useEffect(() => {
843
+ refresh();
844
+ }, [refresh]);
845
+ const totalSubscribers = queries.reduce((total, query) => total + query.subscriberCount, 0);
846
+ return /* @__PURE__ */ jsx("div", {
847
+ style: schemaLayoutStyles,
848
+ children: /* @__PURE__ */ jsxs("div", {
849
+ style: schemaSectionStyles,
850
+ children: [/* @__PURE__ */ jsxs("div", {
851
+ style: schemaSectionHeaderStyles,
852
+ children: [
853
+ /* @__PURE__ */ jsx("div", {
854
+ style: schemaSectionTitleStyles,
855
+ children: "Shared Live Queries"
856
+ }),
857
+ /* @__PURE__ */ jsx("span", {
858
+ style: schemaBadgeStyles,
859
+ children: queries.length
860
+ }),
861
+ /* @__PURE__ */ jsxs("span", {
862
+ style: schemaVersionChipStyles,
863
+ children: [
864
+ totalSubscribers,
865
+ " subscriber",
866
+ totalSubscribers !== 1 ? "s" : ""
867
+ ]
868
+ }),
869
+ /* @__PURE__ */ jsx("button", {
870
+ type: "button",
871
+ style: {
872
+ ...eventLogRefreshButtonStyles,
873
+ marginLeft: "auto"
874
+ },
875
+ onClick: refresh,
876
+ disabled: !selectedInstance,
877
+ children: "↻ Refresh"
878
+ })
879
+ ]
880
+ }), queries.length === 0 ? /* @__PURE__ */ jsxs("div", {
881
+ style: schemaEmptyStyles,
882
+ children: [
883
+ "No active live queries. Queries created via ",
884
+ /* @__PURE__ */ jsx("code", {
885
+ style: inlineCodeStyles,
886
+ children: "useDbQuery"
887
+ }),
888
+ " appear here while components are subscribed."
889
+ ]
890
+ }) : /* @__PURE__ */ jsxs("div", {
891
+ style: schemaTableGridStyles,
892
+ children: [/* @__PURE__ */ jsxs("div", {
893
+ style: liveQueryHeaderRowStyles,
894
+ children: [
895
+ /* @__PURE__ */ jsx("div", {
896
+ style: schemaColHeaderStyles,
897
+ children: "SQL"
898
+ }),
899
+ /* @__PURE__ */ jsx("div", {
900
+ style: schemaColHeaderStyles,
901
+ children: "Parameters"
902
+ }),
903
+ /* @__PURE__ */ jsx("div", {
904
+ style: {
905
+ ...schemaColHeaderStyles,
906
+ textAlign: "center"
907
+ },
908
+ children: "Subscribers"
909
+ })
910
+ ]
911
+ }), queries.map((query) => {
912
+ const parameters = formatLiveQueryParameters(query.parameters);
913
+ return /* @__PURE__ */ jsxs("div", {
914
+ style: liveQueryRowStyles,
915
+ children: [
916
+ /* @__PURE__ */ jsx("div", {
917
+ style: liveQuerySqlStyles,
918
+ children: query.sql
919
+ }),
920
+ /* @__PURE__ */ jsx("div", {
921
+ style: liveQueryParametersStyles,
922
+ children: parameters
923
+ }),
924
+ /* @__PURE__ */ jsx("div", {
925
+ style: schemaStatusCellStyles,
926
+ children: /* @__PURE__ */ jsx("span", {
927
+ style: query.subscriberCount > 0 ? schemaActiveTagStyles : liveQueryIdleTagStyles,
928
+ children: query.subscriberCount
929
+ })
930
+ })
931
+ ]
932
+ }, `${query.sql}|${parameters}`);
933
+ })]
934
+ })]
935
+ })
936
+ });
716
937
  }
717
938
  function formatLiveQueryParameters(parameters) {
718
- try {
719
- return JSON.stringify(parameters);
720
- } catch {
721
- return String(parameters);
722
- }
939
+ try {
940
+ return JSON.stringify(parameters);
941
+ } catch {
942
+ return String(parameters);
943
+ }
723
944
  }
724
- var PAGE_SIZE = 50;
945
+ const PAGE_SIZE = 50;
725
946
  function buildEventLogQuery(filters, afterSyncId) {
726
- const conditions = [];
727
- if (filters.dataset) conditions.push(`dataset = '${filters.dataset}'`);
728
- if (filters.origin) conditions.push(`origin = '${filters.origin}'`);
729
- if (filters.status) conditions.push(`status = '${filters.status}'`);
730
- if (afterSyncId !== null) conditions.push(`sync_id < ${afterSyncId}`);
731
- const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
732
- return `SELECT * FROM "worker"."crdt_events" ${where} ORDER BY sync_id DESC LIMIT ${PAGE_SIZE + 1}`;
947
+ const conditions = [];
948
+ if (filters.dataset) conditions.push(`dataset = '${filters.dataset}'`);
949
+ if (filters.origin) conditions.push(`origin = '${filters.origin}'`);
950
+ if (filters.status) conditions.push(`status = '${filters.status}'`);
951
+ if (afterSyncId !== null) conditions.push(`sync_id < ${afterSyncId}`);
952
+ return `SELECT * FROM "worker"."crdt_events" ${conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : ""} ORDER BY sync_id DESC LIMIT 51`;
733
953
  }
734
- function EventLogTab({
735
- selectedInstance
736
- }) {
737
- const baseTableNames = useMemo(
738
- () => selectedInstance?.instance._internal.crdtTablesConfig.map((table) => table.baseTableName) ?? [],
739
- [selectedInstance]
740
- );
741
- const [filters, setFilters] = useState({ dataset: "", origin: "", status: "" });
742
- const [events, setEvents] = useState([]);
743
- const [hasMore, setHasMore] = useState(false);
744
- const [isLoading, setIsLoading] = useState(false);
745
- const [expandedId, setExpandedId] = useState(null);
746
- const afterSyncIdRef = useRef(null);
747
- const isLoadingRef = useRef(false);
748
- const executeQuery = useCallback(
749
- async (sql) => {
750
- if (!selectedInstance) return [];
751
- const result = await selectedInstance.instance._internal.executeAsync({ sql, parameters: [] });
752
- return result.rows;
753
- },
754
- [selectedInstance]
755
- );
756
- const load = useCallback(
757
- async (reset, currentFilters) => {
758
- if (!selectedInstance || isLoadingRef.current) return;
759
- isLoadingRef.current = true;
760
- setIsLoading(true);
761
- try {
762
- const afterSyncId = reset ? null : afterSyncIdRef.current;
763
- const sql = buildEventLogQuery(currentFilters, afterSyncId);
764
- const rows = await executeQuery(sql);
765
- const page = rows.slice(0, PAGE_SIZE);
766
- setHasMore(rows.length > PAGE_SIZE);
767
- if (reset) {
768
- setEvents(page);
769
- } else {
770
- setEvents((prev) => [...prev, ...page]);
771
- }
772
- afterSyncIdRef.current = page.at(-1)?.sync_id ?? null;
773
- } finally {
774
- isLoadingRef.current = false;
775
- setIsLoading(false);
776
- }
777
- },
778
- [selectedInstance, executeQuery]
779
- );
780
- useEffect(() => {
781
- afterSyncIdRef.current = null;
782
- setEvents([]);
783
- void load(true, filters);
784
- }, [filters, load]);
785
- const applyFilters = (next) => {
786
- setFilters(next);
787
- };
788
- if (!selectedInstance) return null;
789
- return /* @__PURE__ */ jsxs("div", { style: eventLogLayoutStyles, children: [
790
- /* @__PURE__ */ jsxs("div", { style: eventLogToolbarStyles, children: [
791
- /* @__PURE__ */ jsxs(
792
- "select",
793
- {
794
- value: filters.dataset,
795
- onChange: (e) => applyFilters({ ...filters, dataset: e.target.value }),
796
- style: eventLogFilterSelectStyles,
797
- children: [
798
- /* @__PURE__ */ jsx("option", { value: "", children: "All datasets" }),
799
- baseTableNames.map((name) => /* @__PURE__ */ jsx("option", { value: name, children: name }, name))
800
- ]
801
- }
802
- ),
803
- /* @__PURE__ */ jsxs(
804
- "select",
805
- {
806
- value: filters.origin,
807
- onChange: (e) => applyFilters({ ...filters, origin: e.target.value }),
808
- style: eventLogFilterSelectStyles,
809
- children: [
810
- /* @__PURE__ */ jsx("option", { value: "", children: "All origins" }),
811
- /* @__PURE__ */ jsx("option", { value: "own", children: "own" }),
812
- /* @__PURE__ */ jsx("option", { value: "remote", children: "remote" }),
813
- /* @__PURE__ */ jsx("option", { value: "local", children: "local" })
814
- ]
815
- }
816
- ),
817
- /* @__PURE__ */ jsxs(
818
- "select",
819
- {
820
- value: filters.status,
821
- onChange: (e) => applyFilters({ ...filters, status: e.target.value }),
822
- style: eventLogFilterSelectStyles,
823
- children: [
824
- /* @__PURE__ */ jsx("option", { value: "", children: "All statuses" }),
825
- /* @__PURE__ */ jsx("option", { value: "applied", children: "applied" }),
826
- /* @__PURE__ */ jsx("option", { value: "pending", children: "pending" }),
827
- /* @__PURE__ */ jsx("option", { value: "failed", children: "failed" }),
828
- /* @__PURE__ */ jsx("option", { value: "deduped", children: "deduped" })
829
- ]
830
- }
831
- ),
832
- /* @__PURE__ */ jsxs(
833
- "button",
834
- {
835
- type: "button",
836
- style: eventLogRefreshButtonStyles,
837
- disabled: isLoading,
838
- onClick: () => void load(true, filters),
839
- children: [
840
- isLoading ? "\u2026" : "\u21BB",
841
- " Refresh"
842
- ]
843
- }
844
- ),
845
- events.length > 0 && /* @__PURE__ */ jsxs("span", { style: eventLogCountStyles, children: [
846
- events.length,
847
- hasMore ? "+" : "",
848
- " events"
849
- ] })
850
- ] }),
851
- events.length === 0 && !isLoading ? /* @__PURE__ */ jsx("div", { style: eventLogEmptyStyles, children: "No events match the current filters." }) : /* @__PURE__ */ jsxs("div", { style: eventLogListStyles, children: [
852
- events.map((event) => {
853
- const isExpanded = expandedId === event.sync_id;
854
- return /* @__PURE__ */ jsxs("div", { style: getEventRowStyles(isExpanded), children: [
855
- /* @__PURE__ */ jsxs(
856
- "button",
857
- {
858
- type: "button",
859
- style: eventRowHeaderStyles,
860
- onClick: () => setExpandedId(isExpanded ? null : event.sync_id),
861
- children: [
862
- /* @__PURE__ */ jsxs("span", { style: eventSyncIdStyles, children: [
863
- "#",
864
- event.sync_id
865
- ] }),
866
- /* @__PURE__ */ jsx(EventTypeBadge, { type: event.type }),
867
- /* @__PURE__ */ jsx(EventOriginBadge, { origin: event.origin }),
868
- /* @__PURE__ */ jsx(EventStatusBadge, { status: event.status }),
869
- /* @__PURE__ */ jsx("span", { style: eventDatasetStyles, children: event.dataset }),
870
- /* @__PURE__ */ jsx("span", { style: eventItemIdStyles, children: event.item_id }),
871
- /* @__PURE__ */ jsx("span", { style: eventTimestampStyles, children: formatHlcTimestamp(event.timestamp) }),
872
- /* @__PURE__ */ jsx("span", { style: eventChevronStyles, children: isExpanded ? "\u25B2" : "\u25BC" })
873
- ]
874
- }
875
- ),
876
- isExpanded && /* @__PURE__ */ jsxs("div", { style: eventPayloadStyles, children: [
877
- /* @__PURE__ */ jsxs("div", { style: eventPayloadMetaStyles, children: [
878
- /* @__PURE__ */ jsxs("span", { style: eventMetaItemStyles, children: [
879
- "schema v",
880
- event.schema_version
881
- ] }),
882
- /* @__PURE__ */ jsxs("span", { style: eventMetaItemStyles, children: [
883
- "node: ",
884
- event.source_node_id || "\u2014"
885
- ] }),
886
- /* @__PURE__ */ jsxs("span", { style: eventMetaItemStyles, children: [
887
- "ts: ",
888
- event.timestamp
889
- ] })
890
- ] }),
891
- /* @__PURE__ */ jsx("pre", { style: eventPayloadPreStyles, children: formatPayload(event.payload) })
892
- ] })
893
- ] }, event.sync_id);
894
- }),
895
- hasMore && /* @__PURE__ */ jsx(
896
- "button",
897
- {
898
- type: "button",
899
- style: loadMoreButtonStyles,
900
- disabled: isLoading,
901
- onClick: () => void load(false, filters),
902
- children: isLoading ? "Loading\u2026" : `Load ${PAGE_SIZE} more`
903
- }
904
- )
905
- ] })
906
- ] });
954
+ function EventLogTab({ selectedInstance }) {
955
+ const baseTableNames = useMemo(() => selectedInstance?.instance._internal.crdtTablesConfig.map((table) => table.baseTableName) ?? [], [selectedInstance]);
956
+ const [filters, setFilters] = useState({
957
+ dataset: "",
958
+ origin: "",
959
+ status: ""
960
+ });
961
+ const [events, setEvents] = useState([]);
962
+ const [hasMore, setHasMore] = useState(false);
963
+ const [isLoading, setIsLoading] = useState(false);
964
+ const [expandedId, setExpandedId] = useState(null);
965
+ const afterSyncIdRef = useRef(null);
966
+ const isLoadingRef = useRef(false);
967
+ const executeQuery = useCallback(async (sql) => {
968
+ if (!selectedInstance) return [];
969
+ return (await selectedInstance.instance._internal.executeAsync({
970
+ sql,
971
+ parameters: []
972
+ })).rows;
973
+ }, [selectedInstance]);
974
+ const load = useCallback(async (reset, currentFilters) => {
975
+ if (!selectedInstance || isLoadingRef.current) return;
976
+ isLoadingRef.current = true;
977
+ setIsLoading(true);
978
+ try {
979
+ const sql = buildEventLogQuery(currentFilters, reset ? null : afterSyncIdRef.current);
980
+ const rows = await executeQuery(sql);
981
+ const page = rows.slice(0, PAGE_SIZE);
982
+ setHasMore(rows.length > PAGE_SIZE);
983
+ if (reset) setEvents(page);
984
+ else setEvents((prev) => [...prev, ...page]);
985
+ afterSyncIdRef.current = page.at(-1)?.sync_id ?? null;
986
+ } finally {
987
+ isLoadingRef.current = false;
988
+ setIsLoading(false);
989
+ }
990
+ }, [selectedInstance, executeQuery]);
991
+ useEffect(() => {
992
+ afterSyncIdRef.current = null;
993
+ setEvents([]);
994
+ load(true, filters);
995
+ }, [filters, load]);
996
+ const applyFilters = (next) => {
997
+ setFilters(next);
998
+ };
999
+ if (!selectedInstance) return null;
1000
+ return /* @__PURE__ */ jsxs("div", {
1001
+ style: eventLogLayoutStyles,
1002
+ children: [/* @__PURE__ */ jsxs("div", {
1003
+ style: eventLogToolbarStyles,
1004
+ children: [
1005
+ /* @__PURE__ */ jsxs("select", {
1006
+ value: filters.dataset,
1007
+ onChange: (e) => applyFilters({
1008
+ ...filters,
1009
+ dataset: e.target.value
1010
+ }),
1011
+ style: eventLogFilterSelectStyles,
1012
+ children: [/* @__PURE__ */ jsx("option", {
1013
+ value: "",
1014
+ children: "All datasets"
1015
+ }), baseTableNames.map((name) => /* @__PURE__ */ jsx("option", {
1016
+ value: name,
1017
+ children: name
1018
+ }, name))]
1019
+ }),
1020
+ /* @__PURE__ */ jsxs("select", {
1021
+ value: filters.origin,
1022
+ onChange: (e) => applyFilters({
1023
+ ...filters,
1024
+ origin: e.target.value
1025
+ }),
1026
+ style: eventLogFilterSelectStyles,
1027
+ children: [
1028
+ /* @__PURE__ */ jsx("option", {
1029
+ value: "",
1030
+ children: "All origins"
1031
+ }),
1032
+ /* @__PURE__ */ jsx("option", {
1033
+ value: "own",
1034
+ children: "own"
1035
+ }),
1036
+ /* @__PURE__ */ jsx("option", {
1037
+ value: "remote",
1038
+ children: "remote"
1039
+ }),
1040
+ /* @__PURE__ */ jsx("option", {
1041
+ value: "local",
1042
+ children: "local"
1043
+ })
1044
+ ]
1045
+ }),
1046
+ /* @__PURE__ */ jsxs("select", {
1047
+ value: filters.status,
1048
+ onChange: (e) => applyFilters({
1049
+ ...filters,
1050
+ status: e.target.value
1051
+ }),
1052
+ style: eventLogFilterSelectStyles,
1053
+ children: [
1054
+ /* @__PURE__ */ jsx("option", {
1055
+ value: "",
1056
+ children: "All statuses"
1057
+ }),
1058
+ /* @__PURE__ */ jsx("option", {
1059
+ value: "applied",
1060
+ children: "applied"
1061
+ }),
1062
+ /* @__PURE__ */ jsx("option", {
1063
+ value: "pending",
1064
+ children: "pending"
1065
+ }),
1066
+ /* @__PURE__ */ jsx("option", {
1067
+ value: "failed",
1068
+ children: "failed"
1069
+ }),
1070
+ /* @__PURE__ */ jsx("option", {
1071
+ value: "deduped",
1072
+ children: "deduped"
1073
+ })
1074
+ ]
1075
+ }),
1076
+ /* @__PURE__ */ jsxs("button", {
1077
+ type: "button",
1078
+ style: eventLogRefreshButtonStyles,
1079
+ disabled: isLoading,
1080
+ onClick: () => void load(true, filters),
1081
+ children: [isLoading ? "…" : "↻", " Refresh"]
1082
+ }),
1083
+ events.length > 0 && /* @__PURE__ */ jsxs("span", {
1084
+ style: eventLogCountStyles,
1085
+ children: [
1086
+ events.length,
1087
+ hasMore ? "+" : "",
1088
+ " events"
1089
+ ]
1090
+ })
1091
+ ]
1092
+ }), events.length === 0 && !isLoading ? /* @__PURE__ */ jsx("div", {
1093
+ style: eventLogEmptyStyles,
1094
+ children: "No events match the current filters."
1095
+ }) : /* @__PURE__ */ jsxs("div", {
1096
+ style: eventLogListStyles,
1097
+ children: [events.map((event) => {
1098
+ const isExpanded = expandedId === event.sync_id;
1099
+ return /* @__PURE__ */ jsxs("div", {
1100
+ style: getEventRowStyles(isExpanded),
1101
+ children: [/* @__PURE__ */ jsxs("button", {
1102
+ type: "button",
1103
+ style: eventRowHeaderStyles,
1104
+ onClick: () => setExpandedId(isExpanded ? null : event.sync_id),
1105
+ children: [
1106
+ /* @__PURE__ */ jsxs("span", {
1107
+ style: eventSyncIdStyles,
1108
+ children: ["#", event.sync_id]
1109
+ }),
1110
+ /* @__PURE__ */ jsx(EventTypeBadge, { type: event.type }),
1111
+ /* @__PURE__ */ jsx(EventOriginBadge, { origin: event.origin }),
1112
+ /* @__PURE__ */ jsx(EventStatusBadge, { status: event.status }),
1113
+ /* @__PURE__ */ jsx("span", {
1114
+ style: eventDatasetStyles,
1115
+ children: event.dataset
1116
+ }),
1117
+ /* @__PURE__ */ jsx("span", {
1118
+ style: eventItemIdStyles,
1119
+ children: event.item_id
1120
+ }),
1121
+ /* @__PURE__ */ jsx("span", {
1122
+ style: eventTimestampStyles,
1123
+ children: formatHlcTimestamp(event.timestamp)
1124
+ }),
1125
+ /* @__PURE__ */ jsx("span", {
1126
+ style: eventChevronStyles,
1127
+ children: isExpanded ? "▲" : "▼"
1128
+ })
1129
+ ]
1130
+ }), isExpanded && /* @__PURE__ */ jsxs("div", {
1131
+ style: eventPayloadStyles,
1132
+ children: [/* @__PURE__ */ jsxs("div", {
1133
+ style: eventPayloadMetaStyles,
1134
+ children: [
1135
+ /* @__PURE__ */ jsxs("span", {
1136
+ style: eventMetaItemStyles,
1137
+ children: ["schema v", event.schema_version]
1138
+ }),
1139
+ /* @__PURE__ */ jsxs("span", {
1140
+ style: eventMetaItemStyles,
1141
+ children: ["node: ", event.source_node_id || "—"]
1142
+ }),
1143
+ /* @__PURE__ */ jsxs("span", {
1144
+ style: eventMetaItemStyles,
1145
+ children: ["ts: ", event.timestamp]
1146
+ })
1147
+ ]
1148
+ }), /* @__PURE__ */ jsx("pre", {
1149
+ style: eventPayloadPreStyles,
1150
+ children: formatPayload(event.payload)
1151
+ })]
1152
+ })]
1153
+ }, event.sync_id);
1154
+ }), hasMore && /* @__PURE__ */ jsx("button", {
1155
+ type: "button",
1156
+ style: loadMoreButtonStyles,
1157
+ disabled: isLoading,
1158
+ onClick: () => void load(false, filters),
1159
+ children: isLoading ? "Loading…" : `Load ${PAGE_SIZE} more`
1160
+ })]
1161
+ })]
1162
+ });
907
1163
  }
908
1164
  function EventTypeBadge({ type }) {
909
- const { style, label } = type === "item-created" ? { style: eventTypeCreateStyles, label: "create" } : type === "item-deleted" ? { style: eventTypeDeleteStyles, label: "delete" } : { style: eventTypeUpdateStyles, label: "update" };
910
- return /* @__PURE__ */ jsx("span", { style, children: label });
1165
+ const { style, label } = type === "item-created" ? {
1166
+ style: eventTypeCreateStyles,
1167
+ label: "create"
1168
+ } : type === "item-deleted" ? {
1169
+ style: eventTypeDeleteStyles,
1170
+ label: "delete"
1171
+ } : {
1172
+ style: eventTypeUpdateStyles,
1173
+ label: "update"
1174
+ };
1175
+ return /* @__PURE__ */ jsx("span", {
1176
+ style,
1177
+ children: label
1178
+ });
911
1179
  }
912
1180
  function EventOriginBadge({ origin }) {
913
- const style = origin === "own" ? eventOriginOwnStyles : origin === "remote" ? eventOriginRemoteStyles : eventOriginLocalStyles;
914
- return /* @__PURE__ */ jsx("span", { style, children: origin });
1181
+ return /* @__PURE__ */ jsx("span", {
1182
+ style: origin === "own" ? eventOriginOwnStyles : origin === "remote" ? eventOriginRemoteStyles : eventOriginLocalStyles,
1183
+ children: origin
1184
+ });
915
1185
  }
916
1186
  function EventStatusBadge({ status }) {
917
- const style = status === "applied" ? eventStatusAppliedStyles : status === "pending" ? eventStatusPendingStyles : status === "failed" ? eventStatusFailedStyles : eventStatusSkippedStyles;
918
- return /* @__PURE__ */ jsx("span", { style, children: status });
1187
+ return /* @__PURE__ */ jsx("span", {
1188
+ style: status === "applied" ? eventStatusAppliedStyles : status === "pending" ? eventStatusPendingStyles : status === "failed" ? eventStatusFailedStyles : eventStatusSkippedStyles,
1189
+ children: status
1190
+ });
919
1191
  }
920
1192
  function formatHlcTimestamp(ts) {
921
- const ms = Number(ts.split("-")[0]);
922
- if (!Number.isNaN(ms) && ms > 1e12) {
923
- return new Date(ms).toLocaleTimeString();
924
- }
925
- return ts.slice(0, 19).replace("T", " ");
1193
+ const ms = Number(ts.split("-")[0]);
1194
+ if (!Number.isNaN(ms) && ms > 0xe8d4a51000) return new Date(ms).toLocaleTimeString();
1195
+ return ts.slice(0, 19).replace("T", " ");
926
1196
  }
927
1197
  function formatPayload(raw) {
928
- try {
929
- return JSON.stringify(JSON.parse(raw), null, 2);
930
- } catch {
931
- return raw;
932
- }
1198
+ try {
1199
+ return JSON.stringify(JSON.parse(raw), null, 2);
1200
+ } catch {
1201
+ return raw;
1202
+ }
933
1203
  }
934
- function QueryRunnerTab({
935
- selectedInstance,
936
- queryTarget,
937
- setQueryTarget,
938
- query,
939
- setQuery,
940
- queryState,
941
- canRunQuery,
942
- runQuery
943
- }) {
944
- return /* @__PURE__ */ jsxs("div", { style: queryRunnerLayoutStyles, children: [
945
- /* @__PURE__ */ jsxs("div", { style: queryToolbarStyles, children: [
946
- /* @__PURE__ */ jsxs("div", { style: targetToggleStyles, children: [
947
- /* @__PURE__ */ jsx(
948
- "button",
949
- {
950
- type: "button",
951
- style: getTargetButtonStyles(queryTarget === "memory"),
952
- onClick: () => setQueryTarget("memory"),
953
- children: "Memory DB"
954
- }
955
- ),
956
- /* @__PURE__ */ jsx(
957
- "button",
958
- {
959
- type: "button",
960
- style: getTargetButtonStyles(queryTarget === "worker"),
961
- onClick: () => setQueryTarget("worker"),
962
- children: "Worker DB"
963
- }
964
- )
965
- ] }),
966
- /* @__PURE__ */ jsxs("div", { style: queryToolbarRightStyles, children: [
967
- !selectedInstance && /* @__PURE__ */ jsx("span", { style: noInstanceWarningStyles, children: "No instance selected" }),
968
- /* @__PURE__ */ jsx("span", { style: shortcutHintStyles, children: "\u2318\u21B5 to run" }),
969
- /* @__PURE__ */ jsx(
970
- "button",
971
- {
972
- type: "button",
973
- style: runButtonStyles(canRunQuery, queryState.status === "running"),
974
- disabled: !canRunQuery,
975
- onClick: () => void runQuery(),
976
- children: queryState.status === "running" ? /* @__PURE__ */ jsxs(Fragment, { children: [
977
- /* @__PURE__ */ jsx("span", { style: runningDotStyles }),
978
- "Running\u2026"
979
- ] }) : /* @__PURE__ */ jsx(Fragment, { children: "\u25B6 Run" })
980
- }
981
- )
982
- ] })
983
- ] }),
984
- /* @__PURE__ */ jsx("div", { style: editorWrapperStyles, children: /* @__PURE__ */ jsx(
985
- "textarea",
986
- {
987
- value: query,
988
- onChange: (event) => setQuery(event.target.value),
989
- onKeyDown: (event) => {
990
- if ((event.metaKey || event.ctrlKey) && event.key === "Enter" && canRunQuery) {
991
- event.preventDefault();
992
- void runQuery();
993
- }
994
- },
995
- style: textareaStyles,
996
- placeholder: "SELECT * FROM your_table LIMIT 100",
997
- spellCheck: false
998
- }
999
- ) }),
1000
- /* @__PURE__ */ jsx("div", { style: helperTextStyles, children: queryTarget === "worker" ? "Worker DB is read-only \u2014 only SELECT, PRAGMA, and EXPLAIN are allowed." : "Memory DB allows writes only to CRDT tables." }),
1001
- queryState.status === "error" && /* @__PURE__ */ jsxs("div", { style: errorPanelStyles, children: [
1002
- /* @__PURE__ */ jsxs("div", { style: resultHeaderStyles, children: [
1003
- /* @__PURE__ */ jsx("span", { style: errorBadgeStyles, children: "Error" }),
1004
- /* @__PURE__ */ jsxs("span", { style: resultMetaStyles, children: [
1005
- queryState.error.target,
1006
- " \xB7 ",
1007
- queryState.error.sql
1008
- ] })
1009
- ] }),
1010
- /* @__PURE__ */ jsx("pre", { style: errorMessageStyles, children: queryState.error.message })
1011
- ] }),
1012
- queryState.status === "success" && /* @__PURE__ */ jsxs("div", { style: resultPanelStyles, children: [
1013
- /* @__PURE__ */ jsxs("div", { style: resultHeaderStyles, children: [
1014
- /* @__PURE__ */ jsxs("span", { style: successBadgeStyles, children: [
1015
- queryState.output.rowCount,
1016
- " row",
1017
- queryState.output.rowCount !== 1 ? "s" : ""
1018
- ] }),
1019
- /* @__PURE__ */ jsxs("span", { style: resultMetaStyles, children: [
1020
- queryState.output.target,
1021
- " \xB7 ",
1022
- queryState.output.durationMs,
1023
- "ms"
1024
- ] })
1025
- ] }),
1026
- /* @__PURE__ */ jsx(ResultTable, { rows: queryState.output.rows })
1027
- ] })
1028
- ] });
1204
+ function QueryRunnerTab({ selectedInstance, queryTarget, setQueryTarget, query, setQuery, queryState, canRunQuery, runQuery }) {
1205
+ return /* @__PURE__ */ jsxs("div", {
1206
+ style: queryRunnerLayoutStyles,
1207
+ children: [
1208
+ /* @__PURE__ */ jsxs("div", {
1209
+ style: queryToolbarStyles,
1210
+ children: [/* @__PURE__ */ jsxs("div", {
1211
+ style: targetToggleStyles,
1212
+ children: [/* @__PURE__ */ jsx("button", {
1213
+ type: "button",
1214
+ style: getTargetButtonStyles(queryTarget === "memory"),
1215
+ onClick: () => setQueryTarget("memory"),
1216
+ children: "Memory DB"
1217
+ }), /* @__PURE__ */ jsx("button", {
1218
+ type: "button",
1219
+ style: getTargetButtonStyles(queryTarget === "worker"),
1220
+ onClick: () => setQueryTarget("worker"),
1221
+ children: "Worker DB"
1222
+ })]
1223
+ }), /* @__PURE__ */ jsxs("div", {
1224
+ style: queryToolbarRightStyles,
1225
+ children: [
1226
+ !selectedInstance && /* @__PURE__ */ jsx("span", {
1227
+ style: noInstanceWarningStyles,
1228
+ children: "No instance selected"
1229
+ }),
1230
+ /* @__PURE__ */ jsx("span", {
1231
+ style: shortcutHintStyles,
1232
+ children: "⌘↵ to run"
1233
+ }),
1234
+ /* @__PURE__ */ jsx("button", {
1235
+ type: "button",
1236
+ style: runButtonStyles(canRunQuery, queryState.status === "running"),
1237
+ disabled: !canRunQuery,
1238
+ onClick: () => void runQuery(),
1239
+ children: queryState.status === "running" ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", { style: runningDotStyles }), "Running…"] }) : /* @__PURE__ */ jsx(Fragment, { children: "▶ Run" })
1240
+ })
1241
+ ]
1242
+ })]
1243
+ }),
1244
+ /* @__PURE__ */ jsx("div", {
1245
+ style: editorWrapperStyles,
1246
+ children: /* @__PURE__ */ jsx("textarea", {
1247
+ value: query,
1248
+ onChange: (event) => setQuery(event.target.value),
1249
+ onKeyDown: (event) => {
1250
+ if ((event.metaKey || event.ctrlKey) && event.key === "Enter" && canRunQuery) {
1251
+ event.preventDefault();
1252
+ runQuery();
1253
+ }
1254
+ },
1255
+ style: textareaStyles,
1256
+ placeholder: "SELECT * FROM your_table LIMIT 100",
1257
+ spellCheck: false
1258
+ })
1259
+ }),
1260
+ /* @__PURE__ */ jsx("div", {
1261
+ style: helperTextStyles,
1262
+ children: queryTarget === "worker" ? "Worker DB is read-only — only SELECT, PRAGMA, and EXPLAIN are allowed." : "Memory DB allows writes only to CRDT tables."
1263
+ }),
1264
+ queryState.status === "error" && /* @__PURE__ */ jsxs("div", {
1265
+ style: errorPanelStyles,
1266
+ children: [/* @__PURE__ */ jsxs("div", {
1267
+ style: resultHeaderStyles,
1268
+ children: [/* @__PURE__ */ jsx("span", {
1269
+ style: errorBadgeStyles,
1270
+ children: "Error"
1271
+ }), /* @__PURE__ */ jsxs("span", {
1272
+ style: resultMetaStyles,
1273
+ children: [
1274
+ queryState.error.target,
1275
+ " · ",
1276
+ queryState.error.sql
1277
+ ]
1278
+ })]
1279
+ }), /* @__PURE__ */ jsx("pre", {
1280
+ style: errorMessageStyles,
1281
+ children: queryState.error.message
1282
+ })]
1283
+ }),
1284
+ queryState.status === "success" && /* @__PURE__ */ jsxs("div", {
1285
+ style: resultPanelStyles,
1286
+ children: [/* @__PURE__ */ jsxs("div", {
1287
+ style: resultHeaderStyles,
1288
+ children: [/* @__PURE__ */ jsxs("span", {
1289
+ style: successBadgeStyles,
1290
+ children: [
1291
+ queryState.output.rowCount,
1292
+ " row",
1293
+ queryState.output.rowCount !== 1 ? "s" : ""
1294
+ ]
1295
+ }), /* @__PURE__ */ jsxs("span", {
1296
+ style: resultMetaStyles,
1297
+ children: [
1298
+ queryState.output.target,
1299
+ " · ",
1300
+ queryState.output.durationMs,
1301
+ "ms"
1302
+ ]
1303
+ })]
1304
+ }), /* @__PURE__ */ jsx(ResultTable, { rows: queryState.output.rows })]
1305
+ })
1306
+ ]
1307
+ });
1029
1308
  }
1030
1309
  function ResultTable({ rows }) {
1031
- if (rows.length === 0) {
1032
- return /* @__PURE__ */ jsx("div", { style: resultEmptyStyles, children: "Query returned 0 rows." });
1033
- }
1034
- const firstRow = rows[0];
1035
- if (typeof firstRow !== "object" || firstRow === null) {
1036
- return /* @__PURE__ */ jsx("pre", { style: resultRawStyles, children: JSON.stringify(rows, null, 2) });
1037
- }
1038
- const columns = Object.keys(firstRow);
1039
- return /* @__PURE__ */ jsx("div", { style: tableWrapperStyles, children: /* @__PURE__ */ jsxs("table", { style: tableStyles, children: [
1040
- /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
1041
- /* @__PURE__ */ jsx("th", { style: thRowNumStyles, children: "#" }),
1042
- columns.map((col) => /* @__PURE__ */ jsx("th", { style: thStyles, children: col }, col))
1043
- ] }) }),
1044
- /* @__PURE__ */ jsx("tbody", { children: rows.map((row, rowIdx) => /* @__PURE__ */ jsxs("tr", { style: rowIdx % 2 === 0 ? trStyles : trAltStyles, children: [
1045
- /* @__PURE__ */ jsx("td", { style: tdRowNumStyles, children: rowIdx + 1 }),
1046
- columns.map((col) => {
1047
- const val = row[col];
1048
- return /* @__PURE__ */ jsx("td", { style: tdStyles, children: val === null ? /* @__PURE__ */ jsx("span", { style: nullValueStyles, children: "NULL" }) : typeof val === "object" ? /* @__PURE__ */ jsx("span", { style: jsonValueStyles, children: JSON.stringify(val) }) : String(val) }, col);
1049
- })
1050
- ] }, rowIdx)) })
1051
- ] }) });
1310
+ if (rows.length === 0) return /* @__PURE__ */ jsx("div", {
1311
+ style: resultEmptyStyles,
1312
+ children: "Query returned 0 rows."
1313
+ });
1314
+ const firstRow = rows[0];
1315
+ if (typeof firstRow !== "object" || firstRow === null) return /* @__PURE__ */ jsx("pre", {
1316
+ style: resultRawStyles,
1317
+ children: JSON.stringify(rows, null, 2)
1318
+ });
1319
+ const columns = Object.keys(firstRow);
1320
+ return /* @__PURE__ */ jsx("div", {
1321
+ style: tableWrapperStyles,
1322
+ children: /* @__PURE__ */ jsxs("table", {
1323
+ style: tableStyles,
1324
+ children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", {
1325
+ style: thRowNumStyles,
1326
+ children: "#"
1327
+ }), columns.map((col) => /* @__PURE__ */ jsx("th", {
1328
+ style: thStyles,
1329
+ children: col
1330
+ }, col))] }) }), /* @__PURE__ */ jsx("tbody", { children: rows.map((row, rowIdx) => /* @__PURE__ */ jsxs("tr", {
1331
+ style: rowIdx % 2 === 0 ? trStyles : trAltStyles,
1332
+ children: [/* @__PURE__ */ jsx("td", {
1333
+ style: tdRowNumStyles,
1334
+ children: rowIdx + 1
1335
+ }), columns.map((col) => {
1336
+ const val = row[col];
1337
+ return /* @__PURE__ */ jsx("td", {
1338
+ style: tdStyles,
1339
+ children: val === null ? /* @__PURE__ */ jsx("span", {
1340
+ style: nullValueStyles,
1341
+ children: "NULL"
1342
+ }) : typeof val === "object" ? /* @__PURE__ */ jsx("span", {
1343
+ style: jsonValueStyles,
1344
+ children: JSON.stringify(val)
1345
+ }) : String(val)
1346
+ }, col);
1347
+ })]
1348
+ }, rowIdx)) })]
1349
+ })
1350
+ });
1052
1351
  }
1053
1352
  function formatInstanceLabel(dbId, instanceId, duplicateCount) {
1054
- if (duplicateCount < 2) {
1055
- return dbId;
1056
- }
1057
- return `${dbId} (${instanceId.slice(0, 6)})`;
1353
+ if (duplicateCount < 2) return dbId;
1354
+ return `${dbId} (${instanceId.slice(0, 6)})`;
1058
1355
  }
1059
1356
  function normalizeSingleStatement(query) {
1060
- const trimmed = query.trim();
1061
- if (!trimmed) {
1062
- throw new Error("Enter a SQL statement.");
1063
- }
1064
- const withoutTrailingSemicolons = trimmed.replace(/;+\s*$/u, "");
1065
- if (withoutTrailingSemicolons.includes(";")) {
1066
- throw new Error("Devtools only supports a single SQL statement.");
1067
- }
1068
- return withoutTrailingSemicolons;
1357
+ const trimmed = query.trim();
1358
+ if (!trimmed) throw new Error("Enter a SQL statement.");
1359
+ const withoutTrailingSemicolons = trimmed.replace(/;+\s*$/u, "");
1360
+ if (withoutTrailingSemicolons.includes(";")) throw new Error("Devtools only supports a single SQL statement.");
1361
+ return withoutTrailingSemicolons;
1069
1362
  }
1070
1363
  function getStatementKind(query) {
1071
- const match = query.trimStart().match(/^([a-z]+)/iu);
1072
- return match?.[1]?.toLowerCase() ?? "";
1364
+ return query.trimStart().match(/^([a-z]+)/iu)?.[1]?.toLowerCase() ?? "";
1073
1365
  }
1074
1366
  function isWorkerReadOnlyStatement(statementKind) {
1075
- return statementKind === "select" || statementKind === "pragma";
1367
+ return statementKind === "select" || statementKind === "pragma";
1076
1368
  }
1077
1369
  function getEmptySnapshot() {
1078
- return emptySnapshot;
1370
+ return emptySnapshot;
1079
1371
  }
1080
- var emptySnapshot = {
1081
- instances: []
1082
- };
1083
- var C = {
1084
- bg: "#0e1015",
1085
- bgPanel: "#161921",
1086
- bgCard: "#1c2030",
1087
- bgInput: "#111318",
1088
- border: "#2a2f3e",
1089
- borderLight: "#343a4f",
1090
- text: "#e2e8f0",
1091
- textMuted: "#6b7280",
1092
- textDim: "#9ca3af",
1093
- teal: "#2dd4bf",
1094
- tealDim: "rgba(45,212,191,0.12)",
1095
- tealGlow: "rgba(45,212,191,0.06)",
1096
- error: "#f87171",
1097
- errorBg: "rgba(248,113,113,0.08)",
1098
- errorBorder: "rgba(248,113,113,0.25)",
1099
- success: "#34d399",
1100
- successBg: "rgba(52,211,153,0.08)",
1101
- amber: "#fbbf24"
1102
- };
1103
- var floatingRootStyles = {
1104
- position: "fixed",
1105
- inset: 0,
1106
- pointerEvents: "none",
1107
- zIndex: 9998
1108
- };
1109
- var triggerButtonStyles = {
1110
- position: "absolute",
1111
- right: "16px",
1112
- bottom: "16px",
1113
- display: "inline-flex",
1114
- alignItems: "center",
1115
- gap: "0.3rem",
1116
- border: `1px solid ${C.border}`,
1117
- borderRadius: "8px",
1118
- padding: "0.3rem 0.45rem",
1119
- background: C.bgPanel,
1120
- color: C.text,
1121
- boxShadow: `0 0 0 1px ${C.border}, 0 4px 16px rgba(0,0,0,0.5)`,
1122
- cursor: "grab",
1123
- touchAction: "none",
1124
- userSelect: "none",
1125
- pointerEvents: "auto"
1126
- };
1127
- var triggerIconStyles = {
1128
- color: C.teal,
1129
- fontSize: "0.9rem",
1130
- lineHeight: 1
1131
- };
1132
- var triggerCountStyles = {
1133
- minWidth: "1.1rem",
1134
- borderRadius: "4px",
1135
- padding: "0.05rem 0.25rem",
1136
- backgroundColor: C.tealDim,
1137
- color: C.teal,
1138
- fontSize: "0.65rem",
1139
- fontWeight: 700,
1140
- textAlign: "center",
1141
- fontFamily: "ui-monospace, monospace"
1142
- };
1143
- var overlayStyles = {
1144
- position: "fixed",
1145
- inset: 0,
1146
- zIndex: 9999,
1147
- display: "flex",
1148
- alignItems: "center",
1149
- justifyContent: "center",
1150
- padding: "1.5rem",
1151
- backgroundColor: "rgba(0,0,0,0.72)",
1152
- backdropFilter: "blur(8px)"
1153
- };
1154
- var dialogStyles = {
1155
- width: "min(72rem, 100%)",
1156
- height: "min(90vh, 860px)",
1157
- display: "flex",
1158
- flexDirection: "column",
1159
- border: `1px solid ${C.border}`,
1160
- borderRadius: "16px",
1161
- background: C.bg,
1162
- boxShadow: `0 0 0 1px ${C.border}, 0 40px 80px rgba(0,0,0,0.8), 0 0 60px rgba(45,212,191,0.04)`,
1163
- overflow: "hidden",
1164
- fontFamily: "ui-sans-serif, system-ui, sans-serif",
1165
- color: C.text,
1166
- fontSize: "0.88rem"
1167
- };
1168
- var headerStyles = {
1169
- display: "flex",
1170
- justifyContent: "space-between",
1171
- alignItems: "center",
1172
- gap: "1rem",
1173
- padding: "0.85rem 1.1rem",
1174
- borderBottom: `1px solid ${C.border}`,
1175
- background: C.bgPanel,
1176
- flexShrink: 0
1177
- };
1178
- var headerLeftStyles = {
1179
- display: "flex",
1180
- alignItems: "center",
1181
- gap: "0.75rem"
1182
- };
1183
- var headerLogoStyles = {
1184
- fontSize: "1.3rem",
1185
- color: C.teal,
1186
- lineHeight: 1
1187
- };
1188
- var eyebrowStyles = {
1189
- fontSize: "0.65rem",
1190
- fontWeight: 600,
1191
- letterSpacing: "0.1em",
1192
- textTransform: "uppercase",
1193
- color: C.textMuted,
1194
- fontFamily: "ui-monospace, monospace"
1195
- };
1196
- var titleStyles = {
1197
- margin: "0.05rem 0 0",
1198
- fontSize: "0.95rem",
1199
- fontWeight: 700,
1200
- color: C.text,
1201
- letterSpacing: "-0.01em"
1202
- };
1203
- var headerRightStyles = {
1204
- display: "flex",
1205
- alignItems: "center",
1206
- gap: "0.6rem"
1207
- };
1208
- var instancePickerLabelStyles = {
1209
- display: "flex",
1210
- alignItems: "center",
1211
- gap: "0.5rem"
1212
- };
1213
- var instancePickerTextStyles = {
1214
- fontSize: "0.72rem",
1215
- fontWeight: 600,
1216
- color: C.textMuted,
1217
- textTransform: "uppercase",
1218
- letterSpacing: "0.06em"
1219
- };
1220
- var instancePickerSelectStyles = {
1221
- borderRadius: "7px",
1222
- border: `1px solid ${C.border}`,
1223
- padding: "0.35rem 0.6rem",
1224
- backgroundColor: C.bgCard,
1225
- color: C.text,
1226
- fontSize: "0.82rem",
1227
- fontFamily: "ui-monospace, monospace",
1228
- cursor: "pointer"
1229
- };
1230
- var instanceCountBadgeStyles = {
1231
- fontSize: "0.72rem",
1232
- fontWeight: 600,
1233
- color: C.teal,
1234
- backgroundColor: C.tealDim,
1235
- borderRadius: "5px",
1236
- padding: "0.2rem 0.5rem",
1237
- fontFamily: "ui-monospace, monospace"
1238
- };
1239
- var closeButtonStyles = {
1240
- border: `1px solid ${C.border}`,
1241
- borderRadius: "7px",
1242
- width: "28px",
1243
- height: "28px",
1244
- display: "flex",
1245
- alignItems: "center",
1246
- justifyContent: "center",
1247
- backgroundColor: "transparent",
1248
- color: C.textMuted,
1249
- fontSize: "0.82rem",
1250
- fontWeight: 600,
1251
- cursor: "pointer"
1252
- };
1253
- var emptyStateStyles = {
1254
- display: "flex",
1255
- flexDirection: "column",
1256
- alignItems: "center",
1257
- justifyContent: "center",
1258
- padding: "4rem 2rem",
1259
- gap: "0.75rem",
1260
- flex: 1
1261
- };
1262
- var emptyStateIconStyles = {
1263
- fontSize: "2.5rem",
1264
- color: C.textMuted,
1265
- opacity: 0.4
1266
- };
1267
- var emptyStateTextStyles = {
1268
- margin: 0,
1269
- fontSize: "0.95rem",
1270
- fontWeight: 600,
1271
- color: C.textDim
1272
- };
1273
- var emptyStateSubtextStyles = {
1274
- margin: 0,
1275
- fontSize: "0.82rem",
1276
- color: C.textMuted,
1277
- textAlign: "center"
1278
- };
1279
- var inlineCodeStyles = {
1280
- fontFamily: "ui-monospace, monospace",
1281
- backgroundColor: C.bgCard,
1282
- border: `1px solid ${C.border}`,
1283
- borderRadius: "4px",
1284
- padding: "0.1em 0.4em",
1285
- fontSize: "0.88em",
1286
- color: C.teal
1287
- };
1288
- var contentLayoutStyles = {
1289
- display: "grid",
1290
- gridTemplateColumns: "200px minmax(0, 1fr)",
1291
- flex: 1,
1292
- minHeight: 0,
1293
- overflow: "hidden"
1294
- };
1295
- var sidebarStyles = {
1296
- display: "flex",
1297
- flexDirection: "column",
1298
- gap: "0",
1299
- padding: "0.75rem",
1300
- borderRight: `1px solid ${C.border}`,
1301
- background: C.bgPanel,
1302
- overflowY: "auto"
1303
- };
1304
- var navStyles = {
1305
- display: "flex",
1306
- flexDirection: "column",
1307
- gap: "0.25rem",
1308
- marginBottom: "1rem"
1309
- };
1310
- var navIconStyles = {
1311
- fontSize: "0.7rem",
1312
- opacity: 0.7
1313
- };
1314
- var sidebarInfoStyles = {
1315
- marginTop: "auto",
1316
- padding: "0.75rem",
1317
- borderRadius: "8px",
1318
- background: C.bgCard,
1319
- border: `1px solid ${C.border}`
1320
- };
1321
- var sidebarInfoLabelStyles = {
1322
- fontSize: "0.65rem",
1323
- fontWeight: 600,
1324
- letterSpacing: "0.08em",
1325
- textTransform: "uppercase",
1326
- color: C.textMuted,
1327
- marginBottom: "0.3rem"
1328
- };
1329
- var sidebarInfoValueStyles = {
1330
- fontSize: "0.88rem",
1331
- fontWeight: 600,
1332
- color: C.text,
1333
- wordBreak: "break-word",
1334
- fontFamily: "ui-monospace, monospace"
1335
- };
1336
- var sidebarInfoSubStyles = {
1337
- fontSize: "0.72rem",
1338
- color: C.textMuted,
1339
- fontFamily: "ui-monospace, monospace",
1340
- marginTop: "0.25rem"
1341
- };
1342
- var mainPaneStyles = {
1343
- minWidth: 0,
1344
- overflowY: "auto",
1345
- padding: "1rem"
1346
- };
1347
- var overviewLayoutStyles = {
1348
- display: "flex",
1349
- flexDirection: "column",
1350
- gap: "1.25rem"
1351
- };
1352
- var overviewCardsRowStyles = {
1353
- display: "grid",
1354
- gridTemplateColumns: "repeat(auto-fit, minmax(11rem, 1fr))",
1355
- gap: "0.75rem"
1356
- };
1357
- var overviewCardStyles = {
1358
- padding: "0.9rem 1rem",
1359
- borderRadius: "10px",
1360
- border: `1px solid ${C.border}`,
1361
- background: C.bgCard
1362
- };
1363
- var overviewCardLabelStyles = {
1364
- fontSize: "0.68rem",
1365
- fontWeight: 600,
1366
- letterSpacing: "0.08em",
1367
- textTransform: "uppercase",
1368
- color: C.textMuted,
1369
- marginBottom: "0.4rem"
1370
- };
1371
- var overviewCardValueStyles = {
1372
- fontSize: "1rem",
1373
- fontWeight: 700,
1374
- color: C.text,
1375
- wordBreak: "break-word"
1376
- };
1377
- var overviewSectionStyles = {
1378
- display: "flex",
1379
- flexDirection: "column",
1380
- gap: "0.5rem"
1381
- };
1382
- var overviewSectionTitleStyles = {
1383
- fontSize: "0.72rem",
1384
- fontWeight: 600,
1385
- letterSpacing: "0.08em",
1386
- textTransform: "uppercase",
1387
- color: C.textMuted
1388
- };
1389
- var overviewSectionHeaderStyles = {
1390
- display: "flex",
1391
- alignItems: "center",
1392
- justifyContent: "space-between",
1393
- gap: "0.75rem"
1394
- };
1395
- var overviewRefreshButtonStyles = {
1396
- border: `1px solid ${C.border}`,
1397
- borderRadius: "7px",
1398
- padding: "0.35rem 0.7rem",
1399
- backgroundColor: "transparent",
1400
- color: C.textDim,
1401
- fontSize: "0.78rem",
1402
- fontFamily: "ui-monospace, monospace",
1403
- cursor: "pointer",
1404
- flexShrink: 0
1405
- };
1406
- var overviewAccumulatorValueStyles = {
1407
- padding: "0.75rem",
1408
- borderRadius: "8px",
1409
- border: `1px solid ${C.border}`,
1410
- background: C.bgCard,
1411
- fontFamily: "ui-monospace, monospace",
1412
- fontSize: "0.78rem",
1413
- color: C.text,
1414
- lineHeight: 1.5,
1415
- wordBreak: "break-all"
1416
- };
1417
- var overviewAccumulatorEmptyStyles = {
1418
- color: C.textMuted,
1419
- fontStyle: "italic"
1420
- };
1421
- var overviewAccumulatorErrorStyles = {
1422
- color: C.error
1423
- };
1424
- var overviewEmptyStyles = {
1425
- fontSize: "0.82rem",
1426
- color: C.textMuted,
1427
- fontStyle: "italic"
1428
- };
1429
- var crdtTableListStyles = {
1430
- display: "flex",
1431
- flexDirection: "column",
1432
- gap: "0.25rem"
1433
- };
1434
- var crdtTableRowStyles = {
1435
- display: "flex",
1436
- alignItems: "center",
1437
- gap: "0.6rem",
1438
- padding: "0.5rem 0.75rem",
1439
- borderRadius: "7px",
1440
- background: C.bgCard,
1441
- border: `1px solid ${C.border}`
1442
- };
1443
- var crdtTableIconStyles = {
1444
- color: C.teal,
1445
- fontSize: "0.72rem"
1446
- };
1447
- var crdtTableNameStyles = {
1448
- fontFamily: "ui-monospace, monospace",
1449
- fontSize: "0.85rem",
1450
- color: C.text
1451
- };
1452
- var permissionRowStyles = {
1453
- display: "flex",
1454
- alignItems: "center",
1455
- gap: "0.6rem",
1456
- fontSize: "0.82rem",
1457
- color: C.textDim
1458
- };
1459
- var permissionIconStyles = {
1460
- color: C.success,
1461
- fontWeight: 700,
1462
- fontSize: "0.85rem",
1463
- lineHeight: 1
1464
- };
1465
- var permissionTextStyles = {
1466
- color: C.textDim
1467
- };
1468
- var dataActionsStyles = {
1469
- display: "flex",
1470
- gap: "0.4rem"
1471
- };
1472
- var dataButtonStyles = {
1473
- border: `1px solid ${C.border}`,
1474
- borderRadius: "7px",
1475
- padding: "0.4rem 0.8rem",
1476
- backgroundColor: "transparent",
1477
- color: C.teal,
1478
- fontSize: "0.78rem",
1479
- fontWeight: 600,
1480
- cursor: "pointer",
1481
- whiteSpace: "nowrap"
1482
- };
1483
- var dataStatusSuccessStyles = {
1484
- fontSize: "0.75rem",
1485
- color: C.success
1486
- };
1487
- var dataStatusErrorStyles = {
1488
- fontSize: "0.75rem",
1489
- color: C.error,
1490
- wordBreak: "break-word"
1491
- };
1492
- var dangerZoneStyles = {
1493
- marginTop: "auto",
1494
- borderRadius: "10px",
1495
- border: `1px solid ${C.errorBorder}`,
1496
- padding: "0.75rem 1rem",
1497
- background: C.errorBg
1498
- };
1499
- var dangerZoneTitleStyles = {
1500
- fontSize: "0.65rem",
1501
- fontWeight: 700,
1502
- letterSpacing: "0.08em",
1503
- textTransform: "uppercase",
1504
- color: C.error,
1505
- marginBottom: "0.5rem"
1506
- };
1507
- var dangerZoneRowStyles = {
1508
- display: "flex",
1509
- alignItems: "center",
1510
- justifyContent: "space-between",
1511
- gap: "1rem"
1512
- };
1513
- var dangerZoneDescStyles = {
1514
- fontSize: "0.75rem",
1515
- color: C.textMuted,
1516
- lineHeight: 1.5
1517
- };
1518
- var dangerZoneActionsStyles = {
1519
- display: "flex",
1520
- gap: "0.4rem",
1521
- flexShrink: 0
1522
- };
1523
- var resetButtonStyles = {
1524
- flexShrink: 0,
1525
- border: `1px solid ${C.errorBorder}`,
1526
- borderRadius: "7px",
1527
- padding: "0.35rem 0.75rem",
1528
- backgroundColor: "transparent",
1529
- color: C.error,
1530
- fontSize: "0.78rem",
1531
- fontWeight: 600,
1532
- cursor: "pointer",
1533
- whiteSpace: "nowrap"
1534
- };
1535
- var resetCancelButtonStyles = {
1536
- border: `1px solid ${C.border}`,
1537
- borderRadius: "7px",
1538
- padding: "0.35rem 0.65rem",
1539
- backgroundColor: "transparent",
1540
- color: C.textDim,
1541
- fontSize: "0.78rem",
1542
- fontWeight: 600,
1543
- cursor: "pointer",
1544
- whiteSpace: "nowrap"
1545
- };
1546
- var resetConfirmButtonStyles = {
1547
- border: "none",
1548
- borderRadius: "7px",
1549
- padding: "0.35rem 0.75rem",
1550
- backgroundColor: C.error,
1551
- color: "#0e1015",
1552
- fontSize: "0.78rem",
1553
- fontWeight: 700,
1554
- cursor: "pointer",
1555
- whiteSpace: "nowrap"
1556
- };
1557
- var queryRunnerLayoutStyles = {
1558
- display: "flex",
1559
- flexDirection: "column",
1560
- gap: "0.75rem",
1561
- height: "100%"
1562
- };
1563
- var queryToolbarStyles = {
1564
- display: "flex",
1565
- alignItems: "center",
1566
- justifyContent: "space-between",
1567
- gap: "0.75rem",
1568
- flexWrap: "wrap"
1569
- };
1570
- var targetToggleStyles = {
1571
- display: "flex",
1572
- gap: "0",
1573
- borderRadius: "8px",
1574
- border: `1px solid ${C.border}`,
1575
- overflow: "hidden",
1576
- background: C.bgCard
1577
- };
1578
- var queryToolbarRightStyles = {
1579
- display: "flex",
1580
- alignItems: "center",
1581
- gap: "0.6rem"
1582
- };
1583
- var noInstanceWarningStyles = {
1584
- fontSize: "0.75rem",
1585
- color: C.amber,
1586
- fontWeight: 500
1587
- };
1588
- var shortcutHintStyles = {
1589
- fontSize: "0.72rem",
1590
- color: C.textMuted,
1591
- fontFamily: "ui-monospace, monospace",
1592
- padding: "0.2rem 0.5rem",
1593
- borderRadius: "5px",
1594
- border: `1px solid ${C.border}`,
1595
- background: C.bgCard
1596
- };
1597
- var editorWrapperStyles = {
1598
- borderRadius: "10px",
1599
- border: `1px solid ${C.border}`,
1600
- overflow: "hidden",
1601
- background: C.bgInput
1602
- };
1603
- var textareaStyles = {
1604
- width: "100%",
1605
- minHeight: "9rem",
1606
- resize: "vertical",
1607
- border: "none",
1608
- padding: "0.85rem 1rem",
1609
- backgroundColor: "transparent",
1610
- color: C.text,
1611
- fontSize: "0.875rem",
1612
- fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
1613
- lineHeight: 1.6,
1614
- outline: "none",
1615
- boxSizing: "border-box"
1616
- };
1617
- var helperTextStyles = {
1618
- fontSize: "0.75rem",
1619
- lineHeight: 1.5,
1620
- color: C.textMuted
1621
- };
1622
- var resultPanelStyles = {
1623
- display: "flex",
1624
- flexDirection: "column",
1625
- gap: "0.6rem",
1626
- borderRadius: "10px",
1627
- border: `1px solid ${C.border}`,
1628
- overflow: "hidden",
1629
- background: C.bgPanel
1630
- };
1631
- var errorPanelStyles = {
1632
- display: "flex",
1633
- flexDirection: "column",
1634
- gap: "0.6rem",
1635
- padding: "0.85rem 1rem",
1636
- borderRadius: "10px",
1637
- border: `1px solid ${C.errorBorder}`,
1638
- background: C.errorBg
1639
- };
1640
- var resultHeaderStyles = {
1641
- display: "flex",
1642
- alignItems: "center",
1643
- gap: "0.6rem",
1644
- padding: "0.6rem 0.85rem",
1645
- borderBottom: `1px solid ${C.border}`,
1646
- background: C.bgCard
1647
- };
1648
- var successBadgeStyles = {
1649
- fontSize: "0.72rem",
1650
- fontWeight: 700,
1651
- color: C.success,
1652
- backgroundColor: C.successBg,
1653
- borderRadius: "5px",
1654
- padding: "0.15rem 0.5rem",
1655
- fontFamily: "ui-monospace, monospace"
1656
- };
1657
- var errorBadgeStyles = {
1658
- fontSize: "0.72rem",
1659
- fontWeight: 700,
1660
- color: C.error,
1661
- backgroundColor: C.errorBg,
1662
- borderRadius: "5px",
1663
- padding: "0.15rem 0.5rem",
1664
- fontFamily: "ui-monospace, monospace"
1665
- };
1666
- var resultMetaStyles = {
1667
- fontSize: "0.72rem",
1668
- color: C.textMuted,
1669
- fontFamily: "ui-monospace, monospace"
1670
- };
1671
- var resultEmptyStyles = {
1672
- padding: "1.5rem",
1673
- fontSize: "0.82rem",
1674
- color: C.textMuted,
1675
- fontStyle: "italic",
1676
- textAlign: "center"
1677
- };
1678
- var resultRawStyles = {
1679
- margin: 0,
1680
- padding: "0.85rem 1rem",
1681
- overflowX: "auto",
1682
- whiteSpace: "pre-wrap",
1683
- wordBreak: "break-word",
1684
- fontSize: "0.8rem",
1685
- lineHeight: 1.5,
1686
- color: C.text,
1687
- fontFamily: "ui-monospace, monospace"
1688
- };
1689
- var errorMessageStyles = {
1690
- margin: 0,
1691
- fontSize: "0.82rem",
1692
- lineHeight: 1.6,
1693
- color: C.error,
1694
- fontFamily: "ui-monospace, monospace",
1695
- whiteSpace: "pre-wrap",
1696
- wordBreak: "break-word"
1697
- };
1698
- var tableWrapperStyles = {
1699
- overflowX: "auto",
1700
- maxHeight: "320px",
1701
- overflowY: "auto"
1702
- };
1703
- var tableStyles = {
1704
- width: "100%",
1705
- borderCollapse: "collapse",
1706
- fontSize: "0.8rem",
1707
- fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace"
1708
- };
1709
- var thStyles = {
1710
- padding: "0.5rem 0.85rem",
1711
- textAlign: "left",
1712
- fontWeight: 600,
1713
- fontSize: "0.7rem",
1714
- letterSpacing: "0.05em",
1715
- textTransform: "uppercase",
1716
- color: C.textMuted,
1717
- borderBottom: `1px solid ${C.border}`,
1718
- borderRight: `1px solid ${C.border}`,
1719
- background: C.bgCard,
1720
- whiteSpace: "nowrap",
1721
- position: "sticky",
1722
- top: 0
1723
- };
1724
- var thRowNumStyles = {
1725
- ...thStyles,
1726
- color: C.textMuted,
1727
- opacity: 0.5,
1728
- width: "2.5rem",
1729
- textAlign: "right"
1730
- };
1731
- var trStyles = {
1732
- background: "transparent"
1733
- };
1734
- var trAltStyles = {
1735
- background: C.tealGlow
1736
- };
1737
- var tdStyles = {
1738
- padding: "0.45rem 0.85rem",
1739
- borderBottom: `1px solid ${C.border}`,
1740
- borderRight: `1px solid ${C.border}`,
1741
- color: C.text,
1742
- whiteSpace: "nowrap",
1743
- maxWidth: "300px",
1744
- overflow: "hidden",
1745
- textOverflow: "ellipsis"
1746
- };
1747
- var tdRowNumStyles = {
1748
- ...tdStyles,
1749
- color: C.textMuted,
1750
- opacity: 0.5,
1751
- textAlign: "right",
1752
- userSelect: "none"
1753
- };
1754
- var nullValueStyles = {
1755
- color: C.textMuted,
1756
- fontStyle: "italic",
1757
- opacity: 0.6
1758
- };
1759
- var jsonValueStyles = {
1760
- color: C.textDim
1761
- };
1372
+ const emptySnapshot = { instances: [] };
1373
+ const C = {
1374
+ bg: "#0e1015",
1375
+ bgPanel: "#161921",
1376
+ bgCard: "#1c2030",
1377
+ bgInput: "#111318",
1378
+ border: "#2a2f3e",
1379
+ borderLight: "#343a4f",
1380
+ text: "#e2e8f0",
1381
+ textMuted: "#6b7280",
1382
+ textDim: "#9ca3af",
1383
+ teal: "#2dd4bf",
1384
+ tealDim: "rgba(45,212,191,0.12)",
1385
+ tealGlow: "rgba(45,212,191,0.06)",
1386
+ error: "#f87171",
1387
+ errorBg: "rgba(248,113,113,0.08)",
1388
+ errorBorder: "rgba(248,113,113,0.25)",
1389
+ success: "#34d399",
1390
+ successBg: "rgba(52,211,153,0.08)",
1391
+ amber: "#fbbf24"
1392
+ };
1393
+ const floatingRootStyles = {
1394
+ position: "fixed",
1395
+ inset: 0,
1396
+ pointerEvents: "none",
1397
+ zIndex: 9998
1398
+ };
1399
+ const triggerButtonStyles = {
1400
+ position: "absolute",
1401
+ right: "16px",
1402
+ bottom: "16px",
1403
+ display: "inline-flex",
1404
+ alignItems: "center",
1405
+ gap: "0.3rem",
1406
+ border: `1px solid ${C.border}`,
1407
+ borderRadius: "8px",
1408
+ padding: "0.3rem 0.45rem",
1409
+ background: C.bgPanel,
1410
+ color: C.text,
1411
+ boxShadow: `0 0 0 1px ${C.border}, 0 4px 16px rgba(0,0,0,0.5)`,
1412
+ cursor: "grab",
1413
+ touchAction: "none",
1414
+ userSelect: "none",
1415
+ pointerEvents: "auto"
1416
+ };
1417
+ const triggerIconStyles = {
1418
+ color: C.teal,
1419
+ fontSize: "0.9rem",
1420
+ lineHeight: 1
1421
+ };
1422
+ const triggerCountStyles = {
1423
+ minWidth: "1.1rem",
1424
+ borderRadius: "4px",
1425
+ padding: "0.05rem 0.25rem",
1426
+ backgroundColor: C.tealDim,
1427
+ color: C.teal,
1428
+ fontSize: "0.65rem",
1429
+ fontWeight: 700,
1430
+ textAlign: "center",
1431
+ fontFamily: "ui-monospace, monospace"
1432
+ };
1433
+ const overlayStyles = {
1434
+ position: "fixed",
1435
+ inset: 0,
1436
+ zIndex: 9999,
1437
+ display: "flex",
1438
+ alignItems: "center",
1439
+ justifyContent: "center",
1440
+ padding: "1.5rem",
1441
+ backgroundColor: "rgba(0,0,0,0.72)",
1442
+ backdropFilter: "blur(8px)"
1443
+ };
1444
+ const dialogStyles = {
1445
+ width: "min(72rem, 100%)",
1446
+ height: "min(90vh, 860px)",
1447
+ display: "flex",
1448
+ flexDirection: "column",
1449
+ border: `1px solid ${C.border}`,
1450
+ borderRadius: "16px",
1451
+ background: C.bg,
1452
+ boxShadow: `0 0 0 1px ${C.border}, 0 40px 80px rgba(0,0,0,0.8), 0 0 60px rgba(45,212,191,0.04)`,
1453
+ overflow: "hidden",
1454
+ fontFamily: "ui-sans-serif, system-ui, sans-serif",
1455
+ color: C.text,
1456
+ fontSize: "0.88rem"
1457
+ };
1458
+ const headerStyles = {
1459
+ display: "flex",
1460
+ justifyContent: "space-between",
1461
+ alignItems: "center",
1462
+ gap: "1rem",
1463
+ padding: "0.85rem 1.1rem",
1464
+ borderBottom: `1px solid ${C.border}`,
1465
+ background: C.bgPanel,
1466
+ flexShrink: 0
1467
+ };
1468
+ const headerLeftStyles = {
1469
+ display: "flex",
1470
+ alignItems: "center",
1471
+ gap: "0.75rem"
1472
+ };
1473
+ const headerLogoStyles = {
1474
+ fontSize: "1.3rem",
1475
+ color: C.teal,
1476
+ lineHeight: 1
1477
+ };
1478
+ const eyebrowStyles = {
1479
+ fontSize: "0.65rem",
1480
+ fontWeight: 600,
1481
+ letterSpacing: "0.1em",
1482
+ textTransform: "uppercase",
1483
+ color: C.textMuted,
1484
+ fontFamily: "ui-monospace, monospace"
1485
+ };
1486
+ const titleStyles = {
1487
+ margin: "0.05rem 0 0",
1488
+ fontSize: "0.95rem",
1489
+ fontWeight: 700,
1490
+ color: C.text,
1491
+ letterSpacing: "-0.01em"
1492
+ };
1493
+ const headerRightStyles = {
1494
+ display: "flex",
1495
+ alignItems: "center",
1496
+ gap: "0.6rem"
1497
+ };
1498
+ const instancePickerLabelStyles = {
1499
+ display: "flex",
1500
+ alignItems: "center",
1501
+ gap: "0.5rem"
1502
+ };
1503
+ const instancePickerTextStyles = {
1504
+ fontSize: "0.72rem",
1505
+ fontWeight: 600,
1506
+ color: C.textMuted,
1507
+ textTransform: "uppercase",
1508
+ letterSpacing: "0.06em"
1509
+ };
1510
+ const instancePickerSelectStyles = {
1511
+ borderRadius: "7px",
1512
+ border: `1px solid ${C.border}`,
1513
+ padding: "0.35rem 0.6rem",
1514
+ backgroundColor: C.bgCard,
1515
+ color: C.text,
1516
+ fontSize: "0.82rem",
1517
+ fontFamily: "ui-monospace, monospace",
1518
+ cursor: "pointer"
1519
+ };
1520
+ const instanceCountBadgeStyles = {
1521
+ fontSize: "0.72rem",
1522
+ fontWeight: 600,
1523
+ color: C.teal,
1524
+ backgroundColor: C.tealDim,
1525
+ borderRadius: "5px",
1526
+ padding: "0.2rem 0.5rem",
1527
+ fontFamily: "ui-monospace, monospace"
1528
+ };
1529
+ const closeButtonStyles = {
1530
+ border: `1px solid ${C.border}`,
1531
+ borderRadius: "7px",
1532
+ width: "28px",
1533
+ height: "28px",
1534
+ display: "flex",
1535
+ alignItems: "center",
1536
+ justifyContent: "center",
1537
+ backgroundColor: "transparent",
1538
+ color: C.textMuted,
1539
+ fontSize: "0.82rem",
1540
+ fontWeight: 600,
1541
+ cursor: "pointer"
1542
+ };
1543
+ const emptyStateStyles = {
1544
+ display: "flex",
1545
+ flexDirection: "column",
1546
+ alignItems: "center",
1547
+ justifyContent: "center",
1548
+ padding: "4rem 2rem",
1549
+ gap: "0.75rem",
1550
+ flex: 1
1551
+ };
1552
+ const emptyStateIconStyles = {
1553
+ fontSize: "2.5rem",
1554
+ color: C.textMuted,
1555
+ opacity: .4
1556
+ };
1557
+ const emptyStateTextStyles = {
1558
+ margin: 0,
1559
+ fontSize: "0.95rem",
1560
+ fontWeight: 600,
1561
+ color: C.textDim
1562
+ };
1563
+ const emptyStateSubtextStyles = {
1564
+ margin: 0,
1565
+ fontSize: "0.82rem",
1566
+ color: C.textMuted,
1567
+ textAlign: "center"
1568
+ };
1569
+ const inlineCodeStyles = {
1570
+ fontFamily: "ui-monospace, monospace",
1571
+ backgroundColor: C.bgCard,
1572
+ border: `1px solid ${C.border}`,
1573
+ borderRadius: "4px",
1574
+ padding: "0.1em 0.4em",
1575
+ fontSize: "0.88em",
1576
+ color: C.teal
1577
+ };
1578
+ const contentLayoutStyles = {
1579
+ display: "grid",
1580
+ gridTemplateColumns: "200px minmax(0, 1fr)",
1581
+ flex: 1,
1582
+ minHeight: 0,
1583
+ overflow: "hidden"
1584
+ };
1585
+ const sidebarStyles = {
1586
+ display: "flex",
1587
+ flexDirection: "column",
1588
+ gap: "0",
1589
+ padding: "0.75rem",
1590
+ borderRight: `1px solid ${C.border}`,
1591
+ background: C.bgPanel,
1592
+ overflowY: "auto"
1593
+ };
1594
+ const navStyles = {
1595
+ display: "flex",
1596
+ flexDirection: "column",
1597
+ gap: "0.25rem",
1598
+ marginBottom: "1rem"
1599
+ };
1600
+ const navIconStyles = {
1601
+ fontSize: "0.7rem",
1602
+ opacity: .7
1603
+ };
1604
+ const sidebarInfoStyles = {
1605
+ marginTop: "auto",
1606
+ padding: "0.75rem",
1607
+ borderRadius: "8px",
1608
+ background: C.bgCard,
1609
+ border: `1px solid ${C.border}`
1610
+ };
1611
+ const sidebarInfoLabelStyles = {
1612
+ fontSize: "0.65rem",
1613
+ fontWeight: 600,
1614
+ letterSpacing: "0.08em",
1615
+ textTransform: "uppercase",
1616
+ color: C.textMuted,
1617
+ marginBottom: "0.3rem"
1618
+ };
1619
+ const sidebarInfoValueStyles = {
1620
+ fontSize: "0.88rem",
1621
+ fontWeight: 600,
1622
+ color: C.text,
1623
+ wordBreak: "break-word",
1624
+ fontFamily: "ui-monospace, monospace"
1625
+ };
1626
+ const sidebarInfoSubStyles = {
1627
+ fontSize: "0.72rem",
1628
+ color: C.textMuted,
1629
+ fontFamily: "ui-monospace, monospace",
1630
+ marginTop: "0.25rem"
1631
+ };
1632
+ const mainPaneStyles = {
1633
+ minWidth: 0,
1634
+ overflowY: "auto",
1635
+ padding: "1rem"
1636
+ };
1637
+ const overviewLayoutStyles = {
1638
+ display: "flex",
1639
+ flexDirection: "column",
1640
+ gap: "1.25rem"
1641
+ };
1642
+ const overviewCardsRowStyles = {
1643
+ display: "grid",
1644
+ gridTemplateColumns: "repeat(auto-fit, minmax(11rem, 1fr))",
1645
+ gap: "0.75rem"
1646
+ };
1647
+ const overviewCardStyles = {
1648
+ padding: "0.9rem 1rem",
1649
+ borderRadius: "10px",
1650
+ border: `1px solid ${C.border}`,
1651
+ background: C.bgCard
1652
+ };
1653
+ const overviewCardLabelStyles = {
1654
+ fontSize: "0.68rem",
1655
+ fontWeight: 600,
1656
+ letterSpacing: "0.08em",
1657
+ textTransform: "uppercase",
1658
+ color: C.textMuted,
1659
+ marginBottom: "0.4rem"
1660
+ };
1661
+ const overviewCardValueStyles = {
1662
+ fontSize: "1rem",
1663
+ fontWeight: 700,
1664
+ color: C.text,
1665
+ wordBreak: "break-word"
1666
+ };
1667
+ const overviewSectionStyles = {
1668
+ display: "flex",
1669
+ flexDirection: "column",
1670
+ gap: "0.5rem"
1671
+ };
1672
+ const overviewSectionTitleStyles = {
1673
+ fontSize: "0.72rem",
1674
+ fontWeight: 600,
1675
+ letterSpacing: "0.08em",
1676
+ textTransform: "uppercase",
1677
+ color: C.textMuted
1678
+ };
1679
+ const overviewSectionHeaderStyles = {
1680
+ display: "flex",
1681
+ alignItems: "center",
1682
+ justifyContent: "space-between",
1683
+ gap: "0.75rem"
1684
+ };
1685
+ const overviewRefreshButtonStyles = {
1686
+ border: `1px solid ${C.border}`,
1687
+ borderRadius: "7px",
1688
+ padding: "0.35rem 0.7rem",
1689
+ backgroundColor: "transparent",
1690
+ color: C.textDim,
1691
+ fontSize: "0.78rem",
1692
+ fontFamily: "ui-monospace, monospace",
1693
+ cursor: "pointer",
1694
+ flexShrink: 0
1695
+ };
1696
+ const overviewAccumulatorValueStyles = {
1697
+ padding: "0.75rem",
1698
+ borderRadius: "8px",
1699
+ border: `1px solid ${C.border}`,
1700
+ background: C.bgCard,
1701
+ fontFamily: "ui-monospace, monospace",
1702
+ fontSize: "0.78rem",
1703
+ color: C.text,
1704
+ lineHeight: 1.5,
1705
+ wordBreak: "break-all"
1706
+ };
1707
+ const overviewAccumulatorEmptyStyles = {
1708
+ color: C.textMuted,
1709
+ fontStyle: "italic"
1710
+ };
1711
+ const overviewAccumulatorErrorStyles = { color: C.error };
1712
+ const overviewEmptyStyles = {
1713
+ fontSize: "0.82rem",
1714
+ color: C.textMuted,
1715
+ fontStyle: "italic"
1716
+ };
1717
+ const crdtTableListStyles = {
1718
+ display: "flex",
1719
+ flexDirection: "column",
1720
+ gap: "0.25rem"
1721
+ };
1722
+ const crdtTableRowStyles = {
1723
+ display: "flex",
1724
+ alignItems: "center",
1725
+ gap: "0.6rem",
1726
+ padding: "0.5rem 0.75rem",
1727
+ borderRadius: "7px",
1728
+ background: C.bgCard,
1729
+ border: `1px solid ${C.border}`
1730
+ };
1731
+ const crdtTableIconStyles = {
1732
+ color: C.teal,
1733
+ fontSize: "0.72rem"
1734
+ };
1735
+ const crdtTableNameStyles = {
1736
+ fontFamily: "ui-monospace, monospace",
1737
+ fontSize: "0.85rem",
1738
+ color: C.text
1739
+ };
1740
+ const permissionRowStyles = {
1741
+ display: "flex",
1742
+ alignItems: "center",
1743
+ gap: "0.6rem",
1744
+ fontSize: "0.82rem",
1745
+ color: C.textDim
1746
+ };
1747
+ const permissionIconStyles = {
1748
+ color: C.success,
1749
+ fontWeight: 700,
1750
+ fontSize: "0.85rem",
1751
+ lineHeight: 1
1752
+ };
1753
+ const permissionTextStyles = { color: C.textDim };
1754
+ const dataActionsStyles = {
1755
+ display: "flex",
1756
+ gap: "0.4rem"
1757
+ };
1758
+ const dataButtonStyles = {
1759
+ border: `1px solid ${C.border}`,
1760
+ borderRadius: "7px",
1761
+ padding: "0.4rem 0.8rem",
1762
+ backgroundColor: "transparent",
1763
+ color: C.teal,
1764
+ fontSize: "0.78rem",
1765
+ fontWeight: 600,
1766
+ cursor: "pointer",
1767
+ whiteSpace: "nowrap"
1768
+ };
1769
+ const dataStatusSuccessStyles = {
1770
+ fontSize: "0.75rem",
1771
+ color: C.success
1772
+ };
1773
+ const dataStatusErrorStyles = {
1774
+ fontSize: "0.75rem",
1775
+ color: C.error,
1776
+ wordBreak: "break-word"
1777
+ };
1778
+ const dangerZoneStyles = {
1779
+ marginTop: "auto",
1780
+ borderRadius: "10px",
1781
+ border: `1px solid ${C.errorBorder}`,
1782
+ padding: "0.75rem 1rem",
1783
+ background: C.errorBg
1784
+ };
1785
+ const dangerZoneTitleStyles = {
1786
+ fontSize: "0.65rem",
1787
+ fontWeight: 700,
1788
+ letterSpacing: "0.08em",
1789
+ textTransform: "uppercase",
1790
+ color: C.error,
1791
+ marginBottom: "0.5rem"
1792
+ };
1793
+ const dangerZoneRowStyles = {
1794
+ display: "flex",
1795
+ alignItems: "center",
1796
+ justifyContent: "space-between",
1797
+ gap: "1rem"
1798
+ };
1799
+ const dangerZoneDescStyles = {
1800
+ fontSize: "0.75rem",
1801
+ color: C.textMuted,
1802
+ lineHeight: 1.5
1803
+ };
1804
+ const dangerZoneActionsStyles = {
1805
+ display: "flex",
1806
+ gap: "0.4rem",
1807
+ flexShrink: 0
1808
+ };
1809
+ const resetButtonStyles = {
1810
+ flexShrink: 0,
1811
+ border: `1px solid ${C.errorBorder}`,
1812
+ borderRadius: "7px",
1813
+ padding: "0.35rem 0.75rem",
1814
+ backgroundColor: "transparent",
1815
+ color: C.error,
1816
+ fontSize: "0.78rem",
1817
+ fontWeight: 600,
1818
+ cursor: "pointer",
1819
+ whiteSpace: "nowrap"
1820
+ };
1821
+ const resetCancelButtonStyles = {
1822
+ border: `1px solid ${C.border}`,
1823
+ borderRadius: "7px",
1824
+ padding: "0.35rem 0.65rem",
1825
+ backgroundColor: "transparent",
1826
+ color: C.textDim,
1827
+ fontSize: "0.78rem",
1828
+ fontWeight: 600,
1829
+ cursor: "pointer",
1830
+ whiteSpace: "nowrap"
1831
+ };
1832
+ const resetConfirmButtonStyles = {
1833
+ border: "none",
1834
+ borderRadius: "7px",
1835
+ padding: "0.35rem 0.75rem",
1836
+ backgroundColor: C.error,
1837
+ color: "#0e1015",
1838
+ fontSize: "0.78rem",
1839
+ fontWeight: 700,
1840
+ cursor: "pointer",
1841
+ whiteSpace: "nowrap"
1842
+ };
1843
+ const queryRunnerLayoutStyles = {
1844
+ display: "flex",
1845
+ flexDirection: "column",
1846
+ gap: "0.75rem",
1847
+ height: "100%"
1848
+ };
1849
+ const queryToolbarStyles = {
1850
+ display: "flex",
1851
+ alignItems: "center",
1852
+ justifyContent: "space-between",
1853
+ gap: "0.75rem",
1854
+ flexWrap: "wrap"
1855
+ };
1856
+ const targetToggleStyles = {
1857
+ display: "flex",
1858
+ gap: "0",
1859
+ borderRadius: "8px",
1860
+ border: `1px solid ${C.border}`,
1861
+ overflow: "hidden",
1862
+ background: C.bgCard
1863
+ };
1864
+ const queryToolbarRightStyles = {
1865
+ display: "flex",
1866
+ alignItems: "center",
1867
+ gap: "0.6rem"
1868
+ };
1869
+ const noInstanceWarningStyles = {
1870
+ fontSize: "0.75rem",
1871
+ color: C.amber,
1872
+ fontWeight: 500
1873
+ };
1874
+ const shortcutHintStyles = {
1875
+ fontSize: "0.72rem",
1876
+ color: C.textMuted,
1877
+ fontFamily: "ui-monospace, monospace",
1878
+ padding: "0.2rem 0.5rem",
1879
+ borderRadius: "5px",
1880
+ border: `1px solid ${C.border}`,
1881
+ background: C.bgCard
1882
+ };
1883
+ const editorWrapperStyles = {
1884
+ borderRadius: "10px",
1885
+ border: `1px solid ${C.border}`,
1886
+ overflow: "hidden",
1887
+ background: C.bgInput
1888
+ };
1889
+ const textareaStyles = {
1890
+ width: "100%",
1891
+ minHeight: "9rem",
1892
+ resize: "vertical",
1893
+ border: "none",
1894
+ padding: "0.85rem 1rem",
1895
+ backgroundColor: "transparent",
1896
+ color: C.text,
1897
+ fontSize: "0.875rem",
1898
+ fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
1899
+ lineHeight: 1.6,
1900
+ outline: "none",
1901
+ boxSizing: "border-box"
1902
+ };
1903
+ const helperTextStyles = {
1904
+ fontSize: "0.75rem",
1905
+ lineHeight: 1.5,
1906
+ color: C.textMuted
1907
+ };
1908
+ const resultPanelStyles = {
1909
+ display: "flex",
1910
+ flexDirection: "column",
1911
+ gap: "0.6rem",
1912
+ borderRadius: "10px",
1913
+ border: `1px solid ${C.border}`,
1914
+ overflow: "hidden",
1915
+ background: C.bgPanel
1916
+ };
1917
+ const errorPanelStyles = {
1918
+ display: "flex",
1919
+ flexDirection: "column",
1920
+ gap: "0.6rem",
1921
+ padding: "0.85rem 1rem",
1922
+ borderRadius: "10px",
1923
+ border: `1px solid ${C.errorBorder}`,
1924
+ background: C.errorBg
1925
+ };
1926
+ const resultHeaderStyles = {
1927
+ display: "flex",
1928
+ alignItems: "center",
1929
+ gap: "0.6rem",
1930
+ padding: "0.6rem 0.85rem",
1931
+ borderBottom: `1px solid ${C.border}`,
1932
+ background: C.bgCard
1933
+ };
1934
+ const successBadgeStyles = {
1935
+ fontSize: "0.72rem",
1936
+ fontWeight: 700,
1937
+ color: C.success,
1938
+ backgroundColor: C.successBg,
1939
+ borderRadius: "5px",
1940
+ padding: "0.15rem 0.5rem",
1941
+ fontFamily: "ui-monospace, monospace"
1942
+ };
1943
+ const errorBadgeStyles = {
1944
+ fontSize: "0.72rem",
1945
+ fontWeight: 700,
1946
+ color: C.error,
1947
+ backgroundColor: C.errorBg,
1948
+ borderRadius: "5px",
1949
+ padding: "0.15rem 0.5rem",
1950
+ fontFamily: "ui-monospace, monospace"
1951
+ };
1952
+ const resultMetaStyles = {
1953
+ fontSize: "0.72rem",
1954
+ color: C.textMuted,
1955
+ fontFamily: "ui-monospace, monospace"
1956
+ };
1957
+ const resultEmptyStyles = {
1958
+ padding: "1.5rem",
1959
+ fontSize: "0.82rem",
1960
+ color: C.textMuted,
1961
+ fontStyle: "italic",
1962
+ textAlign: "center"
1963
+ };
1964
+ const resultRawStyles = {
1965
+ margin: 0,
1966
+ padding: "0.85rem 1rem",
1967
+ overflowX: "auto",
1968
+ whiteSpace: "pre-wrap",
1969
+ wordBreak: "break-word",
1970
+ fontSize: "0.8rem",
1971
+ lineHeight: 1.5,
1972
+ color: C.text,
1973
+ fontFamily: "ui-monospace, monospace"
1974
+ };
1975
+ const errorMessageStyles = {
1976
+ margin: 0,
1977
+ fontSize: "0.82rem",
1978
+ lineHeight: 1.6,
1979
+ color: C.error,
1980
+ fontFamily: "ui-monospace, monospace",
1981
+ whiteSpace: "pre-wrap",
1982
+ wordBreak: "break-word"
1983
+ };
1984
+ const tableWrapperStyles = {
1985
+ overflowX: "auto",
1986
+ maxHeight: "320px",
1987
+ overflowY: "auto"
1988
+ };
1989
+ const tableStyles = {
1990
+ width: "100%",
1991
+ borderCollapse: "collapse",
1992
+ fontSize: "0.8rem",
1993
+ fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace"
1994
+ };
1995
+ const thStyles = {
1996
+ padding: "0.5rem 0.85rem",
1997
+ textAlign: "left",
1998
+ fontWeight: 600,
1999
+ fontSize: "0.7rem",
2000
+ letterSpacing: "0.05em",
2001
+ textTransform: "uppercase",
2002
+ color: C.textMuted,
2003
+ borderBottom: `1px solid ${C.border}`,
2004
+ borderRight: `1px solid ${C.border}`,
2005
+ background: C.bgCard,
2006
+ whiteSpace: "nowrap",
2007
+ position: "sticky",
2008
+ top: 0
2009
+ };
2010
+ const thRowNumStyles = {
2011
+ ...thStyles,
2012
+ color: C.textMuted,
2013
+ opacity: .5,
2014
+ width: "2.5rem",
2015
+ textAlign: "right"
2016
+ };
2017
+ const trStyles = { background: "transparent" };
2018
+ const trAltStyles = { background: C.tealGlow };
2019
+ const tdStyles = {
2020
+ padding: "0.45rem 0.85rem",
2021
+ borderBottom: `1px solid ${C.border}`,
2022
+ borderRight: `1px solid ${C.border}`,
2023
+ color: C.text,
2024
+ whiteSpace: "nowrap",
2025
+ maxWidth: "300px",
2026
+ overflow: "hidden",
2027
+ textOverflow: "ellipsis"
2028
+ };
2029
+ const tdRowNumStyles = {
2030
+ ...tdStyles,
2031
+ color: C.textMuted,
2032
+ opacity: .5,
2033
+ textAlign: "right",
2034
+ userSelect: "none"
2035
+ };
2036
+ const nullValueStyles = {
2037
+ color: C.textMuted,
2038
+ fontStyle: "italic",
2039
+ opacity: .6
2040
+ };
2041
+ const jsonValueStyles = { color: C.textDim };
1762
2042
  function getTabButtonStyles(isActive) {
1763
- return {
1764
- display: "flex",
1765
- alignItems: "center",
1766
- gap: "0.5rem",
1767
- width: "100%",
1768
- border: "none",
1769
- borderRadius: "7px",
1770
- padding: "0.6rem 0.75rem",
1771
- background: isActive ? C.tealDim : "transparent",
1772
- color: isActive ? C.teal : C.textDim,
1773
- fontSize: "0.82rem",
1774
- fontWeight: isActive ? 700 : 500,
1775
- textAlign: "left",
1776
- cursor: "pointer",
1777
- transition: "background 0.15s",
1778
- borderLeft: isActive ? `2px solid ${C.teal}` : "2px solid transparent"
1779
- };
2043
+ return {
2044
+ display: "flex",
2045
+ alignItems: "center",
2046
+ gap: "0.5rem",
2047
+ width: "100%",
2048
+ border: "none",
2049
+ borderRadius: "7px",
2050
+ padding: "0.6rem 0.75rem",
2051
+ background: isActive ? C.tealDim : "transparent",
2052
+ color: isActive ? C.teal : C.textDim,
2053
+ fontSize: "0.82rem",
2054
+ fontWeight: isActive ? 700 : 500,
2055
+ textAlign: "left",
2056
+ cursor: "pointer",
2057
+ transition: "background 0.15s",
2058
+ borderLeft: isActive ? `2px solid ${C.teal}` : "2px solid transparent"
2059
+ };
1780
2060
  }
1781
2061
  function getTargetButtonStyles(isActive) {
1782
- return {
1783
- border: "none",
1784
- borderRight: `1px solid ${C.border}`,
1785
- padding: "0.45rem 0.85rem",
1786
- background: isActive ? C.tealDim : "transparent",
1787
- color: isActive ? C.teal : C.textMuted,
1788
- fontSize: "0.78rem",
1789
- fontWeight: isActive ? 700 : 500,
1790
- cursor: "pointer",
1791
- fontFamily: "ui-monospace, monospace",
1792
- transition: "background 0.1s",
1793
- whiteSpace: "nowrap"
1794
- };
2062
+ return {
2063
+ border: "none",
2064
+ borderRight: `1px solid ${C.border}`,
2065
+ padding: "0.45rem 0.85rem",
2066
+ background: isActive ? C.tealDim : "transparent",
2067
+ color: isActive ? C.teal : C.textMuted,
2068
+ fontSize: "0.78rem",
2069
+ fontWeight: isActive ? 700 : 500,
2070
+ cursor: "pointer",
2071
+ fontFamily: "ui-monospace, monospace",
2072
+ transition: "background 0.1s",
2073
+ whiteSpace: "nowrap"
2074
+ };
1795
2075
  }
1796
2076
  function runButtonStyles(enabled, running) {
1797
- return {
1798
- display: "inline-flex",
1799
- alignItems: "center",
1800
- gap: "0.4rem",
1801
- border: "none",
1802
- borderRadius: "7px",
1803
- padding: "0.45rem 0.9rem",
1804
- background: enabled ? C.teal : C.bgCard,
1805
- color: enabled ? "#0e1015" : C.textMuted,
1806
- fontSize: "0.82rem",
1807
- fontWeight: 700,
1808
- fontFamily: "ui-monospace, monospace",
1809
- cursor: enabled ? "pointer" : "not-allowed",
1810
- opacity: running ? 0.75 : 1,
1811
- transition: "background 0.15s",
1812
- whiteSpace: "nowrap"
1813
- };
2077
+ return {
2078
+ display: "inline-flex",
2079
+ alignItems: "center",
2080
+ gap: "0.4rem",
2081
+ border: "none",
2082
+ borderRadius: "7px",
2083
+ padding: "0.45rem 0.9rem",
2084
+ background: enabled ? C.teal : C.bgCard,
2085
+ color: enabled ? "#0e1015" : C.textMuted,
2086
+ fontSize: "0.82rem",
2087
+ fontWeight: 700,
2088
+ fontFamily: "ui-monospace, monospace",
2089
+ cursor: enabled ? "pointer" : "not-allowed",
2090
+ opacity: running ? .75 : 1,
2091
+ transition: "background 0.15s",
2092
+ whiteSpace: "nowrap"
2093
+ };
1814
2094
  }
1815
- var runningDotStyles = {
1816
- width: "6px",
1817
- height: "6px",
1818
- borderRadius: "50%",
1819
- backgroundColor: "currentColor"
1820
- };
1821
- var schemaLayoutStyles = {
1822
- display: "flex",
1823
- flexDirection: "column",
1824
- gap: "1.5rem"
1825
- };
1826
- var schemaSectionStyles = {
1827
- display: "flex",
1828
- flexDirection: "column",
1829
- gap: "0.65rem"
1830
- };
1831
- var schemaSectionHeaderStyles = {
1832
- display: "flex",
1833
- alignItems: "center",
1834
- gap: "0.6rem"
1835
- };
1836
- var schemaSectionTitleStyles = {
1837
- fontSize: "0.72rem",
1838
- fontWeight: 700,
1839
- letterSpacing: "0.08em",
1840
- textTransform: "uppercase",
1841
- color: C.textMuted
1842
- };
1843
- var schemaBadgeStyles = {
1844
- fontSize: "0.68rem",
1845
- fontWeight: 700,
1846
- color: C.teal,
1847
- backgroundColor: C.tealDim,
1848
- borderRadius: "4px",
1849
- padding: "0.1rem 0.4rem",
1850
- fontFamily: "ui-monospace, monospace"
1851
- };
1852
- var schemaMigrationsMetaStyles = {
1853
- display: "flex",
1854
- alignItems: "center",
1855
- gap: "0.5rem",
1856
- marginLeft: "auto"
1857
- };
1858
- var schemaVersionChipStyles = {
1859
- fontSize: "0.68rem",
1860
- fontFamily: "ui-monospace, monospace",
1861
- color: C.textMuted,
1862
- backgroundColor: C.bgCard,
1863
- border: `1px solid ${C.border}`,
1864
- borderRadius: "4px",
1865
- padding: "0.1rem 0.5rem"
1866
- };
1867
- var schemaTableGridStyles = {
1868
- borderRadius: "10px",
1869
- border: `1px solid ${C.border}`,
1870
- overflow: "hidden"
1871
- };
1872
- var schemaTableHeaderRowStyles = {
1873
- display: "grid",
1874
- gridTemplateColumns: "1fr 1fr 90px",
1875
- gap: 0,
1876
- backgroundColor: C.bgCard,
1877
- borderBottom: `1px solid ${C.border}`
1878
- };
1879
- var schemaColHeaderStyles = {
1880
- padding: "0.5rem 0.85rem",
1881
- fontSize: "0.68rem",
1882
- fontWeight: 700,
1883
- letterSpacing: "0.07em",
1884
- textTransform: "uppercase",
1885
- color: C.textMuted,
1886
- borderRight: `1px solid ${C.border}`
1887
- };
1888
- var schemaTableRowStyles = {
1889
- display: "grid",
1890
- gridTemplateColumns: "1fr 1fr 90px",
1891
- gap: 0,
1892
- borderBottom: `1px solid ${C.border}`
1893
- };
1894
- var schemaTableNameStyles = {
1895
- display: "flex",
1896
- alignItems: "center",
1897
- gap: "0.5rem",
1898
- padding: "0.6rem 0.85rem",
1899
- fontSize: "0.82rem",
1900
- fontFamily: "ui-monospace, monospace",
1901
- color: C.text,
1902
- borderRight: `1px solid ${C.border}`
1903
- };
1904
- var schemaTableIconStyles = {
1905
- color: C.teal,
1906
- fontSize: "0.68rem",
1907
- opacity: 0.8
1908
- };
1909
- var schemaCrdtNameStyles = {
1910
- display: "flex",
1911
- alignItems: "center",
1912
- padding: "0.6rem 0.85rem",
1913
- fontSize: "0.82rem",
1914
- fontFamily: "ui-monospace, monospace",
1915
- color: C.textDim,
1916
- borderRight: `1px solid ${C.border}`
1917
- };
1918
- var schemaStatusCellStyles = {
1919
- display: "flex",
1920
- alignItems: "center",
1921
- justifyContent: "center",
1922
- padding: "0.6rem 0.5rem"
1923
- };
1924
- var schemaActiveTagStyles = {
1925
- fontSize: "0.68rem",
1926
- fontWeight: 700,
1927
- color: C.success,
1928
- backgroundColor: C.successBg,
1929
- borderRadius: "4px",
1930
- padding: "0.15rem 0.45rem",
1931
- fontFamily: "ui-monospace, monospace"
1932
- };
1933
- var schemaEmptyStyles = {
1934
- fontSize: "0.82rem",
1935
- color: C.textMuted,
1936
- fontStyle: "italic"
1937
- };
1938
- var migrationListStyles = {
1939
- display: "flex",
1940
- flexDirection: "column",
1941
- gap: "0.35rem"
2095
+ const runningDotStyles = {
2096
+ width: "6px",
2097
+ height: "6px",
2098
+ borderRadius: "50%",
2099
+ backgroundColor: "currentColor"
2100
+ };
2101
+ const schemaLayoutStyles = {
2102
+ display: "flex",
2103
+ flexDirection: "column",
2104
+ gap: "1.5rem"
2105
+ };
2106
+ const schemaSectionStyles = {
2107
+ display: "flex",
2108
+ flexDirection: "column",
2109
+ gap: "0.65rem"
2110
+ };
2111
+ const schemaSectionHeaderStyles = {
2112
+ display: "flex",
2113
+ alignItems: "center",
2114
+ gap: "0.6rem"
2115
+ };
2116
+ const schemaSectionTitleStyles = {
2117
+ fontSize: "0.72rem",
2118
+ fontWeight: 700,
2119
+ letterSpacing: "0.08em",
2120
+ textTransform: "uppercase",
2121
+ color: C.textMuted
2122
+ };
2123
+ const schemaBadgeStyles = {
2124
+ fontSize: "0.68rem",
2125
+ fontWeight: 700,
2126
+ color: C.teal,
2127
+ backgroundColor: C.tealDim,
2128
+ borderRadius: "4px",
2129
+ padding: "0.1rem 0.4rem",
2130
+ fontFamily: "ui-monospace, monospace"
2131
+ };
2132
+ const schemaMigrationsMetaStyles = {
2133
+ display: "flex",
2134
+ alignItems: "center",
2135
+ gap: "0.5rem",
2136
+ marginLeft: "auto"
2137
+ };
2138
+ const schemaVersionChipStyles = {
2139
+ fontSize: "0.68rem",
2140
+ fontFamily: "ui-monospace, monospace",
2141
+ color: C.textMuted,
2142
+ backgroundColor: C.bgCard,
2143
+ border: `1px solid ${C.border}`,
2144
+ borderRadius: "4px",
2145
+ padding: "0.1rem 0.5rem"
2146
+ };
2147
+ const schemaTableGridStyles = {
2148
+ borderRadius: "10px",
2149
+ border: `1px solid ${C.border}`,
2150
+ overflow: "hidden"
2151
+ };
2152
+ const schemaTableHeaderRowStyles = {
2153
+ display: "grid",
2154
+ gridTemplateColumns: "1fr 1fr 90px",
2155
+ gap: 0,
2156
+ backgroundColor: C.bgCard,
2157
+ borderBottom: `1px solid ${C.border}`
2158
+ };
2159
+ const schemaColHeaderStyles = {
2160
+ padding: "0.5rem 0.85rem",
2161
+ fontSize: "0.68rem",
2162
+ fontWeight: 700,
2163
+ letterSpacing: "0.07em",
2164
+ textTransform: "uppercase",
2165
+ color: C.textMuted,
2166
+ borderRight: `1px solid ${C.border}`
2167
+ };
2168
+ const schemaTableRowStyles = {
2169
+ display: "grid",
2170
+ gridTemplateColumns: "1fr 1fr 90px",
2171
+ gap: 0,
2172
+ borderBottom: `1px solid ${C.border}`
2173
+ };
2174
+ const schemaTableNameStyles = {
2175
+ display: "flex",
2176
+ alignItems: "center",
2177
+ gap: "0.5rem",
2178
+ padding: "0.6rem 0.85rem",
2179
+ fontSize: "0.82rem",
2180
+ fontFamily: "ui-monospace, monospace",
2181
+ color: C.text,
2182
+ borderRight: `1px solid ${C.border}`
2183
+ };
2184
+ const schemaTableIconStyles = {
2185
+ color: C.teal,
2186
+ fontSize: "0.68rem",
2187
+ opacity: .8
2188
+ };
2189
+ const schemaCrdtNameStyles = {
2190
+ display: "flex",
2191
+ alignItems: "center",
2192
+ padding: "0.6rem 0.85rem",
2193
+ fontSize: "0.82rem",
2194
+ fontFamily: "ui-monospace, monospace",
2195
+ color: C.textDim,
2196
+ borderRight: `1px solid ${C.border}`
2197
+ };
2198
+ const schemaStatusCellStyles = {
2199
+ display: "flex",
2200
+ alignItems: "center",
2201
+ justifyContent: "center",
2202
+ padding: "0.6rem 0.5rem"
2203
+ };
2204
+ const schemaActiveTagStyles = {
2205
+ fontSize: "0.68rem",
2206
+ fontWeight: 700,
2207
+ color: C.success,
2208
+ backgroundColor: C.successBg,
2209
+ borderRadius: "4px",
2210
+ padding: "0.15rem 0.45rem",
2211
+ fontFamily: "ui-monospace, monospace"
2212
+ };
2213
+ const schemaEmptyStyles = {
2214
+ fontSize: "0.82rem",
2215
+ color: C.textMuted,
2216
+ fontStyle: "italic"
2217
+ };
2218
+ const migrationListStyles = {
2219
+ display: "flex",
2220
+ flexDirection: "column",
2221
+ gap: "0.35rem"
1942
2222
  };
1943
2223
  function getMigrationRowStyles(applied) {
1944
- return {
1945
- display: "grid",
1946
- gridTemplateColumns: "3.5rem 1fr 70px",
1947
- alignItems: "center",
1948
- gap: "0.75rem",
1949
- padding: "0.55rem 0.85rem",
1950
- borderRadius: "8px",
1951
- background: applied ? C.bgCard : "transparent",
1952
- border: `1px solid ${applied ? C.border : C.borderLight}`,
1953
- opacity: applied ? 1 : 0.55
1954
- };
2224
+ return {
2225
+ display: "grid",
2226
+ gridTemplateColumns: "3.5rem 1fr 70px",
2227
+ alignItems: "center",
2228
+ gap: "0.75rem",
2229
+ padding: "0.55rem 0.85rem",
2230
+ borderRadius: "8px",
2231
+ background: applied ? C.bgCard : "transparent",
2232
+ border: `1px solid ${applied ? C.border : C.borderLight}`,
2233
+ opacity: applied ? 1 : .55
2234
+ };
1955
2235
  }
1956
- var migrationVersionStyles = {
1957
- fontSize: "0.78rem",
1958
- fontWeight: 700,
1959
- fontFamily: "ui-monospace, monospace",
1960
- color: C.textDim
1961
- };
1962
- var migrationBarTrackStyles = {
1963
- height: "4px",
1964
- borderRadius: "2px",
1965
- backgroundColor: C.border,
1966
- overflow: "hidden"
2236
+ const migrationVersionStyles = {
2237
+ fontSize: "0.78rem",
2238
+ fontWeight: 700,
2239
+ fontFamily: "ui-monospace, monospace",
2240
+ color: C.textDim
2241
+ };
2242
+ const migrationBarTrackStyles = {
2243
+ height: "4px",
2244
+ borderRadius: "2px",
2245
+ backgroundColor: C.border,
2246
+ overflow: "hidden"
1967
2247
  };
1968
2248
  function getMigrationBarFillStyles(applied) {
1969
- return {
1970
- height: "100%",
1971
- width: applied ? "100%" : "0%",
1972
- borderRadius: "2px",
1973
- backgroundColor: C.teal,
1974
- transition: "width 0.3s ease"
1975
- };
2249
+ return {
2250
+ height: "100%",
2251
+ width: applied ? "100%" : "0%",
2252
+ borderRadius: "2px",
2253
+ backgroundColor: C.teal,
2254
+ transition: "width 0.3s ease"
2255
+ };
1976
2256
  }
1977
2257
  function getMigrationTagStyles(applied, isCurrent) {
1978
- if (isCurrent) {
1979
- return {
1980
- fontSize: "0.68rem",
1981
- fontWeight: 700,
1982
- color: C.teal,
1983
- backgroundColor: C.tealDim,
1984
- borderRadius: "4px",
1985
- padding: "0.15rem 0.45rem",
1986
- fontFamily: "ui-monospace, monospace",
1987
- textAlign: "center"
1988
- };
1989
- }
1990
- if (applied) {
1991
- return {
1992
- fontSize: "0.68rem",
1993
- fontWeight: 600,
1994
- color: C.success,
1995
- backgroundColor: C.successBg,
1996
- borderRadius: "4px",
1997
- padding: "0.15rem 0.45rem",
1998
- fontFamily: "ui-monospace, monospace",
1999
- textAlign: "center"
2000
- };
2001
- }
2002
- return {
2003
- fontSize: "0.68rem",
2004
- fontWeight: 600,
2005
- color: C.amber,
2006
- backgroundColor: "rgba(251,191,36,0.08)",
2007
- borderRadius: "4px",
2008
- padding: "0.15rem 0.45rem",
2009
- fontFamily: "ui-monospace, monospace",
2010
- textAlign: "center"
2011
- };
2258
+ if (isCurrent) return {
2259
+ fontSize: "0.68rem",
2260
+ fontWeight: 700,
2261
+ color: C.teal,
2262
+ backgroundColor: C.tealDim,
2263
+ borderRadius: "4px",
2264
+ padding: "0.15rem 0.45rem",
2265
+ fontFamily: "ui-monospace, monospace",
2266
+ textAlign: "center"
2267
+ };
2268
+ if (applied) return {
2269
+ fontSize: "0.68rem",
2270
+ fontWeight: 600,
2271
+ color: C.success,
2272
+ backgroundColor: C.successBg,
2273
+ borderRadius: "4px",
2274
+ padding: "0.15rem 0.45rem",
2275
+ fontFamily: "ui-monospace, monospace",
2276
+ textAlign: "center"
2277
+ };
2278
+ return {
2279
+ fontSize: "0.68rem",
2280
+ fontWeight: 600,
2281
+ color: C.amber,
2282
+ backgroundColor: "rgba(251,191,36,0.08)",
2283
+ borderRadius: "4px",
2284
+ padding: "0.15rem 0.45rem",
2285
+ fontFamily: "ui-monospace, monospace",
2286
+ textAlign: "center"
2287
+ };
2012
2288
  }
2013
- var liveQueryHeaderRowStyles = {
2014
- display: "grid",
2015
- gridTemplateColumns: "minmax(0, 1fr) 220px 110px",
2016
- gap: 0,
2017
- backgroundColor: C.bgCard,
2018
- borderBottom: `1px solid ${C.border}`
2019
- };
2020
- var liveQueryRowStyles = {
2021
- display: "grid",
2022
- gridTemplateColumns: "minmax(0, 1fr) 220px 110px",
2023
- gap: 0,
2024
- borderBottom: `1px solid ${C.border}`
2025
- };
2026
- var liveQuerySqlStyles = {
2027
- padding: "0.6rem 0.85rem",
2028
- fontSize: "0.78rem",
2029
- fontFamily: "ui-monospace, monospace",
2030
- color: C.text,
2031
- borderRight: `1px solid ${C.border}`,
2032
- whiteSpace: "pre-wrap",
2033
- overflowWrap: "anywhere"
2034
- };
2035
- var liveQueryParametersStyles = {
2036
- padding: "0.6rem 0.85rem",
2037
- fontSize: "0.78rem",
2038
- fontFamily: "ui-monospace, monospace",
2039
- color: C.textDim,
2040
- borderRight: `1px solid ${C.border}`,
2041
- whiteSpace: "pre-wrap",
2042
- overflowWrap: "anywhere"
2043
- };
2044
- var liveQueryIdleTagStyles = {
2045
- fontSize: "0.68rem",
2046
- fontWeight: 700,
2047
- color: C.textMuted,
2048
- backgroundColor: C.bgCard,
2049
- border: `1px solid ${C.border}`,
2050
- borderRadius: "4px",
2051
- padding: "0.15rem 0.45rem",
2052
- fontFamily: "ui-monospace, monospace"
2053
- };
2054
- var eventLogLayoutStyles = {
2055
- display: "flex",
2056
- flexDirection: "column",
2057
- gap: "0.75rem",
2058
- height: "100%"
2059
- };
2060
- var eventLogToolbarStyles = {
2061
- display: "flex",
2062
- alignItems: "center",
2063
- gap: "0.5rem",
2064
- flexWrap: "wrap",
2065
- flexShrink: 0
2066
- };
2067
- var eventLogFilterSelectStyles = {
2068
- borderRadius: "7px",
2069
- border: `1px solid ${C.border}`,
2070
- padding: "0.35rem 0.6rem",
2071
- backgroundColor: C.bgCard,
2072
- color: C.text,
2073
- fontSize: "0.78rem",
2074
- fontFamily: "ui-monospace, monospace",
2075
- cursor: "pointer"
2076
- };
2077
- var eventLogRefreshButtonStyles = {
2078
- border: `1px solid ${C.border}`,
2079
- borderRadius: "7px",
2080
- padding: "0.35rem 0.7rem",
2081
- backgroundColor: "transparent",
2082
- color: C.textDim,
2083
- fontSize: "0.78rem",
2084
- fontFamily: "ui-monospace, monospace",
2085
- cursor: "pointer"
2086
- };
2087
- var eventLogCountStyles = {
2088
- marginLeft: "auto",
2089
- fontSize: "0.72rem",
2090
- fontFamily: "ui-monospace, monospace",
2091
- color: C.textMuted
2092
- };
2093
- var eventLogEmptyStyles = {
2094
- padding: "2rem",
2095
- textAlign: "center",
2096
- fontSize: "0.82rem",
2097
- color: C.textMuted,
2098
- fontStyle: "italic"
2099
- };
2100
- var eventLogListStyles = {
2101
- display: "flex",
2102
- flexDirection: "column",
2103
- gap: "0.25rem",
2104
- overflowY: "auto",
2105
- flex: 1
2289
+ const liveQueryHeaderRowStyles = {
2290
+ display: "grid",
2291
+ gridTemplateColumns: "minmax(0, 1fr) 220px 110px",
2292
+ gap: 0,
2293
+ backgroundColor: C.bgCard,
2294
+ borderBottom: `1px solid ${C.border}`
2295
+ };
2296
+ const liveQueryRowStyles = {
2297
+ display: "grid",
2298
+ gridTemplateColumns: "minmax(0, 1fr) 220px 110px",
2299
+ gap: 0,
2300
+ borderBottom: `1px solid ${C.border}`
2301
+ };
2302
+ const liveQuerySqlStyles = {
2303
+ padding: "0.6rem 0.85rem",
2304
+ fontSize: "0.78rem",
2305
+ fontFamily: "ui-monospace, monospace",
2306
+ color: C.text,
2307
+ borderRight: `1px solid ${C.border}`,
2308
+ whiteSpace: "pre-wrap",
2309
+ overflowWrap: "anywhere"
2310
+ };
2311
+ const liveQueryParametersStyles = {
2312
+ padding: "0.6rem 0.85rem",
2313
+ fontSize: "0.78rem",
2314
+ fontFamily: "ui-monospace, monospace",
2315
+ color: C.textDim,
2316
+ borderRight: `1px solid ${C.border}`,
2317
+ whiteSpace: "pre-wrap",
2318
+ overflowWrap: "anywhere"
2319
+ };
2320
+ const liveQueryIdleTagStyles = {
2321
+ fontSize: "0.68rem",
2322
+ fontWeight: 700,
2323
+ color: C.textMuted,
2324
+ backgroundColor: C.bgCard,
2325
+ border: `1px solid ${C.border}`,
2326
+ borderRadius: "4px",
2327
+ padding: "0.15rem 0.45rem",
2328
+ fontFamily: "ui-monospace, monospace"
2329
+ };
2330
+ const eventLogLayoutStyles = {
2331
+ display: "flex",
2332
+ flexDirection: "column",
2333
+ gap: "0.75rem",
2334
+ height: "100%"
2335
+ };
2336
+ const eventLogToolbarStyles = {
2337
+ display: "flex",
2338
+ alignItems: "center",
2339
+ gap: "0.5rem",
2340
+ flexWrap: "wrap",
2341
+ flexShrink: 0
2342
+ };
2343
+ const eventLogFilterSelectStyles = {
2344
+ borderRadius: "7px",
2345
+ border: `1px solid ${C.border}`,
2346
+ padding: "0.35rem 0.6rem",
2347
+ backgroundColor: C.bgCard,
2348
+ color: C.text,
2349
+ fontSize: "0.78rem",
2350
+ fontFamily: "ui-monospace, monospace",
2351
+ cursor: "pointer"
2352
+ };
2353
+ const eventLogRefreshButtonStyles = {
2354
+ border: `1px solid ${C.border}`,
2355
+ borderRadius: "7px",
2356
+ padding: "0.35rem 0.7rem",
2357
+ backgroundColor: "transparent",
2358
+ color: C.textDim,
2359
+ fontSize: "0.78rem",
2360
+ fontFamily: "ui-monospace, monospace",
2361
+ cursor: "pointer"
2362
+ };
2363
+ const eventLogCountStyles = {
2364
+ marginLeft: "auto",
2365
+ fontSize: "0.72rem",
2366
+ fontFamily: "ui-monospace, monospace",
2367
+ color: C.textMuted
2368
+ };
2369
+ const eventLogEmptyStyles = {
2370
+ padding: "2rem",
2371
+ textAlign: "center",
2372
+ fontSize: "0.82rem",
2373
+ color: C.textMuted,
2374
+ fontStyle: "italic"
2375
+ };
2376
+ const eventLogListStyles = {
2377
+ display: "flex",
2378
+ flexDirection: "column",
2379
+ gap: "0.25rem",
2380
+ overflowY: "auto",
2381
+ flex: 1
2106
2382
  };
2107
2383
  function getEventRowStyles(isExpanded) {
2108
- return {
2109
- borderRadius: "8px",
2110
- border: `1px solid ${isExpanded ? `${C.teal}40` : C.border}`,
2111
- background: isExpanded ? C.tealGlow : C.bgCard,
2112
- overflow: "hidden",
2113
- flexShrink: 0
2114
- };
2384
+ return {
2385
+ borderRadius: "8px",
2386
+ border: `1px solid ${isExpanded ? `${C.teal}40` : C.border}`,
2387
+ background: isExpanded ? C.tealGlow : C.bgCard,
2388
+ overflow: "hidden",
2389
+ flexShrink: 0
2390
+ };
2115
2391
  }
2116
- var eventRowHeaderStyles = {
2117
- display: "flex",
2118
- alignItems: "center",
2119
- gap: "0.5rem",
2120
- width: "100%",
2121
- padding: "0.5rem 0.75rem",
2122
- background: "transparent",
2123
- border: "none",
2124
- cursor: "pointer",
2125
- textAlign: "left",
2126
- flexWrap: "wrap"
2127
- };
2128
- var eventSyncIdStyles = {
2129
- fontSize: "0.7rem",
2130
- fontFamily: "ui-monospace, monospace",
2131
- color: C.textMuted,
2132
- minWidth: "3.5rem"
2133
- };
2134
- var eventDatasetStyles = {
2135
- fontSize: "0.8rem",
2136
- fontFamily: "ui-monospace, monospace",
2137
- color: C.text,
2138
- fontWeight: 600
2139
- };
2140
- var eventItemIdStyles = {
2141
- fontSize: "0.75rem",
2142
- fontFamily: "ui-monospace, monospace",
2143
- color: C.textMuted,
2144
- flex: 1,
2145
- overflow: "hidden",
2146
- textOverflow: "ellipsis",
2147
- whiteSpace: "nowrap",
2148
- minWidth: 0
2149
- };
2150
- var eventTimestampStyles = {
2151
- fontSize: "0.7rem",
2152
- fontFamily: "ui-monospace, monospace",
2153
- color: C.textMuted,
2154
- marginLeft: "auto"
2155
- };
2156
- var eventChevronStyles = {
2157
- fontSize: "0.6rem",
2158
- color: C.textMuted,
2159
- marginLeft: "0.25rem"
2160
- };
2161
- var eventPayloadStyles = {
2162
- borderTop: `1px solid ${C.border}`,
2163
- padding: "0.6rem 0.75rem"
2164
- };
2165
- var eventPayloadMetaStyles = {
2166
- display: "flex",
2167
- gap: "0.75rem",
2168
- marginBottom: "0.5rem"
2169
- };
2170
- var eventMetaItemStyles = {
2171
- fontSize: "0.68rem",
2172
- fontFamily: "ui-monospace, monospace",
2173
- color: C.textMuted
2174
- };
2175
- var eventPayloadPreStyles = {
2176
- margin: 0,
2177
- fontSize: "0.78rem",
2178
- fontFamily: "ui-monospace, monospace",
2179
- color: C.text,
2180
- lineHeight: 1.5,
2181
- whiteSpace: "pre-wrap",
2182
- wordBreak: "break-word"
2183
- };
2184
- var loadMoreButtonStyles = {
2185
- width: "100%",
2186
- border: `1px solid ${C.border}`,
2187
- borderRadius: "8px",
2188
- padding: "0.6rem",
2189
- backgroundColor: "transparent",
2190
- color: C.textDim,
2191
- fontSize: "0.78rem",
2192
- fontFamily: "ui-monospace, monospace",
2193
- cursor: "pointer",
2194
- flexShrink: 0
2195
- };
2196
- var eventTypeBadgeBase = {
2197
- fontSize: "0.65rem",
2198
- fontWeight: 700,
2199
- borderRadius: "4px",
2200
- padding: "0.1rem 0.4rem",
2201
- fontFamily: "ui-monospace, monospace",
2202
- whiteSpace: "nowrap"
2203
- };
2204
- var eventTypeCreateStyles = {
2205
- ...eventTypeBadgeBase,
2206
- color: C.teal,
2207
- backgroundColor: C.tealDim
2208
- };
2209
- var eventTypeUpdateStyles = {
2210
- ...eventTypeBadgeBase,
2211
- color: "#a78bfa",
2212
- backgroundColor: "rgba(167,139,250,0.12)"
2213
- };
2214
- var eventTypeDeleteStyles = {
2215
- ...eventTypeBadgeBase,
2216
- color: C.error,
2217
- backgroundColor: "rgba(248,113,113,0.12)"
2218
- };
2219
- var eventOriginOwnStyles = {
2220
- ...eventTypeBadgeBase,
2221
- color: C.success,
2222
- backgroundColor: C.successBg
2223
- };
2224
- var eventOriginRemoteStyles = {
2225
- ...eventTypeBadgeBase,
2226
- color: C.amber,
2227
- backgroundColor: "rgba(251,191,36,0.1)"
2228
- };
2229
- var eventOriginLocalStyles = {
2230
- ...eventTypeBadgeBase,
2231
- color: C.textDim,
2232
- backgroundColor: C.bgCard,
2233
- border: `1px solid ${C.border}`
2234
- };
2235
- var eventStatusAppliedStyles = {
2236
- ...eventTypeBadgeBase,
2237
- color: C.success,
2238
- backgroundColor: C.successBg
2239
- };
2240
- var eventStatusPendingStyles = {
2241
- ...eventTypeBadgeBase,
2242
- color: C.amber,
2243
- backgroundColor: "rgba(251,191,36,0.1)"
2244
- };
2245
- var eventStatusFailedStyles = {
2246
- ...eventTypeBadgeBase,
2247
- color: C.error,
2248
- backgroundColor: C.errorBg
2249
- };
2250
- var eventStatusSkippedStyles = {
2251
- ...eventTypeBadgeBase,
2252
- color: C.textMuted,
2253
- backgroundColor: C.bgCard
2254
- };
2255
- export {
2256
- SQLiteSyncDevtools
2257
- };
2392
+ const eventRowHeaderStyles = {
2393
+ display: "flex",
2394
+ alignItems: "center",
2395
+ gap: "0.5rem",
2396
+ width: "100%",
2397
+ padding: "0.5rem 0.75rem",
2398
+ background: "transparent",
2399
+ border: "none",
2400
+ cursor: "pointer",
2401
+ textAlign: "left",
2402
+ flexWrap: "wrap"
2403
+ };
2404
+ const eventSyncIdStyles = {
2405
+ fontSize: "0.7rem",
2406
+ fontFamily: "ui-monospace, monospace",
2407
+ color: C.textMuted,
2408
+ minWidth: "3.5rem"
2409
+ };
2410
+ const eventDatasetStyles = {
2411
+ fontSize: "0.8rem",
2412
+ fontFamily: "ui-monospace, monospace",
2413
+ color: C.text,
2414
+ fontWeight: 600
2415
+ };
2416
+ const eventItemIdStyles = {
2417
+ fontSize: "0.75rem",
2418
+ fontFamily: "ui-monospace, monospace",
2419
+ color: C.textMuted,
2420
+ flex: 1,
2421
+ overflow: "hidden",
2422
+ textOverflow: "ellipsis",
2423
+ whiteSpace: "nowrap",
2424
+ minWidth: 0
2425
+ };
2426
+ const eventTimestampStyles = {
2427
+ fontSize: "0.7rem",
2428
+ fontFamily: "ui-monospace, monospace",
2429
+ color: C.textMuted,
2430
+ marginLeft: "auto"
2431
+ };
2432
+ const eventChevronStyles = {
2433
+ fontSize: "0.6rem",
2434
+ color: C.textMuted,
2435
+ marginLeft: "0.25rem"
2436
+ };
2437
+ const eventPayloadStyles = {
2438
+ borderTop: `1px solid ${C.border}`,
2439
+ padding: "0.6rem 0.75rem"
2440
+ };
2441
+ const eventPayloadMetaStyles = {
2442
+ display: "flex",
2443
+ gap: "0.75rem",
2444
+ marginBottom: "0.5rem"
2445
+ };
2446
+ const eventMetaItemStyles = {
2447
+ fontSize: "0.68rem",
2448
+ fontFamily: "ui-monospace, monospace",
2449
+ color: C.textMuted
2450
+ };
2451
+ const eventPayloadPreStyles = {
2452
+ margin: 0,
2453
+ fontSize: "0.78rem",
2454
+ fontFamily: "ui-monospace, monospace",
2455
+ color: C.text,
2456
+ lineHeight: 1.5,
2457
+ whiteSpace: "pre-wrap",
2458
+ wordBreak: "break-word"
2459
+ };
2460
+ const loadMoreButtonStyles = {
2461
+ width: "100%",
2462
+ border: `1px solid ${C.border}`,
2463
+ borderRadius: "8px",
2464
+ padding: "0.6rem",
2465
+ backgroundColor: "transparent",
2466
+ color: C.textDim,
2467
+ fontSize: "0.78rem",
2468
+ fontFamily: "ui-monospace, monospace",
2469
+ cursor: "pointer",
2470
+ flexShrink: 0
2471
+ };
2472
+ const eventTypeBadgeBase = {
2473
+ fontSize: "0.65rem",
2474
+ fontWeight: 700,
2475
+ borderRadius: "4px",
2476
+ padding: "0.1rem 0.4rem",
2477
+ fontFamily: "ui-monospace, monospace",
2478
+ whiteSpace: "nowrap"
2479
+ };
2480
+ const eventTypeCreateStyles = {
2481
+ ...eventTypeBadgeBase,
2482
+ color: C.teal,
2483
+ backgroundColor: C.tealDim
2484
+ };
2485
+ const eventTypeUpdateStyles = {
2486
+ ...eventTypeBadgeBase,
2487
+ color: "#a78bfa",
2488
+ backgroundColor: "rgba(167,139,250,0.12)"
2489
+ };
2490
+ const eventTypeDeleteStyles = {
2491
+ ...eventTypeBadgeBase,
2492
+ color: C.error,
2493
+ backgroundColor: "rgba(248,113,113,0.12)"
2494
+ };
2495
+ const eventOriginOwnStyles = {
2496
+ ...eventTypeBadgeBase,
2497
+ color: C.success,
2498
+ backgroundColor: C.successBg
2499
+ };
2500
+ const eventOriginRemoteStyles = {
2501
+ ...eventTypeBadgeBase,
2502
+ color: C.amber,
2503
+ backgroundColor: "rgba(251,191,36,0.1)"
2504
+ };
2505
+ const eventOriginLocalStyles = {
2506
+ ...eventTypeBadgeBase,
2507
+ color: C.textDim,
2508
+ backgroundColor: C.bgCard,
2509
+ border: `1px solid ${C.border}`
2510
+ };
2511
+ const eventStatusAppliedStyles = {
2512
+ ...eventTypeBadgeBase,
2513
+ color: C.success,
2514
+ backgroundColor: C.successBg
2515
+ };
2516
+ const eventStatusPendingStyles = {
2517
+ ...eventTypeBadgeBase,
2518
+ color: C.amber,
2519
+ backgroundColor: "rgba(251,191,36,0.1)"
2520
+ };
2521
+ const eventStatusFailedStyles = {
2522
+ ...eventTypeBadgeBase,
2523
+ color: C.error,
2524
+ backgroundColor: C.errorBg
2525
+ };
2526
+ const eventStatusSkippedStyles = {
2527
+ ...eventTypeBadgeBase,
2528
+ color: C.textMuted,
2529
+ backgroundColor: C.bgCard
2530
+ };
2531
+ //#endregion
2532
+ export { SQLiteSyncDevtools };
2533
+
2258
2534
  //# sourceMappingURL=index.js.map