@reifydb/console 0.3.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 ADDED
@@ -0,0 +1,1675 @@
1
+ // src/components/Console.tsx
2
+ import { useCallback as useCallback3, useEffect as useEffect4, useRef as useRef4, useState as useState5 } from "react";
3
+ import { Client } from "@reifydb/client";
4
+
5
+ // src/executor/ws-executor.ts
6
+ var WsExecutor = class {
7
+ client;
8
+ constructor(client) {
9
+ this.client = client;
10
+ }
11
+ async execute(statement) {
12
+ const trimmed = statement.trim();
13
+ const query = trimmed.endsWith(";") ? trimmed.slice(0, -1).trim() : trimmed;
14
+ if (!query) {
15
+ return { success: true, data: [], executionTime: 0 };
16
+ }
17
+ const startTime = performance.now();
18
+ try {
19
+ const frames = await this.client.admin(query, null, []);
20
+ const executionTime = Math.round(performance.now() - startTime);
21
+ const results = frames[0] ?? [];
22
+ const data = results.map((row) => {
23
+ if (row && typeof row === "object") {
24
+ const plainRow = {};
25
+ for (const [key, value] of Object.entries(row)) {
26
+ plainRow[key] = value;
27
+ }
28
+ return plainRow;
29
+ }
30
+ return row;
31
+ });
32
+ return { success: true, data, executionTime };
33
+ } catch (error) {
34
+ const executionTime = Math.round(performance.now() - startTime);
35
+ let errorMessage;
36
+ if (error && typeof error === "object" && "diagnostic" in error) {
37
+ const diagnostic = error.diagnostic;
38
+ errorMessage = diagnostic.message;
39
+ } else if (error instanceof Error) {
40
+ errorMessage = error.message;
41
+ } else {
42
+ errorMessage = String(error);
43
+ }
44
+ return { success: false, error: errorMessage, executionTime };
45
+ }
46
+ }
47
+ };
48
+
49
+ // src/state/use-console-store.tsx
50
+ import { createContext, useContext, useReducer } from "react";
51
+
52
+ // src/state/console-store.ts
53
+ var nextHistoryId = 1;
54
+ function consoleReducer(state, action) {
55
+ switch (action.type) {
56
+ case "SET_CODE":
57
+ return { ...state, code: action.code };
58
+ case "EXECUTE_START":
59
+ return { ...state, isExecuting: true, result: null };
60
+ case "EXECUTE_SUCCESS": {
61
+ const entry = {
62
+ id: String(nextHistoryId++),
63
+ query: action.query,
64
+ timestamp: Date.now(),
65
+ success: true,
66
+ rowCount: action.result.data?.length,
67
+ executionTime: action.result.executionTime
68
+ };
69
+ return {
70
+ ...state,
71
+ isExecuting: false,
72
+ result: action.result,
73
+ history: [entry, ...state.history],
74
+ activeTab: "results"
75
+ };
76
+ }
77
+ case "EXECUTE_ERROR": {
78
+ const entry = {
79
+ id: String(nextHistoryId++),
80
+ query: action.query,
81
+ timestamp: Date.now(),
82
+ success: false,
83
+ executionTime: action.result.executionTime
84
+ };
85
+ return {
86
+ ...state,
87
+ isExecuting: false,
88
+ result: action.result,
89
+ history: [entry, ...state.history],
90
+ activeTab: "results"
91
+ };
92
+ }
93
+ case "CLEAR_RESULTS":
94
+ return { ...state, result: null };
95
+ case "SET_TAB":
96
+ return { ...state, activeTab: action.tab };
97
+ case "LOAD_HISTORY":
98
+ return { ...state, history: action.entries };
99
+ case "CLEAR_HISTORY":
100
+ return { ...state, history: [] };
101
+ case "LOAD_QUERY":
102
+ return { ...state, code: action.code, activeTab: "results" };
103
+ default:
104
+ return state;
105
+ }
106
+ }
107
+ var initialConsoleState = {
108
+ code: "",
109
+ isExecuting: false,
110
+ result: null,
111
+ history: [],
112
+ activeTab: "results"
113
+ };
114
+
115
+ // src/state/use-console-store.tsx
116
+ import { jsx } from "react/jsx-runtime";
117
+ var ConsoleContext = createContext(null);
118
+ function ConsoleProvider({ children, initialCode }) {
119
+ const [state, dispatch] = useReducer(consoleReducer, {
120
+ ...initialConsoleState,
121
+ code: initialCode ?? ""
122
+ });
123
+ return /* @__PURE__ */ jsx(ConsoleContext.Provider, { value: { state, dispatch }, children });
124
+ }
125
+ function useConsoleStore() {
126
+ const ctx = useContext(ConsoleContext);
127
+ if (!ctx) {
128
+ throw new Error("useConsoleStore must be used within a ConsoleProvider");
129
+ }
130
+ return ctx;
131
+ }
132
+
133
+ // src/state/history.ts
134
+ var DEFAULT_KEY = "reifydb-console-history";
135
+ var MAX_ENTRIES = 500;
136
+ function loadHistory(key = DEFAULT_KEY) {
137
+ try {
138
+ const raw = localStorage.getItem(key);
139
+ if (!raw) return [];
140
+ const entries = JSON.parse(raw);
141
+ return Array.isArray(entries) ? entries : [];
142
+ } catch {
143
+ return [];
144
+ }
145
+ }
146
+ function saveHistory(entries, key = DEFAULT_KEY) {
147
+ try {
148
+ const trimmed = entries.slice(0, MAX_ENTRIES);
149
+ localStorage.setItem(key, JSON.stringify(trimmed));
150
+ } catch {
151
+ }
152
+ }
153
+
154
+ // src/components/layout/SplitPane.tsx
155
+ import { useState, useCallback, useRef, useEffect } from "react";
156
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
157
+ function SplitPane({ top, bottom, initialSplit = 50 }) {
158
+ const [split, setSplit] = useState(initialSplit);
159
+ const containerRef = useRef(null);
160
+ const dragging = useRef(false);
161
+ const onMouseDown = useCallback(() => {
162
+ dragging.current = true;
163
+ document.body.style.cursor = "row-resize";
164
+ document.body.style.userSelect = "none";
165
+ }, []);
166
+ useEffect(() => {
167
+ const onMouseMove = (e) => {
168
+ if (!dragging.current || !containerRef.current) return;
169
+ const rect = containerRef.current.getBoundingClientRect();
170
+ const pct = (e.clientY - rect.top) / rect.height * 100;
171
+ setSplit(Math.min(Math.max(pct, 15), 85));
172
+ };
173
+ const onMouseUp = () => {
174
+ if (dragging.current) {
175
+ dragging.current = false;
176
+ document.body.style.cursor = "";
177
+ document.body.style.userSelect = "";
178
+ }
179
+ };
180
+ document.addEventListener("mousemove", onMouseMove);
181
+ document.addEventListener("mouseup", onMouseUp);
182
+ return () => {
183
+ document.removeEventListener("mousemove", onMouseMove);
184
+ document.removeEventListener("mouseup", onMouseUp);
185
+ };
186
+ }, []);
187
+ return /* @__PURE__ */ jsxs("div", { className: "rdb-split", ref: containerRef, children: [
188
+ /* @__PURE__ */ jsx2("div", { className: "rdb-split__top", style: { height: `${split}%` }, children: top }),
189
+ /* @__PURE__ */ jsx2("div", { className: "rdb-split__handle", onMouseDown }),
190
+ /* @__PURE__ */ jsx2("div", { className: "rdb-split__bottom", children: bottom })
191
+ ] });
192
+ }
193
+
194
+ // src/components/layout/TabBar.tsx
195
+ import { jsx as jsx3 } from "react/jsx-runtime";
196
+ function TabBar({ activeTab, tabs, onTabChange }) {
197
+ return /* @__PURE__ */ jsx3("div", { className: "rdb-tabs", children: tabs.map((tab) => /* @__PURE__ */ jsx3(
198
+ "button",
199
+ {
200
+ className: `rdb-tabs__tab${activeTab === tab.id ? " rdb-tabs__tab--active" : ""}`,
201
+ onClick: () => onTabChange(tab.id),
202
+ children: tab.label
203
+ },
204
+ tab.id
205
+ )) });
206
+ }
207
+
208
+ // src/components/editor/QueryEditor.tsx
209
+ import { useRef as useRef2 } from "react";
210
+ import Editor from "@monaco-editor/react";
211
+
212
+ // src/monaco/rql-language.ts
213
+ var TRANSFORMS = [
214
+ "aggregate",
215
+ "append",
216
+ "create",
217
+ "derive",
218
+ "deferred",
219
+ "distinct",
220
+ "extend",
221
+ "filter",
222
+ "from",
223
+ "group",
224
+ "insert",
225
+ "join",
226
+ "map",
227
+ "sort",
228
+ "take",
229
+ "union",
230
+ "view",
231
+ "with"
232
+ ];
233
+ var MODULES = ["date", "math", "text"];
234
+ var BUILTIN_FUNCTIONS = ["case"];
235
+ var KEYWORDS = ["set", "as", "on", "by"];
236
+ var LITERALS = ["none", "true", "false"];
237
+ var rqlLanguageDefinition = {
238
+ defaultToken: "invalid",
239
+ ignoreCase: true,
240
+ keywords: [...TRANSFORMS, ...MODULES, ...BUILTIN_FUNCTIONS, ...KEYWORDS, ...LITERALS],
241
+ operators: ["+", "-", "*", "/", "//", "%", "=", "==", "!=", "->", "=>", ">", "<", ">=", "<=", "~=", "&&", "||", "??"],
242
+ tokenizer: {
243
+ root: [
244
+ // Comments
245
+ [/#.*/, "comment"],
246
+ // Named arguments
247
+ [/(\w+)\s*:/, "key"],
248
+ // Identifiers and keywords (case insensitive)
249
+ [
250
+ /[a-zA-Z_$][\w$]*/,
251
+ {
252
+ cases: {
253
+ "@keywords": "keyword",
254
+ "@default": "identifier"
255
+ }
256
+ }
257
+ ],
258
+ // Whitespace
259
+ { include: "@whitespace" },
260
+ // Brackets
261
+ [/[{}()[\]]/, "@brackets"],
262
+ // Numbers with underscores support
263
+ [/[+-]?(?:[\d_]+(?:\.[\d_]+)?|\.[\d_]+)/, "number"],
264
+ // Strings
265
+ [/"([^"\\]|\\.)*$/, "string.invalid"],
266
+ [/"/, { token: "string.quote", bracket: "@open", next: "@string" }],
267
+ // Single-quoted strings
268
+ [/'([^'\\]|\\.)*$/, "string.invalid"],
269
+ [/'/, { token: "string.quote", bracket: "@open", next: "@singlestring" }],
270
+ // Operators
271
+ [/[+\-*/%]/, "operator"],
272
+ [/\/\//, "operator"],
273
+ [/==|!=|->|=>|>=|<=|~=|>|</, "operator"],
274
+ [/&&|\|\||\?\?/, "operator"]
275
+ ],
276
+ string: [
277
+ [/[^\\"]+/, "string"],
278
+ [/\\./, "string.escape"],
279
+ [/"/, { token: "string.quote", bracket: "@close", next: "@pop" }]
280
+ ],
281
+ singlestring: [
282
+ [/[^\\']+/, "string"],
283
+ [/\\./, "string.escape"],
284
+ [/'/, { token: "string.quote", bracket: "@close", next: "@pop" }]
285
+ ],
286
+ whitespace: [
287
+ [/[ \t\r\n]+/, "white"],
288
+ [/\/\*/, "comment", "@comment"],
289
+ [/\/\/.*$/, "comment"]
290
+ ],
291
+ comment: [
292
+ [/[^/*]+/, "comment"],
293
+ [/\/\*/, "comment", "@push"],
294
+ [/\*\//, "comment", "@pop"],
295
+ [/[/*]/, "comment"]
296
+ ]
297
+ }
298
+ };
299
+ var rqlLanguageConfiguration = {
300
+ comments: {
301
+ lineComment: "#",
302
+ blockComment: ["/*", "*/"]
303
+ },
304
+ brackets: [
305
+ ["{", "}"],
306
+ ["[", "]"],
307
+ ["(", ")"]
308
+ ],
309
+ autoClosingPairs: [
310
+ { open: "{", close: "}" },
311
+ { open: "[", close: "]" },
312
+ { open: "(", close: ")" },
313
+ { open: '"', close: '"', notIn: ["string"] },
314
+ { open: "'", close: "'", notIn: ["string"] }
315
+ ],
316
+ surroundingPairs: [
317
+ { open: "{", close: "}" },
318
+ { open: "[", close: "]" },
319
+ { open: "(", close: ")" },
320
+ { open: '"', close: '"' },
321
+ { open: "'", close: "'" }
322
+ ],
323
+ folding: {
324
+ offSide: true
325
+ }
326
+ };
327
+
328
+ // src/monaco/themes.ts
329
+ var brutalistLightTheme = {
330
+ base: "vs",
331
+ inherit: true,
332
+ rules: [
333
+ { token: "keyword", foreground: "0D9488", fontStyle: "bold" },
334
+ { token: "string", foreground: "16A34A" },
335
+ { token: "string.quote", foreground: "16A34A" },
336
+ { token: "number", foreground: "B91C1C", fontStyle: "bold" },
337
+ { token: "comment", foreground: "6B7280", fontStyle: "italic" },
338
+ { token: "operator", foreground: "383838" },
339
+ { token: "identifier", foreground: "1A1A1A" },
340
+ { token: "key", foreground: "0D9488", fontStyle: "bold" }
341
+ ],
342
+ colors: {
343
+ "editor.background": "#FFFFFF",
344
+ "editor.foreground": "#1A1A1A",
345
+ "editor.lineHighlightBackground": "#F8F8F7",
346
+ "editor.selectionBackground": "#A7F3D0",
347
+ "editorCursor.foreground": "#14B8A6",
348
+ "editorLineNumber.foreground": "#9CA3AF",
349
+ "editorLineNumber.activeForeground": "#383838"
350
+ }
351
+ };
352
+ var brutalistDarkTheme = {
353
+ base: "vs-dark",
354
+ inherit: true,
355
+ rules: [
356
+ { token: "keyword", foreground: "14B8A6", fontStyle: "bold" },
357
+ { token: "string", foreground: "4ADE80" },
358
+ { token: "string.quote", foreground: "4ADE80" },
359
+ { token: "number", foreground: "F87171", fontStyle: "bold" },
360
+ { token: "comment", foreground: "9CA3AF", fontStyle: "italic" },
361
+ { token: "operator", foreground: "E5E7EB" },
362
+ { token: "identifier", foreground: "F3F4F6" },
363
+ { token: "key", foreground: "60A5FA", fontStyle: "bold" }
364
+ ],
365
+ colors: {
366
+ "editor.background": "#1A1A1A",
367
+ "editor.foreground": "#F3F4F6",
368
+ "editor.lineHighlightBackground": "#2A2A2A",
369
+ "editor.selectionBackground": "#1A3A36",
370
+ "editorCursor.foreground": "#14B8A6",
371
+ "editorLineNumber.foreground": "#6B7280",
372
+ "editorLineNumber.activeForeground": "#E5E7EB"
373
+ }
374
+ };
375
+ var premiumLightTheme = {
376
+ base: "vs",
377
+ inherit: true,
378
+ rules: [
379
+ { token: "keyword", foreground: "0D9488", fontStyle: "bold" },
380
+ { token: "string", foreground: "059669" },
381
+ { token: "string.quote", foreground: "059669" },
382
+ { token: "number", foreground: "DB2777", fontStyle: "bold" },
383
+ { token: "comment", foreground: "9CA3AF", fontStyle: "italic" },
384
+ { token: "operator", foreground: "525252" },
385
+ { token: "identifier", foreground: "1A1A1A" },
386
+ { token: "key", foreground: "0D9488", fontStyle: "bold" }
387
+ ],
388
+ colors: {
389
+ "editor.background": "#FFFFFF",
390
+ "editor.foreground": "#1A1A1A",
391
+ "editor.lineHighlightBackground": "#F5F5F5",
392
+ "editor.selectionBackground": "#99F6E4",
393
+ "editorCursor.foreground": "#0D9488",
394
+ "editorLineNumber.foreground": "#9CA3AF",
395
+ "editorLineNumber.activeForeground": "#525252"
396
+ }
397
+ };
398
+ var premiumDarkTheme = {
399
+ base: "vs-dark",
400
+ inherit: true,
401
+ rules: [
402
+ { token: "keyword", foreground: "14B8A6", fontStyle: "bold" },
403
+ { token: "string", foreground: "34D399" },
404
+ { token: "string.quote", foreground: "34D399" },
405
+ { token: "number", foreground: "F472B6", fontStyle: "bold" },
406
+ { token: "comment", foreground: "525252", fontStyle: "italic" },
407
+ { token: "operator", foreground: "A3A3A3" },
408
+ { token: "identifier", foreground: "E5E5E5" },
409
+ { token: "key", foreground: "14B8A6", fontStyle: "bold" }
410
+ ],
411
+ colors: {
412
+ "editor.background": "#1A1A1A",
413
+ "editor.foreground": "#E5E5E5",
414
+ "editor.lineHighlightBackground": "#252525",
415
+ "editor.selectionBackground": "#14B8A640",
416
+ "editorCursor.foreground": "#14B8A6",
417
+ "editorLineNumber.foreground": "#525252",
418
+ "editorLineNumber.activeForeground": "#A3A3A3"
419
+ }
420
+ };
421
+
422
+ // src/monaco/register.ts
423
+ var registered = false;
424
+ function registerRqlLanguage(monaco) {
425
+ if (registered) return;
426
+ monaco.languages.register({ id: "rql" });
427
+ monaco.languages.setMonarchTokensProvider("rql", rqlLanguageDefinition);
428
+ monaco.languages.setLanguageConfiguration("rql", rqlLanguageConfiguration);
429
+ monaco.editor.defineTheme("premium-dark", premiumDarkTheme);
430
+ monaco.editor.defineTheme("premium-light", premiumLightTheme);
431
+ monaco.editor.defineTheme("brutalist-dark", brutalistDarkTheme);
432
+ monaco.editor.defineTheme("brutalist-light", brutalistLightTheme);
433
+ registered = true;
434
+ }
435
+
436
+ // src/components/editor/QueryEditor.tsx
437
+ import { jsx as jsx4 } from "react/jsx-runtime";
438
+ function QueryEditor({ code, onChange, onRun, theme = "light" }) {
439
+ const editorRef = useRef2(null);
440
+ const onRunRef = useRef2(onRun);
441
+ onRunRef.current = onRun;
442
+ const handleMount = (editor, monaco) => {
443
+ editorRef.current = editor;
444
+ registerRqlLanguage(monaco);
445
+ editor.addAction({
446
+ id: "run-query",
447
+ label: "Run Query",
448
+ keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter],
449
+ run: () => {
450
+ onRunRef.current();
451
+ }
452
+ });
453
+ };
454
+ const handleBeforeMount = (monaco) => {
455
+ registerRqlLanguage(monaco);
456
+ };
457
+ return /* @__PURE__ */ jsx4(
458
+ Editor,
459
+ {
460
+ height: "100%",
461
+ language: "rql",
462
+ theme: theme === "light" ? "premium-light" : "premium-dark",
463
+ value: code,
464
+ onChange: (value) => onChange(value || ""),
465
+ beforeMount: handleBeforeMount,
466
+ onMount: handleMount,
467
+ options: {
468
+ minimap: { enabled: false },
469
+ lineNumbers: "on",
470
+ glyphMargin: false,
471
+ folding: true,
472
+ lineDecorationsWidth: 16,
473
+ lineNumbersMinChars: 3,
474
+ scrollBeyondLastLine: false,
475
+ scrollbar: { vertical: "auto", horizontal: "auto" },
476
+ overviewRulerLanes: 0,
477
+ hideCursorInOverviewRuler: true,
478
+ overviewRulerBorder: false,
479
+ renderLineHighlight: "line",
480
+ fontFamily: "'IBM Plex Mono', monospace",
481
+ fontSize: 13,
482
+ padding: { top: 8, bottom: 8 },
483
+ wordWrap: "on",
484
+ automaticLayout: true
485
+ }
486
+ }
487
+ );
488
+ }
489
+
490
+ // src/components/editor/EditorToolbar.tsx
491
+ import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
492
+ function EditorToolbar({
493
+ onRun,
494
+ onClear,
495
+ isExecuting,
496
+ connectionLabel,
497
+ connectionStatus,
498
+ connectionLocked,
499
+ onToggleConnectionPanel
500
+ }) {
501
+ return /* @__PURE__ */ jsxs2("div", { className: "rdb-editor-toolbar", children: [
502
+ /* @__PURE__ */ jsxs2("div", { className: "rdb-editor-toolbar__left", children: [
503
+ connectionLocked ? /* @__PURE__ */ jsxs2("span", { className: "rdb-editor-toolbar__connection rdb-editor-toolbar__connection--locked", children: [
504
+ /* @__PURE__ */ jsx5("span", { className: `rdb-editor-toolbar__connection-dot rdb-editor-toolbar__connection-dot--${connectionStatus}`, children: "\u25CF" }),
505
+ /* @__PURE__ */ jsxs2("span", { children: [
506
+ "[",
507
+ connectionLabel,
508
+ "]"
509
+ ] })
510
+ ] }) : /* @__PURE__ */ jsxs2(
511
+ "button",
512
+ {
513
+ className: "rdb-editor-toolbar__connection",
514
+ onClick: onToggleConnectionPanel,
515
+ children: [
516
+ /* @__PURE__ */ jsx5("span", { className: `rdb-editor-toolbar__connection-dot rdb-editor-toolbar__connection-dot--${connectionStatus}`, children: "\u25CF" }),
517
+ /* @__PURE__ */ jsxs2("span", { children: [
518
+ "[",
519
+ connectionLabel,
520
+ "]"
521
+ ] })
522
+ ]
523
+ }
524
+ ),
525
+ /* @__PURE__ */ jsx5("span", { className: "rdb-editor-toolbar__hint", children: "ctrl+enter to run" })
526
+ ] }),
527
+ /* @__PURE__ */ jsxs2("div", { className: "rdb-editor-toolbar__actions", children: [
528
+ /* @__PURE__ */ jsx5(
529
+ "button",
530
+ {
531
+ className: "rdb-editor-toolbar__btn rdb-editor-toolbar__btn--secondary",
532
+ onClick: onClear,
533
+ disabled: isExecuting,
534
+ children: "[clear]"
535
+ }
536
+ ),
537
+ /* @__PURE__ */ jsx5(
538
+ "button",
539
+ {
540
+ className: "rdb-editor-toolbar__btn",
541
+ onClick: onRun,
542
+ disabled: isExecuting,
543
+ children: isExecuting ? "[running...]" : "[run]"
544
+ }
545
+ )
546
+ ] })
547
+ ] });
548
+ }
549
+
550
+ // src/format/value.ts
551
+ function getValueStyle(value) {
552
+ if (value === null || value === void 0) {
553
+ return { color: "var(--rdb-color-muted)", italic: true };
554
+ }
555
+ const t = value.type;
556
+ if (typeof t === "string") {
557
+ switch (t) {
558
+ case "None":
559
+ return { color: "var(--rdb-color-muted)", italic: true };
560
+ case "Boolean":
561
+ return { color: "var(--rdb-color-value-boolean)" };
562
+ case "Int1":
563
+ case "Int2":
564
+ case "Int4":
565
+ case "Int8":
566
+ case "Int16":
567
+ case "Uint1":
568
+ case "Uint2":
569
+ case "Uint4":
570
+ case "Uint8":
571
+ case "Uint16":
572
+ case "Float4":
573
+ case "Float8":
574
+ case "Decimal":
575
+ return { color: "var(--rdb-color-value-number)" };
576
+ case "Date":
577
+ case "DateTime":
578
+ case "Time":
579
+ case "Duration":
580
+ return { color: "var(--rdb-color-value-date)" };
581
+ case "Uuid4":
582
+ case "Uuid7":
583
+ case "IdentityId":
584
+ return { color: "var(--rdb-color-value-uuid)" };
585
+ case "Utf8":
586
+ return { color: "var(--rdb-color-value-string)" };
587
+ case "Blob":
588
+ return { color: "var(--rdb-color-secondary)" };
589
+ }
590
+ }
591
+ switch (typeof value) {
592
+ case "number":
593
+ case "bigint":
594
+ return { color: "var(--rdb-color-value-number)" };
595
+ case "boolean":
596
+ return { color: "var(--rdb-color-value-boolean)" };
597
+ case "string":
598
+ return { color: "var(--rdb-color-value-string)" };
599
+ default:
600
+ return {};
601
+ }
602
+ }
603
+ function formatValue(value) {
604
+ if (value === null || value === void 0) {
605
+ return "none";
606
+ }
607
+ if (typeof value === "object" && typeof value.type === "string") {
608
+ return value.toString();
609
+ }
610
+ if (typeof value === "bigint") {
611
+ return value.toString();
612
+ }
613
+ if (typeof value === "object") {
614
+ return JSON.stringify(value);
615
+ }
616
+ return String(value);
617
+ }
618
+
619
+ // src/components/results/ResultsTable.tsx
620
+ import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
621
+ function ResultsTable({ data }) {
622
+ if (data.length === 0) return null;
623
+ const columns = Object.keys(data[0]);
624
+ return /* @__PURE__ */ jsx6("div", { className: "rdb-results", children: /* @__PURE__ */ jsxs3("table", { className: "rdb-results__table", children: [
625
+ /* @__PURE__ */ jsx6("thead", { children: /* @__PURE__ */ jsx6("tr", { children: columns.map((col) => /* @__PURE__ */ jsx6("th", { children: col }, col)) }) }),
626
+ /* @__PURE__ */ jsx6("tbody", { children: data.map((row, i) => /* @__PURE__ */ jsx6("tr", { children: columns.map((col) => {
627
+ const vs = getValueStyle(row[col]);
628
+ return /* @__PURE__ */ jsx6(
629
+ "td",
630
+ {
631
+ style: {
632
+ color: vs.color,
633
+ fontStyle: vs.italic ? "italic" : void 0
634
+ },
635
+ children: formatValue(row[col])
636
+ },
637
+ col
638
+ );
639
+ }) }, i)) })
640
+ ] }) });
641
+ }
642
+
643
+ // src/components/results/ResultsError.tsx
644
+ import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
645
+ function ResultsError({ message }) {
646
+ return /* @__PURE__ */ jsx7("div", { className: "rdb-results__error", children: /* @__PURE__ */ jsxs4("pre", { children: [
647
+ "ERR: ",
648
+ message
649
+ ] }) });
650
+ }
651
+
652
+ // src/components/results/ResultsEmpty.tsx
653
+ import { jsx as jsx8 } from "react/jsx-runtime";
654
+ function ResultsEmpty() {
655
+ return /* @__PURE__ */ jsx8("div", { className: "rdb-results__empty", children: "$ 0 rows returned." });
656
+ }
657
+
658
+ // src/components/results/ResultsStatusBar.tsx
659
+ import { useCallback as useCallback2 } from "react";
660
+ import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
661
+ function ResultsStatusBar({ rowCount, executionTime, data }) {
662
+ const copyAsCsv = useCallback2(() => {
663
+ if (!data || data.length === 0) return;
664
+ const columns = Object.keys(data[0]);
665
+ const header = columns.join(",");
666
+ const rows = data.map(
667
+ (row) => columns.map((col) => {
668
+ const val = formatValue(row[col]);
669
+ return val.includes(",") || val.includes('"') || val.includes("\n") ? `"${val.replace(/"/g, '""')}"` : val;
670
+ }).join(",")
671
+ );
672
+ navigator.clipboard.writeText([header, ...rows].join("\n"));
673
+ }, [data]);
674
+ const copyAsJson = useCallback2(() => {
675
+ if (!data || data.length === 0) return;
676
+ const serialized = data.map((row) => {
677
+ const obj = {};
678
+ for (const [key, val] of Object.entries(row)) {
679
+ obj[key] = formatValue(val);
680
+ }
681
+ return obj;
682
+ });
683
+ navigator.clipboard.writeText(JSON.stringify(serialized, null, 2));
684
+ }, [data]);
685
+ return /* @__PURE__ */ jsxs5("div", { className: "rdb-status-bar", children: [
686
+ /* @__PURE__ */ jsxs5("div", { className: "rdb-status-bar__info", children: [
687
+ /* @__PURE__ */ jsxs5("span", { children: [
688
+ rowCount,
689
+ " row",
690
+ rowCount !== 1 ? "s" : ""
691
+ ] }),
692
+ /* @__PURE__ */ jsxs5("span", { children: [
693
+ "(",
694
+ executionTime,
695
+ "ms)"
696
+ ] })
697
+ ] }),
698
+ /* @__PURE__ */ jsxs5("div", { className: "rdb-status-bar__actions", children: [
699
+ /* @__PURE__ */ jsx9("button", { className: "rdb-status-bar__btn", onClick: copyAsCsv, title: "Copy as CSV", children: "[CSV]" }),
700
+ /* @__PURE__ */ jsx9("button", { className: "rdb-status-bar__btn", onClick: copyAsJson, title: "Copy as JSON", children: "[JSON]" })
701
+ ] })
702
+ ] });
703
+ }
704
+
705
+ // src/components/results/ResultsPanel.tsx
706
+ import { Fragment, jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
707
+ function ResultsPanel({ result }) {
708
+ if (!result) {
709
+ return /* @__PURE__ */ jsx10("div", { className: "rdb-results__empty", children: "$ run a query to see results" });
710
+ }
711
+ if (!result.success && result.error) {
712
+ return /* @__PURE__ */ jsx10(ResultsError, { message: result.error });
713
+ }
714
+ const data = result.data ?? [];
715
+ if (data.length === 0) {
716
+ return /* @__PURE__ */ jsx10(ResultsEmpty, {});
717
+ }
718
+ return /* @__PURE__ */ jsxs6(Fragment, { children: [
719
+ /* @__PURE__ */ jsx10(ResultsTable, { data }),
720
+ /* @__PURE__ */ jsx10(
721
+ ResultsStatusBar,
722
+ {
723
+ rowCount: data.length,
724
+ executionTime: result.executionTime,
725
+ data
726
+ }
727
+ )
728
+ ] });
729
+ }
730
+
731
+ // src/components/schema/SchemaBrowser.tsx
732
+ import { useEffect as useEffect2, useState as useState3 } from "react";
733
+
734
+ // src/components/schema/SchemaNode.tsx
735
+ import { useState as useState2 } from "react";
736
+ import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
737
+ function SchemaNode({ label, labelClass, type, typeClass, children }) {
738
+ const [expanded, setExpanded] = useState2(false);
739
+ const hasChildren = !!children;
740
+ return /* @__PURE__ */ jsxs7("div", { className: "rdb-schema__node", children: [
741
+ /* @__PURE__ */ jsxs7(
742
+ "div",
743
+ {
744
+ className: "rdb-schema__node-header",
745
+ onClick: () => hasChildren && setExpanded(!expanded),
746
+ children: [
747
+ hasChildren && /* @__PURE__ */ jsx11("span", { className: "rdb-schema__node-toggle", children: expanded ? "\u25BE" : "\u25B8" }),
748
+ !hasChildren && /* @__PURE__ */ jsx11("span", { className: "rdb-schema__node-toggle" }),
749
+ type && /* @__PURE__ */ jsx11("span", { className: typeClass ? "rdb-schema__node-type " + typeClass : "rdb-schema__node-type", children: type }),
750
+ /* @__PURE__ */ jsx11("span", { className: `rdb-schema__node-label${labelClass ? ` ${labelClass}` : ""}`, children: label })
751
+ ]
752
+ }
753
+ ),
754
+ expanded && hasChildren && /* @__PURE__ */ jsx11("div", { className: "rdb-schema__node-children", children })
755
+ ] });
756
+ }
757
+
758
+ // src/components/schema/SchemaBrowser.tsx
759
+ import { Fragment as Fragment2, jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
760
+ var TYPE_NAMES = {
761
+ 1: "Float4",
762
+ 2: "Float8",
763
+ 3: "Int1",
764
+ 4: "Int2",
765
+ 5: "Int4",
766
+ 6: "Int8",
767
+ 7: "Int16",
768
+ 8: "Utf8",
769
+ 9: "Uint1",
770
+ 10: "Uint2",
771
+ 11: "Uint4",
772
+ 12: "Uint8",
773
+ 13: "Uint16",
774
+ 14: "Boolean",
775
+ 15: "Date",
776
+ 16: "DateTime",
777
+ 17: "Time",
778
+ 18: "Duration",
779
+ 19: "IdentityId",
780
+ 20: "Uuid4",
781
+ 21: "Uuid7",
782
+ 22: "Blob",
783
+ 23: "Int",
784
+ 24: "Decimal",
785
+ 25: "Uint",
786
+ 26: "Any",
787
+ 27: "DictionaryId",
788
+ 28: "List"
789
+ };
790
+ var SOURCE_TYPE_TABLE = 1;
791
+ var SOURCE_TYPE_VIEW = 2;
792
+ var SOURCE_TYPE_VTABLE = 3;
793
+ var SOURCE_TYPE_RINGBUFFER = 4;
794
+ function resolveTypeName(typeId) {
795
+ const isOptional = (typeId & 128) !== 0;
796
+ const baseId = typeId & 127;
797
+ const name = TYPE_NAMES[baseId] ?? `Unknown(${baseId})`;
798
+ return isOptional ? `${name}?` : name;
799
+ }
800
+ function extractNum(value) {
801
+ if (typeof value === "number") return value;
802
+ if (typeof value === "bigint") return Number(value);
803
+ if (value && typeof value === "object" && typeof value.valueOf === "function") {
804
+ const v = value.valueOf();
805
+ if (typeof v === "number") return v;
806
+ if (typeof v === "bigint") return Number(v);
807
+ }
808
+ return Number(value);
809
+ }
810
+ function extractStr(value) {
811
+ if (typeof value === "string") return value;
812
+ if (value && typeof value === "object" && typeof value.valueOf === "function") {
813
+ const v = value.valueOf();
814
+ if (typeof v === "string") return v;
815
+ }
816
+ return String(value);
817
+ }
818
+ async function queryRows(executor, query) {
819
+ const result = await executor.execute(query);
820
+ return result.success && result.data ? result.data : [];
821
+ }
822
+ function typeColorClass(typeName) {
823
+ const base = typeName.replace(/\?$/, "");
824
+ switch (base) {
825
+ case "Float4":
826
+ case "Float8":
827
+ case "Int1":
828
+ case "Int2":
829
+ case "Int4":
830
+ case "Int8":
831
+ case "Int16":
832
+ case "Uint1":
833
+ case "Uint2":
834
+ case "Uint4":
835
+ case "Uint8":
836
+ case "Uint16":
837
+ case "Int":
838
+ case "Uint":
839
+ case "Decimal":
840
+ return "rdb-schema__node-type--numeric";
841
+ case "Utf8":
842
+ case "Blob":
843
+ return "rdb-schema__node-type--string";
844
+ case "Boolean":
845
+ return "rdb-schema__node-type--boolean";
846
+ case "Date":
847
+ case "DateTime":
848
+ case "Time":
849
+ case "Duration":
850
+ return "rdb-schema__node-type--temporal";
851
+ case "IdentityId":
852
+ case "Uuid4":
853
+ case "Uuid7":
854
+ case "DictionaryId":
855
+ return "rdb-schema__node-type--identity";
856
+ default:
857
+ return void 0;
858
+ }
859
+ }
860
+ var CATEGORY_GROUPS = [
861
+ { key: "table", label: "Tables" },
862
+ { key: "vtable", label: "Virtual Tables" },
863
+ { key: "view", label: "Views" },
864
+ { key: "ringbuffer", label: "Ring Buffers" },
865
+ { key: "procedure", label: "Procedures" },
866
+ { key: "handler", label: "Handlers" },
867
+ { key: "enum", label: "Enums" },
868
+ { key: "event", label: "Events" },
869
+ { key: "dictionary", label: "Dictionaries" },
870
+ { key: "migration", label: "Migrations" }
871
+ ];
872
+ function SchemaBrowser({ executor }) {
873
+ const [namespaces, setNamespaces] = useState3([]);
874
+ const [loading, setLoading] = useState3(true);
875
+ const loadSchema = async () => {
876
+ setLoading(true);
877
+ try {
878
+ const [nsRows, tableRows, viewRows, vtableRows, rbRows, colRows, vtableColRows, procRows, handlerRows, enumRows, eventRows, dictRows, migrationRows] = await Promise.all([
879
+ queryRows(executor, "FROM system::namespaces MAP { id, name }"),
880
+ queryRows(executor, "FROM system::tables MAP { id, namespace_id, name }"),
881
+ queryRows(executor, "FROM system::views MAP { id, namespace_id, name, kind }"),
882
+ queryRows(executor, "FROM system::virtual_tables MAP { id, namespace_id, name }"),
883
+ queryRows(executor, "FROM system::ringbuffers MAP { id, namespace_id, name }"),
884
+ queryRows(executor, "FROM system::columns MAP { source_id, source_type, name, type, position }"),
885
+ queryRows(executor, "FROM system::virtual_table_columns MAP { vtable_id, name, type, position }"),
886
+ queryRows(executor, "FROM system::procedures MAP { id, namespace_id, name }"),
887
+ queryRows(executor, "FROM system::handlers MAP { id, namespace_id, name }"),
888
+ queryRows(executor, "FROM system::enums MAP { id, namespace_id, name }"),
889
+ queryRows(executor, "FROM system::events MAP { id, namespace_id, name }"),
890
+ queryRows(executor, "FROM system::dictionaries MAP { id, namespace_id, name }"),
891
+ queryRows(executor, "FROM system::migrations MAP { name }")
892
+ ]);
893
+ const nsMap = /* @__PURE__ */ new Map();
894
+ for (const row of nsRows) {
895
+ nsMap.set(extractNum(row.id), extractStr(row.name));
896
+ }
897
+ const columnsBySource = /* @__PURE__ */ new Map();
898
+ const rawColumns = /* @__PURE__ */ new Map();
899
+ for (const row of colRows) {
900
+ const key = `${extractNum(row.source_type)}:${extractNum(row.source_id)}`;
901
+ if (!rawColumns.has(key)) rawColumns.set(key, []);
902
+ rawColumns.get(key).push({
903
+ name: extractStr(row.name),
904
+ type: resolveTypeName(extractNum(row.type)),
905
+ position: extractNum(row.position)
906
+ });
907
+ }
908
+ for (const row of vtableColRows) {
909
+ const key = `${SOURCE_TYPE_VTABLE}:${extractNum(row.vtable_id)}`;
910
+ if (!rawColumns.has(key)) rawColumns.set(key, []);
911
+ rawColumns.get(key).push({
912
+ name: extractStr(row.name),
913
+ type: resolveTypeName(extractNum(row.type)),
914
+ position: extractNum(row.position)
915
+ });
916
+ }
917
+ for (const [key, cols] of rawColumns) {
918
+ cols.sort((a, b) => a.position - b.position);
919
+ columnsBySource.set(key, cols.map((c) => ({ name: c.name, type: c.type })));
920
+ }
921
+ const nsSources = /* @__PURE__ */ new Map();
922
+ const addSource = (id, nsId, name, category, sourceType) => {
923
+ if (!nsSources.has(nsId)) nsSources.set(nsId, []);
924
+ const columns = columnsBySource.get(`${sourceType}:${id}`) ?? [];
925
+ nsSources.get(nsId).push({ name: extractStr(name), category, columns });
926
+ };
927
+ for (const row of tableRows) {
928
+ addSource(extractNum(row.id), extractNum(row.namespace_id), extractStr(row.name), "table", SOURCE_TYPE_TABLE);
929
+ }
930
+ for (const row of viewRows) {
931
+ addSource(extractNum(row.id), extractNum(row.namespace_id), extractStr(row.name), "view", SOURCE_TYPE_VIEW);
932
+ }
933
+ for (const row of vtableRows) {
934
+ addSource(extractNum(row.id), extractNum(row.namespace_id), extractStr(row.name), "vtable", SOURCE_TYPE_VTABLE);
935
+ }
936
+ for (const row of rbRows) {
937
+ addSource(extractNum(row.id), extractNum(row.namespace_id), extractStr(row.name), "ringbuffer", SOURCE_TYPE_RINGBUFFER);
938
+ }
939
+ const addLeafSource = (nsId, name, category) => {
940
+ if (!nsSources.has(nsId)) nsSources.set(nsId, []);
941
+ nsSources.get(nsId).push({ name: extractStr(name), category, columns: [] });
942
+ };
943
+ for (const row of procRows) {
944
+ addLeafSource(extractNum(row.namespace_id), extractStr(row.name), "procedure");
945
+ }
946
+ for (const row of handlerRows) {
947
+ addLeafSource(extractNum(row.namespace_id), extractStr(row.name), "handler");
948
+ }
949
+ for (const row of enumRows) {
950
+ addLeafSource(extractNum(row.namespace_id), extractStr(row.name), "enum");
951
+ }
952
+ for (const row of eventRows) {
953
+ addLeafSource(extractNum(row.namespace_id), extractStr(row.name), "event");
954
+ }
955
+ for (const row of dictRows) {
956
+ addLeafSource(extractNum(row.namespace_id), extractStr(row.name), "dictionary");
957
+ }
958
+ let systemNsId;
959
+ for (const [id, name] of nsMap) {
960
+ if (name === "system") {
961
+ systemNsId = id;
962
+ break;
963
+ }
964
+ }
965
+ if (systemNsId !== void 0) {
966
+ for (const row of migrationRows) {
967
+ addLeafSource(systemNsId, extractStr(row.name), "migration");
968
+ }
969
+ }
970
+ const result = [];
971
+ for (const [nsId, nsName] of nsMap) {
972
+ const sources = nsSources.get(nsId) ?? [];
973
+ sources.sort((a, b) => a.name.localeCompare(b.name));
974
+ result.push({ name: nsName, sources });
975
+ }
976
+ result.sort((a, b) => a.name.localeCompare(b.name));
977
+ setNamespaces(result);
978
+ } catch {
979
+ setNamespaces([]);
980
+ } finally {
981
+ setLoading(false);
982
+ }
983
+ };
984
+ useEffect2(() => {
985
+ loadSchema();
986
+ }, [executor]);
987
+ const toolbar = /* @__PURE__ */ jsx12("div", { className: "rdb-schema__toolbar", children: /* @__PURE__ */ jsx12(
988
+ "button",
989
+ {
990
+ className: "rdb-schema__reload-btn",
991
+ onClick: loadSchema,
992
+ disabled: loading,
993
+ children: loading ? "[loading...]" : "[reload]"
994
+ }
995
+ ) });
996
+ if (loading) {
997
+ return /* @__PURE__ */ jsxs8(Fragment2, { children: [
998
+ toolbar,
999
+ /* @__PURE__ */ jsx12("div", { className: "rdb-history__empty", children: "$ loading schema..." })
1000
+ ] });
1001
+ }
1002
+ if (namespaces.length === 0) {
1003
+ return /* @__PURE__ */ jsxs8(Fragment2, { children: [
1004
+ toolbar,
1005
+ /* @__PURE__ */ jsx12("div", { className: "rdb-history__empty", children: "$ no tables found" })
1006
+ ] });
1007
+ }
1008
+ return /* @__PURE__ */ jsxs8(Fragment2, { children: [
1009
+ toolbar,
1010
+ /* @__PURE__ */ jsx12("div", { children: namespaces.map((ns) => /* @__PURE__ */ jsx12(SchemaNode, { label: ns.name, labelClass: "rdb-schema__node-label--namespace", children: CATEGORY_GROUPS.map(({ key, label }) => {
1011
+ const sources = ns.sources.filter((s) => s.category === key);
1012
+ if (sources.length === 0) return null;
1013
+ return /* @__PURE__ */ jsx12(SchemaNode, { label: `${label} (${sources.length})`, labelClass: "rdb-schema__node-label--category", children: sources.map((source) => /* @__PURE__ */ jsx12(SchemaNode, { label: source.name, children: source.columns.length > 0 ? source.columns.map((col) => /* @__PURE__ */ jsx12(
1014
+ SchemaNode,
1015
+ {
1016
+ label: col.name,
1017
+ labelClass: "rdb-schema__node-label--column",
1018
+ type: col.type,
1019
+ typeClass: typeColorClass(col.type)
1020
+ },
1021
+ col.name
1022
+ )) : void 0 }, source.name)) }, key);
1023
+ }) }, ns.name)) })
1024
+ ] });
1025
+ }
1026
+
1027
+ // src/components/history/HistoryPanel.tsx
1028
+ import { useState as useState4 } from "react";
1029
+
1030
+ // src/components/history/HistoryEntry.tsx
1031
+ import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
1032
+ function formatTimestamp(ts) {
1033
+ const d = new Date(ts);
1034
+ const hh = String(d.getHours()).padStart(2, "0");
1035
+ const mm = String(d.getMinutes()).padStart(2, "0");
1036
+ const ss = String(d.getSeconds()).padStart(2, "0");
1037
+ return `${hh}:${mm}:${ss}`;
1038
+ }
1039
+ function HistoryEntryRow({ entry, onClick }) {
1040
+ return /* @__PURE__ */ jsxs9("div", { className: "rdb-history__entry", onClick: () => onClick(entry.query), children: [
1041
+ /* @__PURE__ */ jsxs9("div", { className: "rdb-history__entry-meta", children: [
1042
+ /* @__PURE__ */ jsx13("span", { children: formatTimestamp(entry.timestamp) }),
1043
+ /* @__PURE__ */ jsxs9("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
1044
+ /* @__PURE__ */ jsxs9("span", { children: [
1045
+ entry.executionTime,
1046
+ "ms"
1047
+ ] }),
1048
+ /* @__PURE__ */ jsx13(
1049
+ "span",
1050
+ {
1051
+ className: `rdb-history__entry-indicator ${entry.success ? "rdb-history__entry-indicator--success" : "rdb-history__entry-indicator--error"}`
1052
+ }
1053
+ )
1054
+ ] })
1055
+ ] }),
1056
+ /* @__PURE__ */ jsx13("div", { className: "rdb-history__entry-query", children: entry.query })
1057
+ ] });
1058
+ }
1059
+
1060
+ // src/components/history/HistoryPanel.tsx
1061
+ import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
1062
+ function HistoryPanel({ entries, onSelect }) {
1063
+ const [search, setSearch] = useState4("");
1064
+ const filtered = search ? entries.filter((e) => e.query.toLowerCase().includes(search.toLowerCase())) : entries;
1065
+ return /* @__PURE__ */ jsxs10("div", { className: "rdb-history", children: [
1066
+ /* @__PURE__ */ jsx14("div", { className: "rdb-history__search", children: /* @__PURE__ */ jsx14(
1067
+ "input",
1068
+ {
1069
+ type: "text",
1070
+ className: "rdb-history__search-input",
1071
+ placeholder: "search history...",
1072
+ value: search,
1073
+ onChange: (e) => setSearch(e.target.value)
1074
+ }
1075
+ ) }),
1076
+ /* @__PURE__ */ jsx14("div", { className: "rdb-history__list", children: filtered.length === 0 ? /* @__PURE__ */ jsx14("div", { className: "rdb-history__empty", children: entries.length === 0 ? "$ no history yet" : "$ no matching queries" }) : filtered.map((entry) => /* @__PURE__ */ jsx14(HistoryEntryRow, { entry, onClick: onSelect }, entry.id)) })
1077
+ ] });
1078
+ }
1079
+
1080
+ // src/components/connection/ConnectionPanel.tsx
1081
+ import { useEffect as useEffect3, useRef as useRef3 } from "react";
1082
+ import { Fragment as Fragment3, jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
1083
+ function ConnectionPanel({
1084
+ mode,
1085
+ wsUrl,
1086
+ status,
1087
+ error,
1088
+ onModeChange,
1089
+ onUrlChange,
1090
+ onConnect,
1091
+ onDisconnect,
1092
+ onClose
1093
+ }) {
1094
+ const panelRef = useRef3(null);
1095
+ useEffect3(() => {
1096
+ function handleClickOutside(e) {
1097
+ if (panelRef.current && !panelRef.current.contains(e.target)) {
1098
+ onClose();
1099
+ }
1100
+ }
1101
+ function handleEscape(e) {
1102
+ if (e.key === "Escape") onClose();
1103
+ }
1104
+ document.addEventListener("mousedown", handleClickOutside);
1105
+ document.addEventListener("keydown", handleEscape);
1106
+ return () => {
1107
+ document.removeEventListener("mousedown", handleClickOutside);
1108
+ document.removeEventListener("keydown", handleEscape);
1109
+ };
1110
+ }, [onClose]);
1111
+ const isWsConnected = mode === "websocket" && status === "connected";
1112
+ const isWsConnecting = mode === "websocket" && status === "connecting";
1113
+ return /* @__PURE__ */ jsxs11("div", { className: "rdb-connection-panel", ref: panelRef, children: [
1114
+ /* @__PURE__ */ jsx15("div", { className: "rdb-connection-panel__header", children: "connection" }),
1115
+ /* @__PURE__ */ jsxs11("div", { className: "rdb-connection-panel__modes", children: [
1116
+ /* @__PURE__ */ jsx15(
1117
+ "button",
1118
+ {
1119
+ className: `rdb-connection-panel__mode-btn ${mode === "wasm" ? "rdb-connection-panel__mode-btn--active" : ""}`,
1120
+ onClick: () => onModeChange("wasm"),
1121
+ children: "[wasm (in-browser)]"
1122
+ }
1123
+ ),
1124
+ /* @__PURE__ */ jsx15(
1125
+ "button",
1126
+ {
1127
+ className: `rdb-connection-panel__mode-btn ${mode === "websocket" ? "rdb-connection-panel__mode-btn--active" : ""}`,
1128
+ onClick: () => onModeChange("websocket"),
1129
+ children: "[websocket (remote)]"
1130
+ }
1131
+ )
1132
+ ] }),
1133
+ mode === "websocket" && /* @__PURE__ */ jsxs11(Fragment3, { children: [
1134
+ /* @__PURE__ */ jsxs11("div", { className: "rdb-connection-panel__url-row", children: [
1135
+ /* @__PURE__ */ jsx15("span", { className: "rdb-connection-panel__url-label", children: "url:" }),
1136
+ /* @__PURE__ */ jsx15(
1137
+ "input",
1138
+ {
1139
+ className: "rdb-connection-panel__url-input",
1140
+ type: "text",
1141
+ value: wsUrl,
1142
+ onChange: (e) => onUrlChange(e.target.value),
1143
+ placeholder: "ws://localhost:8090",
1144
+ disabled: isWsConnected || isWsConnecting
1145
+ }
1146
+ )
1147
+ ] }),
1148
+ /* @__PURE__ */ jsx15("div", { className: "rdb-connection-panel__actions", children: isWsConnected ? /* @__PURE__ */ jsx15("button", { className: "rdb-connection-panel__action-btn", onClick: onDisconnect, children: "[disconnect]" }) : /* @__PURE__ */ jsx15(
1149
+ "button",
1150
+ {
1151
+ className: "rdb-connection-panel__action-btn",
1152
+ onClick: onConnect,
1153
+ disabled: isWsConnecting || !wsUrl.trim(),
1154
+ children: isWsConnecting ? "[connecting...]" : "[connect]"
1155
+ }
1156
+ ) })
1157
+ ] }),
1158
+ /* @__PURE__ */ jsxs11("div", { className: "rdb-connection-panel__status", children: [
1159
+ /* @__PURE__ */ jsx15("span", { className: `rdb-connection-panel__status-dot rdb-connection-panel__status-dot--${status}`, children: "\u25CF" }),
1160
+ /* @__PURE__ */ jsx15("span", { children: status })
1161
+ ] }),
1162
+ error && /* @__PURE__ */ jsx15("div", { className: "rdb-connection-panel__error", children: error })
1163
+ ] });
1164
+ }
1165
+
1166
+ // src/components/Console.tsx
1167
+ import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
1168
+ var TABS = [
1169
+ { id: "results", label: "Results" },
1170
+ { id: "history", label: "History" },
1171
+ { id: "schema", label: "Schema" }
1172
+ ];
1173
+ var WS_URL_STORAGE_KEY = "rdb-console-ws-url";
1174
+ function ConsoleInner({ executor, historyKey, connection, theme = "light" }) {
1175
+ const { state, dispatch } = useConsoleStore();
1176
+ const connectionLocked = connection != null;
1177
+ const lockedWsUrl = connection?.mode === "websocket" ? connection.url : null;
1178
+ const [connectionMode, setConnectionMode] = useState5(
1179
+ connection ? connection.mode : "wasm"
1180
+ );
1181
+ const [wsUrl, setWsUrl] = useState5(() => {
1182
+ if (connection?.mode === "websocket") return connection.url;
1183
+ try {
1184
+ return localStorage.getItem(WS_URL_STORAGE_KEY) || "ws://localhost:8090";
1185
+ } catch {
1186
+ return "ws://localhost:8090";
1187
+ }
1188
+ });
1189
+ const [connectionStatus, setConnectionStatus] = useState5(
1190
+ connection?.mode === "websocket" ? "connecting" : "connected"
1191
+ );
1192
+ const [connectionError, setConnectionError] = useState5(null);
1193
+ const [activeExecutor, setActiveExecutor] = useState5(executor);
1194
+ const [showConnectionPanel, setShowConnectionPanel] = useState5(false);
1195
+ const wsClientRef = useRef4(null);
1196
+ const reconnectTimerRef = useRef4(null);
1197
+ useEffect4(() => {
1198
+ if (connectionLocked) return;
1199
+ try {
1200
+ localStorage.setItem(WS_URL_STORAGE_KEY, wsUrl);
1201
+ } catch {
1202
+ }
1203
+ }, [wsUrl, connectionLocked]);
1204
+ useEffect4(() => {
1205
+ if (connectionMode === "wasm") {
1206
+ setActiveExecutor(executor);
1207
+ }
1208
+ }, [executor, connectionMode]);
1209
+ useEffect4(() => {
1210
+ if (!lockedWsUrl) return;
1211
+ const url = lockedWsUrl;
1212
+ let cancelled = false;
1213
+ let backoff = 1e3;
1214
+ const maxBackoff = 3e4;
1215
+ async function connect() {
1216
+ if (cancelled) return;
1217
+ setConnectionStatus("connecting");
1218
+ setConnectionError(null);
1219
+ try {
1220
+ if (wsClientRef.current) {
1221
+ wsClientRef.current.disconnect();
1222
+ wsClientRef.current = null;
1223
+ }
1224
+ const client = await Client.connect_ws(url, { timeoutMs: 3e4 });
1225
+ if (cancelled) {
1226
+ client.disconnect();
1227
+ return;
1228
+ }
1229
+ wsClientRef.current = client;
1230
+ const wsExecutor = new WsExecutor(client);
1231
+ setActiveExecutor(wsExecutor);
1232
+ setConnectionStatus("connected");
1233
+ backoff = 1e3;
1234
+ } catch (err) {
1235
+ if (cancelled) return;
1236
+ setConnectionStatus("error");
1237
+ setConnectionError(err instanceof Error ? err.message : String(err));
1238
+ reconnectTimerRef.current = setTimeout(() => {
1239
+ connect();
1240
+ }, backoff);
1241
+ backoff = Math.min(backoff * 2, maxBackoff);
1242
+ }
1243
+ }
1244
+ connect();
1245
+ return () => {
1246
+ cancelled = true;
1247
+ if (reconnectTimerRef.current) {
1248
+ clearTimeout(reconnectTimerRef.current);
1249
+ reconnectTimerRef.current = null;
1250
+ }
1251
+ if (wsClientRef.current) {
1252
+ wsClientRef.current.disconnect();
1253
+ wsClientRef.current = null;
1254
+ }
1255
+ };
1256
+ }, [lockedWsUrl]);
1257
+ useEffect4(() => {
1258
+ const entries = loadHistory(historyKey);
1259
+ if (entries.length > 0) {
1260
+ dispatch({ type: "LOAD_HISTORY", entries });
1261
+ }
1262
+ }, [historyKey, dispatch]);
1263
+ useEffect4(() => {
1264
+ saveHistory(state.history, historyKey);
1265
+ }, [state.history, historyKey]);
1266
+ const handleConnect = useCallback3(async () => {
1267
+ if (!wsUrl.trim()) return;
1268
+ setConnectionStatus("connecting");
1269
+ setConnectionError(null);
1270
+ try {
1271
+ if (wsClientRef.current) {
1272
+ wsClientRef.current.disconnect();
1273
+ wsClientRef.current = null;
1274
+ }
1275
+ const client = await Client.connect_ws(wsUrl, { timeoutMs: 3e4 });
1276
+ wsClientRef.current = client;
1277
+ const wsExecutor = new WsExecutor(client);
1278
+ setActiveExecutor(wsExecutor);
1279
+ setConnectionStatus("connected");
1280
+ } catch (err) {
1281
+ setConnectionStatus("error");
1282
+ setConnectionError(err instanceof Error ? err.message : String(err));
1283
+ }
1284
+ }, [wsUrl]);
1285
+ const handleDisconnect = useCallback3(() => {
1286
+ if (wsClientRef.current) {
1287
+ wsClientRef.current.disconnect();
1288
+ wsClientRef.current = null;
1289
+ }
1290
+ setActiveExecutor(executor);
1291
+ setConnectionMode("wasm");
1292
+ setConnectionStatus("connected");
1293
+ setConnectionError(null);
1294
+ }, [executor]);
1295
+ const handleModeChange = useCallback3((mode) => {
1296
+ if (mode === "wasm" && connectionMode === "websocket") {
1297
+ if (wsClientRef.current) {
1298
+ wsClientRef.current.disconnect();
1299
+ wsClientRef.current = null;
1300
+ }
1301
+ setActiveExecutor(executor);
1302
+ setConnectionStatus("connected");
1303
+ setConnectionError(null);
1304
+ } else if (mode === "websocket" && connectionMode === "wasm") {
1305
+ setConnectionStatus("disconnected");
1306
+ setConnectionError(null);
1307
+ }
1308
+ setConnectionMode(mode);
1309
+ }, [connectionMode, executor]);
1310
+ const connectionLabel = connectionMode === "wasm" ? "wasm" : wsUrl;
1311
+ const handleRun = useCallback3(async () => {
1312
+ if (state.isExecuting || !state.code.trim()) return;
1313
+ dispatch({ type: "EXECUTE_START" });
1314
+ try {
1315
+ const result = await activeExecutor.execute(state.code);
1316
+ if (result.success) {
1317
+ dispatch({ type: "EXECUTE_SUCCESS", result, query: state.code });
1318
+ } else {
1319
+ dispatch({ type: "EXECUTE_ERROR", result, query: state.code });
1320
+ }
1321
+ } catch (err) {
1322
+ dispatch({
1323
+ type: "EXECUTE_ERROR",
1324
+ result: {
1325
+ success: false,
1326
+ error: err instanceof Error ? err.message : String(err),
1327
+ executionTime: 0
1328
+ },
1329
+ query: state.code
1330
+ });
1331
+ }
1332
+ }, [state.isExecuting, state.code, activeExecutor, dispatch]);
1333
+ const handleClear = useCallback3(() => {
1334
+ dispatch({ type: "CLEAR_RESULTS" });
1335
+ }, [dispatch]);
1336
+ const handleSelectHistory = useCallback3((query) => {
1337
+ dispatch({ type: "LOAD_QUERY", code: query });
1338
+ }, [dispatch]);
1339
+ const editorPane = /* @__PURE__ */ jsxs12("div", { style: { display: "flex", flexDirection: "column", height: "100%" }, children: [
1340
+ /* @__PURE__ */ jsxs12("div", { style: { position: "relative" }, children: [
1341
+ /* @__PURE__ */ jsx16(
1342
+ EditorToolbar,
1343
+ {
1344
+ onRun: handleRun,
1345
+ onClear: handleClear,
1346
+ isExecuting: state.isExecuting,
1347
+ connectionLabel,
1348
+ connectionStatus,
1349
+ connectionLocked,
1350
+ onToggleConnectionPanel: () => setShowConnectionPanel((v) => !v)
1351
+ }
1352
+ ),
1353
+ !connectionLocked && showConnectionPanel && /* @__PURE__ */ jsx16(
1354
+ ConnectionPanel,
1355
+ {
1356
+ mode: connectionMode,
1357
+ wsUrl,
1358
+ status: connectionStatus,
1359
+ error: connectionError,
1360
+ onModeChange: handleModeChange,
1361
+ onUrlChange: setWsUrl,
1362
+ onConnect: handleConnect,
1363
+ onDisconnect: handleDisconnect,
1364
+ onClose: () => setShowConnectionPanel(false)
1365
+ }
1366
+ )
1367
+ ] }),
1368
+ /* @__PURE__ */ jsx16("div", { style: { flex: 1, minHeight: 0 }, children: /* @__PURE__ */ jsx16(
1369
+ QueryEditor,
1370
+ {
1371
+ code: state.code,
1372
+ onChange: (code) => dispatch({ type: "SET_CODE", code }),
1373
+ onRun: handleRun,
1374
+ theme
1375
+ }
1376
+ ) })
1377
+ ] });
1378
+ const bottomPane = /* @__PURE__ */ jsxs12("div", { style: { display: "flex", flexDirection: "column", height: "100%" }, children: [
1379
+ /* @__PURE__ */ jsx16(
1380
+ TabBar,
1381
+ {
1382
+ activeTab: state.activeTab,
1383
+ tabs: TABS,
1384
+ onTabChange: (tab) => dispatch({ type: "SET_TAB", tab })
1385
+ }
1386
+ ),
1387
+ /* @__PURE__ */ jsx16("div", { style: { flex: 1, overflow: "auto", minHeight: 0 }, children: state.activeTab === "results" ? /* @__PURE__ */ jsx16(ResultsPanel, { result: state.result }) : state.activeTab === "history" ? /* @__PURE__ */ jsx16(HistoryPanel, { entries: state.history, onSelect: handleSelectHistory }) : /* @__PURE__ */ jsx16(SchemaBrowser, { executor: activeExecutor }) })
1388
+ ] });
1389
+ return /* @__PURE__ */ jsx16("div", { className: `rdb-console${theme === "light" ? " rdb-theme-light" : ""}`, children: /* @__PURE__ */ jsx16("div", { className: "rdb-console__main", children: /* @__PURE__ */ jsx16(SplitPane, { top: editorPane, bottom: bottomPane, initialSplit: 45 }) }) });
1390
+ }
1391
+ function Console({ executor, initialCode, historyKey, connection, theme }) {
1392
+ return /* @__PURE__ */ jsx16(ConsoleProvider, { initialCode, children: /* @__PURE__ */ jsx16(ConsoleInner, { executor, historyKey, connection, theme }) });
1393
+ }
1394
+
1395
+ // src/components/Snippet.tsx
1396
+ import { useState as useState6, useCallback as useCallback4, useEffect as useEffect5, useRef as useRef5 } from "react";
1397
+ import Editor2 from "@monaco-editor/react";
1398
+
1399
+ // src/components/SnippetResults.tsx
1400
+ import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
1401
+ function SnippetResults({ data, columns, maxKeyLength }) {
1402
+ return /* @__PURE__ */ jsx17("div", { className: "rdb-snippet__rows", children: data.map((row, i) => /* @__PURE__ */ jsxs13("div", { className: "rdb-snippet__row", children: [
1403
+ /* @__PURE__ */ jsxs13("div", { className: "rdb-snippet__row-label", children: [
1404
+ "-- row ",
1405
+ i + 1,
1406
+ " --"
1407
+ ] }),
1408
+ columns.map((col) => {
1409
+ const vs = getValueStyle(row[col]);
1410
+ return /* @__PURE__ */ jsxs13("div", { className: "rdb-snippet__field", children: [
1411
+ /* @__PURE__ */ jsx17(
1412
+ "span",
1413
+ {
1414
+ className: "rdb-snippet__field-key",
1415
+ style: { minWidth: `${maxKeyLength}ch` },
1416
+ children: ` ${col.padEnd(maxKeyLength)}`
1417
+ }
1418
+ ),
1419
+ /* @__PURE__ */ jsx17("span", { className: "rdb-snippet__field-eq", children: "= " }),
1420
+ /* @__PURE__ */ jsx17(
1421
+ "span",
1422
+ {
1423
+ className: `rdb-snippet__field-value${vs.italic ? " rdb-snippet__field-value--italic" : ""}`,
1424
+ style: vs.color ? { color: vs.color } : void 0,
1425
+ children: formatValue(row[col])
1426
+ }
1427
+ )
1428
+ ] }, col);
1429
+ })
1430
+ ] }, i)) });
1431
+ }
1432
+
1433
+ // src/components/Snippet.tsx
1434
+ import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
1435
+ function Snippet({
1436
+ executor,
1437
+ initialCode,
1438
+ title = "reifydb playground",
1439
+ description,
1440
+ className,
1441
+ theme = "light"
1442
+ }) {
1443
+ const [code, setCode] = useState6(initialCode);
1444
+ const [result, setResult] = useState6(null);
1445
+ const [isExecuting, setIsExecuting] = useState6(false);
1446
+ const [copied, setCopied] = useState6(false);
1447
+ const [isFullscreen, setIsFullscreen] = useState6(false);
1448
+ const editorRef = useRef5(null);
1449
+ const handleRunRef = useRef5(() => {
1450
+ });
1451
+ const lineCount = code.split("\n").length;
1452
+ const editorHeight = Math.max(lineCount * 20 + 16, 80);
1453
+ useEffect5(() => {
1454
+ if (!isFullscreen) return;
1455
+ const handleEsc = (e) => {
1456
+ if (e.key === "Escape") setIsFullscreen(false);
1457
+ };
1458
+ document.addEventListener("keydown", handleEsc);
1459
+ document.body.style.overflow = "hidden";
1460
+ return () => {
1461
+ document.removeEventListener("keydown", handleEsc);
1462
+ document.body.style.overflow = "";
1463
+ };
1464
+ }, [isFullscreen]);
1465
+ const handleRun = useCallback4(async () => {
1466
+ if (isExecuting) return;
1467
+ setResult(null);
1468
+ setIsExecuting(true);
1469
+ await new Promise((r) => setTimeout(r, 0));
1470
+ try {
1471
+ const res = await executor.execute(code);
1472
+ if (res.success) {
1473
+ setResult({ data: res.data ?? [] });
1474
+ } else {
1475
+ setResult({ data: [], error: res.error });
1476
+ }
1477
+ } catch (err) {
1478
+ setResult({ data: [], error: err instanceof Error ? err.message : String(err) });
1479
+ } finally {
1480
+ setIsExecuting(false);
1481
+ }
1482
+ }, [code, executor, isExecuting]);
1483
+ handleRunRef.current = handleRun;
1484
+ const handleReset = useCallback4(() => {
1485
+ setCode(initialCode);
1486
+ setResult(null);
1487
+ }, [initialCode]);
1488
+ const handleCopy = useCallback4(async () => {
1489
+ await navigator.clipboard.writeText(code);
1490
+ setCopied(true);
1491
+ setTimeout(() => setCopied(false), 2e3);
1492
+ }, [code]);
1493
+ const handleEditorDidMount = (editor, monaco) => {
1494
+ editorRef.current = editor;
1495
+ registerRqlLanguage(monaco);
1496
+ editor.addAction({
1497
+ id: "run-query",
1498
+ label: "Run Query",
1499
+ keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter],
1500
+ run: () => {
1501
+ handleRunRef.current();
1502
+ }
1503
+ });
1504
+ };
1505
+ const handleBeforeMount = (monaco) => {
1506
+ registerRqlLanguage(monaco);
1507
+ };
1508
+ const columns = result?.data && result.data.length > 0 ? Object.keys(result.data[0]) : [];
1509
+ const maxKeyLength = columns.length > 0 ? Math.max(...columns.map((c) => c.length)) : 0;
1510
+ const content = /* @__PURE__ */ jsxs14("div", { className: `rdb-snippet${isFullscreen ? " rdb-snippet--fullscreen" : ""}${theme === "light" ? " rdb-theme-light" : ""}${className ? ` ${className}` : ""}`, children: [
1511
+ /* @__PURE__ */ jsxs14("div", { className: "rdb-snippet__header", children: [
1512
+ /* @__PURE__ */ jsxs14("div", { className: "rdb-snippet__title", children: [
1513
+ /* @__PURE__ */ jsx18("span", { className: "rdb-snippet__title-marker", children: "$" }),
1514
+ " ",
1515
+ title
1516
+ ] }),
1517
+ /* @__PURE__ */ jsxs14("div", { className: "rdb-snippet__actions", children: [
1518
+ /* @__PURE__ */ jsx18(
1519
+ "button",
1520
+ {
1521
+ onClick: () => setIsFullscreen(!isFullscreen),
1522
+ className: "rdb-snippet__action-btn",
1523
+ title: isFullscreen ? "Exit fullscreen" : "Fullscreen",
1524
+ children: isFullscreen ? "[\xD7]" : "[[]]"
1525
+ }
1526
+ ),
1527
+ /* @__PURE__ */ jsx18(
1528
+ "button",
1529
+ {
1530
+ onClick: handleCopy,
1531
+ className: "rdb-snippet__action-btn",
1532
+ title: "Copy code",
1533
+ children: copied ? "[ok]" : "[cp]"
1534
+ }
1535
+ ),
1536
+ /* @__PURE__ */ jsx18(
1537
+ "button",
1538
+ {
1539
+ onClick: handleReset,
1540
+ className: "rdb-snippet__action-btn",
1541
+ title: "Reset code",
1542
+ children: "[\u21BA]"
1543
+ }
1544
+ )
1545
+ ] })
1546
+ ] }),
1547
+ description && /* @__PURE__ */ jsx18("div", { className: "rdb-snippet__description", children: /* @__PURE__ */ jsxs14("p", { className: "rdb-snippet__description-text", children: [
1548
+ /* @__PURE__ */ jsx18("span", { className: "rdb-snippet__description-marker", children: "// " }),
1549
+ description
1550
+ ] }) }),
1551
+ /* @__PURE__ */ jsx18(
1552
+ "div",
1553
+ {
1554
+ className: isFullscreen ? "rdb-snippet__editor--fullscreen" : "rdb-snippet__editor",
1555
+ style: isFullscreen ? void 0 : { height: editorHeight },
1556
+ children: /* @__PURE__ */ jsx18(
1557
+ Editor2,
1558
+ {
1559
+ height: "100%",
1560
+ language: "rql",
1561
+ theme: theme === "light" ? "premium-light" : "premium-dark",
1562
+ value: code,
1563
+ onChange: (value) => setCode(value || ""),
1564
+ beforeMount: handleBeforeMount,
1565
+ onMount: handleEditorDidMount,
1566
+ options: {
1567
+ minimap: { enabled: false },
1568
+ lineNumbers: "on",
1569
+ glyphMargin: false,
1570
+ folding: false,
1571
+ lineDecorationsWidth: 16,
1572
+ lineNumbersMinChars: 3,
1573
+ scrollBeyondLastLine: false,
1574
+ scrollbar: {
1575
+ vertical: isFullscreen ? "auto" : "hidden",
1576
+ horizontal: isFullscreen ? "auto" : "hidden"
1577
+ },
1578
+ overviewRulerLanes: 0,
1579
+ hideCursorInOverviewRuler: true,
1580
+ overviewRulerBorder: false,
1581
+ renderLineHighlight: "none",
1582
+ fontFamily: "'IBM Plex Mono', monospace",
1583
+ fontSize: 13,
1584
+ padding: { top: 8, bottom: 8 },
1585
+ wordWrap: "on",
1586
+ automaticLayout: true
1587
+ }
1588
+ }
1589
+ )
1590
+ }
1591
+ ),
1592
+ /* @__PURE__ */ jsxs14("div", { className: "rdb-snippet__toolbar", children: [
1593
+ /* @__PURE__ */ jsx18("span", { className: "rdb-snippet__hint", children: isExecuting ? "$ running..." : "$ ctrl+enter to run" }),
1594
+ /* @__PURE__ */ jsx18(
1595
+ "button",
1596
+ {
1597
+ onClick: handleRun,
1598
+ disabled: isExecuting,
1599
+ className: `rdb-snippet__run-btn${isExecuting ? " rdb-snippet__run-btn--loading" : ""}`,
1600
+ children: isExecuting ? "[running...]" : "[run]"
1601
+ }
1602
+ )
1603
+ ] }),
1604
+ result && /* @__PURE__ */ jsxs14("div", { className: `rdb-snippet__results${isFullscreen ? " rdb-snippet__results--fullscreen" : ""}`, children: [
1605
+ /* @__PURE__ */ jsxs14("div", { className: "rdb-snippet__results-header", children: [
1606
+ /* @__PURE__ */ jsx18("span", { children: result.error ? "--- error ---" : "--- output ---" }),
1607
+ result.data && !result.error && /* @__PURE__ */ jsxs14("span", { children: [
1608
+ "(",
1609
+ result.data.length,
1610
+ " row",
1611
+ result.data.length !== 1 ? "s" : "",
1612
+ ")"
1613
+ ] })
1614
+ ] }),
1615
+ result.error && /* @__PURE__ */ jsx18("div", { className: "rdb-snippet__error", children: /* @__PURE__ */ jsxs14("pre", { className: "rdb-snippet__error-text", children: [
1616
+ "ERR: ",
1617
+ result.error
1618
+ ] }) }),
1619
+ result.data && result.data.length > 0 && !result.error && /* @__PURE__ */ jsx18(SnippetResults, { data: result.data, columns, maxKeyLength }),
1620
+ result.data && result.data.length === 0 && !result.error && /* @__PURE__ */ jsx18("div", { className: "rdb-snippet__empty", children: "$ 0 rows returned." })
1621
+ ] })
1622
+ ] });
1623
+ if (isFullscreen) {
1624
+ return /* @__PURE__ */ jsx18("div", { className: "rdb-snippet__overlay", children: /* @__PURE__ */ jsx18("div", { className: "rdb-snippet__overlay-inner", children: content }) });
1625
+ }
1626
+ return content;
1627
+ }
1628
+
1629
+ // src/executor/wasm-executor.ts
1630
+ var WasmExecutor = class {
1631
+ db;
1632
+ constructor(db) {
1633
+ this.db = db;
1634
+ }
1635
+ async execute(statement) {
1636
+ const trimmed = statement.trim();
1637
+ const query = trimmed.endsWith(";") ? trimmed.slice(0, -1).trim() : trimmed;
1638
+ if (!query) {
1639
+ return { success: true, data: [], executionTime: 0 };
1640
+ }
1641
+ const startTime = performance.now();
1642
+ try {
1643
+ const results = await this.db.admin(query);
1644
+ const executionTime = Math.round(performance.now() - startTime);
1645
+ return {
1646
+ success: true,
1647
+ data: Array.isArray(results) ? results : [],
1648
+ executionTime
1649
+ };
1650
+ } catch (error) {
1651
+ const executionTime = Math.round(performance.now() - startTime);
1652
+ return {
1653
+ success: false,
1654
+ error: error instanceof Error ? error.message : String(error),
1655
+ executionTime
1656
+ };
1657
+ }
1658
+ }
1659
+ };
1660
+ export {
1661
+ Console,
1662
+ Snippet,
1663
+ WasmExecutor,
1664
+ WsExecutor,
1665
+ brutalistDarkTheme,
1666
+ brutalistLightTheme,
1667
+ formatValue,
1668
+ getValueStyle,
1669
+ premiumDarkTheme,
1670
+ premiumLightTheme,
1671
+ registerRqlLanguage,
1672
+ rqlLanguageConfiguration,
1673
+ rqlLanguageDefinition
1674
+ };
1675
+ //# sourceMappingURL=index.js.map