@reddb-io/ui 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/build/_app/immutable/assets/0.BWZTMKZW.css +1 -0
  2. package/build/_app/immutable/assets/AnalyticsView.BLAJezw4.css +1 -0
  3. package/build/_app/immutable/assets/{Workspace.CvP5De7i.css → Workspace.DM2E1WiF.css} +1 -1
  4. package/build/_app/immutable/chunks/{C9rXzYLu.js → B-yl15ta.js} +1 -1
  5. package/build/_app/immutable/chunks/B5euRbKa.js +1 -0
  6. package/build/_app/immutable/chunks/BRIMmWzq.js +1 -0
  7. package/build/_app/immutable/chunks/BgOTHNR5.js +1 -0
  8. package/build/_app/immutable/chunks/Bgb6fHGb.js +18 -0
  9. package/build/_app/immutable/chunks/Btd6PFkC.js +1 -0
  10. package/build/_app/immutable/chunks/C-kqMbRi.js +1 -0
  11. package/build/_app/immutable/chunks/C3SGj6Qd.js +2 -0
  12. package/build/_app/immutable/chunks/{C278awGv.js → C7kf23SQ.js} +1 -1
  13. package/build/_app/immutable/chunks/CGFL56WJ.js +1 -0
  14. package/build/_app/immutable/chunks/CHvQYbpl.js +1 -0
  15. package/build/_app/immutable/chunks/CO7K4bD2.js +1164 -0
  16. package/build/_app/immutable/chunks/CP65IkJc.js +1 -0
  17. package/build/_app/immutable/chunks/CxnvJShw.js +404 -0
  18. package/build/_app/immutable/chunks/D02PB2u7.js +1 -0
  19. package/build/_app/immutable/chunks/DCJ0QyYH.js +1 -0
  20. package/build/_app/immutable/chunks/DN7v3Tar.js +2 -0
  21. package/build/_app/immutable/chunks/DRlh90Cv.js +1 -0
  22. package/build/_app/immutable/entry/app.BeX4Tmu5.js +2 -0
  23. package/build/_app/immutable/entry/start.D7y1MZex.js +1 -0
  24. package/build/_app/immutable/nodes/0.C0e5KQVb.js +2 -0
  25. package/build/_app/immutable/nodes/1.ceiVuZbB.js +1 -0
  26. package/build/_app/immutable/nodes/10.DeFqKRR2.js +96 -0
  27. package/build/_app/immutable/nodes/12.CzMvqoYS.js +3 -0
  28. package/build/_app/immutable/nodes/14.CAG5_cGP.js +1 -0
  29. package/build/_app/immutable/nodes/15.CRDBqbiH.js +60 -0
  30. package/build/_app/immutable/nodes/8.CAG5_cGP.js +1 -0
  31. package/build/_app/version.json +1 -1
  32. package/build/index.html +18 -15
  33. package/dist/embed/AnalyticsView-SKyGxeAx.js +23337 -0
  34. package/dist/embed/AnalyticsView-SKyGxeAx.js.map +1 -0
  35. package/dist/embed/RedUiEmbedRoot-BzVzGAFK.js +31960 -0
  36. package/dist/embed/RedUiEmbedRoot-BzVzGAFK.js.map +1 -0
  37. package/dist/embed/event-BvRbkLjD.js +46 -0
  38. package/dist/embed/event-BvRbkLjD.js.map +1 -0
  39. package/dist/embed/index-0hA141D2.js +85 -0
  40. package/dist/embed/index-0hA141D2.js.map +1 -0
  41. package/dist/embed/index-BVxMkfHe.js +8 -0
  42. package/dist/embed/index-BVxMkfHe.js.map +1 -0
  43. package/dist/embed/index-BY6fc1oQ.js +856 -0
  44. package/dist/embed/index-BY6fc1oQ.js.map +1 -0
  45. package/dist/embed/index-client-BHUUkI8H.js +3304 -0
  46. package/dist/embed/index-client-BHUUkI8H.js.map +1 -0
  47. package/dist/embed/index.js +1 -1
  48. package/dist/embed/{sigma.esm-D5yoExsH.js → sigma.esm-BawyGZ3s.js} +2 -2
  49. package/dist/embed/{sigma.esm-D5yoExsH.js.map → sigma.esm-BawyGZ3s.js.map} +1 -1
  50. package/dist/embed/window-ZR8_mM8o.js +1889 -0
  51. package/dist/embed/window-ZR8_mM8o.js.map +1 -0
  52. package/package.json +7 -3
  53. package/src/app.css +86 -20
  54. package/src/lib/AnalyticsView.svelte +209 -0
  55. package/src/lib/AskView.svelte +255 -0
  56. package/src/lib/ClusterView.svelte +415 -95
  57. package/src/lib/CommandPalette.svelte +2 -0
  58. package/src/lib/ConnectDropdown.svelte +60 -3
  59. package/src/lib/DevConsole.svelte +155 -0
  60. package/src/lib/ErrorBoundary.fixture.svelte +11 -0
  61. package/src/lib/ErrorBoundary.fixtures.svelte.ts +5 -0
  62. package/src/lib/ErrorBoundary.svelte +78 -0
  63. package/src/lib/ErrorBoundaryCrashChild.fixture.svelte +9 -0
  64. package/src/lib/GlobalProgressBar.svelte +9 -0
  65. package/src/lib/LoadingOverlay.svelte +109 -0
  66. package/src/lib/MetricChart.svelte +85 -0
  67. package/src/lib/QueryEditor.svelte +48 -7
  68. package/src/lib/ResultsPane.svelte +76 -8
  69. package/src/lib/SchemaTree.svelte +25 -1
  70. package/src/lib/SecurityView.svelte +176 -65
  71. package/src/lib/SettingsView.svelte +1111 -254
  72. package/src/lib/StatusBar.svelte +19 -1
  73. package/src/lib/Topbar.svelte +29 -1
  74. package/src/lib/Workspace.svelte +136 -5
  75. package/src/lib/activity.svelte.ts +44 -35
  76. package/src/lib/collection-preview.ts +14 -0
  77. package/src/lib/connections.svelte.ts +167 -4
  78. package/src/lib/embed/RedUiEmbedRoot.svelte +13 -8
  79. package/src/lib/embed/index.ts +34 -1
  80. package/src/lib/index.ts +10 -0
  81. package/src/lib/loading.svelte.ts +142 -0
  82. package/src/lib/permission-gate.ts +120 -0
  83. package/src/lib/policies.ts +136 -0
  84. package/src/lib/query-tabs.svelte.ts +132 -53
  85. package/src/lib/reddb/analytics.ts +208 -0
  86. package/src/lib/reddb/ask.ts +123 -0
  87. package/src/lib/reddb/client.ts +292 -73
  88. package/src/lib/reddb/cluster-status.ts +306 -0
  89. package/src/lib/reddb/desktop-error.ts +89 -0
  90. package/src/lib/reddb/dev-console.ts +186 -0
  91. package/src/lib/reddb/index.ts +5 -0
  92. package/src/lib/reddb/local-url-provider.ts +28 -1
  93. package/src/lib/reddb/redwire-ws-spike.ts +590 -0
  94. package/src/lib/reddb/tauri-encrypted-store.ts +4 -9
  95. package/src/lib/router.svelte.ts +12 -0
  96. package/src/lib/settings-authoring-client.ts +336 -0
  97. package/src/lib/settings-sections.ts +292 -196
  98. package/src/lib/tabs.svelte.ts +5 -0
  99. package/src/lib/workspace-session.ts +81 -0
  100. package/build/_app/immutable/assets/0.DQDLkSdR.css +0 -1
  101. package/build/_app/immutable/chunks/65XjEwaF.js +0 -367
  102. package/build/_app/immutable/chunks/BGcIe2ep.js +0 -2
  103. package/build/_app/immutable/chunks/BjFADNkA.js +0 -992
  104. package/build/_app/immutable/chunks/BrvvOVaJ.js +0 -1
  105. package/build/_app/immutable/chunks/D9CTkMjK.js +0 -1
  106. package/build/_app/immutable/chunks/oiO4RLqp.js +0 -1
  107. package/build/_app/immutable/chunks/pDJnDxXM.js +0 -1
  108. package/build/_app/immutable/entry/app.DdaMXHAv.js +0 -2
  109. package/build/_app/immutable/entry/start.-MLBtQXB.js +0 -1
  110. package/build/_app/immutable/nodes/0.Ysoz3Y3h.js +0 -1
  111. package/build/_app/immutable/nodes/1.C2jbGTOJ.js +0 -1
  112. package/build/_app/immutable/nodes/12.DQG5zpEx.js +0 -60
  113. package/build/_app/immutable/nodes/8.CrHI4F9p.js +0 -134
  114. package/dist/embed/RedUiEmbedRoot-BwFUA5X-.js +0 -28624
  115. package/dist/embed/RedUiEmbedRoot-BwFUA5X-.js.map +0 -1
  116. package/dist/embed/index-DGhgtnaK.js +0 -577
  117. package/dist/embed/index-DGhgtnaK.js.map +0 -1
  118. package/dist/embed/index-client-ItCEU64C.js +0 -3087
  119. package/dist/embed/index-client-ItCEU64C.js.map +0 -1
  120. /package/build/_app/immutable/assets/{12.Dblyk0Kr.css → 15.Dblyk0Kr.css} +0 -0
  121. /package/build/_app/immutable/nodes/{10.CAG5_cGP.js → 13.CAG5_cGP.js} +0 -0
