@eclipse-lyra/extension-duckdb 0.0.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/api.d.ts +3 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +9 -0
- package/dist/api.js.map +1 -0
- package/dist/duckdb-editor.d.ts +47 -0
- package/dist/duckdb-editor.d.ts.map +1 -0
- package/dist/duckdb-extension-D0_ZZcoC.js +534 -0
- package/dist/duckdb-extension-D0_ZZcoC.js.map +1 -0
- package/dist/duckdb-extension-manager-BlVBXxTt.js +436 -0
- package/dist/duckdb-extension-manager-BlVBXxTt.js.map +1 -0
- package/dist/duckdb-extension-manager.d.ts +38 -0
- package/dist/duckdb-extension-manager.d.ts.map +1 -0
- package/dist/duckdb-extension.d.ts +2 -0
- package/dist/duckdb-extension.d.ts.map +1 -0
- package/dist/duckdb-service.d.ts +45 -0
- package/dist/duckdb-service.d.ts.map +1 -0
- package/dist/i18n.json.d.ts +14 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/package.json +34 -0
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
import { createLogger, rootContext } from "@eclipse-lyra/core";
|
|
2
|
+
import * as duckdb from "/home/ekaraca/appspace/packages/extension-duckdb/node_modules/@duckdb/duckdb-wasm/dist/duckdb-browser.mjs";
|
|
3
|
+
import duckdb_wasm_mvp from "/home/ekaraca/appspace/packages/extension-duckdb/node_modules/@duckdb/duckdb-wasm/dist/duckdb-mvp.wasm?url";
|
|
4
|
+
import mvp_worker from "/home/ekaraca/appspace/packages/extension-duckdb/node_modules/@duckdb/duckdb-wasm/dist/duckdb-browser-mvp.worker.js?url";
|
|
5
|
+
import duckdb_wasm_eh from "/home/ekaraca/appspace/packages/extension-duckdb/node_modules/@duckdb/duckdb-wasm/dist/duckdb-eh.wasm?url";
|
|
6
|
+
import eh_worker from "/home/ekaraca/appspace/packages/extension-duckdb/node_modules/@duckdb/duckdb-wasm/dist/duckdb-browser-eh.worker.js?url";
|
|
7
|
+
import { css, LitElement, html } from "lit";
|
|
8
|
+
import { property, state, customElement } from "lit/decorators.js";
|
|
9
|
+
import { repeat } from "lit/directives/repeat.js";
|
|
10
|
+
const logger = createLogger("DuckDBService");
|
|
11
|
+
const MANUAL_BUNDLES = {
|
|
12
|
+
mvp: { mainModule: duckdb_wasm_mvp, mainWorker: mvp_worker },
|
|
13
|
+
eh: { mainModule: duckdb_wasm_eh, mainWorker: eh_worker }
|
|
14
|
+
};
|
|
15
|
+
const IN_MEMORY_KEY = "__memory__";
|
|
16
|
+
const OPFS_DB_DIR = "duckdb-databases";
|
|
17
|
+
const EXTENSION_NAME_REGEX = /^[a-zA-Z][a-zA-Z0-9_]*$/;
|
|
18
|
+
const DB_NAME_REGEX = /^[a-zA-Z0-9_.-]+$/;
|
|
19
|
+
function pathFor(name) {
|
|
20
|
+
return `opfs://${OPFS_DB_DIR}/${name}.duckdb`;
|
|
21
|
+
}
|
|
22
|
+
function toPlainValue(v) {
|
|
23
|
+
if (v === null || v === void 0) return v;
|
|
24
|
+
if (typeof v === "bigint") return Number(v);
|
|
25
|
+
if (v instanceof Date) return v.toISOString();
|
|
26
|
+
if (typeof v === "object" && v !== null && typeof v.toJSON === "function") {
|
|
27
|
+
return v.toJSON();
|
|
28
|
+
}
|
|
29
|
+
return v;
|
|
30
|
+
}
|
|
31
|
+
function tableToPlainArrays(table) {
|
|
32
|
+
const raw = table.toArray?.();
|
|
33
|
+
const rowObjects = Array.isArray(raw) ? raw : [];
|
|
34
|
+
if (rowObjects.length === 0) return { columns: [], rows: [] };
|
|
35
|
+
const columns = Object.keys(rowObjects[0]);
|
|
36
|
+
const rows = rowObjects.map((obj) => columns.map((col) => toPlainValue(obj[col])));
|
|
37
|
+
return { columns, rows };
|
|
38
|
+
}
|
|
39
|
+
async function ensureOPFSDatabaseDir() {
|
|
40
|
+
const root = await navigator.storage.getDirectory();
|
|
41
|
+
await root.getDirectoryHandle(OPFS_DB_DIR, { create: true });
|
|
42
|
+
}
|
|
43
|
+
async function createConnection(path) {
|
|
44
|
+
const bundle = await duckdb.selectBundle(MANUAL_BUNDLES);
|
|
45
|
+
const worker = new Worker(bundle.mainWorker);
|
|
46
|
+
const log = new duckdb.ConsoleLogger();
|
|
47
|
+
const db = new duckdb.AsyncDuckDB(log, worker);
|
|
48
|
+
await db.instantiate(bundle.mainModule, bundle.pthreadWorker);
|
|
49
|
+
if (path) {
|
|
50
|
+
await ensureOPFSDatabaseDir();
|
|
51
|
+
await db.open({
|
|
52
|
+
path,
|
|
53
|
+
accessMode: duckdb.DuckDBAccessMode.READ_WRITE
|
|
54
|
+
});
|
|
55
|
+
logger.info(`DuckDB-WASM opened: ${path} (read-write)`);
|
|
56
|
+
}
|
|
57
|
+
const conn = await db.connect();
|
|
58
|
+
logger.info("DuckDB-WASM initialized");
|
|
59
|
+
return { db, conn, worker };
|
|
60
|
+
}
|
|
61
|
+
class DuckDBDatabase {
|
|
62
|
+
constructor(name, db, conn, worker, onClose, onDeleteFromOPFS) {
|
|
63
|
+
this.name = name;
|
|
64
|
+
this.db = db;
|
|
65
|
+
this.conn = conn;
|
|
66
|
+
this.worker = worker;
|
|
67
|
+
this.onClose = onClose;
|
|
68
|
+
this.onDeleteFromOPFS = onDeleteFromOPFS;
|
|
69
|
+
this.key = name ?? IN_MEMORY_KEY;
|
|
70
|
+
}
|
|
71
|
+
async runQuery(sql) {
|
|
72
|
+
const trimmed = sql.trim();
|
|
73
|
+
if (!trimmed) return { rows: [], columns: [] };
|
|
74
|
+
try {
|
|
75
|
+
const table = await this.conn.query(trimmed);
|
|
76
|
+
return tableToPlainArrays(table);
|
|
77
|
+
} catch (err) {
|
|
78
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
79
|
+
logger.error(`Query failed: ${msg}`);
|
|
80
|
+
throw new Error(`Query failed: ${msg}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async enableExtension(extensionName) {
|
|
84
|
+
if (!EXTENSION_NAME_REGEX.test(extensionName)) {
|
|
85
|
+
throw new Error(`Invalid extension name: ${extensionName}`);
|
|
86
|
+
}
|
|
87
|
+
const installSql = `INSTALL ${extensionName}`;
|
|
88
|
+
const loadSql = `LOAD ${extensionName}`;
|
|
89
|
+
try {
|
|
90
|
+
await this.conn.query(installSql);
|
|
91
|
+
await this.conn.query(loadSql);
|
|
92
|
+
logger.info(`DuckDB extension enabled: ${extensionName}`);
|
|
93
|
+
} catch (err) {
|
|
94
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
95
|
+
logger.error(`Failed to enable extension ${extensionName}: ${msg}`);
|
|
96
|
+
throw new Error(`Failed to enable extension ${extensionName}: ${msg}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
async close() {
|
|
100
|
+
try {
|
|
101
|
+
await this.conn.close();
|
|
102
|
+
} catch (e) {
|
|
103
|
+
logger.warn("Error closing DuckDB connection: " + (e instanceof Error ? e.message : String(e)));
|
|
104
|
+
}
|
|
105
|
+
try {
|
|
106
|
+
this.db.terminate();
|
|
107
|
+
} catch (e) {
|
|
108
|
+
logger.warn("Error terminating DuckDB: " + (e instanceof Error ? e.message : String(e)));
|
|
109
|
+
}
|
|
110
|
+
this.onClose(this.key);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
class DuckDBService {
|
|
114
|
+
constructor() {
|
|
115
|
+
this.databases = /* @__PURE__ */ new Map();
|
|
116
|
+
}
|
|
117
|
+
keyFor(name) {
|
|
118
|
+
return name === void 0 || name === "" ? IN_MEMORY_KEY : name;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Open a database by name. Stored in OPFS as `duckdb-databases/<name>.duckdb`. Omit name for in-memory.
|
|
122
|
+
* Returns the same abstraction if that database is already open.
|
|
123
|
+
*/
|
|
124
|
+
async open(name) {
|
|
125
|
+
const key = this.keyFor(name);
|
|
126
|
+
const existing = this.databases.get(key);
|
|
127
|
+
if (existing) return existing;
|
|
128
|
+
if (key !== IN_MEMORY_KEY && !DB_NAME_REGEX.test(name)) {
|
|
129
|
+
throw new Error(`Invalid database name: ${name}`);
|
|
130
|
+
}
|
|
131
|
+
const nameOrNull = name === void 0 || name === "" ? null : name;
|
|
132
|
+
const path = nameOrNull ? pathFor(nameOrNull) : null;
|
|
133
|
+
const { db, conn, worker } = await createConnection(path);
|
|
134
|
+
const dbObj = new DuckDBDatabase(
|
|
135
|
+
nameOrNull,
|
|
136
|
+
db,
|
|
137
|
+
conn,
|
|
138
|
+
worker,
|
|
139
|
+
(k) => this.databases.delete(k),
|
|
140
|
+
nameOrNull ? (n) => this.removeOPFSDatabase(n) : void 0
|
|
141
|
+
);
|
|
142
|
+
this.databases.set(key, dbObj);
|
|
143
|
+
return dbObj;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* List persisted database names (files in OPFS under duckdb-databases/, without .duckdb extension).
|
|
147
|
+
*/
|
|
148
|
+
async listDatabases() {
|
|
149
|
+
try {
|
|
150
|
+
const root = await navigator.storage.getDirectory();
|
|
151
|
+
const dir = await root.getDirectoryHandle(OPFS_DB_DIR, { create: false });
|
|
152
|
+
const names = [];
|
|
153
|
+
for await (const [entryName, handle] of dir) {
|
|
154
|
+
if (handle.kind === "file" && entryName.endsWith(".duckdb")) {
|
|
155
|
+
names.push(entryName.slice(0, -".duckdb".length));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return names.sort();
|
|
159
|
+
} catch (err) {
|
|
160
|
+
if (err instanceof Error && err.name === "NotFoundError") return [];
|
|
161
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
162
|
+
logger.error(`listDatabases failed: ${msg}`);
|
|
163
|
+
return [];
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Close the database if open and remove its file from OPFS. Name is the simple database name (e.g. `appspace`).
|
|
168
|
+
*/
|
|
169
|
+
async delete(name) {
|
|
170
|
+
if (!DB_NAME_REGEX.test(name)) {
|
|
171
|
+
throw new Error(`Invalid database name: ${name}`);
|
|
172
|
+
}
|
|
173
|
+
const existing = this.databases.get(name);
|
|
174
|
+
if (existing) await existing.close();
|
|
175
|
+
await this.removeOPFSDatabase(name);
|
|
176
|
+
}
|
|
177
|
+
async removeOPFSDatabase(name) {
|
|
178
|
+
try {
|
|
179
|
+
const root = await navigator.storage.getDirectory();
|
|
180
|
+
const dir = await root.getDirectoryHandle(OPFS_DB_DIR, { create: false });
|
|
181
|
+
await dir.removeEntry(`${name}.duckdb`);
|
|
182
|
+
logger.info(`DuckDB removed: ${name}`);
|
|
183
|
+
} catch (err) {
|
|
184
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
185
|
+
logger.error(`Failed to delete database ${name}: ${msg}`);
|
|
186
|
+
throw new Error(`Failed to delete database: ${msg}`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
const duckdbService = new DuckDBService();
|
|
191
|
+
var __defProp = Object.defineProperty;
|
|
192
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
193
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
194
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
195
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
196
|
+
if (decorator = decorators[i])
|
|
197
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
198
|
+
if (kind && result) __defProp(target, key, result);
|
|
199
|
+
return result;
|
|
200
|
+
};
|
|
201
|
+
const DUCKDB_AVAILABLE_EXTENSIONS = [
|
|
202
|
+
{ name: "json", description: "JSON file and functions" },
|
|
203
|
+
{ name: "parquet", description: "Parquet file support" },
|
|
204
|
+
{ name: "csv", description: "CSV file support" },
|
|
205
|
+
{ name: "httpfs", description: "HTTP(S) and S3 access" },
|
|
206
|
+
{ name: "fts", description: "Full-text search" },
|
|
207
|
+
{ name: "inet", description: "IP address types" },
|
|
208
|
+
{ name: "jemalloc", description: "Memory allocator" },
|
|
209
|
+
{ name: "substrait", description: "Substrait integration" }
|
|
210
|
+
];
|
|
211
|
+
let LyraDuckDBExtensionManager = class extends LitElement {
|
|
212
|
+
constructor() {
|
|
213
|
+
super(...arguments);
|
|
214
|
+
this.open = false;
|
|
215
|
+
this.db = null;
|
|
216
|
+
this.databaseLabel = "In-memory";
|
|
217
|
+
this.selectedExtensions = /* @__PURE__ */ new Set();
|
|
218
|
+
this.installing = false;
|
|
219
|
+
this.installError = null;
|
|
220
|
+
}
|
|
221
|
+
configure(options) {
|
|
222
|
+
this.db = options.db;
|
|
223
|
+
this.databaseLabel = options.databaseLabel;
|
|
224
|
+
this.selectedExtensions = /* @__PURE__ */ new Set();
|
|
225
|
+
this.installError = null;
|
|
226
|
+
}
|
|
227
|
+
show() {
|
|
228
|
+
this.open = true;
|
|
229
|
+
}
|
|
230
|
+
hide() {
|
|
231
|
+
this.open = false;
|
|
232
|
+
}
|
|
233
|
+
toggleExtension(name) {
|
|
234
|
+
const next = new Set(this.selectedExtensions);
|
|
235
|
+
if (next.has(name)) next.delete(name);
|
|
236
|
+
else next.add(name);
|
|
237
|
+
this.selectedExtensions = next;
|
|
238
|
+
this.installError = null;
|
|
239
|
+
}
|
|
240
|
+
async installSelected() {
|
|
241
|
+
if (!this.db || this.selectedExtensions.size === 0) return;
|
|
242
|
+
this.installing = true;
|
|
243
|
+
this.installError = null;
|
|
244
|
+
const toInstall = [...this.selectedExtensions];
|
|
245
|
+
try {
|
|
246
|
+
for (const name of toInstall) {
|
|
247
|
+
await this.db.enableExtension(name);
|
|
248
|
+
}
|
|
249
|
+
this.selectedExtensions = /* @__PURE__ */ new Set();
|
|
250
|
+
} catch (err) {
|
|
251
|
+
this.installError = err instanceof Error ? err.message : String(err);
|
|
252
|
+
} finally {
|
|
253
|
+
this.installing = false;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
render() {
|
|
257
|
+
const dbReady = this.db !== null;
|
|
258
|
+
const canInstall = dbReady && this.selectedExtensions.size > 0 && !this.installing;
|
|
259
|
+
return html`
|
|
260
|
+
<wa-dialog
|
|
261
|
+
label="DuckDB extensions"
|
|
262
|
+
?open=${this.open}
|
|
263
|
+
@wa-after-hide=${() => {
|
|
264
|
+
this.open = false;
|
|
265
|
+
this.dispatchEvent(new CustomEvent("hide", { bubbles: true, composed: true }));
|
|
266
|
+
}}
|
|
267
|
+
>
|
|
268
|
+
<div class="extension-manager">
|
|
269
|
+
<p class="extension-manager-description">
|
|
270
|
+
Database: <strong>${this.databaseLabel}</strong>. Select extensions to install.
|
|
271
|
+
</p>
|
|
272
|
+
|
|
273
|
+
${!dbReady ? html`
|
|
274
|
+
<wa-alert variant="warning" open>
|
|
275
|
+
<wa-icon slot="icon" name="triangle-exclamation"></wa-icon>
|
|
276
|
+
Open or create a database and run a query first so a connection exists.
|
|
277
|
+
</wa-alert>
|
|
278
|
+
` : ""}
|
|
279
|
+
|
|
280
|
+
${this.installError ? html`
|
|
281
|
+
<wa-alert variant="danger" open closable @wa-after-hide=${() => this.installError = null}>
|
|
282
|
+
<wa-icon slot="icon" name="circle-exclamation"></wa-icon>
|
|
283
|
+
${this.installError}
|
|
284
|
+
</wa-alert>
|
|
285
|
+
` : ""}
|
|
286
|
+
|
|
287
|
+
<div class="extension-list">
|
|
288
|
+
<div class="extension-list-header">
|
|
289
|
+
<strong>Available extensions</strong>
|
|
290
|
+
</div>
|
|
291
|
+
${repeat(
|
|
292
|
+
DUCKDB_AVAILABLE_EXTENSIONS,
|
|
293
|
+
(ext) => ext.name,
|
|
294
|
+
(ext) => html`
|
|
295
|
+
<div class="extension-item">
|
|
296
|
+
<wa-checkbox
|
|
297
|
+
?checked=${this.selectedExtensions.has(ext.name)}
|
|
298
|
+
?disabled=${!dbReady}
|
|
299
|
+
@wa-change=${() => this.toggleExtension(ext.name)}
|
|
300
|
+
>
|
|
301
|
+
<span class="extension-name">${ext.name}</span>
|
|
302
|
+
<span class="extension-desc">${ext.description}</span>
|
|
303
|
+
</wa-checkbox>
|
|
304
|
+
</div>
|
|
305
|
+
`
|
|
306
|
+
)}
|
|
307
|
+
</div>
|
|
308
|
+
</div>
|
|
309
|
+
<div slot="footer" class="extension-manager-footer">
|
|
310
|
+
<wa-button
|
|
311
|
+
variant="primary"
|
|
312
|
+
?disabled=${!canInstall}
|
|
313
|
+
@click=${() => this.installSelected()}
|
|
314
|
+
>
|
|
315
|
+
${this.installing ? "Installing…" : `Install selected (${this.selectedExtensions.size})`}
|
|
316
|
+
</wa-button>
|
|
317
|
+
<wa-button variant="default" @click=${() => this.hide()}>
|
|
318
|
+
Done
|
|
319
|
+
</wa-button>
|
|
320
|
+
</div>
|
|
321
|
+
</wa-dialog>
|
|
322
|
+
`;
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
LyraDuckDBExtensionManager.styles = css`
|
|
326
|
+
:host {
|
|
327
|
+
display: contents;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
.extension-manager {
|
|
331
|
+
display: flex;
|
|
332
|
+
flex-direction: column;
|
|
333
|
+
gap: 1rem;
|
|
334
|
+
padding: 1rem;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
.extension-manager-description {
|
|
338
|
+
margin: 0;
|
|
339
|
+
font-size: 0.95rem;
|
|
340
|
+
opacity: 0.9;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
.extension-list {
|
|
344
|
+
display: flex;
|
|
345
|
+
flex-direction: column;
|
|
346
|
+
gap: 0.25rem;
|
|
347
|
+
max-height: 360px;
|
|
348
|
+
overflow-y: auto;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
.extension-list-header {
|
|
352
|
+
padding: 0.5rem 0;
|
|
353
|
+
border-bottom: 1px solid var(--wa-color-neutral-200, #e5e7eb);
|
|
354
|
+
margin-bottom: 0.25rem;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.extension-item {
|
|
358
|
+
display: flex;
|
|
359
|
+
align-items: center;
|
|
360
|
+
padding: 0.5rem 0;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
.extension-item wa-checkbox {
|
|
364
|
+
display: flex;
|
|
365
|
+
align-items: center;
|
|
366
|
+
gap: 0.5rem;
|
|
367
|
+
flex: 1;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
.extension-name {
|
|
371
|
+
font-family: ui-monospace, monospace;
|
|
372
|
+
font-size: 0.95rem;
|
|
373
|
+
min-width: 6rem;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
.extension-desc {
|
|
377
|
+
font-size: 0.875rem;
|
|
378
|
+
opacity: 0.8;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
.extension-manager-footer {
|
|
382
|
+
display: flex;
|
|
383
|
+
gap: 0.5rem;
|
|
384
|
+
justify-content: flex-end;
|
|
385
|
+
padding-top: 1rem;
|
|
386
|
+
border-top: 1px solid var(--wa-color-neutral-200, #e5e7eb);
|
|
387
|
+
}
|
|
388
|
+
`;
|
|
389
|
+
__decorateClass([
|
|
390
|
+
property({ type: Boolean })
|
|
391
|
+
], LyraDuckDBExtensionManager.prototype, "open", 2);
|
|
392
|
+
__decorateClass([
|
|
393
|
+
property({ attribute: false })
|
|
394
|
+
], LyraDuckDBExtensionManager.prototype, "db", 2);
|
|
395
|
+
__decorateClass([
|
|
396
|
+
property()
|
|
397
|
+
], LyraDuckDBExtensionManager.prototype, "databaseLabel", 2);
|
|
398
|
+
__decorateClass([
|
|
399
|
+
state()
|
|
400
|
+
], LyraDuckDBExtensionManager.prototype, "selectedExtensions", 2);
|
|
401
|
+
__decorateClass([
|
|
402
|
+
state()
|
|
403
|
+
], LyraDuckDBExtensionManager.prototype, "installing", 2);
|
|
404
|
+
__decorateClass([
|
|
405
|
+
state()
|
|
406
|
+
], LyraDuckDBExtensionManager.prototype, "installError", 2);
|
|
407
|
+
LyraDuckDBExtensionManager = __decorateClass([
|
|
408
|
+
customElement("lyra-duckdb-extension-manager")
|
|
409
|
+
], LyraDuckDBExtensionManager);
|
|
410
|
+
class DuckDBExtensionManagerService {
|
|
411
|
+
constructor() {
|
|
412
|
+
this.managerInstance = null;
|
|
413
|
+
}
|
|
414
|
+
showExtensionManager(options) {
|
|
415
|
+
if (!this.managerInstance) {
|
|
416
|
+
this.managerInstance = document.createElement("lyra-duckdb-extension-manager");
|
|
417
|
+
document.body.appendChild(this.managerInstance);
|
|
418
|
+
}
|
|
419
|
+
this.managerInstance.configure(options);
|
|
420
|
+
this.managerInstance.show();
|
|
421
|
+
return this.managerInstance;
|
|
422
|
+
}
|
|
423
|
+
getManager() {
|
|
424
|
+
return this.managerInstance;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
const duckdbExtensionManagerService = new DuckDBExtensionManagerService();
|
|
428
|
+
rootContext.put("duckdbExtensionManagerService", duckdbExtensionManagerService);
|
|
429
|
+
export {
|
|
430
|
+
DUCKDB_AVAILABLE_EXTENSIONS as D,
|
|
431
|
+
DuckDBDatabase as a,
|
|
432
|
+
DuckDBService as b,
|
|
433
|
+
duckdbService as c,
|
|
434
|
+
duckdbExtensionManagerService as d
|
|
435
|
+
};
|
|
436
|
+
//# sourceMappingURL=duckdb-extension-manager-BlVBXxTt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duckdb-extension-manager-BlVBXxTt.js","sources":["../src/duckdb-service.ts","../src/duckdb-extension-manager.ts"],"sourcesContent":["import { createLogger } from '@eclipse-lyra/core';\nimport * as duckdb from '@duckdb/duckdb-wasm';\nimport duckdb_wasm_mvp from '@duckdb/duckdb-wasm/dist/duckdb-mvp.wasm?url';\nimport mvp_worker from '@duckdb/duckdb-wasm/dist/duckdb-browser-mvp.worker.js?url';\nimport duckdb_wasm_eh from '@duckdb/duckdb-wasm/dist/duckdb-eh.wasm?url';\nimport eh_worker from '@duckdb/duckdb-wasm/dist/duckdb-browser-eh.worker.js?url';\n\nconst logger = createLogger('DuckDBService');\n\nconst MANUAL_BUNDLES: duckdb.DuckDBBundles = {\n mvp: { mainModule: duckdb_wasm_mvp, mainWorker: mvp_worker },\n eh: { mainModule: duckdb_wasm_eh, mainWorker: eh_worker },\n};\n\nconst IN_MEMORY_KEY = '__memory__';\nconst OPFS_DB_DIR = 'duckdb-databases';\nconst EXTENSION_NAME_REGEX = /^[a-zA-Z][a-zA-Z0-9_]*$/;\nconst DB_NAME_REGEX = /^[a-zA-Z0-9_.-]+$/;\n\nfunction pathFor(name: string): string {\n return `opfs://${OPFS_DB_DIR}/${name}.duckdb`;\n}\n\ntype AsyncDuckDB = duckdb.AsyncDuckDB;\ntype AsyncDuckDBConnection = Awaited<ReturnType<AsyncDuckDB['connect']>>;\n\n/** Plain JS result: columns in order, rows as array of value arrays. */\nexport interface DuckDBQueryResult {\n columns: string[];\n rows: unknown[][];\n}\n\nfunction toPlainValue(v: unknown): unknown {\n if (v === null || v === undefined) return v;\n if (typeof v === 'bigint') return Number(v);\n if (v instanceof Date) return v.toISOString();\n if (typeof v === 'object' && v !== null && typeof (v as { toJSON: unknown }).toJSON === 'function') {\n return (v as { toJSON: () => unknown }).toJSON();\n }\n return v;\n}\n\nfunction tableToPlainArrays(table: { toArray?: () => unknown[] }): { columns: string[]; rows: unknown[][] } {\n const raw = table.toArray?.();\n const rowObjects = Array.isArray(raw) ? (raw as Record<string, unknown>[]) : [];\n if (rowObjects.length === 0) return { columns: [], rows: [] };\n const columns = Object.keys(rowObjects[0]);\n const rows = rowObjects.map((obj) => columns.map((col) => toPlainValue(obj[col])));\n return { columns, rows };\n}\n\nasync function ensureOPFSDatabaseDir(): Promise<void> {\n const root = await navigator.storage.getDirectory();\n await root.getDirectoryHandle(OPFS_DB_DIR, { create: true });\n}\n\nasync function createConnection(path: string | null): Promise<{\n db: AsyncDuckDB;\n conn: AsyncDuckDBConnection;\n worker: Worker;\n}> {\n const bundle = await duckdb.selectBundle(MANUAL_BUNDLES);\n const worker = new Worker(bundle.mainWorker!);\n const log = new duckdb.ConsoleLogger();\n const db = new duckdb.AsyncDuckDB(log, worker);\n await db.instantiate(bundle.mainModule, bundle.pthreadWorker);\n if (path) {\n await ensureOPFSDatabaseDir();\n await db.open({\n path,\n accessMode: duckdb.DuckDBAccessMode.READ_WRITE,\n });\n logger.info(`DuckDB-WASM opened: ${path} (read-write)`);\n }\n const conn = await db.connect();\n logger.info('DuckDB-WASM initialized');\n return { db, conn, worker };\n}\n\n/**\n * Abstraction over a single DuckDB database. Use runQuery, enableExtension, close, or delete.\n */\nexport class DuckDBDatabase {\n private readonly key: string;\n\n constructor(\n readonly name: string | null,\n private db: AsyncDuckDB,\n private conn: AsyncDuckDBConnection,\n private worker: Worker,\n private onClose: (key: string) => void,\n private onDeleteFromOPFS?: (name: string) => Promise<void>,\n ) {\n this.key = name ?? IN_MEMORY_KEY;\n }\n\n async runQuery(sql: string): Promise<DuckDBQueryResult> {\n const trimmed = sql.trim();\n if (!trimmed) return { rows: [], columns: [] };\n\n try {\n const table = await this.conn.query(trimmed);\n return tableToPlainArrays(table);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n logger.error(`Query failed: ${msg}`);\n throw new Error(`Query failed: ${msg}`);\n }\n }\n\n async enableExtension(extensionName: string): Promise<void> {\n if (!EXTENSION_NAME_REGEX.test(extensionName)) {\n throw new Error(`Invalid extension name: ${extensionName}`);\n }\n const installSql = `INSTALL ${extensionName}`;\n const loadSql = `LOAD ${extensionName}`;\n try {\n await this.conn.query(installSql);\n await this.conn.query(loadSql);\n logger.info(`DuckDB extension enabled: ${extensionName}`);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n logger.error(`Failed to enable extension ${extensionName}: ${msg}`);\n throw new Error(`Failed to enable extension ${extensionName}: ${msg}`);\n }\n }\n\n async close(): Promise<void> {\n try {\n await this.conn.close();\n } catch (e) {\n logger.warn('Error closing DuckDB connection: ' + (e instanceof Error ? e.message : String(e)));\n }\n try {\n this.db.terminate();\n } catch (e) {\n logger.warn('Error terminating DuckDB: ' + (e instanceof Error ? e.message : String(e)));\n }\n this.onClose(this.key);\n }\n}\n\nexport class DuckDBService {\n private databases = new Map<string, DuckDBDatabase>();\n\n private keyFor(name: string | undefined): string {\n return name === undefined || name === '' ? IN_MEMORY_KEY : name;\n }\n\n /**\n * Open a database by name. Stored in OPFS as `duckdb-databases/<name>.duckdb`. Omit name for in-memory.\n * Returns the same abstraction if that database is already open.\n */\n async open(name?: string): Promise<DuckDBDatabase> {\n const key = this.keyFor(name);\n const existing = this.databases.get(key);\n if (existing) return existing;\n\n if (key !== IN_MEMORY_KEY && !DB_NAME_REGEX.test(name!)) {\n throw new Error(`Invalid database name: ${name}`);\n }\n\n const nameOrNull = name === undefined || name === '' ? null : name;\n const path = nameOrNull ? pathFor(nameOrNull) : null;\n const { db, conn, worker } = await createConnection(path);\n\n const dbObj = new DuckDBDatabase(\n nameOrNull,\n db,\n conn,\n worker,\n (k) => this.databases.delete(k),\n nameOrNull ? (n) => this.removeOPFSDatabase(n) : undefined,\n );\n this.databases.set(key, dbObj);\n return dbObj;\n }\n\n /**\n * List persisted database names (files in OPFS under duckdb-databases/, without .duckdb extension).\n */\n async listDatabases(): Promise<string[]> {\n try {\n const root = await navigator.storage.getDirectory();\n const dir = await root.getDirectoryHandle(OPFS_DB_DIR, { create: false });\n const names: string[] = [];\n for await (const [entryName, handle] of (dir as unknown as AsyncIterable<[string, FileSystemHandle]>)) {\n if (handle.kind === 'file' && entryName.endsWith('.duckdb')) {\n names.push(entryName.slice(0, -'.duckdb'.length));\n }\n }\n return names.sort();\n } catch (err: unknown) {\n if (err instanceof Error && err.name === 'NotFoundError') return [];\n const msg = err instanceof Error ? err.message : String(err);\n logger.error(`listDatabases failed: ${msg}`);\n return [];\n }\n }\n\n /**\n * Close the database if open and remove its file from OPFS. Name is the simple database name (e.g. `appspace`).\n */\n async delete(name: string): Promise<void> {\n if (!DB_NAME_REGEX.test(name)) {\n throw new Error(`Invalid database name: ${name}`);\n }\n const existing = this.databases.get(name);\n if (existing) await existing.close();\n await this.removeOPFSDatabase(name);\n }\n\n private async removeOPFSDatabase(name: string): Promise<void> {\n try {\n const root = await navigator.storage.getDirectory();\n const dir = await root.getDirectoryHandle(OPFS_DB_DIR, { create: false });\n await dir.removeEntry(`${name}.duckdb`);\n logger.info(`DuckDB removed: ${name}`);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n logger.error(`Failed to delete database ${name}: ${msg}`);\n throw new Error(`Failed to delete database: ${msg}`);\n }\n }\n}\n\nexport const duckdbService = new DuckDBService();\n","import { css, html, LitElement } from \"lit\";\nimport { customElement, property, state } from \"lit/decorators.js\";\nimport { repeat } from \"lit/directives/repeat.js\";\nimport { rootContext } from \"@eclipse-lyra/core\";\nimport type { DuckDBDatabase } from \"./duckdb-service\";\n\nexport const DUCKDB_AVAILABLE_EXTENSIONS: { name: string; description: string }[] = [\n { name: \"json\", description: \"JSON file and functions\" },\n { name: \"parquet\", description: \"Parquet file support\" },\n { name: \"csv\", description: \"CSV file support\" },\n { name: \"httpfs\", description: \"HTTP(S) and S3 access\" },\n { name: \"fts\", description: \"Full-text search\" },\n { name: \"inet\", description: \"IP address types\" },\n { name: \"jemalloc\", description: \"Memory allocator\" },\n { name: \"substrait\", description: \"Substrait integration\" },\n];\n\nexport interface DuckDBExtensionManagerOptions {\n db: DuckDBDatabase | null;\n databaseLabel: string;\n}\n\n@customElement(\"lyra-duckdb-extension-manager\")\nexport class LyraDuckDBExtensionManager extends LitElement {\n @property({ type: Boolean })\n open = false;\n\n @property({ attribute: false })\n db: DuckDBDatabase | null = null;\n\n @property()\n databaseLabel = \"In-memory\";\n\n @state()\n private selectedExtensions = new Set<string>();\n\n @state()\n private installing = false;\n\n @state()\n private installError: string | null = null;\n\n public configure(options: DuckDBExtensionManagerOptions) {\n this.db = options.db;\n this.databaseLabel = options.databaseLabel;\n this.selectedExtensions = new Set();\n this.installError = null;\n }\n\n public show() {\n this.open = true;\n }\n\n public hide() {\n this.open = false;\n }\n\n private toggleExtension(name: string) {\n const next = new Set(this.selectedExtensions);\n if (next.has(name)) next.delete(name);\n else next.add(name);\n this.selectedExtensions = next;\n this.installError = null;\n }\n\n private async installSelected() {\n if (!this.db || this.selectedExtensions.size === 0) return;\n this.installing = true;\n this.installError = null;\n const toInstall = [...this.selectedExtensions];\n try {\n for (const name of toInstall) {\n await this.db.enableExtension(name);\n }\n this.selectedExtensions = new Set();\n } catch (err) {\n this.installError = err instanceof Error ? err.message : String(err);\n } finally {\n this.installing = false;\n }\n }\n\n render() {\n const dbReady = this.db !== null;\n const canInstall = dbReady && this.selectedExtensions.size > 0 && !this.installing;\n\n return html`\n <wa-dialog\n label=\"DuckDB extensions\"\n ?open=${this.open}\n @wa-after-hide=${() => {\n this.open = false;\n this.dispatchEvent(new CustomEvent(\"hide\", { bubbles: true, composed: true }));\n }}\n >\n <div class=\"extension-manager\">\n <p class=\"extension-manager-description\">\n Database: <strong>${this.databaseLabel}</strong>. Select extensions to install.\n </p>\n\n ${!dbReady\n ? html`\n <wa-alert variant=\"warning\" open>\n <wa-icon slot=\"icon\" name=\"triangle-exclamation\"></wa-icon>\n Open or create a database and run a query first so a connection exists.\n </wa-alert>\n `\n : \"\"}\n\n ${this.installError\n ? html`\n <wa-alert variant=\"danger\" open closable @wa-after-hide=${() => (this.installError = null)}>\n <wa-icon slot=\"icon\" name=\"circle-exclamation\"></wa-icon>\n ${this.installError}\n </wa-alert>\n `\n : \"\"}\n\n <div class=\"extension-list\">\n <div class=\"extension-list-header\">\n <strong>Available extensions</strong>\n </div>\n ${repeat(\n DUCKDB_AVAILABLE_EXTENSIONS,\n (ext) => ext.name,\n (ext) => html`\n <div class=\"extension-item\">\n <wa-checkbox\n ?checked=${this.selectedExtensions.has(ext.name)}\n ?disabled=${!dbReady}\n @wa-change=${() => this.toggleExtension(ext.name)}\n >\n <span class=\"extension-name\">${ext.name}</span>\n <span class=\"extension-desc\">${ext.description}</span>\n </wa-checkbox>\n </div>\n `\n )}\n </div>\n </div>\n <div slot=\"footer\" class=\"extension-manager-footer\">\n <wa-button\n variant=\"primary\"\n ?disabled=${!canInstall}\n @click=${() => this.installSelected()}\n >\n ${this.installing ? \"Installing…\" : `Install selected (${this.selectedExtensions.size})`}\n </wa-button>\n <wa-button variant=\"default\" @click=${() => this.hide()}>\n Done\n </wa-button>\n </div>\n </wa-dialog>\n `;\n }\n\n static styles = css`\n :host {\n display: contents;\n }\n\n .extension-manager {\n display: flex;\n flex-direction: column;\n gap: 1rem;\n padding: 1rem;\n }\n\n .extension-manager-description {\n margin: 0;\n font-size: 0.95rem;\n opacity: 0.9;\n }\n\n .extension-list {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n max-height: 360px;\n overflow-y: auto;\n }\n\n .extension-list-header {\n padding: 0.5rem 0;\n border-bottom: 1px solid var(--wa-color-neutral-200, #e5e7eb);\n margin-bottom: 0.25rem;\n }\n\n .extension-item {\n display: flex;\n align-items: center;\n padding: 0.5rem 0;\n }\n\n .extension-item wa-checkbox {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n flex: 1;\n }\n\n .extension-name {\n font-family: ui-monospace, monospace;\n font-size: 0.95rem;\n min-width: 6rem;\n }\n\n .extension-desc {\n font-size: 0.875rem;\n opacity: 0.8;\n }\n\n .extension-manager-footer {\n display: flex;\n gap: 0.5rem;\n justify-content: flex-end;\n padding-top: 1rem;\n border-top: 1px solid var(--wa-color-neutral-200, #e5e7eb);\n }\n `;\n}\n\nclass DuckDBExtensionManagerService {\n private managerInstance: LyraDuckDBExtensionManager | null = null;\n\n public showExtensionManager(options: DuckDBExtensionManagerOptions): LyraDuckDBExtensionManager {\n if (!this.managerInstance) {\n this.managerInstance = document.createElement(\"lyra-duckdb-extension-manager\") as LyraDuckDBExtensionManager;\n document.body.appendChild(this.managerInstance);\n }\n this.managerInstance.configure(options);\n this.managerInstance.show();\n return this.managerInstance;\n }\n\n public getManager(): LyraDuckDBExtensionManager | null {\n return this.managerInstance;\n }\n}\n\nexport const duckdbExtensionManagerService = new DuckDBExtensionManagerService();\nrootContext.put(\"duckdbExtensionManagerService\", duckdbExtensionManagerService);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"lyra-duckdb-extension-manager\": LyraDuckDBExtensionManager;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
import { DuckDBDatabase } from './duckdb-service';
|
|
3
|
+
export declare const DUCKDB_AVAILABLE_EXTENSIONS: {
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
}[];
|
|
7
|
+
export interface DuckDBExtensionManagerOptions {
|
|
8
|
+
db: DuckDBDatabase | null;
|
|
9
|
+
databaseLabel: string;
|
|
10
|
+
}
|
|
11
|
+
export declare class LyraDuckDBExtensionManager extends LitElement {
|
|
12
|
+
open: boolean;
|
|
13
|
+
db: DuckDBDatabase | null;
|
|
14
|
+
databaseLabel: string;
|
|
15
|
+
private selectedExtensions;
|
|
16
|
+
private installing;
|
|
17
|
+
private installError;
|
|
18
|
+
configure(options: DuckDBExtensionManagerOptions): void;
|
|
19
|
+
show(): void;
|
|
20
|
+
hide(): void;
|
|
21
|
+
private toggleExtension;
|
|
22
|
+
private installSelected;
|
|
23
|
+
render(): import('lit-html').TemplateResult<1>;
|
|
24
|
+
static styles: import('lit').CSSResult;
|
|
25
|
+
}
|
|
26
|
+
declare class DuckDBExtensionManagerService {
|
|
27
|
+
private managerInstance;
|
|
28
|
+
showExtensionManager(options: DuckDBExtensionManagerOptions): LyraDuckDBExtensionManager;
|
|
29
|
+
getManager(): LyraDuckDBExtensionManager | null;
|
|
30
|
+
}
|
|
31
|
+
export declare const duckdbExtensionManagerService: DuckDBExtensionManagerService;
|
|
32
|
+
declare global {
|
|
33
|
+
interface HTMLElementTagNameMap {
|
|
34
|
+
"lyra-duckdb-extension-manager": LyraDuckDBExtensionManager;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=duckdb-extension-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duckdb-extension-manager.d.ts","sourceRoot":"","sources":["../src/duckdb-extension-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,UAAU,EAAE,MAAM,KAAK,CAAC;AAI5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,eAAO,MAAM,2BAA2B,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,EAS9E,CAAC;AAEF,MAAM,WAAW,6BAA6B;IAC5C,EAAE,EAAE,cAAc,GAAG,IAAI,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,qBACa,0BAA2B,SAAQ,UAAU;IAExD,IAAI,UAAS;IAGb,EAAE,EAAE,cAAc,GAAG,IAAI,CAAQ;IAGjC,aAAa,SAAe;IAG5B,OAAO,CAAC,kBAAkB,CAAqB;IAG/C,OAAO,CAAC,UAAU,CAAS;IAG3B,OAAO,CAAC,YAAY,CAAuB;IAEpC,SAAS,CAAC,OAAO,EAAE,6BAA6B;IAOhD,IAAI;IAIJ,IAAI;IAIX,OAAO,CAAC,eAAe;YAQT,eAAe;IAiB7B,MAAM;IA0EN,MAAM,CAAC,MAAM,0BA+DX;CACH;AAED,cAAM,6BAA6B;IACjC,OAAO,CAAC,eAAe,CAA2C;IAE3D,oBAAoB,CAAC,OAAO,EAAE,6BAA6B,GAAG,0BAA0B;IAUxF,UAAU,IAAI,0BAA0B,GAAG,IAAI;CAGvD;AAED,eAAO,MAAM,6BAA6B,+BAAsC,CAAC;AAGjF,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,+BAA+B,EAAE,0BAA0B,CAAC;KAC7D;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duckdb-extension.d.ts","sourceRoot":"","sources":["../src/duckdb-extension.ts"],"names":[],"mappings":"AAGA,OAAO,iBAAiB,CAAC;AACzB,OAAO,4BAA4B,CAAC;AAEpC,MAAM,CAAC,OAAO,mBAyBb"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as duckdb from '@duckdb/duckdb-wasm';
|
|
2
|
+
type AsyncDuckDB = duckdb.AsyncDuckDB;
|
|
3
|
+
type AsyncDuckDBConnection = Awaited<ReturnType<AsyncDuckDB['connect']>>;
|
|
4
|
+
/** Plain JS result: columns in order, rows as array of value arrays. */
|
|
5
|
+
export interface DuckDBQueryResult {
|
|
6
|
+
columns: string[];
|
|
7
|
+
rows: unknown[][];
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Abstraction over a single DuckDB database. Use runQuery, enableExtension, close, or delete.
|
|
11
|
+
*/
|
|
12
|
+
export declare class DuckDBDatabase {
|
|
13
|
+
readonly name: string | null;
|
|
14
|
+
private db;
|
|
15
|
+
private conn;
|
|
16
|
+
private worker;
|
|
17
|
+
private onClose;
|
|
18
|
+
private onDeleteFromOPFS?;
|
|
19
|
+
private readonly key;
|
|
20
|
+
constructor(name: string | null, db: AsyncDuckDB, conn: AsyncDuckDBConnection, worker: Worker, onClose: (key: string) => void, onDeleteFromOPFS?: ((name: string) => Promise<void>) | undefined);
|
|
21
|
+
runQuery(sql: string): Promise<DuckDBQueryResult>;
|
|
22
|
+
enableExtension(extensionName: string): Promise<void>;
|
|
23
|
+
close(): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
export declare class DuckDBService {
|
|
26
|
+
private databases;
|
|
27
|
+
private keyFor;
|
|
28
|
+
/**
|
|
29
|
+
* Open a database by name. Stored in OPFS as `duckdb-databases/<name>.duckdb`. Omit name for in-memory.
|
|
30
|
+
* Returns the same abstraction if that database is already open.
|
|
31
|
+
*/
|
|
32
|
+
open(name?: string): Promise<DuckDBDatabase>;
|
|
33
|
+
/**
|
|
34
|
+
* List persisted database names (files in OPFS under duckdb-databases/, without .duckdb extension).
|
|
35
|
+
*/
|
|
36
|
+
listDatabases(): Promise<string[]>;
|
|
37
|
+
/**
|
|
38
|
+
* Close the database if open and remove its file from OPFS. Name is the simple database name (e.g. `appspace`).
|
|
39
|
+
*/
|
|
40
|
+
delete(name: string): Promise<void>;
|
|
41
|
+
private removeOPFSDatabase;
|
|
42
|
+
}
|
|
43
|
+
export declare const duckdbService: DuckDBService;
|
|
44
|
+
export {};
|
|
45
|
+
//# sourceMappingURL=duckdb-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duckdb-service.d.ts","sourceRoot":"","sources":["../src/duckdb-service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,qBAAqB,CAAC;AAsB9C,KAAK,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;AACtC,KAAK,qBAAqB,GAAG,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAEzE,wEAAwE;AACxE,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC;CACnB;AAiDD;;GAEG;AACH,qBAAa,cAAc;IAIvB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAC5B,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,gBAAgB,CAAC;IAR3B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;gBAGlB,IAAI,EAAE,MAAM,GAAG,IAAI,EACpB,EAAE,EAAE,WAAW,EACf,IAAI,EAAE,qBAAqB,EAC3B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,EAC9B,gBAAgB,CAAC,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,aAAA;IAKtD,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAcjD,eAAe,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBrD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAa7B;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,SAAS,CAAqC;IAEtD,OAAO,CAAC,MAAM;IAId;;;OAGG;IACG,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAyBlD;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAmBxC;;OAEG;IACG,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAS3B,kBAAkB;CAYjC;AAED,eAAO,MAAM,aAAa,eAAsB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
"namespace": "extensions",
|
|
3
|
+
"en": {
|
|
4
|
+
"EXT_DUCKDB_NAME": "DuckDB",
|
|
5
|
+
"EXT_DUCKDB_DESC": "In-browser SQL engine (DuckDB-WASM) for advanced queries, analytics, and Parquet/CSV/JSON."
|
|
6
|
+
},
|
|
7
|
+
"de": {
|
|
8
|
+
"EXT_DUCKDB_NAME": "DuckDB",
|
|
9
|
+
"EXT_DUCKDB_DESC": "SQL-Engine im Browser (DuckDB-WASM) für erweiterte Abfragen, Analysen und Parquet/CSV/JSON."
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
;
|
|
13
|
+
|
|
14
|
+
export default _default;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { contributionRegistry, SYSTEM_LANGUAGE_BUNDLES, i18nLazy, extensionRegistry } from "@eclipse-lyra/core";
|
|
2
|
+
import pkg from "../package.json";
|
|
3
|
+
const namespace = "extensions";
|
|
4
|
+
const en = { "EXT_DUCKDB_NAME": "DuckDB", "EXT_DUCKDB_DESC": "In-browser SQL engine (DuckDB-WASM) for advanced queries, analytics, and Parquet/CSV/JSON." };
|
|
5
|
+
const de = { "EXT_DUCKDB_NAME": "DuckDB", "EXT_DUCKDB_DESC": "SQL-Engine im Browser (DuckDB-WASM) für erweiterte Abfragen, Analysen und Parquet/CSV/JSON." };
|
|
6
|
+
const bundle = {
|
|
7
|
+
namespace,
|
|
8
|
+
en,
|
|
9
|
+
de
|
|
10
|
+
};
|
|
11
|
+
contributionRegistry.registerContribution(SYSTEM_LANGUAGE_BUNDLES, bundle);
|
|
12
|
+
const t = i18nLazy("extensions");
|
|
13
|
+
extensionRegistry.registerExtension({
|
|
14
|
+
id: pkg.name,
|
|
15
|
+
name: t("EXT_DUCKDB_NAME"),
|
|
16
|
+
description: t("EXT_DUCKDB_DESC"),
|
|
17
|
+
loader: () => import("./duckdb-extension-D0_ZZcoC.js"),
|
|
18
|
+
icon: "database",
|
|
19
|
+
dependencies: ["@eclipse-lyra/extension-monaco-editor"]
|
|
20
|
+
});
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import {\n extensionRegistry,\n i18nLazy,\n contributionRegistry,\n SYSTEM_LANGUAGE_BUNDLES,\n} from '@eclipse-lyra/core';\nimport bundle from './i18n.json';\nimport pkg from '../package.json';\n\ncontributionRegistry.registerContribution(SYSTEM_LANGUAGE_BUNDLES, bundle as any);\n\nconst t = i18nLazy('extensions');\n\nextensionRegistry.registerExtension({\n id: pkg.name,\n name: t('EXT_DUCKDB_NAME'),\n description: t('EXT_DUCKDB_DESC'),\n loader: () => import('./duckdb-extension'),\n icon: 'database',\n dependencies: ['@eclipse-lyra/extension-monaco-editor'],\n});\n"],"names":[],"mappings":";;;;;;;;;;AASA,qBAAqB,qBAAqB,yBAAyB,MAAa;AAEhF,MAAM,IAAI,SAAS,YAAY;AAE/B,kBAAkB,kBAAkB;AAAA,EAClC,IAAI,IAAI;AAAA,EACR,MAAM,EAAE,iBAAiB;AAAA,EACzB,aAAa,EAAE,iBAAiB;AAAA,EAChC,QAAQ,MAAM,OAAO,gCAAoB;AAAA,EACzC,MAAM;AAAA,EACN,cAAc,CAAC,uCAAuC;AACxD,CAAC;"}
|