@plures/pluresdb 1.4.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.
Files changed (96) hide show
  1. package/LICENSE +72 -0
  2. package/README.md +450 -0
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/better-sqlite3-shared.d.ts +12 -0
  5. package/dist/better-sqlite3-shared.d.ts.map +1 -0
  6. package/dist/better-sqlite3-shared.js +143 -0
  7. package/dist/better-sqlite3-shared.js.map +1 -0
  8. package/dist/better-sqlite3.d.ts +4 -0
  9. package/dist/better-sqlite3.d.ts.map +1 -0
  10. package/dist/better-sqlite3.js +8 -0
  11. package/dist/better-sqlite3.js.map +1 -0
  12. package/dist/cli.d.ts +7 -0
  13. package/dist/cli.d.ts.map +1 -0
  14. package/dist/cli.js +258 -0
  15. package/dist/cli.js.map +1 -0
  16. package/dist/node-index.d.ts +148 -0
  17. package/dist/node-index.d.ts.map +1 -0
  18. package/dist/node-index.js +665 -0
  19. package/dist/node-index.js.map +1 -0
  20. package/dist/node-wrapper.d.ts +44 -0
  21. package/dist/node-wrapper.d.ts.map +1 -0
  22. package/dist/node-wrapper.js +296 -0
  23. package/dist/node-wrapper.js.map +1 -0
  24. package/dist/types/index.d.ts +28 -0
  25. package/dist/types/index.d.ts.map +1 -0
  26. package/dist/types/index.js +3 -0
  27. package/dist/types/index.js.map +1 -0
  28. package/dist/types/node-types.d.ts +71 -0
  29. package/dist/types/node-types.d.ts.map +1 -0
  30. package/dist/types/node-types.js +6 -0
  31. package/dist/types/node-types.js.map +1 -0
  32. package/dist/vscode/extension.d.ts +81 -0
  33. package/dist/vscode/extension.d.ts.map +1 -0
  34. package/dist/vscode/extension.js +309 -0
  35. package/dist/vscode/extension.js.map +1 -0
  36. package/examples/basic-usage.d.ts +2 -0
  37. package/examples/basic-usage.d.ts.map +1 -0
  38. package/examples/basic-usage.js +26 -0
  39. package/examples/basic-usage.js.map +1 -0
  40. package/examples/basic-usage.ts +29 -0
  41. package/examples/vscode-extension-example/README.md +95 -0
  42. package/examples/vscode-extension-example/package.json +49 -0
  43. package/examples/vscode-extension-example/src/extension.ts +172 -0
  44. package/examples/vscode-extension-example/tsconfig.json +12 -0
  45. package/examples/vscode-extension-integration.d.ts +31 -0
  46. package/examples/vscode-extension-integration.d.ts.map +1 -0
  47. package/examples/vscode-extension-integration.js +319 -0
  48. package/examples/vscode-extension-integration.js.map +1 -0
  49. package/examples/vscode-extension-integration.ts +41 -0
  50. package/legacy/benchmarks/memory-benchmarks.ts +350 -0
  51. package/legacy/benchmarks/run-benchmarks.ts +315 -0
  52. package/legacy/better-sqlite3-shared.ts +157 -0
  53. package/legacy/better-sqlite3.ts +4 -0
  54. package/legacy/cli.ts +241 -0
  55. package/legacy/config.ts +50 -0
  56. package/legacy/core/crdt.ts +107 -0
  57. package/legacy/core/database.ts +529 -0
  58. package/legacy/healthcheck.ts +162 -0
  59. package/legacy/http/api-server.ts +438 -0
  60. package/legacy/index.ts +28 -0
  61. package/legacy/logic/rules.ts +46 -0
  62. package/legacy/main.rs +3 -0
  63. package/legacy/main.ts +197 -0
  64. package/legacy/network/websocket-server.ts +115 -0
  65. package/legacy/node-index.ts +823 -0
  66. package/legacy/node-wrapper.ts +329 -0
  67. package/legacy/sqlite-compat.ts +633 -0
  68. package/legacy/sqlite3-compat.ts +55 -0
  69. package/legacy/storage/kv-storage.ts +73 -0
  70. package/legacy/tests/core.test.ts +305 -0
  71. package/legacy/tests/fixtures/performance-data.json +71 -0
  72. package/legacy/tests/fixtures/test-data.json +129 -0
  73. package/legacy/tests/integration/api-server.test.ts +334 -0
  74. package/legacy/tests/integration/mesh-network.test.ts +303 -0
  75. package/legacy/tests/logic.test.ts +34 -0
  76. package/legacy/tests/performance/load.test.ts +290 -0
  77. package/legacy/tests/security/input-validation.test.ts +286 -0
  78. package/legacy/tests/unit/core.test.ts +226 -0
  79. package/legacy/tests/unit/subscriptions.test.ts +135 -0
  80. package/legacy/tests/unit/vector-search.test.ts +173 -0
  81. package/legacy/tests/vscode_extension_test.ts +281 -0
  82. package/legacy/types/index.ts +32 -0
  83. package/legacy/types/node-types.ts +80 -0
  84. package/legacy/util/debug.ts +14 -0
  85. package/legacy/vector/index.ts +59 -0
  86. package/legacy/vscode/extension.ts +387 -0
  87. package/package.json +127 -0
  88. package/scripts/compiled-crud-verify.ts +30 -0
  89. package/scripts/dogfood.ts +297 -0
  90. package/scripts/postinstall.js +156 -0
  91. package/scripts/release-check.js +190 -0
  92. package/scripts/run-tests.ts +178 -0
  93. package/scripts/setup-libclang.ps1 +209 -0
  94. package/scripts/update-changelog.js +214 -0
  95. package/web/README.md +27 -0
  96. package/web/svelte/package.json +31 -0