@@ -0,0 +1,336 @@
1
+ import type { QueryResult } from "./reddb/client";
2
+
3
+ export type ConfigValueType =
4
+ | "bool"
5
+ | "boolean"
6
+ | "int"
7
+ | "integer"
8
+ | "float"
9
+ | "number"
10
+ | "count"
11
+ | "string"
12
+ | "text"
13
+ | "url"
14
+ | "object"
15
+ | "array"
16
+ | "list";
17
+
18
+ export interface ConfigEntry {
19
+ key: string;
20
+ value: unknown;
21
+ collection?: string;
22
+ version?: number;
23
+ valueType?: ConfigValueType;
24
+ schemaVersion?: number;
25
+ tags?: unknown;
26
+ }
27
+
28
+ export interface SecretReference {
29
+ type: "secret_ref";
30
+ store?: string;
31
+ collection?: string;
32
+ key: string;
33
+ masked?: boolean;
34
+ }
35
+
36
+ export interface SecretEntry {
37
+ key: string;
38
+ value: "***";
39
+ status?: string;
40
+ version?: number;
41
+ }
42
+
43
+ export interface RevealedSecret {
44
+ key: string;
45
+ value: string;
46
+ }
47
+
48
+ export interface QueryTransport {
49
+ query(sql: string): Promise<QueryResult>;
50
+ }
51
+
52
+ export type ConfigMutationValue =
53
+ | string
54
+ | number
55
+ | boolean
56
+ | null
57
+ | unknown[]
58
+ | Record<string, unknown>;
59
+
60
+ function optionalString(value: unknown): string | undefined {
61
+ return typeof value === "string" && value.trim() ? value : undefined;
62
+ }
63
+
64
+ function optionalNumber(value: unknown): number | undefined {
65
+ return typeof value === "number" && Number.isFinite(value)
66
+ ? value
67
+ : undefined;
68
+ }
69
+
70
+ function readValueType(
71
+ values: Record<string, unknown>
72
+ ): ConfigValueType | undefined {
73
+ const raw =
74
+ optionalString(values.value_type) ??
75
+ optionalString(values.valueType) ??
76
+ optionalString(values["value-type"]);
77
+ return raw?.toLowerCase() as ConfigValueType | undefined;
78
+ }
79
+
80
+ function readSchemaVersion(
81
+ values: Record<string, unknown>
82
+ ): number | undefined {
83
+ return (
84
+ optionalNumber(values.schema_version) ??
85
+ optionalNumber(values.schemaVersion) ??
86
+ optionalNumber(values["schema-version"])
87
+ );
88
+ }
89
+
90
+ function readSecretReference(value: unknown): SecretReference | undefined {
91
+ if (typeof value === "string") {
92
+ const trimmed = value.trim();
93
+ if (trimmed === "&***") {
94
+ return { type: "secret_ref", key: "***", masked: true };
95
+ }
96
+ if (/^&[A-Za-z0-9_.-]+$/.test(trimmed)) {
97
+ return { type: "secret_ref", key: trimmed.slice(1) };
98
+ }
99
+ return undefined;
100
+ }
101
+
102
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
103
+ return undefined;
104
+ }
105
+
106
+ const ref = value as Record<string, unknown>;
107
+ if (ref.type !== "secret_ref") return undefined;
108
+ const key =
109
+ optionalString(ref.key) ??
110
+ optionalString(ref.path) ??
111
+ optionalString(ref.name);
112
+ if (!key) return undefined;
113
+
114
+ const secretRef: SecretReference = { type: "secret_ref", key };
115
+ const store = optionalString(ref.store);
116
+ const collection = optionalString(ref.collection);
117
+ if (store) secretRef.store = store;
118
+ if (collection) secretRef.collection = collection;
119
+ if (key === "***") secretRef.masked = true;
120
+ return secretRef;
121
+ }
122
+
123
+ function normalizeConfigPrefix(prefix: string | undefined): string | undefined {
124
+ const suffix = prefix?.trim();
125
+ if (!suffix) return undefined;
126
+ return normalizeConfigPath(suffix, "SHOW CONFIG prefix");
127
+ }
128
+
129
+ function normalizeConfigPath(path: string, label: string): string {
130
+ const trimmed = path.trim();
131
+ if (!/^[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_]*)*$/.test(trimmed)) {
132
+ throw new Error(`${label} must be a dotted identifier path`);
133
+ }
134
+ return trimmed;
135
+ }
136
+
137
+ function quoteSqlString(value: string): string {
138
+ return `'${value.replace(/'/g, "''")}'`;
139
+ }
140
+
141
+ export function configValueToSqlLiteral(value: ConfigMutationValue): string {
142
+ if (value === null) return "NULL";
143
+ if (typeof value === "boolean") return value ? "true" : "false";
144
+ if (typeof value === "number") {
145
+ if (!Number.isFinite(value)) {
146
+ throw new Error("Config number value must be finite");
147
+ }
148
+ return String(value);
149
+ }
150
+ if (typeof value === "string") return quoteSqlString(value);
151
+ return JSON.stringify(value);
152
+ }
153
+
154
+ export function buildSetConfigStatement(
155
+ key: string,
156
+ value: ConfigMutationValue
157
+ ): string {
158
+ return `SET CONFIG ${normalizeConfigPath(
159
+ key,
160
+ "SET CONFIG key"
161
+ )} = ${configValueToSqlLiteral(value)}`;
162
+ }
163
+
164
+ export function buildDeleteConfigStatement(key: string): string {
165
+ const normalized = normalizeConfigPath(key, "DELETE CONFIG key");
166
+ const splitAt = normalized.lastIndexOf(".");
167
+ if (splitAt <= 0 || splitAt === normalized.length - 1) {
168
+ throw new Error("DELETE CONFIG key must include a collection and key");
169
+ }
170
+ return `DELETE CONFIG ${normalized.slice(0, splitAt)} ${normalized.slice(
171
+ splitAt + 1
172
+ )}`;
173
+ }
174
+
175
+ export function buildSetSecretStatement(key: string, value: string): string {
176
+ return `SET SECRET ${normalizeConfigPath(
177
+ key,
178
+ "SET SECRET key"
179
+ )} = ${quoteSqlString(value)}`;
180
+ }
181
+
182
+ export function buildDeleteSecretStatement(key: string): string {
183
+ return `DELETE SECRET ${normalizeConfigPath(key, "DELETE SECRET key")}`;
184
+ }
185
+
186
+ export function buildRevealSecretStatement(key: string): string {
187
+ return `UNSEAL VAULT ${normalizeConfigPath(key, "UNSEAL VAULT key")}`;
188
+ }
189
+
190
+ export function parseConfigMutationResult(
191
+ result: QueryResult,
192
+ operation: "SET CONFIG" | "DELETE CONFIG"
193
+ ): QueryResult {
194
+ if (!result.ok) throw new Error(result.error ?? `${operation} failed`);
195
+ return result;
196
+ }
197
+
198
+ export function parseSecretMutationResult(
199
+ result: QueryResult,
200
+ operation: "SET SECRET" | "DELETE SECRET"
201
+ ): QueryResult {
202
+ if (!result.ok) throw new Error(result.error ?? `${operation} failed`);
203
+ return {
204
+ ...result,
205
+ query: operation,
206
+ record_count: 0,
207
+ result: { columns: [], records: [] },
208
+ };
209
+ }
210
+
211
+ export function parseRevealSecretResult(
212
+ result: QueryResult,
213
+ key: string
214
+ ): RevealedSecret {
215
+ if (!result.ok) throw new Error(result.error ?? "UNSEAL VAULT failed");
216
+
217
+ for (const record of result.result.records) {
218
+ const values = record.values;
219
+ const rowKey = optionalString(values.key);
220
+ if (rowKey && rowKey !== key) continue;
221
+
222
+ const value = values.value ?? values.plaintext ?? values.secret;
223
+ if (typeof value === "string") return { key, value };
224
+ }
225
+
226
+ throw new Error("UNSEAL VAULT returned no plaintext value");
227
+ }
228
+
229
+ export function parseShowConfigResult(result: QueryResult): ConfigEntry[] {
230
+ if (!result.ok) throw new Error(result.error ?? "SHOW CONFIG failed");
231
+
232
+ const entries: ConfigEntry[] = [];
233
+ for (const record of result.result.records) {
234
+ const values = record.values;
235
+ const key = optionalString(values.key);
236
+ if (!key || values.tombstone === true) continue;
237
+
238
+ const entry: ConfigEntry = {
239
+ key,
240
+ value: readSecretReference(values.value) ?? values.value,
241
+ };
242
+ const collection = optionalString(values.collection);
243
+ const version = optionalNumber(values.version);
244
+ const valueType = readValueType(values);
245
+ const schemaVersion = readSchemaVersion(values);
246
+
247
+ if (collection) entry.collection = collection;
248
+ if (version !== undefined) entry.version = version;
249
+ if (valueType) entry.valueType = valueType;
250
+ if (schemaVersion !== undefined) entry.schemaVersion = schemaVersion;
251
+ if ("tags" in values) entry.tags = values.tags;
252
+ entries.push(entry);
253
+ }
254
+
255
+ return entries.sort((left, right) => left.key.localeCompare(right.key));
256
+ }
257
+
258
+ export function parseShowSecretsResult(result: QueryResult): SecretEntry[] {
259
+ if (!result.ok) throw new Error(result.error ?? "SHOW SECRETS failed");
260
+
261
+ const entries: SecretEntry[] = [];
262
+ for (const record of result.result.records) {
263
+ const values = record.values;
264
+ const key = optionalString(values.key);
265
+ if (!key) continue;
266
+
267
+ const value = values.value;
268
+ if (value !== "***") {
269
+ throw new Error("SHOW SECRETS returned an unmasked secret value");
270
+ }
271
+
272
+ const entry: SecretEntry = { key, value: "***" };
273
+ const status = optionalString(values.status);
274
+ const version = optionalNumber(values.version);
275
+ if (status) entry.status = status;
276
+ if (version !== undefined) entry.version = version;
277
+ entries.push(entry);
278
+ }
279
+
280
+ return entries.sort((left, right) => left.key.localeCompare(right.key));
281
+ }
282
+
283
+ export class SettingsAuthoringClient {
284
+ constructor(private readonly transport: QueryTransport) {}
285
+
286
+ async showConfig(prefix?: string): Promise<ConfigEntry[]> {
287
+ const suffix = normalizeConfigPrefix(prefix);
288
+ const result = await this.transport.query(
289
+ suffix ? `SHOW CONFIG ${suffix}` : "SHOW CONFIG"
290
+ );
291
+ return parseShowConfigResult(result);
292
+ }
293
+
294
+ async showSecrets(prefix?: string): Promise<SecretEntry[]> {
295
+ const suffix = normalizeConfigPrefix(prefix);
296
+ const result = await this.transport.query(
297
+ suffix ? `SHOW SECRETS ${suffix}` : "SHOW SECRETS"
298
+ );
299
+ return parseShowSecretsResult(result);
300
+ }
301
+
302
+ async setConfig(
303
+ key: string,
304
+ value: ConfigMutationValue
305
+ ): Promise<QueryResult> {
306
+ const result = await this.transport.query(
307
+ buildSetConfigStatement(key, value)
308
+ );
309
+ return parseConfigMutationResult(result, "SET CONFIG");
310
+ }
311
+
312
+ async unsetConfig(key: string): Promise<QueryResult> {
313
+ const result = await this.transport.query(buildDeleteConfigStatement(key));
314
+ return parseConfigMutationResult(result, "DELETE CONFIG");
315
+ }
316
+
317
+ async setSecret(key: string, value: string): Promise<QueryResult> {
318
+ const result = await this.transport.query(
319
+ buildSetSecretStatement(key, value)
320
+ );
321
+ return parseSecretMutationResult(result, "SET SECRET");
322
+ }
323
+
324
+ async deleteSecret(key: string): Promise<QueryResult> {
325
+ const result = await this.transport.query(buildDeleteSecretStatement(key));
326
+ return parseSecretMutationResult(result, "DELETE SECRET");
327
+ }
328
+
329
+ async revealSecret(key: string): Promise<RevealedSecret> {
330
+ const normalized = normalizeConfigPath(key, "UNSEAL VAULT key");
331
+ const result = await this.transport.query(
332
+ buildRevealSecretStatement(normalized)
333
+ );
334
+ return parseRevealSecretResult(result, normalized);
335
+ }
336
+ }