@eclipse-lyra/extension-pglite 0.7.29 → 0.7.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ extensionRegistry.registerExtension({
4
4
  id: pkg.name,
5
5
  name: "PGlite",
6
6
  description: "In-browser PostgreSQL via PGlite",
7
- loader: () => import("./pglite-extension-S3jWuf1w.js"),
7
+ loader: () => import("./pglite-extension-BIBBJgOR.js"),
8
8
  icon: "database",
9
9
  dependencies: ["@eclipse-lyra/extension-sqleditor"],
10
10
  experimental: true
@@ -0,0 +1,430 @@
1
+ import { promptDialog, toastError, toastInfo, appSettings, contributionRegistry } from "@eclipse-lyra/core";
2
+ const DEFINITIONS = [
3
+ {
4
+ id: "live",
5
+ label: "live",
6
+ description: "Reactive/live queries for PGlite",
7
+ load: async () => import("@electric-sql/pglite/live")
8
+ },
9
+ {
10
+ id: "vector",
11
+ label: "pgvector",
12
+ description: "Vector similarity search",
13
+ load: async () => import("@electric-sql/pglite/vector")
14
+ },
15
+ {
16
+ id: "amcheck",
17
+ label: "amcheck",
18
+ description: "Index structure consistency checks",
19
+ load: async () => import("@electric-sql/pglite/contrib/amcheck")
20
+ },
21
+ {
22
+ id: "age",
23
+ label: "Apache AGE",
24
+ description: "Graph database extension on top of PostgreSQL",
25
+ load: async () => import("@electric-sql/pglite/age")
26
+ },
27
+ {
28
+ id: "auto_explain",
29
+ label: "auto_explain",
30
+ description: "Automatically log execution plans for slow statements",
31
+ load: async () => import("@electric-sql/pglite/contrib/auto_explain")
32
+ },
33
+ {
34
+ id: "bloom",
35
+ label: "bloom",
36
+ description: "Bloom filter index access method",
37
+ load: async () => import("@electric-sql/pglite/contrib/bloom")
38
+ },
39
+ {
40
+ id: "btree_gin",
41
+ label: "btree_gin",
42
+ description: "B-tree equivalent GIN operator classes",
43
+ load: async () => import("@electric-sql/pglite/contrib/btree_gin")
44
+ },
45
+ {
46
+ id: "btree_gist",
47
+ label: "btree_gist",
48
+ description: "B-tree equivalent GiST operator classes",
49
+ load: async () => import("@electric-sql/pglite/contrib/btree_gist")
50
+ },
51
+ {
52
+ id: "citext",
53
+ label: "citext",
54
+ description: "Case-insensitive text type",
55
+ load: async () => import("@electric-sql/pglite/contrib/citext")
56
+ },
57
+ {
58
+ id: "cube",
59
+ label: "cube",
60
+ description: "Multidimensional cube data type",
61
+ load: async () => import("@electric-sql/pglite/contrib/cube")
62
+ },
63
+ {
64
+ id: "dict_int",
65
+ label: "dict_int",
66
+ description: "Integer dictionary template for full-text search",
67
+ load: async () => import("@electric-sql/pglite/contrib/dict_int")
68
+ },
69
+ {
70
+ id: "dict_xsyn",
71
+ label: "dict_xsyn",
72
+ description: "Extended synonym dictionary for full-text search",
73
+ load: async () => import("@electric-sql/pglite/contrib/dict_xsyn")
74
+ },
75
+ {
76
+ id: "earthdistance",
77
+ label: "earthdistance",
78
+ description: "Great-circle distance calculations on Earth",
79
+ load: async () => import("@electric-sql/pglite/contrib/earthdistance")
80
+ },
81
+ {
82
+ id: "file_fdw",
83
+ label: "file_fdw",
84
+ description: "Foreign-data wrapper for file system access",
85
+ load: async () => import("@electric-sql/pglite/contrib/file_fdw")
86
+ },
87
+ {
88
+ id: "fuzzystrmatch",
89
+ label: "fuzzystrmatch",
90
+ description: "String similarity and distance functions",
91
+ load: async () => import("@electric-sql/pglite/contrib/fuzzystrmatch")
92
+ },
93
+ {
94
+ id: "hstore",
95
+ label: "hstore",
96
+ description: "Key/value store within a single value",
97
+ load: async () => import("@electric-sql/pglite/contrib/hstore")
98
+ },
99
+ {
100
+ id: "intarray",
101
+ label: "intarray",
102
+ description: "Functions and operators for integer arrays",
103
+ load: async () => import("@electric-sql/pglite/contrib/intarray")
104
+ },
105
+ {
106
+ id: "isn",
107
+ label: "isn",
108
+ description: "Data types for various international product numbering standards",
109
+ load: async () => import("@electric-sql/pglite/contrib/isn")
110
+ },
111
+ {
112
+ id: "lo",
113
+ label: "lo",
114
+ description: "Large object (BLOB) support",
115
+ load: async () => import("@electric-sql/pglite/contrib/lo")
116
+ },
117
+ {
118
+ id: "ltree",
119
+ label: "ltree",
120
+ description: "Hierarchical label tree data type",
121
+ load: async () => import("@electric-sql/pglite/contrib/ltree")
122
+ },
123
+ {
124
+ id: "pageinspect",
125
+ label: "pageinspect",
126
+ description: "Low-level inspection of database pages",
127
+ load: async () => import("@electric-sql/pglite/contrib/pageinspect")
128
+ },
129
+ {
130
+ id: "pg_buffercache",
131
+ label: "pg_buffercache",
132
+ description: "Inspect the shared buffer cache",
133
+ load: async () => import("@electric-sql/pglite/contrib/pg_buffercache")
134
+ },
135
+ {
136
+ id: "pg_freespacemap",
137
+ label: "pg_freespacemap",
138
+ description: "Inspect the free space map",
139
+ load: async () => import("@electric-sql/pglite/contrib/pg_freespacemap")
140
+ },
141
+ {
142
+ id: "pg_hashids",
143
+ label: "pg_hashids",
144
+ description: "Hashids support for Postgres",
145
+ load: async () => import("@electric-sql/pglite/pg_hashids")
146
+ },
147
+ {
148
+ id: "pg_ivm",
149
+ label: "pg_ivm",
150
+ description: "Incremental view maintenance",
151
+ load: async () => import("@electric-sql/pglite/pg_ivm")
152
+ },
153
+ {
154
+ id: "pg_surgery",
155
+ label: "pg_surgery",
156
+ description: "Low-level relation surgery helpers",
157
+ load: async () => import("@electric-sql/pglite/contrib/pg_surgery")
158
+ },
159
+ {
160
+ id: "pg_trgm",
161
+ label: "pg_trgm",
162
+ description: "Trigram-based text similarity",
163
+ load: async () => import("@electric-sql/pglite/contrib/pg_trgm")
164
+ },
165
+ {
166
+ id: "pg_uuidv7",
167
+ label: "pg_uuidv7",
168
+ description: "UUID v7 generation",
169
+ load: async () => import("@electric-sql/pglite/pg_uuidv7")
170
+ },
171
+ {
172
+ id: "pg_visibility",
173
+ label: "pg_visibility",
174
+ description: "Inspect visibility map and page-level visibility",
175
+ load: async () => import("@electric-sql/pglite/contrib/pg_visibility")
176
+ },
177
+ {
178
+ id: "pg_walinspect",
179
+ label: "pg_walinspect",
180
+ description: "Inspect write-ahead log contents",
181
+ load: async () => import("@electric-sql/pglite/contrib/pg_walinspect")
182
+ },
183
+ {
184
+ id: "pgcrypto",
185
+ label: "pgcrypto",
186
+ description: "Cryptographic functions for PostgreSQL",
187
+ load: async () => import("@electric-sql/pglite/contrib/pgcrypto")
188
+ },
189
+ {
190
+ id: "pgtap",
191
+ label: "pgtap",
192
+ description: "TAP-emitting unit tests for Postgres",
193
+ load: async () => import("@electric-sql/pglite/pgtap")
194
+ },
195
+ {
196
+ id: "seg",
197
+ label: "seg",
198
+ description: "Floating point interval/segment data type",
199
+ load: async () => import("@electric-sql/pglite/contrib/seg")
200
+ },
201
+ {
202
+ id: "tablefunc",
203
+ label: "tablefunc",
204
+ description: "Table-returning helper functions",
205
+ load: async () => import("@electric-sql/pglite/contrib/tablefunc")
206
+ },
207
+ {
208
+ id: "tcn",
209
+ label: "tcn",
210
+ description: "Trigger-based change notifications",
211
+ load: async () => import("@electric-sql/pglite/contrib/tcn")
212
+ },
213
+ {
214
+ id: "tsm_system_rows",
215
+ label: "tsm_system_rows",
216
+ description: "TABLESAMPLE SYSTEM_ROWS method",
217
+ load: async () => import("@electric-sql/pglite/contrib/tsm_system_rows")
218
+ },
219
+ {
220
+ id: "tsm_system_time",
221
+ label: "tsm_system_time",
222
+ description: "TABLESAMPLE SYSTEM_TIME method",
223
+ load: async () => import("@electric-sql/pglite/contrib/tsm_system_time")
224
+ },
225
+ {
226
+ id: "unaccent",
227
+ label: "unaccent",
228
+ description: "Accent-removal text search dictionary",
229
+ load: async () => import("@electric-sql/pglite/contrib/unaccent")
230
+ },
231
+ {
232
+ id: "uuid_ossp",
233
+ label: "uuid_ossp",
234
+ description: "UUID generation functions (various versions)",
235
+ load: async () => import("@electric-sql/pglite/contrib/uuid_ossp")
236
+ }
237
+ ];
238
+ const PGLITE_EXTENSIONS_BY_ID = DEFINITIONS.reduce((acc, def) => {
239
+ acc[def.id] = def;
240
+ return acc;
241
+ }, {});
242
+ function listPgliteExtensions() {
243
+ return [...DEFINITIONS];
244
+ }
245
+ async function loadPgliteExtensionModule(id) {
246
+ const def = PGLITE_EXTENSIONS_BY_ID[id];
247
+ if (!def) {
248
+ throw new Error(`Unknown PGlite extension: ${id}`);
249
+ }
250
+ const mod = await def.load();
251
+ const ext = mod[id];
252
+ if (!ext) {
253
+ throw new Error(
254
+ `Extension "${id}" not found in loaded module for id "${id}".`
255
+ );
256
+ }
257
+ return ext;
258
+ }
259
+ async function createPglite(persistentId, extensions) {
260
+ const { PGlite: PGliteCtor } = await import("@electric-sql/pglite");
261
+ const options = extensions && Object.keys(extensions).length > 0 ? { extensions } : {};
262
+ const AnyPGlite = PGliteCtor;
263
+ return persistentId ? new AnyPGlite(`idb://${persistentId}`, options) : new AnyPGlite(options);
264
+ }
265
+ const PGLITE_DB_SETTING_KEY = "pglite.databases";
266
+ const DB_NAME_REGEX = /^[a-zA-Z0-9_.-]+$/;
267
+ async function getDatabaseNames() {
268
+ const stored = await appSettings.get(PGLITE_DB_SETTING_KEY);
269
+ if (!Array.isArray(stored)) return [];
270
+ return stored.filter((name) => typeof name === "string").sort();
271
+ }
272
+ async function saveDatabaseNames(names) {
273
+ await appSettings.set(PGLITE_DB_SETTING_KEY, [...new Set(names)].sort());
274
+ }
275
+ class PgliteSqlDatabase {
276
+ constructor() {
277
+ this.engineId = "pglite";
278
+ this.db = null;
279
+ this.currentId = null;
280
+ this.enabledExtensions = /* @__PURE__ */ new Set();
281
+ }
282
+ get currentConnectionId() {
283
+ return this.currentId;
284
+ }
285
+ async listConnections() {
286
+ const names = await getDatabaseNames();
287
+ return [
288
+ {
289
+ id: null,
290
+ label: "In-memory",
291
+ isDefault: true
292
+ },
293
+ ...names.map((name) => ({
294
+ id: name,
295
+ label: name
296
+ }))
297
+ ];
298
+ }
299
+ async selectConnection(id) {
300
+ if (this.db && this.currentId === id) return;
301
+ if (this.db && this.db.close) {
302
+ await this.db.close();
303
+ }
304
+ this.db = null;
305
+ const extensions = await this.resolveEnabledExtensions();
306
+ this.db = await createPglite(id ?? void 0, extensions);
307
+ this.currentId = id;
308
+ }
309
+ async runQuery(sql) {
310
+ if (!this.db) {
311
+ await this.selectConnection(null);
312
+ }
313
+ if (!this.db) {
314
+ return { columns: [], rows: [] };
315
+ }
316
+ const result = await this.db.query(sql);
317
+ const rows = Array.isArray(result.rows) ? result.rows : [];
318
+ if (!rows.length) return { columns: [], rows: [] };
319
+ const columns = Object.keys(rows[0]);
320
+ const matrix = rows.map((row) => columns.map((c) => row[c]));
321
+ return { columns, rows: matrix };
322
+ }
323
+ async close() {
324
+ if (!this.db) return;
325
+ await this.db.close?.();
326
+ this.db = null;
327
+ this.currentId = null;
328
+ }
329
+ async createConnection() {
330
+ const raw = await promptDialog("New PGlite database name", "");
331
+ if (raw == null) return null;
332
+ const name = raw.trim();
333
+ if (!name) {
334
+ toastError("Name cannot be empty");
335
+ return null;
336
+ }
337
+ if (!DB_NAME_REGEX.test(name)) {
338
+ toastError("Name may only contain letters, numbers, and . _ -");
339
+ return null;
340
+ }
341
+ const existing = await getDatabaseNames();
342
+ if (existing.includes(name)) {
343
+ toastError(`Database "${name}" already exists`);
344
+ return null;
345
+ }
346
+ await saveDatabaseNames([...existing, name]);
347
+ toastInfo(`Database "${name}" created`);
348
+ return {
349
+ id: name,
350
+ label: name,
351
+ isDefault: false
352
+ };
353
+ }
354
+ async deleteConnection(id) {
355
+ if (!id) return;
356
+ const names = await getDatabaseNames();
357
+ if (!names.includes(id)) return;
358
+ const next = names.filter((n) => n !== id);
359
+ await saveDatabaseNames(next);
360
+ if (this.currentId === id) {
361
+ await this.close();
362
+ }
363
+ }
364
+ async listDbExtensions() {
365
+ if (!this.db) {
366
+ await this.selectConnection(null);
367
+ }
368
+ if (!this.db) {
369
+ return listPgliteExtensions().map((def) => ({
370
+ id: def.id,
371
+ label: def.label,
372
+ description: def.description,
373
+ installed: false
374
+ }));
375
+ }
376
+ const result = await this.db.query("SELECT extname FROM pg_extension");
377
+ const rows = Array.isArray(result.rows) ? result.rows : [];
378
+ const installedNames = new Set(
379
+ rows.map((row) => row.extname).filter((name) => typeof name === "string")
380
+ );
381
+ return listPgliteExtensions().map((def) => ({
382
+ id: def.id,
383
+ label: def.label,
384
+ description: def.description,
385
+ installed: installedNames.has(def.id)
386
+ }));
387
+ }
388
+ async enableDbExtension(id) {
389
+ this.enabledExtensions.add(id);
390
+ if (this.db) {
391
+ await this.db.close?.();
392
+ this.db = null;
393
+ }
394
+ await this.selectConnection(this.currentId ?? null);
395
+ if (!this.db) return;
396
+ const db = this.db;
397
+ await db.query(`CREATE EXTENSION IF NOT EXISTS ${id};`);
398
+ }
399
+ async resolveEnabledExtensions() {
400
+ if (!this.enabledExtensions.size) {
401
+ return void 0;
402
+ }
403
+ const entries = await Promise.all(
404
+ [...this.enabledExtensions].map(
405
+ async (extId) => [
406
+ extId,
407
+ await loadPgliteExtensionModule(extId)
408
+ ]
409
+ )
410
+ );
411
+ const result = {};
412
+ for (const [extId, ext] of entries) {
413
+ result[extId] = ext;
414
+ }
415
+ return result;
416
+ }
417
+ }
418
+ const pgliteSqlAdapterContribution = {
419
+ id: "pglite",
420
+ label: "PostgreSQL (PGlite)",
421
+ icon: "database",
422
+ loader: async () => new PgliteSqlDatabase()
423
+ };
424
+ function activate() {
425
+ contributionRegistry.registerContribution("system.sqladapters", pgliteSqlAdapterContribution);
426
+ }
427
+ export {
428
+ activate as default
429
+ };
430
+ //# sourceMappingURL=pglite-extension-BIBBJgOR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pglite-extension-BIBBJgOR.js","sources":["../src/pglite-extensions.ts","../src/pglite-sqldatabase.ts","../src/pglite-extension.ts"],"sourcesContent":["export interface PgliteExtensionDefinition {\n id: string;\n label: string;\n description: string;\n load: () => Promise<Record<string, unknown>>;\n}\n\nconst DEFINITIONS: PgliteExtensionDefinition[] = [\n {\n id: 'live',\n label: 'live',\n description: 'Reactive/live queries for PGlite',\n load: async () => import('@electric-sql/pglite/live'),\n },\n {\n id: 'vector',\n label: 'pgvector',\n description: 'Vector similarity search',\n load: async () => import('@electric-sql/pglite/vector'),\n },\n {\n id: 'amcheck',\n label: 'amcheck',\n description: 'Index structure consistency checks',\n load: async () => import('@electric-sql/pglite/contrib/amcheck'),\n },\n {\n id: 'age',\n label: 'Apache AGE',\n description: 'Graph database extension on top of PostgreSQL',\n load: async () => import('@electric-sql/pglite/age'),\n },\n {\n id: 'auto_explain',\n label: 'auto_explain',\n description: 'Automatically log execution plans for slow statements',\n load: async () => import('@electric-sql/pglite/contrib/auto_explain'),\n },\n {\n id: 'bloom',\n label: 'bloom',\n description: 'Bloom filter index access method',\n load: async () => import('@electric-sql/pglite/contrib/bloom'),\n },\n {\n id: 'btree_gin',\n label: 'btree_gin',\n description: 'B-tree equivalent GIN operator classes',\n load: async () => import('@electric-sql/pglite/contrib/btree_gin'),\n },\n {\n id: 'btree_gist',\n label: 'btree_gist',\n description: 'B-tree equivalent GiST operator classes',\n load: async () => import('@electric-sql/pglite/contrib/btree_gist'),\n },\n {\n id: 'citext',\n label: 'citext',\n description: 'Case-insensitive text type',\n load: async () => import('@electric-sql/pglite/contrib/citext'),\n },\n {\n id: 'cube',\n label: 'cube',\n description: 'Multidimensional cube data type',\n load: async () => import('@electric-sql/pglite/contrib/cube'),\n },\n {\n id: 'dict_int',\n label: 'dict_int',\n description: 'Integer dictionary template for full-text search',\n load: async () => import('@electric-sql/pglite/contrib/dict_int'),\n },\n {\n id: 'dict_xsyn',\n label: 'dict_xsyn',\n description: 'Extended synonym dictionary for full-text search',\n load: async () => import('@electric-sql/pglite/contrib/dict_xsyn'),\n },\n {\n id: 'earthdistance',\n label: 'earthdistance',\n description: 'Great-circle distance calculations on Earth',\n load: async () => import('@electric-sql/pglite/contrib/earthdistance'),\n },\n {\n id: 'file_fdw',\n label: 'file_fdw',\n description: 'Foreign-data wrapper for file system access',\n load: async () => import('@electric-sql/pglite/contrib/file_fdw'),\n },\n {\n id: 'fuzzystrmatch',\n label: 'fuzzystrmatch',\n description: 'String similarity and distance functions',\n load: async () => import('@electric-sql/pglite/contrib/fuzzystrmatch'),\n },\n {\n id: 'hstore',\n label: 'hstore',\n description: 'Key/value store within a single value',\n load: async () => import('@electric-sql/pglite/contrib/hstore'),\n },\n {\n id: 'intarray',\n label: 'intarray',\n description: 'Functions and operators for integer arrays',\n load: async () => import('@electric-sql/pglite/contrib/intarray'),\n },\n {\n id: 'isn',\n label: 'isn',\n description:\n 'Data types for various international product numbering standards',\n load: async () => import('@electric-sql/pglite/contrib/isn'),\n },\n {\n id: 'lo',\n label: 'lo',\n description: 'Large object (BLOB) support',\n load: async () => import('@electric-sql/pglite/contrib/lo'),\n },\n {\n id: 'ltree',\n label: 'ltree',\n description: 'Hierarchical label tree data type',\n load: async () => import('@electric-sql/pglite/contrib/ltree'),\n },\n {\n id: 'pageinspect',\n label: 'pageinspect',\n description: 'Low-level inspection of database pages',\n load: async () => import('@electric-sql/pglite/contrib/pageinspect'),\n },\n {\n id: 'pg_buffercache',\n label: 'pg_buffercache',\n description: 'Inspect the shared buffer cache',\n load: async () => import('@electric-sql/pglite/contrib/pg_buffercache'),\n },\n {\n id: 'pg_freespacemap',\n label: 'pg_freespacemap',\n description: 'Inspect the free space map',\n load: async () => import('@electric-sql/pglite/contrib/pg_freespacemap'),\n },\n {\n id: 'pg_hashids',\n label: 'pg_hashids',\n description: 'Hashids support for Postgres',\n load: async () => import('@electric-sql/pglite/pg_hashids'),\n },\n {\n id: 'pg_ivm',\n label: 'pg_ivm',\n description: 'Incremental view maintenance',\n load: async () => import('@electric-sql/pglite/pg_ivm'),\n },\n {\n id: 'pg_surgery',\n label: 'pg_surgery',\n description: 'Low-level relation surgery helpers',\n load: async () => import('@electric-sql/pglite/contrib/pg_surgery'),\n },\n {\n id: 'pg_trgm',\n label: 'pg_trgm',\n description: 'Trigram-based text similarity',\n load: async () => import('@electric-sql/pglite/contrib/pg_trgm'),\n },\n {\n id: 'pg_uuidv7',\n label: 'pg_uuidv7',\n description: 'UUID v7 generation',\n load: async () => import('@electric-sql/pglite/pg_uuidv7'),\n },\n {\n id: 'pg_visibility',\n label: 'pg_visibility',\n description: 'Inspect visibility map and page-level visibility',\n load: async () => import('@electric-sql/pglite/contrib/pg_visibility'),\n },\n {\n id: 'pg_walinspect',\n label: 'pg_walinspect',\n description: 'Inspect write-ahead log contents',\n load: async () => import('@electric-sql/pglite/contrib/pg_walinspect'),\n },\n {\n id: 'pgcrypto',\n label: 'pgcrypto',\n description: 'Cryptographic functions for PostgreSQL',\n load: async () => import('@electric-sql/pglite/contrib/pgcrypto'),\n },\n {\n id: 'pgtap',\n label: 'pgtap',\n description: 'TAP-emitting unit tests for Postgres',\n load: async () => import('@electric-sql/pglite/pgtap'),\n },\n {\n id: 'seg',\n label: 'seg',\n description: 'Floating point interval/segment data type',\n load: async () => import('@electric-sql/pglite/contrib/seg'),\n },\n {\n id: 'tablefunc',\n label: 'tablefunc',\n description: 'Table-returning helper functions',\n load: async () => import('@electric-sql/pglite/contrib/tablefunc'),\n },\n {\n id: 'tcn',\n label: 'tcn',\n description: 'Trigger-based change notifications',\n load: async () => import('@electric-sql/pglite/contrib/tcn'),\n },\n {\n id: 'tsm_system_rows',\n label: 'tsm_system_rows',\n description: 'TABLESAMPLE SYSTEM_ROWS method',\n load: async () =>\n import('@electric-sql/pglite/contrib/tsm_system_rows'),\n },\n {\n id: 'tsm_system_time',\n label: 'tsm_system_time',\n description: 'TABLESAMPLE SYSTEM_TIME method',\n load: async () =>\n import('@electric-sql/pglite/contrib/tsm_system_time'),\n },\n {\n id: 'unaccent',\n label: 'unaccent',\n description: 'Accent-removal text search dictionary',\n load: async () => import('@electric-sql/pglite/contrib/unaccent'),\n },\n {\n id: 'uuid_ossp',\n label: 'uuid_ossp',\n description: 'UUID generation functions (various versions)',\n load: async () => import('@electric-sql/pglite/contrib/uuid_ossp'),\n },\n];\n\nexport const PGLITE_EXTENSIONS_BY_ID: Record<string, PgliteExtensionDefinition> =\n DEFINITIONS.reduce((acc, def) => {\n acc[def.id] = def;\n return acc;\n }, {} as Record<string, PgliteExtensionDefinition>);\n\nexport function listPgliteExtensions(): PgliteExtensionDefinition[] {\n return [...DEFINITIONS];\n}\n\nexport async function loadPgliteExtensionModule(\n id: string,\n): Promise<unknown> {\n const def = PGLITE_EXTENSIONS_BY_ID[id];\n if (!def) {\n throw new Error(`Unknown PGlite extension: ${id}`);\n }\n const mod = await def.load();\n const ext = mod[id];\n if (!ext) {\n throw new Error(\n `Extension \"${id}\" not found in loaded module for id \"${id}\".`,\n );\n }\n return ext;\n}\n\n","import type { PGlite } from '@electric-sql/pglite';\nimport type {\n SqlAdapterContribution,\n SqlConnectionInfo,\n SqlDatabase,\n SqlDatabaseExtensionInfo,\n} from '@eclipse-lyra/extension-sqleditor';\nimport {\n appSettings,\n toastError,\n toastInfo,\n promptDialog,\n} from '@eclipse-lyra/core';\nimport {\n listPgliteExtensions,\n loadPgliteExtensionModule,\n} from './pglite-extensions';\n\nasync function createPglite(\n persistentId?: string,\n extensions?: Record<string, unknown>,\n): Promise<PGlite> {\n const { PGlite: PGliteCtor } = await import('@electric-sql/pglite');\n const options =\n extensions && Object.keys(extensions).length > 0 ? { extensions } : {};\n const AnyPGlite = PGliteCtor as unknown as {\n new (dataDirOrOptions?: unknown, optionsOrUndefined?: unknown): PGlite;\n };\n return persistentId\n ? new AnyPGlite(`idb://${persistentId}`, options)\n : new AnyPGlite(options);\n}\nconst PGLITE_DB_SETTING_KEY = 'pglite.databases';\nconst DB_NAME_REGEX = /^[a-zA-Z0-9_.-]+$/;\n\nasync function getDatabaseNames(): Promise<string[]> {\n const stored = await appSettings.get(PGLITE_DB_SETTING_KEY);\n if (!Array.isArray(stored)) return [];\n return stored.filter((name): name is string => typeof name === 'string').sort();\n}\n\nasync function saveDatabaseNames(names: string[]): Promise<void> {\n await appSettings.set(PGLITE_DB_SETTING_KEY, [...new Set(names)].sort());\n}\n\nclass PgliteSqlDatabase implements SqlDatabase {\n readonly engineId = 'pglite';\n\n private db: PGlite | null = null;\n private currentId: string | null = null;\n private enabledExtensions = new Set<string>();\n\n get currentConnectionId(): string | null {\n return this.currentId;\n }\n\n async listConnections(): Promise<SqlConnectionInfo[]> {\n const names = await getDatabaseNames();\n return [\n {\n id: null,\n label: 'In-memory',\n isDefault: true,\n },\n ...names.map((name) => ({\n id: name,\n label: name,\n })),\n ];\n }\n\n async selectConnection(id: string | null): Promise<void> {\n if (this.db && this.currentId === id) return;\n if (this.db && this.db.close) {\n await this.db.close();\n }\n this.db = null;\n const extensions = await this.resolveEnabledExtensions();\n this.db = await createPglite(id ?? undefined, extensions);\n this.currentId = id;\n }\n\n async runQuery(sql: string): Promise<{ columns: string[]; rows: unknown[][] }> {\n if (!this.db) {\n await this.selectConnection(null);\n }\n if (!this.db) {\n return { columns: [], rows: [] };\n }\n const result = await this.db.query(sql);\n const rows = Array.isArray(result.rows) ? (result.rows as Record<string, unknown>[]) : [];\n if (!rows.length) return { columns: [], rows: [] };\n const columns = Object.keys(rows[0]);\n const matrix = rows.map((row) => columns.map((c) => row[c]));\n return { columns, rows: matrix };\n }\n\n async close(): Promise<void> {\n if (!this.db) return;\n await this.db.close?.();\n this.db = null;\n this.currentId = null;\n }\n\n async createConnection(): Promise<SqlConnectionInfo | null> {\n const raw = await promptDialog('New PGlite database name', '');\n if (raw == null) return null;\n const name = raw.trim();\n if (!name) {\n toastError('Name cannot be empty');\n return null;\n }\n if (!DB_NAME_REGEX.test(name)) {\n toastError('Name may only contain letters, numbers, and . _ -');\n return null;\n }\n const existing = await getDatabaseNames();\n if (existing.includes(name)) {\n toastError(`Database \"${name}\" already exists`);\n return null;\n }\n await saveDatabaseNames([...existing, name]);\n toastInfo(`Database \"${name}\" created`);\n return {\n id: name,\n label: name,\n isDefault: false,\n };\n }\n\n async deleteConnection(id: string): Promise<void> {\n if (!id) return;\n const names = await getDatabaseNames();\n if (!names.includes(id)) return;\n const next = names.filter((n) => n !== id);\n await saveDatabaseNames(next);\n if (this.currentId === id) {\n await this.close();\n }\n }\n\n async listDbExtensions(): Promise<SqlDatabaseExtensionInfo[]> {\n if (!this.db) {\n await this.selectConnection(null);\n }\n if (!this.db) {\n return listPgliteExtensions().map<SqlDatabaseExtensionInfo>((def) => ({\n id: def.id,\n label: def.label,\n description: def.description,\n installed: false,\n }));\n }\n\n const result = await this.db.query('SELECT extname FROM pg_extension');\n const rows = Array.isArray(result.rows)\n ? (result.rows as Record<string, unknown>[])\n : [];\n const installedNames = new Set(\n rows\n .map((row) => row.extname)\n .filter((name): name is string => typeof name === 'string'),\n );\n\n return listPgliteExtensions().map<SqlDatabaseExtensionInfo>((def) => ({\n id: def.id,\n label: def.label,\n description: def.description,\n installed: installedNames.has(def.id),\n }));\n }\n\n async enableDbExtension(id: string): Promise<void> {\n this.enabledExtensions.add(id);\n if (this.db) {\n await this.db.close?.();\n this.db = null;\n }\n await this.selectConnection(this.currentId ?? null);\n if (!this.db) return;\n const db = this.db as PGlite;\n await db.query(`CREATE EXTENSION IF NOT EXISTS ${id};`);\n }\n\n private async resolveEnabledExtensions(): Promise<\n Record<string, unknown> | undefined\n > {\n if (!this.enabledExtensions.size) {\n return undefined;\n }\n const entries: [string, unknown][] = await Promise.all(\n [...this.enabledExtensions].map(\n async (extId): Promise<[string, unknown]> => [\n extId,\n await loadPgliteExtensionModule(extId),\n ],\n ),\n );\n const result: Record<string, unknown> = {};\n for (const [extId, ext] of entries) {\n result[extId] = ext;\n }\n return result;\n }\n}\n\nexport const pgliteSqlAdapterContribution: SqlAdapterContribution = {\n id: 'pglite',\n label: 'PostgreSQL (PGlite)',\n icon: 'database',\n loader: async () => new PgliteSqlDatabase(),\n};\n\n","import { contributionRegistry } from '@eclipse-lyra/core';\nimport { pgliteSqlAdapterContribution } from './pglite-sqldatabase';\n\nexport default function activate() {\n contributionRegistry.registerContribution('system.sqladapters', pgliteSqlAdapterContribution);\n}\n\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export interface PgliteExtensionDefinition {
2
+ id: string;
3
+ label: string;
4
+ description: string;
5
+ load: () => Promise<Record<string, unknown>>;
6
+ }
7
+ export declare const PGLITE_EXTENSIONS_BY_ID: Record<string, PgliteExtensionDefinition>;
8
+ export declare function listPgliteExtensions(): PgliteExtensionDefinition[];
9
+ export declare function loadPgliteExtensionModule(id: string): Promise<unknown>;
10
+ //# sourceMappingURL=pglite-extensions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pglite-extensions.d.ts","sourceRoot":"","sources":["../src/pglite-extensions.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,yBAAyB;IACxC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC9C;AAkPD,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAIzB,CAAC;AAEtD,wBAAgB,oBAAoB,IAAI,yBAAyB,EAAE,CAElE;AAED,wBAAsB,yBAAyB,CAC7C,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,OAAO,CAAC,CAalB"}
@@ -1 +1 @@
1
- {"version":3,"file":"pglite-sqldatabase.d.ts","sourceRoot":"","sources":["../src/pglite-sqldatabase.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,sBAAsB,EAGvB,MAAM,mCAAmC,CAAC;AAwH3C,eAAO,MAAM,4BAA4B,EAAE,sBAK1C,CAAC"}
1
+ {"version":3,"file":"pglite-sqldatabase.d.ts","sourceRoot":"","sources":["../src/pglite-sqldatabase.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,sBAAsB,EAIvB,MAAM,mCAAmC,CAAC;AAwM3C,eAAO,MAAM,4BAA4B,EAAE,sBAK1C,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eclipse-lyra/extension-pglite",
3
- "version": "0.7.29",
3
+ "version": "0.7.31",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -1,116 +0,0 @@
1
- import { promptDialog, toastError, toastInfo, appSettings, contributionRegistry } from "@eclipse-lyra/core";
2
- async function createPglite(persistentId) {
3
- const { PGlite: PGliteCtor } = await import("@electric-sql/pglite");
4
- return persistentId ? new PGliteCtor(`idb://${persistentId}`) : new PGliteCtor();
5
- }
6
- const PGLITE_DB_SETTING_KEY = "pglite.databases";
7
- const DB_NAME_REGEX = /^[a-zA-Z0-9_.-]+$/;
8
- async function getDatabaseNames() {
9
- const stored = await appSettings.get(PGLITE_DB_SETTING_KEY);
10
- if (!Array.isArray(stored)) return [];
11
- return stored.filter((name) => typeof name === "string").sort();
12
- }
13
- async function saveDatabaseNames(names) {
14
- await appSettings.set(PGLITE_DB_SETTING_KEY, [...new Set(names)].sort());
15
- }
16
- class PgliteSqlDatabase {
17
- constructor() {
18
- this.engineId = "pglite";
19
- this.db = null;
20
- this.currentId = null;
21
- }
22
- get currentConnectionId() {
23
- return this.currentId;
24
- }
25
- async listConnections() {
26
- const names = await getDatabaseNames();
27
- return [
28
- {
29
- id: null,
30
- label: "In-memory",
31
- isDefault: true
32
- },
33
- ...names.map((name) => ({
34
- id: name,
35
- label: name
36
- }))
37
- ];
38
- }
39
- async selectConnection(id) {
40
- if (this.db && this.currentId === id) return;
41
- if (this.db && this.db.close) {
42
- await this.db.close();
43
- }
44
- this.db = null;
45
- this.db = await createPglite(id ?? void 0);
46
- this.currentId = id;
47
- }
48
- async runQuery(sql) {
49
- if (!this.db) {
50
- await this.selectConnection(null);
51
- }
52
- if (!this.db) {
53
- return { columns: [], rows: [] };
54
- }
55
- const result = await this.db.query(sql);
56
- const rows = Array.isArray(result.rows) ? result.rows : [];
57
- if (!rows.length) return { columns: [], rows: [] };
58
- const columns = Object.keys(rows[0]);
59
- const matrix = rows.map((row) => columns.map((c) => row[c]));
60
- return { columns, rows: matrix };
61
- }
62
- async close() {
63
- if (!this.db) return;
64
- await this.db.close?.();
65
- this.db = null;
66
- this.currentId = null;
67
- }
68
- async createConnection() {
69
- const raw = await promptDialog("New PGlite database name", "");
70
- if (raw == null) return null;
71
- const name = raw.trim();
72
- if (!name) {
73
- toastError("Name cannot be empty");
74
- return null;
75
- }
76
- if (!DB_NAME_REGEX.test(name)) {
77
- toastError("Name may only contain letters, numbers, and . _ -");
78
- return null;
79
- }
80
- const existing = await getDatabaseNames();
81
- if (existing.includes(name)) {
82
- toastError(`Database "${name}" already exists`);
83
- return null;
84
- }
85
- await saveDatabaseNames([...existing, name]);
86
- toastInfo(`Database "${name}" created`);
87
- return {
88
- id: name,
89
- label: name,
90
- isDefault: false
91
- };
92
- }
93
- async deleteConnection(id) {
94
- if (!id) return;
95
- const names = await getDatabaseNames();
96
- if (!names.includes(id)) return;
97
- const next = names.filter((n) => n !== id);
98
- await saveDatabaseNames(next);
99
- if (this.currentId === id) {
100
- await this.close();
101
- }
102
- }
103
- }
104
- const pgliteSqlAdapterContribution = {
105
- id: "pglite",
106
- label: "PostgreSQL (PGlite)",
107
- icon: "database",
108
- loader: async () => new PgliteSqlDatabase()
109
- };
110
- function activate() {
111
- contributionRegistry.registerContribution("system.sqladapters", pgliteSqlAdapterContribution);
112
- }
113
- export {
114
- activate as default
115
- };
116
- //# sourceMappingURL=pglite-extension-S3jWuf1w.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pglite-extension-S3jWuf1w.js","sources":["../src/pglite-sqldatabase.ts","../src/pglite-extension.ts"],"sourcesContent":["import type { PGlite } from '@electric-sql/pglite';\nimport type {\n SqlAdapterContribution,\n SqlConnectionInfo,\n SqlDatabase,\n} from '@eclipse-lyra/extension-sqleditor';\nimport {\n appSettings,\n toastError,\n toastInfo,\n promptDialog,\n} from '@eclipse-lyra/core';\n\nasync function createPglite(persistentId?: string): Promise<PGlite> {\n const { PGlite: PGliteCtor } = await import('@electric-sql/pglite');\n return persistentId ? new PGliteCtor(`idb://${persistentId}`) : new PGliteCtor();\n}\nconst PGLITE_DB_SETTING_KEY = 'pglite.databases';\nconst DB_NAME_REGEX = /^[a-zA-Z0-9_.-]+$/;\n\nasync function getDatabaseNames(): Promise<string[]> {\n const stored = await appSettings.get(PGLITE_DB_SETTING_KEY);\n if (!Array.isArray(stored)) return [];\n return stored.filter((name): name is string => typeof name === 'string').sort();\n}\n\nasync function saveDatabaseNames(names: string[]): Promise<void> {\n await appSettings.set(PGLITE_DB_SETTING_KEY, [...new Set(names)].sort());\n}\n\nclass PgliteSqlDatabase implements SqlDatabase {\n readonly engineId = 'pglite';\n\n private db: PGlite | null = null;\n private currentId: string | null = null;\n\n get currentConnectionId(): string | null {\n return this.currentId;\n }\n\n async listConnections(): Promise<SqlConnectionInfo[]> {\n const names = await getDatabaseNames();\n return [\n {\n id: null,\n label: 'In-memory',\n isDefault: true,\n },\n ...names.map((name) => ({\n id: name,\n label: name,\n })),\n ];\n }\n\n async selectConnection(id: string | null): Promise<void> {\n if (this.db && this.currentId === id) return;\n if (this.db && this.db.close) {\n await this.db.close();\n }\n this.db = null;\n this.db = await createPglite(id ?? undefined);\n this.currentId = id;\n }\n\n async runQuery(sql: string): Promise<{ columns: string[]; rows: unknown[][] }> {\n if (!this.db) {\n await this.selectConnection(null);\n }\n if (!this.db) {\n return { columns: [], rows: [] };\n }\n const result = await this.db.query(sql);\n const rows = Array.isArray(result.rows) ? (result.rows as Record<string, unknown>[]) : [];\n if (!rows.length) return { columns: [], rows: [] };\n const columns = Object.keys(rows[0]);\n const matrix = rows.map((row) => columns.map((c) => row[c]));\n return { columns, rows: matrix };\n }\n\n async close(): Promise<void> {\n if (!this.db) return;\n await this.db.close?.();\n this.db = null;\n this.currentId = null;\n }\n\n async createConnection(): Promise<SqlConnectionInfo | null> {\n const raw = await promptDialog('New PGlite database name', '');\n if (raw == null) return null;\n const name = raw.trim();\n if (!name) {\n toastError('Name cannot be empty');\n return null;\n }\n if (!DB_NAME_REGEX.test(name)) {\n toastError('Name may only contain letters, numbers, and . _ -');\n return null;\n }\n const existing = await getDatabaseNames();\n if (existing.includes(name)) {\n toastError(`Database \"${name}\" already exists`);\n return null;\n }\n await saveDatabaseNames([...existing, name]);\n toastInfo(`Database \"${name}\" created`);\n return {\n id: name,\n label: name,\n isDefault: false,\n };\n }\n\n async deleteConnection(id: string): Promise<void> {\n if (!id) return;\n const names = await getDatabaseNames();\n if (!names.includes(id)) return;\n const next = names.filter((n) => n !== id);\n await saveDatabaseNames(next);\n if (this.currentId === id) {\n await this.close();\n }\n }\n}\n\nexport const pgliteSqlAdapterContribution: SqlAdapterContribution = {\n id: 'pglite',\n label: 'PostgreSQL (PGlite)',\n icon: 'database',\n loader: async () => new PgliteSqlDatabase(),\n};\n\n","import { contributionRegistry } from '@eclipse-lyra/core';\nimport { pgliteSqlAdapterContribution } from './pglite-sqldatabase';\n\nexport default function activate() {\n contributionRegistry.registerContribution('system.sqladapters', pgliteSqlAdapterContribution);\n}\n\n"],"names":[],"mappings":"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"}