@@ -0,0 +1,665 @@
1
+ "use strict";
2
+ /**
3
+ * Node.js Entry Point for PluresDB
4
+ * This provides a clean API for VSCode extensions and other Node.js applications
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
40
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
41
+ };
42
+ var __importDefault = (this && this.__importDefault) || function (mod) {
43
+ return (mod && mod.__esModule) ? mod : { "default": mod };
44
+ };
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ exports.PluresVSCodeExtension = exports.createPluresExtension = exports.default = exports.BetterSQLite3Database = exports.BetterSQLite3Statement = exports.SQLiteCompatibleAPI = exports.PluresNode = void 0;
47
+ const node_events_1 = require("node:events");
48
+ const node_child_process_1 = require("node:child_process");
49
+ const path = __importStar(require("node:path"));
50
+ const fs = __importStar(require("node:fs"));
51
+ const os = __importStar(require("node:os"));
52
+ const node_process_1 = __importDefault(require("node:process"));
53
+ const better_sqlite3_shared_1 = require("./better-sqlite3-shared");
54
+ const packageRoot = typeof __dirname !== "undefined"
55
+ ? path.resolve(__dirname, "..")
56
+ : node_process_1.default.cwd();
57
+ class PluresNode extends node_events_1.EventEmitter {
58
+ process = null;
59
+ config;
60
+ denoPath;
61
+ isRunning = false;
62
+ apiUrl = "";
63
+ constructor(options = {}) {
64
+ super();
65
+ this.config = {
66
+ port: 34567,
67
+ host: "localhost",
68
+ dataDir: path.join(os.homedir(), ".pluresdb"),
69
+ webPort: 34568,
70
+ logLevel: "info",
71
+ ...options.config,
72
+ };
73
+ this.denoPath = options.denoPath || this.findDenoPath();
74
+ if (options.autoStart !== false) {
75
+ this.start();
76
+ }
77
+ }
78
+ findDenoPath() {
79
+ // Try to find Deno in common locations
80
+ const possiblePaths = [
81
+ "deno", // In PATH
82
+ path.join(os.homedir(), ".deno", "bin", "deno"),
83
+ path.join(os.homedir(), ".local", "bin", "deno"),
84
+ "/usr/local/bin/deno",
85
+ "/opt/homebrew/bin/deno",
86
+ "C:\\Users\\" + os.userInfo().username + "\\.deno\\bin\\deno.exe",
87
+ "C:\\Program Files\\deno\\deno.exe",
88
+ ];
89
+ for (const denoPath of possiblePaths) {
90
+ try {
91
+ if (fs.existsSync(denoPath) || this.isCommandAvailable(denoPath)) {
92
+ return denoPath;
93
+ }
94
+ }
95
+ catch {
96
+ // Continue to next path
97
+ }
98
+ }
99
+ throw new Error("Deno not found. Please install Deno from https://deno.land/");
100
+ }
101
+ isCommandAvailable(command) {
102
+ try {
103
+ require("child_process").execSync(`"${command}" --version`, {
104
+ stdio: "ignore",
105
+ });
106
+ return true;
107
+ }
108
+ catch {
109
+ return false;
110
+ }
111
+ }
112
+ async start() {
113
+ if (this.isRunning) {
114
+ return;
115
+ }
116
+ return new Promise((resolve, reject) => {
117
+ try {
118
+ // Ensure data directory exists
119
+ if (!fs.existsSync(this.config.dataDir)) {
120
+ fs.mkdirSync(this.config.dataDir, { recursive: true });
121
+ }
122
+ const kvPath = path.join(this.config.dataDir, "pluresdb.kv");
123
+ // Find the main.ts file
124
+ const mainTsPath = path.join(packageRoot, "src", "main.ts");
125
+ if (!fs.existsSync(mainTsPath)) {
126
+ throw new Error("PluresDB main.ts not found. Please ensure the package is properly installed.");
127
+ }
128
+ // Start the Deno process
129
+ const args = [
130
+ "run",
131
+ "-A",
132
+ "--unstable-kv",
133
+ "--no-lock",
134
+ mainTsPath,
135
+ "serve",
136
+ "--port",
137
+ this.config.port.toString(),
138
+ "--host",
139
+ this.config.host,
140
+ "--kv",
141
+ kvPath,
142
+ ];
143
+ this.process = (0, node_child_process_1.spawn)(this.denoPath, args, {
144
+ stdio: ["pipe", "pipe", "pipe"],
145
+ cwd: packageRoot,
146
+ });
147
+ this.apiUrl = `http://${this.config.host}:${this.config.port}`;
148
+ // Handle process events
149
+ this.process.on("error", (error) => {
150
+ this.emit("error", error);
151
+ reject(error);
152
+ });
153
+ this.process.on("exit", (code) => {
154
+ this.isRunning = false;
155
+ this.emit("exit", code);
156
+ });
157
+ // Wait for server to start
158
+ this.waitForServer()
159
+ .then(() => {
160
+ this.isRunning = true;
161
+ this.emit("started");
162
+ resolve();
163
+ })
164
+ .catch(reject);
165
+ // Handle stdout/stderr
166
+ this.process.stdout?.on("data", (data) => {
167
+ const output = data.toString();
168
+ this.emit("stdout", output);
169
+ });
170
+ this.process.stderr?.on("data", (data) => {
171
+ const output = data.toString();
172
+ this.emit("stderr", output);
173
+ });
174
+ }
175
+ catch (error) {
176
+ reject(error);
177
+ }
178
+ });
179
+ }
180
+ async waitForServer(timeout = 20000) {
181
+ const startTime = Date.now();
182
+ while (Date.now() - startTime < timeout) {
183
+ try {
184
+ const response = await fetch(`${this.apiUrl}/api/config`);
185
+ if (response.ok) {
186
+ return;
187
+ }
188
+ }
189
+ catch {
190
+ // Server not ready yet
191
+ }
192
+ await new Promise((resolve) => setTimeout(resolve, 100));
193
+ }
194
+ throw new Error("Server failed to start within timeout");
195
+ }
196
+ async stop() {
197
+ if (!this.isRunning || !this.process) {
198
+ return;
199
+ }
200
+ return new Promise((resolve) => {
201
+ this.process.kill("SIGTERM");
202
+ this.process.on("exit", () => {
203
+ this.isRunning = false;
204
+ this.emit("stopped");
205
+ resolve();
206
+ });
207
+ // Force kill after 5 seconds
208
+ setTimeout(() => {
209
+ if (this.process && this.isRunning) {
210
+ this.process.kill("SIGKILL");
211
+ }
212
+ resolve();
213
+ }, 5000);
214
+ });
215
+ }
216
+ getApiUrl() {
217
+ return this.apiUrl;
218
+ }
219
+ getWebUrl() {
220
+ return `http://${this.config.host}:${this.config.webPort}`;
221
+ }
222
+ isServerRunning() {
223
+ return this.isRunning;
224
+ }
225
+ // SQLite-compatible API methods
226
+ async query(sql, params = []) {
227
+ const response = await fetch(`${this.apiUrl}/api/query`, {
228
+ method: "POST",
229
+ headers: { "Content-Type": "application/json" },
230
+ body: JSON.stringify({ sql, params }),
231
+ });
232
+ if (!response.ok) {
233
+ throw new Error(`Query failed: ${response.statusText}`);
234
+ }
235
+ return response.json();
236
+ }
237
+ async put(key, value) {
238
+ const response = await fetch(`${this.apiUrl}/api/data`, {
239
+ method: "PUT",
240
+ headers: { "Content-Type": "application/json" },
241
+ body: JSON.stringify({ key, value }),
242
+ });
243
+ if (!response.ok) {
244
+ throw new Error(`Put failed: ${response.statusText}`);
245
+ }
246
+ }
247
+ async get(key) {
248
+ const response = await fetch(`${this.apiUrl}/api/data/${encodeURIComponent(key)}`);
249
+ if (!response.ok) {
250
+ if (response.status === 404) {
251
+ return null;
252
+ }
253
+ throw new Error(`Get failed: ${response.statusText}`);
254
+ }
255
+ return response.json();
256
+ }
257
+ async delete(key) {
258
+ const response = await fetch(`${this.apiUrl}/api/data/${encodeURIComponent(key)}`, {
259
+ method: "DELETE",
260
+ });
261
+ if (!response.ok) {
262
+ throw new Error(`Delete failed: ${response.statusText}`);
263
+ }
264
+ }
265
+ async vectorSearch(query, limit = 10) {
266
+ const response = await fetch(`${this.apiUrl}/api/vsearch`, {
267
+ method: "POST",
268
+ headers: { "Content-Type": "application/json" },
269
+ body: JSON.stringify({ query, limit }),
270
+ });
271
+ if (!response.ok) {
272
+ throw new Error(`Vector search failed: ${response.statusText}`);
273
+ }
274
+ return response.json();
275
+ }
276
+ async list(prefix) {
277
+ const url = prefix
278
+ ? `${this.apiUrl}/api/list?prefix=${encodeURIComponent(prefix)}`
279
+ : `${this.apiUrl}/api/list`;
280
+ const response = await fetch(url);
281
+ if (!response.ok) {
282
+ throw new Error(`List failed: ${response.statusText}`);
283
+ }
284
+ return response.json();
285
+ }
286
+ async getConfig() {
287
+ const response = await fetch(`${this.apiUrl}/api/config`);
288
+ if (!response.ok) {
289
+ throw new Error(`Get config failed: ${response.statusText}`);
290
+ }
291
+ return response.json();
292
+ }
293
+ async setConfig(config) {
294
+ const response = await fetch(`${this.apiUrl}/api/config`, {
295
+ method: "POST",
296
+ headers: { "Content-Type": "application/json" },
297
+ body: JSON.stringify(config),
298
+ });
299
+ if (!response.ok) {
300
+ throw new Error(`Set config failed: ${response.statusText}`);
301
+ }
302
+ }
303
+ // P2P API methods
304
+ async createIdentity(options) {
305
+ const response = await fetch(`${this.apiUrl}/api/identity`, {
306
+ method: "POST",
307
+ headers: { "Content-Type": "application/json" },
308
+ body: JSON.stringify(options),
309
+ });
310
+ if (!response.ok) {
311
+ throw new Error(`Create identity failed: ${response.statusText}`);
312
+ }
313
+ return response.json();
314
+ }
315
+ async searchPeers(query) {
316
+ const response = await fetch(`${this.apiUrl}/api/peers/search?q=${encodeURIComponent(query)}`);
317
+ if (!response.ok) {
318
+ throw new Error(`Search peers failed: ${response.statusText}`);
319
+ }
320
+ return response.json();
321
+ }
322
+ async shareNode(nodeId, targetPeerId, options) {
323
+ const response = await fetch(`${this.apiUrl}/api/share`, {
324
+ method: "POST",
325
+ headers: { "Content-Type": "application/json" },
326
+ body: JSON.stringify({
327
+ nodeId,
328
+ targetPeerId,
329
+ accessLevel: options?.accessLevel || "read-only",
330
+ }),
331
+ });
332
+ if (!response.ok) {
333
+ throw new Error(`Share node failed: ${response.statusText}`);
334
+ }
335
+ return response.json();
336
+ }
337
+ async acceptSharedNode(sharedNodeId) {
338
+ const response = await fetch(`${this.apiUrl}/api/share/accept`, {
339
+ method: "POST",
340
+ headers: { "Content-Type": "application/json" },
341
+ body: JSON.stringify({ sharedNodeId }),
342
+ });
343
+ if (!response.ok) {
344
+ throw new Error(`Accept shared node failed: ${response.statusText}`);
345
+ }
346
+ return response.json();
347
+ }
348
+ async addDevice(device) {
349
+ const response = await fetch(`${this.apiUrl}/api/devices`, {
350
+ method: "POST",
351
+ headers: { "Content-Type": "application/json" },
352
+ body: JSON.stringify(device),
353
+ });
354
+ if (!response.ok) {
355
+ throw new Error(`Add device failed: ${response.statusText}`);
356
+ }
357
+ return response.json();
358
+ }
359
+ async syncWithDevice(deviceId) {
360
+ const response = await fetch(`${this.apiUrl}/api/devices/sync`, {
361
+ method: "POST",
362
+ headers: { "Content-Type": "application/json" },
363
+ body: JSON.stringify({ deviceId }),
364
+ });
365
+ if (!response.ok) {
366
+ throw new Error(`Sync with device failed: ${response.statusText}`);
367
+ }
368
+ return response.json();
369
+ }
370
+ }
371
+ exports.PluresNode = PluresNode;
372
+ exports.default = PluresNode;
373
+ // SQLite-compatible API for easy migration
374
+ class SQLiteCompatibleAPI {
375
+ plures;
376
+ constructor(options) {
377
+ this.plures = new PluresNode(options);
378
+ }
379
+ async start() {
380
+ await this.plures.start();
381
+ }
382
+ async stop() {
383
+ await this.plures.stop();
384
+ }
385
+ // SQLite-compatible methods
386
+ async run(sql, params = []) {
387
+ return this.plures.query(sql, params);
388
+ }
389
+ async get(sql, params = []) {
390
+ const result = await this.plures.query(sql, params);
391
+ return result.rows?.[0] || null;
392
+ }
393
+ async all(sql, params = []) {
394
+ const result = await this.plures.query(sql, params);
395
+ return result.rows || [];
396
+ }
397
+ async exec(sql) {
398
+ return this.plures.query(sql);
399
+ }
400
+ // Additional PluresDB specific methods
401
+ async put(key, value) {
402
+ return this.plures.put(key, value);
403
+ }
404
+ async getValue(key) {
405
+ return this.plures.get(key);
406
+ }
407
+ async delete(key) {
408
+ return this.plures.delete(key);
409
+ }
410
+ async vectorSearch(query, limit = 10) {
411
+ return this.plures.vectorSearch(query, limit);
412
+ }
413
+ async list(prefix) {
414
+ return this.plures.list(prefix);
415
+ }
416
+ getApiUrl() {
417
+ return this.plures.getApiUrl();
418
+ }
419
+ getWebUrl() {
420
+ return this.plures.getWebUrl();
421
+ }
422
+ isRunning() {
423
+ return this.plures.isServerRunning();
424
+ }
425
+ // P2P API methods
426
+ async createIdentity(options) {
427
+ return this.plures.createIdentity(options);
428
+ }
429
+ async searchPeers(query) {
430
+ return this.plures.searchPeers(query);
431
+ }
432
+ async shareNode(nodeId, targetPeerId, options) {
433
+ return this.plures.shareNode(nodeId, targetPeerId, options);
434
+ }
435
+ async acceptSharedNode(sharedNodeId) {
436
+ return this.plures.acceptSharedNode(sharedNodeId);
437
+ }
438
+ async addDevice(device) {
439
+ return this.plures.addDevice(device);
440
+ }
441
+ async syncWithDevice(deviceId) {
442
+ return this.plures.syncWithDevice(deviceId);
443
+ }
444
+ }
445
+ exports.SQLiteCompatibleAPI = SQLiteCompatibleAPI;
446
+ class BetterSQLite3Statement {
447
+ database;
448
+ sql;
449
+ boundParams;
450
+ rawMode = false;
451
+ pluckMode = false;
452
+ expandMode = false;
453
+ reader;
454
+ constructor(database, sql) {
455
+ this.database = database;
456
+ this.sql = sql;
457
+ this.reader = /^\s*select/i.test(sql);
458
+ }
459
+ get databaseInstance() {
460
+ return this.database;
461
+ }
462
+ bind(...params) {
463
+ this.boundParams = (0, better_sqlite3_shared_1.normalizeParameterInput)(params);
464
+ return this;
465
+ }
466
+ raw(toggle = true) {
467
+ this.rawMode = toggle;
468
+ if (toggle) {
469
+ this.pluckMode = false;
470
+ }
471
+ return this;
472
+ }
473
+ pluck(toggle = true) {
474
+ this.pluckMode = toggle;
475
+ if (toggle) {
476
+ this.expandMode = false;
477
+ this.rawMode = false;
478
+ }
479
+ return this;
480
+ }
481
+ expand(toggle = true) {
482
+ this.expandMode = toggle;
483
+ if (toggle) {
484
+ this.pluckMode = false;
485
+ }
486
+ return this;
487
+ }
488
+ safeIntegers() {
489
+ // No-op for compatibility with better-sqlite3 API
490
+ return this;
491
+ }
492
+ async run(...params) {
493
+ const result = await this.database.executeStatement(this.sql, this.resolveParams(params));
494
+ return {
495
+ changes: typeof result.changes === "number" ? result.changes : 0,
496
+ lastInsertRowid: typeof result.lastInsertRowId === "number"
497
+ ? result.lastInsertRowId
498
+ : null,
499
+ columns: result.columns,
500
+ };
501
+ }
502
+ async get(...params) {
503
+ const rows = await this.fetchRows(params);
504
+ return rows.length > 0 ? rows[0] : undefined;
505
+ }
506
+ async all(...params) {
507
+ return await this.fetchRows(params);
508
+ }
509
+ async *iterate(...params) {
510
+ const rows = await this.fetchRows(params);
511
+ for (const row of rows) {
512
+ yield row;
513
+ }
514
+ }
515
+ async columns() {
516
+ const result = await this.database.executeStatement(this.sql, this.boundParams ?? []);
517
+ return result.columns ?? [];
518
+ }
519
+ resolveParams(params) {
520
+ const normalized = (0, better_sqlite3_shared_1.normalizeParameterInput)(params);
521
+ if (normalized.length > 0) {
522
+ return normalized;
523
+ }
524
+ return this.boundParams ? [...this.boundParams] : [];
525
+ }
526
+ async fetchRows(params) {
527
+ const result = await this.database.executeStatement(this.sql, this.resolveParams(params));
528
+ return this.transformRows(result);
529
+ }
530
+ transformRows(result) {
531
+ return result.rows.map((row) => (0, better_sqlite3_shared_1.shapeRow)(row, result.columns, {
532
+ raw: this.rawMode,
533
+ pluck: this.pluckMode,
534
+ expand: this.expandMode,
535
+ }));
536
+ }
537
+ }
538
+ exports.BetterSQLite3Statement = BetterSQLite3Statement;
539
+ class BetterSQLite3Database {
540
+ options;
541
+ plures;
542
+ filename;
543
+ verbose;
544
+ openPromise = null;
545
+ opened = false;
546
+ constructor(filenameOrOptions, maybeOptions) {
547
+ const { filename, options } = this.resolveOptions(filenameOrOptions, maybeOptions);
548
+ this.filename = filename;
549
+ this.options = options;
550
+ this.verbose = options.verbose;
551
+ const config = { ...options.config };
552
+ if (!config.dataDir) {
553
+ const baseDir = options.memory
554
+ ? path.join(os.tmpdir(), "pluresdb", "better-sqlite3-memory")
555
+ : path.join(os.homedir(), ".pluresdb", "better-sqlite3");
556
+ const safeName = (0, better_sqlite3_shared_1.sanitizeDataDirName)(filename === ":memory:" ? "memory" : filename);
557
+ config.dataDir = path.join(baseDir, safeName);
558
+ }
559
+ this.plures = new PluresNode({
560
+ config,
561
+ denoPath: options.denoPath,
562
+ autoStart: false,
563
+ });
564
+ if (options.autoStart !== false) {
565
+ void this.open();
566
+ }
567
+ }
568
+ get name() {
569
+ return this.filename;
570
+ }
571
+ get isOpen() {
572
+ return this.opened;
573
+ }
574
+ async open() {
575
+ await this.ensureOpen();
576
+ return this;
577
+ }
578
+ async close() {
579
+ if (!this.opened && !this.openPromise) {
580
+ return;
581
+ }
582
+ await this.plures.stop();
583
+ this.opened = false;
584
+ this.openPromise = null;
585
+ }
586
+ prepare(sql) {
587
+ if (!this.opened) {
588
+ throw new Error("Database is not open. Call await db.open() before preparing statements.");
589
+ }
590
+ return new BetterSQLite3Statement(this, sql);
591
+ }
592
+ async exec(sql) {
593
+ await this.ensureOpen();
594
+ for (const statement of (0, better_sqlite3_shared_1.splitSqlStatements)(sql)) {
595
+ await this.executeStatement(statement, []);
596
+ }
597
+ return this;
598
+ }
599
+ transaction(fn) {
600
+ return async (...args) => {
601
+ await this.ensureOpen();
602
+ await this.executeStatement("BEGIN", []);
603
+ try {
604
+ const result = await fn(...args);
605
+ await this.executeStatement("COMMIT", []);
606
+ return result;
607
+ }
608
+ catch (error) {
609
+ await this.executeStatement("ROLLBACK", []).catch(() => undefined);
610
+ throw error;
611
+ }
612
+ };
613
+ }
614
+ async pragma(statement) {
615
+ const sql = /^\s*pragma/i.test(statement)
616
+ ? statement
617
+ : `PRAGMA ${statement}`;
618
+ const result = await this.executeStatement(sql, []);
619
+ return result.rows;
620
+ }
621
+ defaultSafeIntegers() {
622
+ return this;
623
+ }
624
+ unsafeMode() {
625
+ return this;
626
+ }
627
+ async executeStatement(sql, params) {
628
+ await this.ensureOpen();
629
+ const normalizedParams = (0, better_sqlite3_shared_1.normalizeParameterInput)(params);
630
+ const raw = await this.plures.query(sql, normalizedParams);
631
+ return (0, better_sqlite3_shared_1.normalizeQueryResult)(raw);
632
+ }
633
+ async ensureOpen() {
634
+ if (this.opened) {
635
+ return;
636
+ }
637
+ if (!this.openPromise) {
638
+ this.openPromise = (async () => {
639
+ await this.plures.start();
640
+ this.opened = true;
641
+ if (this.verbose) {
642
+ this.verbose(`PluresDB ready for better-sqlite3 compatibility (${this.filename})`);
643
+ }
644
+ })();
645
+ }
646
+ await this.openPromise;
647
+ }
648
+ resolveOptions(filenameOrOptions, maybeOptions) {
649
+ if (typeof filenameOrOptions === "string") {
650
+ return {
651
+ filename: filenameOrOptions,
652
+ options: { ...(maybeOptions ?? {}), filename: filenameOrOptions },
653
+ };
654
+ }
655
+ const options = filenameOrOptions ?? {};
656
+ const filename = options.filename ?? ":memory:";
657
+ return { filename, options: { ...options, filename } };
658
+ }
659
+ }
660
+ exports.BetterSQLite3Database = BetterSQLite3Database;
661
+ __exportStar(require("./types/node-types"), exports);
662
+ var extension_1 = require("./vscode/extension");
663
+ Object.defineProperty(exports, "createPluresExtension", { enumerable: true, get: function () { return extension_1.createPluresExtension; } });
664
+ Object.defineProperty(exports, "PluresVSCodeExtension", { enumerable: true, get: function () { return extension_1.PluresVSCodeExtension; } });
665
+ //# sourceMappingURL=node-index.js.map