js-bao 0.2.10 → 0.2.12
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/README.md +174 -0
- package/dist/BaseModel-5YQCROYE.js +17 -0
- package/dist/BaseModel-5YQCROYE.js.map +1 -0
- package/dist/BaseModel-FCNWDJBH.js +17 -0
- package/dist/BaseModel-FCNWDJBH.js.map +1 -0
- package/dist/BrowserDatabaseFactory-PXOTK2DQ.js +119 -0
- package/dist/BrowserDatabaseFactory-PXOTK2DQ.js.map +1 -0
- package/dist/BrowserDatabaseFactory-WD4VX2VZ.js +119 -0
- package/dist/BrowserDatabaseFactory-WD4VX2VZ.js.map +1 -0
- package/dist/IncludeResolver-RCKQGNPZ.js +385 -0
- package/dist/IncludeResolver-RCKQGNPZ.js.map +1 -0
- package/dist/IncludeResolver-WGSQDMS7.js +385 -0
- package/dist/IncludeResolver-WGSQDMS7.js.map +1 -0
- package/dist/NodeDatabaseFactory-J4Z36UF3.js +165 -0
- package/dist/NodeDatabaseFactory-J4Z36UF3.js.map +1 -0
- package/dist/NodeDatabaseFactory-QIEKAXBM.js +10 -0
- package/dist/NodeDatabaseFactory-QIEKAXBM.js.map +1 -0
- package/dist/NodeSqliteEngine-HJSAYE4E.js +383 -0
- package/dist/NodeSqliteEngine-HJSAYE4E.js.map +1 -0
- package/dist/NodeSqliteEngine-I5SLWLME.js +383 -0
- package/dist/NodeSqliteEngine-I5SLWLME.js.map +1 -0
- package/dist/browser.cjs +3779 -3370
- package/dist/browser.d.cts +18 -1
- package/dist/browser.d.ts +18 -1
- package/dist/browser.js +3750 -3341
- package/dist/chunk-3PZWHUZO.js +4153 -0
- package/dist/chunk-3PZWHUZO.js.map +1 -0
- package/dist/chunk-53MS4MN7.js +373 -0
- package/dist/chunk-53MS4MN7.js.map +1 -0
- package/dist/chunk-65G2P4GL.js +709 -0
- package/dist/chunk-65G2P4GL.js.map +1 -0
- package/dist/chunk-6UX3YSCW.js +4151 -0
- package/dist/chunk-6UX3YSCW.js.map +1 -0
- package/dist/chunk-DANSD6BE.js +709 -0
- package/dist/chunk-DANSD6BE.js.map +1 -0
- package/dist/chunk-DF3JEQXA.js +373 -0
- package/dist/chunk-DF3JEQXA.js.map +1 -0
- package/dist/chunk-GO3APTPX.js +61 -0
- package/dist/chunk-GO3APTPX.js.map +1 -0
- package/dist/chunk-ID4U6IQC.js +53 -0
- package/dist/chunk-ID4U6IQC.js.map +1 -0
- package/dist/chunk-RQVS3LVL.js +165 -0
- package/dist/chunk-RQVS3LVL.js.map +1 -0
- package/dist/client.cjs +837 -0
- package/dist/client.d.cts +1101 -0
- package/dist/client.d.ts +1101 -0
- package/dist/client.js +806 -0
- package/dist/cloudflare-do.cjs +3637 -0
- package/dist/cloudflare-do.d.cts +1366 -0
- package/dist/cloudflare-do.d.ts +1366 -0
- package/dist/cloudflare-do.js +3614 -0
- package/dist/cloudflare.cjs +1048 -0
- package/dist/cloudflare.d.cts +1381 -0
- package/dist/cloudflare.d.ts +1381 -0
- package/dist/cloudflare.js +1017 -0
- package/dist/codegen.cjs +259 -18
- package/dist/environment-TOTQICSE.js +17 -0
- package/dist/environment-TOTQICSE.js.map +1 -0
- package/dist/index.cjs +1906 -1493
- package/dist/index.d.cts +19 -2
- package/dist/index.d.ts +19 -2
- package/dist/index.js +1871 -1458
- package/dist/node.cjs +4779 -4366
- package/dist/node.d.cts +18 -1
- package/dist/node.d.ts +18 -1
- package/dist/node.js +4602 -4189
- package/package.json +41 -12
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Logger,
|
|
3
|
+
quoteIdentifier
|
|
4
|
+
} from "./chunk-6UX3YSCW.js";
|
|
5
|
+
|
|
6
|
+
// src/engines/SqljsEngine.ts
|
|
7
|
+
import initSqlJs from "sql.js";
|
|
8
|
+
import { Mutex } from "async-mutex";
|
|
9
|
+
var SQL_WASM_URL = "/sql-wasm.wasm";
|
|
10
|
+
var TransactionalSQLJSOperations = class {
|
|
11
|
+
db;
|
|
12
|
+
engine;
|
|
13
|
+
// For helper methods, changed type to SqljsEngine
|
|
14
|
+
constructor(db, engine) {
|
|
15
|
+
this.db = db;
|
|
16
|
+
this.engine = engine;
|
|
17
|
+
}
|
|
18
|
+
async insert(modelName, data) {
|
|
19
|
+
if (!this.db) throw new Error("SQL.js DB not available in transaction");
|
|
20
|
+
const tableName = this.engine.getTableName(modelName);
|
|
21
|
+
const quotedTableName = quoteIdentifier(tableName);
|
|
22
|
+
const columns = Object.keys(data);
|
|
23
|
+
const quotedColumns = columns.map((column) => quoteIdentifier(column));
|
|
24
|
+
const placeholders = columns.map(() => "?").join(", ");
|
|
25
|
+
const values = Object.values(data);
|
|
26
|
+
const insertSQL = `INSERT OR REPLACE INTO ${quotedTableName} (${quotedColumns.join(
|
|
27
|
+
", "
|
|
28
|
+
)}) VALUES (${placeholders});`;
|
|
29
|
+
this.db.run(insertSQL, values);
|
|
30
|
+
}
|
|
31
|
+
async delete(modelName, id) {
|
|
32
|
+
if (!this.db) throw new Error("SQL.js DB not available in transaction");
|
|
33
|
+
const tableName = this.engine.getTableName(modelName);
|
|
34
|
+
const deleteSQL = `DELETE FROM ${quoteIdentifier(tableName)} WHERE ${quoteIdentifier(
|
|
35
|
+
"id"
|
|
36
|
+
)} = ?;`;
|
|
37
|
+
this.db.run(deleteSQL, [id]);
|
|
38
|
+
}
|
|
39
|
+
async query(sql, params) {
|
|
40
|
+
if (!this.db) throw new Error("SQL.js DB not available in transaction");
|
|
41
|
+
const results = [];
|
|
42
|
+
const stmt = this.db.prepare(sql);
|
|
43
|
+
if (params) {
|
|
44
|
+
stmt.bind(params);
|
|
45
|
+
}
|
|
46
|
+
while (stmt.step()) {
|
|
47
|
+
results.push(stmt.getAsObject());
|
|
48
|
+
}
|
|
49
|
+
stmt.free();
|
|
50
|
+
return results;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
var SqljsEngine = class _SqljsEngine {
|
|
54
|
+
static SQL = null;
|
|
55
|
+
db = null;
|
|
56
|
+
tableNames = /* @__PURE__ */ new Set();
|
|
57
|
+
numOpenTransactions = 0;
|
|
58
|
+
mutex = new Mutex();
|
|
59
|
+
readyPromise;
|
|
60
|
+
constructor(options) {
|
|
61
|
+
Logger.debug("[SqljsEngine] Constructor called. Initializing...");
|
|
62
|
+
this.numOpenTransactions = 0;
|
|
63
|
+
this.readyPromise = this.initialize(options);
|
|
64
|
+
}
|
|
65
|
+
// Make readyPromise accessible if DatabaseFactory wants to await it,
|
|
66
|
+
// though direct call to initialize from constructor and awaiting it is simpler here.
|
|
67
|
+
async ensureReady() {
|
|
68
|
+
return this.readyPromise;
|
|
69
|
+
}
|
|
70
|
+
async initialize(engineOptions) {
|
|
71
|
+
Logger.info("[SqljsEngine] Initializing SQL.js engine...");
|
|
72
|
+
try {
|
|
73
|
+
if (!_SqljsEngine.SQL) {
|
|
74
|
+
const locateFileConfig = engineOptions?.locateFile || ((_file) => engineOptions?.wasmURL || SQL_WASM_URL);
|
|
75
|
+
Logger.debug(
|
|
76
|
+
"[SqljsEngine] Attempting to load SQL.js WASM from:",
|
|
77
|
+
locateFileConfig("sql-wasm.wasm")
|
|
78
|
+
);
|
|
79
|
+
_SqljsEngine.SQL = await initSqlJs({
|
|
80
|
+
locateFile: locateFileConfig
|
|
81
|
+
});
|
|
82
|
+
Logger.info("[SqljsEngine] SQL.js WASM loaded successfully.");
|
|
83
|
+
}
|
|
84
|
+
this.db = new _SqljsEngine.SQL.Database();
|
|
85
|
+
Logger.info("[SqljsEngine] SQL.js Database initialized in memory.");
|
|
86
|
+
this.updateTableNames();
|
|
87
|
+
} catch (error) {
|
|
88
|
+
Logger.error("[SqljsEngine] Error during SQL.js initialization:", error);
|
|
89
|
+
throw error;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
updateTableNames() {
|
|
93
|
+
if (!this.db) return;
|
|
94
|
+
const results = this.db.exec(
|
|
95
|
+
"SELECT name FROM sqlite_master WHERE type='table';"
|
|
96
|
+
);
|
|
97
|
+
this.tableNames.clear();
|
|
98
|
+
if (results.length > 0 && results[0].values) {
|
|
99
|
+
results[0].values.forEach(
|
|
100
|
+
(row) => this.tableNames.add(row[0])
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
getTableName(modelName) {
|
|
105
|
+
return `model_${modelName.toLowerCase()}`;
|
|
106
|
+
}
|
|
107
|
+
mapTypeToSQL(type) {
|
|
108
|
+
switch (type.toLowerCase()) {
|
|
109
|
+
case "string":
|
|
110
|
+
return "TEXT";
|
|
111
|
+
case "number":
|
|
112
|
+
return "REAL";
|
|
113
|
+
case "boolean":
|
|
114
|
+
return "INTEGER";
|
|
115
|
+
case "date":
|
|
116
|
+
return "TEXT";
|
|
117
|
+
default:
|
|
118
|
+
return "TEXT";
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
async createTable(modelName, schema, _options) {
|
|
122
|
+
await this.readyPromise;
|
|
123
|
+
if (!this.db) throw new Error("SQL.js not initialized for createTable");
|
|
124
|
+
const tableName = this.getTableName(modelName);
|
|
125
|
+
const quotedTableName = quoteIdentifier(tableName);
|
|
126
|
+
const idColumn = quoteIdentifier("id");
|
|
127
|
+
const typeColumn = quoteIdentifier("type");
|
|
128
|
+
if (this.tableNames.has(tableName)) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const columns = Array.from(schema.entries()).filter(([field]) => field !== "id" && field !== "type").map(
|
|
132
|
+
([field, fieldOptions]) => `${quoteIdentifier(field)} ${this.mapTypeToSQL(fieldOptions.type)}`
|
|
133
|
+
);
|
|
134
|
+
const metadataColumns = [
|
|
135
|
+
`${quoteIdentifier("_meta_doc_id")} TEXT`,
|
|
136
|
+
`${quoteIdentifier("_meta_permission_hint")} TEXT`
|
|
137
|
+
];
|
|
138
|
+
const createTableSQL = `CREATE TABLE IF NOT EXISTS ${quotedTableName} (
|
|
139
|
+
${idColumn} TEXT PRIMARY KEY,
|
|
140
|
+
${typeColumn} TEXT,
|
|
141
|
+
${columns.join(", ")}${columns.length > 0 ? ", " : ""}${metadataColumns.join(", ")}
|
|
142
|
+
);`;
|
|
143
|
+
this.db.run(createTableSQL);
|
|
144
|
+
for (const [field, fieldOptions] of schema.entries()) {
|
|
145
|
+
if (fieldOptions && fieldOptions.indexed && field !== "id") {
|
|
146
|
+
const indexName = `idx_${tableName}_${field}`;
|
|
147
|
+
const createIndexSQL = `CREATE INDEX IF NOT EXISTS ${quoteIdentifier(
|
|
148
|
+
indexName
|
|
149
|
+
)} ON ${quotedTableName} (${quoteIdentifier(field)});`;
|
|
150
|
+
this.db.run(createIndexSQL);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
const docIdIndexName = `idx_${tableName}_meta_doc_id`;
|
|
154
|
+
const docIdIndexSQL = `CREATE INDEX IF NOT EXISTS ${quoteIdentifier(
|
|
155
|
+
docIdIndexName
|
|
156
|
+
)} ON ${quotedTableName} (${quoteIdentifier("_meta_doc_id")});`;
|
|
157
|
+
this.db.run(docIdIndexSQL);
|
|
158
|
+
this.updateTableNames();
|
|
159
|
+
}
|
|
160
|
+
async createStringSetJunctionTable(modelName, fieldName) {
|
|
161
|
+
await this.readyPromise;
|
|
162
|
+
if (!this.db)
|
|
163
|
+
throw new Error(
|
|
164
|
+
"SQL.js not initialized for createStringSetJunctionTable"
|
|
165
|
+
);
|
|
166
|
+
const junctionTableName = `${this.getTableName(modelName)}_${fieldName}`;
|
|
167
|
+
const quotedJunctionTable = quoteIdentifier(junctionTableName);
|
|
168
|
+
const foreignKeyColumn = `${modelName.toLowerCase()}_id`;
|
|
169
|
+
const quotedForeignKey = quoteIdentifier(foreignKeyColumn);
|
|
170
|
+
const quotedIdColumn = quoteIdentifier("id");
|
|
171
|
+
const quotedValueColumn = quoteIdentifier("value");
|
|
172
|
+
if (this.tableNames.has(junctionTableName)) {
|
|
173
|
+
Logger.debug(
|
|
174
|
+
`[SqljsEngine] StringSet junction table ${junctionTableName} already exists, skipping creation.`
|
|
175
|
+
);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
const createTableSQL = `CREATE TABLE IF NOT EXISTS ${quotedJunctionTable} (
|
|
179
|
+
${quotedIdColumn} TEXT PRIMARY KEY,
|
|
180
|
+
${quotedForeignKey} TEXT NOT NULL,
|
|
181
|
+
${quotedValueColumn} TEXT NOT NULL,
|
|
182
|
+
UNIQUE(${quotedForeignKey}, ${quotedValueColumn})
|
|
183
|
+
);`;
|
|
184
|
+
Logger.info(
|
|
185
|
+
`[SqljsEngine] Creating StringSet junction table ${junctionTableName} for ${modelName}.${fieldName}`
|
|
186
|
+
);
|
|
187
|
+
this.db.run(createTableSQL);
|
|
188
|
+
const indexName = `idx_${junctionTableName}_${modelName.toLowerCase()}_id_value`;
|
|
189
|
+
const indexSQL = `CREATE INDEX IF NOT EXISTS ${quoteIdentifier(
|
|
190
|
+
indexName
|
|
191
|
+
)} ON ${quotedJunctionTable} (${quotedForeignKey}, ${quotedValueColumn});`;
|
|
192
|
+
this.db.run(indexSQL);
|
|
193
|
+
this.updateTableNames();
|
|
194
|
+
Logger.info(
|
|
195
|
+
`[SqljsEngine] StringSet junction table ${junctionTableName} created successfully.`
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
async insertStringSetValues(modelName, fieldName, recordId, values) {
|
|
199
|
+
await this.readyPromise;
|
|
200
|
+
if (!this.db)
|
|
201
|
+
throw new Error("SQL.js not initialized for insertStringSetValues");
|
|
202
|
+
if (values.length === 0) return;
|
|
203
|
+
const junctionTableName = `${this.getTableName(modelName)}_${fieldName}`;
|
|
204
|
+
const modelIdColumn = `${modelName.toLowerCase()}_id`;
|
|
205
|
+
const quotedJunctionTable = quoteIdentifier(junctionTableName);
|
|
206
|
+
const quotedIdColumn = quoteIdentifier("id");
|
|
207
|
+
const quotedModelIdColumn = quoteIdentifier(modelIdColumn);
|
|
208
|
+
const quotedValueColumn = quoteIdentifier("value");
|
|
209
|
+
for (const value of values) {
|
|
210
|
+
const insertSQL = `INSERT OR IGNORE INTO ${quotedJunctionTable} (${quotedIdColumn}, ${quotedModelIdColumn}, ${quotedValueColumn}) VALUES (?, ?, ?);`;
|
|
211
|
+
const junctionId = `${recordId}_${value}`;
|
|
212
|
+
this.db.run(insertSQL, [junctionId, recordId, value]);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
async removeStringSetValues(modelName, fieldName, recordId, values) {
|
|
216
|
+
await this.readyPromise;
|
|
217
|
+
if (!this.db)
|
|
218
|
+
throw new Error("SQL.js not initialized for removeStringSetValues");
|
|
219
|
+
if (values.length === 0) return;
|
|
220
|
+
const junctionTableName = `${this.getTableName(modelName)}_${fieldName}`;
|
|
221
|
+
const modelIdColumn = `${modelName.toLowerCase()}_id`;
|
|
222
|
+
const quotedJunctionTable = quoteIdentifier(junctionTableName);
|
|
223
|
+
const quotedModelIdColumn = quoteIdentifier(modelIdColumn);
|
|
224
|
+
const quotedValueColumn = quoteIdentifier("value");
|
|
225
|
+
for (const value of values) {
|
|
226
|
+
const deleteSQL = `DELETE FROM ${quotedJunctionTable} WHERE ${quotedModelIdColumn} = ? AND ${quotedValueColumn} = ?;`;
|
|
227
|
+
this.db.run(deleteSQL, [recordId, value]);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
async insert(modelName, data) {
|
|
231
|
+
await this.readyPromise;
|
|
232
|
+
if (!this.db) throw new Error("SQL.js not initialized for insert");
|
|
233
|
+
const tableName = this.getTableName(modelName);
|
|
234
|
+
const quotedTableName = quoteIdentifier(tableName);
|
|
235
|
+
const columns = Object.keys(data);
|
|
236
|
+
const quotedColumns = columns.map((column) => quoteIdentifier(column));
|
|
237
|
+
const placeholders = columns.map(() => "?").join(", ");
|
|
238
|
+
const values = Object.values(data);
|
|
239
|
+
const insertSQL = `INSERT OR REPLACE INTO ${quotedTableName} (${quotedColumns.join(
|
|
240
|
+
", "
|
|
241
|
+
)}) VALUES (${placeholders});`;
|
|
242
|
+
this.db.run(insertSQL, values);
|
|
243
|
+
}
|
|
244
|
+
async delete(modelName, id) {
|
|
245
|
+
await this.readyPromise;
|
|
246
|
+
if (!this.db) throw new Error("SQL.js not initialized for delete");
|
|
247
|
+
const tableName = this.getTableName(modelName);
|
|
248
|
+
const deleteSQL = `DELETE FROM ${quoteIdentifier(tableName)} WHERE ${quoteIdentifier(
|
|
249
|
+
"id"
|
|
250
|
+
)} = ?;`;
|
|
251
|
+
this.db.run(deleteSQL, [id]);
|
|
252
|
+
}
|
|
253
|
+
async deleteByDocumentId(modelName, docId) {
|
|
254
|
+
await this.readyPromise;
|
|
255
|
+
if (!this.db)
|
|
256
|
+
throw new Error("SQL.js not initialized for deleteByDocumentId");
|
|
257
|
+
const tableName = this.getTableName(modelName);
|
|
258
|
+
const quotedTableName = quoteIdentifier(tableName);
|
|
259
|
+
if (!this.tableNames.has(tableName)) {
|
|
260
|
+
Logger.debug(
|
|
261
|
+
`[SqljsEngine] Skipping deleteByDocumentId for ${tableName}; table does not exist.`
|
|
262
|
+
);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
const deleteSQL = `DELETE FROM ${quotedTableName} WHERE ${quoteIdentifier(
|
|
266
|
+
"_meta_doc_id"
|
|
267
|
+
)} = ?;`;
|
|
268
|
+
this.db.run(deleteSQL, [docId]);
|
|
269
|
+
for (const existingTableName of this.tableNames) {
|
|
270
|
+
if (existingTableName.startsWith(`${tableName}_`)) {
|
|
271
|
+
const quotedExistingTable = quoteIdentifier(existingTableName);
|
|
272
|
+
const quotedForeignKey = quoteIdentifier(`${modelName.toLowerCase()}_id`);
|
|
273
|
+
const junctionDeleteSQL = `DELETE FROM ${quotedExistingTable} WHERE ${quotedForeignKey} IN (
|
|
274
|
+
SELECT ${quoteIdentifier("id")} FROM ${quotedTableName} WHERE ${quoteIdentifier(
|
|
275
|
+
"_meta_doc_id"
|
|
276
|
+
)} = ?
|
|
277
|
+
);`;
|
|
278
|
+
try {
|
|
279
|
+
this.db.run(junctionDeleteSQL, [docId]);
|
|
280
|
+
const rowsCleared = this.db.getRowsModified();
|
|
281
|
+
Logger.info(
|
|
282
|
+
`[SqljsEngine] Cleared junction table ${existingTableName} for document ${docId}; removed ${rowsCleared} rows.`
|
|
283
|
+
);
|
|
284
|
+
} catch (error) {
|
|
285
|
+
Logger.warn(
|
|
286
|
+
`[SqljsEngine] Warning: Could not clean up junction table ${existingTableName}:`,
|
|
287
|
+
error
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
async query(sql, params) {
|
|
294
|
+
await this.readyPromise;
|
|
295
|
+
if (!this.db) throw new Error("SQL.js not initialized for query");
|
|
296
|
+
const results = [];
|
|
297
|
+
const stmt = this.db.prepare(sql);
|
|
298
|
+
if (params) {
|
|
299
|
+
stmt.bind(params);
|
|
300
|
+
}
|
|
301
|
+
while (stmt.step()) {
|
|
302
|
+
results.push(stmt.getAsObject());
|
|
303
|
+
}
|
|
304
|
+
stmt.free();
|
|
305
|
+
return results;
|
|
306
|
+
}
|
|
307
|
+
async withTransaction(callback) {
|
|
308
|
+
await this.readyPromise;
|
|
309
|
+
if (!this.db)
|
|
310
|
+
throw new Error("SQL.js Database instance not available for transaction");
|
|
311
|
+
let transactionStartedHere = false;
|
|
312
|
+
await this.mutex.runExclusive(async () => {
|
|
313
|
+
if (this.numOpenTransactions === 0) {
|
|
314
|
+
if (!this.db) throw new Error("SQL.js DB not available for BEGIN");
|
|
315
|
+
this.db.run("BEGIN TRANSACTION");
|
|
316
|
+
transactionStartedHere = true;
|
|
317
|
+
}
|
|
318
|
+
this.numOpenTransactions++;
|
|
319
|
+
});
|
|
320
|
+
const transactionalOps = new TransactionalSQLJSOperations(this.db, this);
|
|
321
|
+
try {
|
|
322
|
+
const result = await callback(transactionalOps);
|
|
323
|
+
await this.mutex.runExclusive(async () => {
|
|
324
|
+
this.numOpenTransactions--;
|
|
325
|
+
if (this.numOpenTransactions === 0) {
|
|
326
|
+
if (!this.db) throw new Error("SQL.js DB not available for COMMIT");
|
|
327
|
+
this.db.run("COMMIT");
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
return result;
|
|
331
|
+
} catch (error) {
|
|
332
|
+
Logger.error("[SqljsEngine] Error in transaction, rolling back:", error);
|
|
333
|
+
await this.mutex.runExclusive(async () => {
|
|
334
|
+
if (this.db && this.numOpenTransactions > 0 && transactionStartedHere) {
|
|
335
|
+
try {
|
|
336
|
+
if (!this.db)
|
|
337
|
+
throw new Error("SQL.js DB not available for ROLLBACK");
|
|
338
|
+
this.db.run("ROLLBACK");
|
|
339
|
+
} catch (rollbackError) {
|
|
340
|
+
Logger.error("[SqljsEngine] Error during ROLLBACK:", rollbackError);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
this.numOpenTransactions = 0;
|
|
344
|
+
});
|
|
345
|
+
throw error;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
async close() {
|
|
349
|
+
await this.readyPromise;
|
|
350
|
+
if (this.db) {
|
|
351
|
+
this.db.close();
|
|
352
|
+
this.db = null;
|
|
353
|
+
_SqljsEngine.SQL = null;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
async getTableSchema(_tableName) {
|
|
357
|
+
return void 0;
|
|
358
|
+
}
|
|
359
|
+
async destroy() {
|
|
360
|
+
if (this.db) {
|
|
361
|
+
this.db.close();
|
|
362
|
+
Logger.info("[SqljsEngine] Database closed.");
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
getLastErrorMessage() {
|
|
366
|
+
return void 0;
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
export {
|
|
371
|
+
SqljsEngine
|
|
372
|
+
};
|
|
373
|
+
//# sourceMappingURL=chunk-53MS4MN7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/engines/SqljsEngine.ts"],"sourcesContent":["import initSqlJs, {\n type SqlJsStatic,\n type Database as SQLJsDB,\n type SqlValue,\n} from \"sql.js\";\nimport {\n DatabaseEngine,\n ITransactionalDatabaseOperations,\n} from \"./DatabaseEngine\"; // Adjusted path\nimport { ModelOptions } from \"../types/ormTypes\"; // Adjusted path\nimport { Logger } from \"../models/BaseModel\"; // Import Logger\nimport { Mutex } from \"async-mutex\";\nimport { quoteIdentifier } from \"../utils/sql\";\n\nexport interface SQLJSEngineOptions {\n wasmURL?: string;\n locateFile?: (file: string) => string;\n}\n\n// IMPORTANT: For this engine to work, the sql-wasm.wasm file must be publicly available.\n// By default, this engine expects it at the root path: /sql-wasm.wasm\n// Library users need to ensure their bundler (Webpack, Vite, etc.) makes this file\n// available at the expected location, or this path needs to be configurable.\n// For Vite, placing sql-wasm.wasm in the `public` directory usually works.\n// Future enhancement: Allow passing wasmURL or locateFile via DatabaseConfig.options.\nconst SQL_WASM_URL = \"/sql-wasm.wasm\";\n\n// Helper class for operations within a SQL.js transaction\nclass TransactionalSQLJSOperations implements ITransactionalDatabaseOperations {\n private db: SQLJsDB;\n private engine: SqljsEngine; // For helper methods, changed type to SqljsEngine\n\n constructor(db: SQLJsDB, engine: SqljsEngine) {\n // Changed type to SqljsEngine\n this.db = db;\n this.engine = engine;\n }\n\n async insert(modelName: string, data: any): Promise<void> {\n if (!this.db) throw new Error(\"SQL.js DB not available in transaction\");\n const tableName = this.engine.getTableName(modelName);\n const quotedTableName = quoteIdentifier(tableName);\n const columns = Object.keys(data);\n const quotedColumns = columns.map((column) => quoteIdentifier(column));\n const placeholders = columns.map(() => \"?\").join(\", \");\n const values = Object.values(data);\n const insertSQL = `INSERT OR REPLACE INTO ${quotedTableName} (${quotedColumns.join(\n \", \"\n )}) VALUES (${placeholders});`;\n this.db.run(insertSQL, values as SqlValue[]);\n }\n\n async delete(modelName: string, id: string): Promise<void> {\n if (!this.db) throw new Error(\"SQL.js DB not available in transaction\");\n const tableName = this.engine.getTableName(modelName);\n const deleteSQL = `DELETE FROM ${quoteIdentifier(tableName)} WHERE ${quoteIdentifier(\n \"id\"\n )} = ?;`;\n this.db.run(deleteSQL, [id as SqlValue]);\n }\n\n async query<T extends Record<string, any>>(\n sql: string,\n params?: any[]\n ): Promise<T[]> {\n if (!this.db) throw new Error(\"SQL.js DB not available in transaction\");\n // console.log(\"[TransactionalSQLJSOps] Executing SQL:\", sql, params);\n const results: T[] = [];\n const stmt = this.db.prepare(sql);\n if (params) {\n stmt.bind(params as SqlValue[]);\n }\n while (stmt.step()) {\n results.push(stmt.getAsObject() as T);\n }\n stmt.free();\n return results;\n }\n}\n\nexport class SqljsEngine implements DatabaseEngine {\n private static SQL: SqlJsStatic | null = null;\n private db: SQLJsDB | null = null;\n private tableNames: Set<string> = new Set();\n private numOpenTransactions: number = 0;\n private mutex: Mutex = new Mutex();\n private readyPromise: Promise<void>;\n\n constructor(options?: SQLJSEngineOptions) {\n Logger.debug(\"[SqljsEngine] Constructor called. Initializing...\");\n this.numOpenTransactions = 0;\n // The traditional getInstance pattern for singleton async init is tricky with a factory.\n // The factory will create the instance, and we initialize here.\n // The factory should await this readyPromise.\n this.readyPromise = this.initialize(options);\n }\n\n // Make readyPromise accessible if DatabaseFactory wants to await it,\n // though direct call to initialize from constructor and awaiting it is simpler here.\n public async ensureReady(): Promise<void> {\n return this.readyPromise;\n }\n\n private async initialize(engineOptions?: SQLJSEngineOptions): Promise<void> {\n Logger.info(\"[SqljsEngine] Initializing SQL.js engine...\");\n try {\n if (!SqljsEngine.SQL) {\n const locateFileConfig =\n engineOptions?.locateFile ||\n ((_file: string) => engineOptions?.wasmURL || SQL_WASM_URL);\n Logger.debug(\n \"[SqljsEngine] Attempting to load SQL.js WASM from:\",\n locateFileConfig(\"sql-wasm.wasm\")\n );\n SqljsEngine.SQL = await initSqlJs({\n locateFile: locateFileConfig,\n });\n Logger.info(\"[SqljsEngine] SQL.js WASM loaded successfully.\");\n }\n this.db = new SqljsEngine.SQL.Database();\n Logger.info(\"[SqljsEngine] SQL.js Database initialized in memory.\");\n this.updateTableNames();\n } catch (error) {\n Logger.error(\"[SqljsEngine] Error during SQL.js initialization:\", error);\n throw error; // Re-throw to fail fast if WASM can't load\n }\n }\n\n private updateTableNames(): void {\n if (!this.db) return;\n const results = this.db.exec(\n \"SELECT name FROM sqlite_master WHERE type='table';\"\n );\n this.tableNames.clear();\n if (results.length > 0 && results[0].values) {\n results[0].values.forEach((row: any) =>\n this.tableNames.add(row[0] as string)\n );\n }\n // console.log(\"[SqljsEngine] Existing tables:\", Array.from(this.tableNames));\n }\n\n public getTableName(modelName: string): string {\n return `model_${modelName.toLowerCase()}`;\n }\n\n private mapTypeToSQL(type: string): string {\n switch (type.toLowerCase()) {\n case \"string\":\n return \"TEXT\";\n case \"number\":\n return \"REAL\";\n case \"boolean\":\n return \"INTEGER\";\n case \"date\":\n return \"TEXT\";\n default:\n return \"TEXT\";\n }\n }\n\n async createTable(\n modelName: string,\n schema: Map<string, any>,\n _options: ModelOptions // options from model decorator, _ to indicate not directly used here\n ): Promise<void> {\n await this.readyPromise; // Ensure initialization is complete\n if (!this.db) throw new Error(\"SQL.js not initialized for createTable\");\n const tableName = this.getTableName(modelName);\n const quotedTableName = quoteIdentifier(tableName);\n const idColumn = quoteIdentifier(\"id\");\n const typeColumn = quoteIdentifier(\"type\");\n if (this.tableNames.has(tableName)) {\n // console.log(\n // `[SqljsEngine] Table ${tableName} already exists, skipping creation.`\n // );\n return;\n }\n const columns = Array.from(schema.entries())\n .filter(([field]) => field !== \"id\" && field !== \"type\") // id and type are standard\n .map(\n ([field, fieldOptions]) =>\n `${quoteIdentifier(field)} ${this.mapTypeToSQL(fieldOptions.type)}`\n );\n\n // Add metadata fields for multi-document support\n const metadataColumns = [\n `${quoteIdentifier(\"_meta_doc_id\")} TEXT`,\n `${quoteIdentifier(\"_meta_permission_hint\")} TEXT`,\n ];\n\n const createTableSQL = `CREATE TABLE IF NOT EXISTS ${quotedTableName} (\n ${idColumn} TEXT PRIMARY KEY, \n ${typeColumn} TEXT, \n ${columns.join(\", \")}${\n columns.length > 0 ? \", \" : \"\"\n }${metadataColumns.join(\", \")}\n );`;\n // console.log(\"[SqljsEngine] Executing SQL for createTable:\", createTableSQL);\n this.db.run(createTableSQL);\n\n // Create indexes for fields marked as indexed: true\n for (const [field, fieldOptions] of schema.entries()) {\n // Ensure fieldOptions exists and has the indexed property.\n // field !== \"id\" because 'id' is already the PRIMARY KEY and thus implicitly indexed.\n if (fieldOptions && fieldOptions.indexed && field !== \"id\") {\n const indexName = `idx_${tableName}_${field}`;\n const createIndexSQL = `CREATE INDEX IF NOT EXISTS ${quoteIdentifier(\n indexName\n )} ON ${quotedTableName} (${quoteIdentifier(field)});`;\n // console.log(`[SqljsEngine] Creating index ${indexName} on table ${tableName} for field ${field}: ${createIndexSQL}`);\n this.db.run(createIndexSQL);\n }\n }\n\n // Create index on _meta_doc_id for efficient document-based queries\n const docIdIndexName = `idx_${tableName}_meta_doc_id`;\n const docIdIndexSQL = `CREATE INDEX IF NOT EXISTS ${quoteIdentifier(\n docIdIndexName\n )} ON ${quotedTableName} (${quoteIdentifier(\"_meta_doc_id\")});`;\n this.db.run(docIdIndexSQL);\n\n this.updateTableNames();\n // console.log(`[SqljsEngine] Table ${tableName} created.`);\n }\n\n async createStringSetJunctionTable(\n modelName: string,\n fieldName: string\n ): Promise<void> {\n await this.readyPromise;\n if (!this.db)\n throw new Error(\n \"SQL.js not initialized for createStringSetJunctionTable\"\n );\n\n const junctionTableName = `${this.getTableName(modelName)}_${fieldName}`;\n const quotedJunctionTable = quoteIdentifier(junctionTableName);\n const foreignKeyColumn = `${modelName.toLowerCase()}_id`;\n const quotedForeignKey = quoteIdentifier(foreignKeyColumn);\n const quotedIdColumn = quoteIdentifier(\"id\");\n const quotedValueColumn = quoteIdentifier(\"value\");\n\n if (this.tableNames.has(junctionTableName)) {\n Logger.debug(\n `[SqljsEngine] StringSet junction table ${junctionTableName} already exists, skipping creation.`\n );\n return; // Table already exists\n }\n\n const createTableSQL = `CREATE TABLE IF NOT EXISTS ${quotedJunctionTable} (\n ${quotedIdColumn} TEXT PRIMARY KEY,\n ${quotedForeignKey} TEXT NOT NULL,\n ${quotedValueColumn} TEXT NOT NULL,\n UNIQUE(${quotedForeignKey}, ${quotedValueColumn})\n );`;\n\n Logger.info(\n `[SqljsEngine] Creating StringSet junction table ${junctionTableName} for ${modelName}.${fieldName}`\n );\n this.db.run(createTableSQL);\n\n // Create index for efficient lookups\n const indexName = `idx_${junctionTableName}_${modelName.toLowerCase()}_id_value`;\n const indexSQL = `CREATE INDEX IF NOT EXISTS ${quoteIdentifier(\n indexName\n )} ON ${quotedJunctionTable} (${quotedForeignKey}, ${quotedValueColumn});`;\n this.db.run(indexSQL);\n\n this.updateTableNames();\n Logger.info(\n `[SqljsEngine] StringSet junction table ${junctionTableName} created successfully.`\n );\n }\n\n async insertStringSetValues(\n modelName: string,\n fieldName: string,\n recordId: string,\n values: string[]\n ): Promise<void> {\n await this.readyPromise;\n if (!this.db)\n throw new Error(\"SQL.js not initialized for insertStringSetValues\");\n\n if (values.length === 0) return;\n\n const junctionTableName = `${this.getTableName(modelName)}_${fieldName}`;\n const modelIdColumn = `${modelName.toLowerCase()}_id`;\n const quotedJunctionTable = quoteIdentifier(junctionTableName);\n const quotedIdColumn = quoteIdentifier(\"id\");\n const quotedModelIdColumn = quoteIdentifier(modelIdColumn);\n const quotedValueColumn = quoteIdentifier(\"value\");\n\n for (const value of values) {\n const insertSQL = `INSERT OR IGNORE INTO ${quotedJunctionTable} (${quotedIdColumn}, ${quotedModelIdColumn}, ${quotedValueColumn}) VALUES (?, ?, ?);`;\n const junctionId = `${recordId}_${value}`;\n this.db.run(insertSQL, [junctionId, recordId, value]);\n }\n }\n\n async removeStringSetValues(\n modelName: string,\n fieldName: string,\n recordId: string,\n values: string[]\n ): Promise<void> {\n await this.readyPromise;\n if (!this.db)\n throw new Error(\"SQL.js not initialized for removeStringSetValues\");\n\n if (values.length === 0) return;\n\n const junctionTableName = `${this.getTableName(modelName)}_${fieldName}`;\n const modelIdColumn = `${modelName.toLowerCase()}_id`;\n const quotedJunctionTable = quoteIdentifier(junctionTableName);\n const quotedModelIdColumn = quoteIdentifier(modelIdColumn);\n const quotedValueColumn = quoteIdentifier(\"value\");\n\n for (const value of values) {\n const deleteSQL = `DELETE FROM ${quotedJunctionTable} WHERE ${quotedModelIdColumn} = ? AND ${quotedValueColumn} = ?;`;\n this.db.run(deleteSQL, [recordId, value]);\n }\n }\n\n async insert(modelName: string, data: any): Promise<void> {\n await this.readyPromise;\n if (!this.db) throw new Error(\"SQL.js not initialized for insert\");\n const tableName = this.getTableName(modelName);\n const quotedTableName = quoteIdentifier(tableName);\n const columns = Object.keys(data);\n const quotedColumns = columns.map((column) => quoteIdentifier(column));\n const placeholders = columns.map(() => \"?\").join(\", \");\n const values = Object.values(data);\n const insertSQL = `INSERT OR REPLACE INTO ${quotedTableName} (${quotedColumns.join(\n \", \"\n )}) VALUES (${placeholders});`;\n this.db.run(insertSQL, values as SqlValue[]);\n }\n\n async delete(modelName: string, id: string): Promise<void> {\n await this.readyPromise;\n if (!this.db) throw new Error(\"SQL.js not initialized for delete\");\n const tableName = this.getTableName(modelName);\n const deleteSQL = `DELETE FROM ${quoteIdentifier(tableName)} WHERE ${quoteIdentifier(\n \"id\"\n )} = ?;`;\n this.db.run(deleteSQL, [id as SqlValue]);\n }\n\n async deleteByDocumentId(modelName: string, docId: string): Promise<void> {\n await this.readyPromise;\n if (!this.db)\n throw new Error(\"SQL.js not initialized for deleteByDocumentId\");\n const tableName = this.getTableName(modelName);\n const quotedTableName = quoteIdentifier(tableName);\n\n if (!this.tableNames.has(tableName)) {\n Logger.debug(\n `[SqljsEngine] Skipping deleteByDocumentId for ${tableName}; table does not exist.`\n );\n return;\n }\n\n // Delete all records with the specified document ID\n const deleteSQL = `DELETE FROM ${quotedTableName} WHERE ${quoteIdentifier(\n \"_meta_doc_id\"\n )} = ?;`;\n this.db.run(deleteSQL, [docId as SqlValue]);\n\n // Also clean up StringSet junction tables\n for (const existingTableName of this.tableNames) {\n if (existingTableName.startsWith(`${tableName}_`)) {\n // This is likely a StringSet junction table\n const quotedExistingTable = quoteIdentifier(existingTableName);\n const quotedForeignKey = quoteIdentifier(`${modelName.toLowerCase()}_id`);\n const junctionDeleteSQL = `DELETE FROM ${quotedExistingTable} WHERE ${quotedForeignKey} IN (\n SELECT ${quoteIdentifier(\"id\")} FROM ${quotedTableName} WHERE ${quoteIdentifier(\n \"_meta_doc_id\"\n )} = ?\n );`;\n try {\n this.db.run(junctionDeleteSQL, [docId as SqlValue]);\n const rowsCleared = this.db.getRowsModified();\n Logger.info(\n `[SqljsEngine] Cleared junction table ${existingTableName} for document ${docId}; removed ${rowsCleared} rows.`\n );\n } catch (error) {\n Logger.warn(\n `[SqljsEngine] Warning: Could not clean up junction table ${existingTableName}:`,\n error\n );\n }\n }\n }\n }\n\n async query<T extends Record<string, any>>(\n sql: string,\n params?: any[]\n ): Promise<T[]> {\n await this.readyPromise;\n if (!this.db) throw new Error(\"SQL.js not initialized for query\");\n // console.log(\"[SqljsEngine] Executing direct query:\", sql, params);\n const results: T[] = [];\n const stmt = this.db.prepare(sql);\n if (params) {\n stmt.bind(params as SqlValue[]);\n }\n while (stmt.step()) {\n results.push(stmt.getAsObject() as T);\n }\n stmt.free();\n return results;\n }\n\n async withTransaction<T>(\n callback: (transactionalOps: ITransactionalDatabaseOperations) => Promise<T>\n ): Promise<T> {\n await this.readyPromise;\n if (!this.db)\n throw new Error(\"SQL.js Database instance not available for transaction\");\n\n let transactionStartedHere = false;\n await this.mutex.runExclusive(async () => {\n if (this.numOpenTransactions === 0) {\n // console.log(\"[SqljsEngine] Beginning transaction...\");\n if (!this.db) throw new Error(\"SQL.js DB not available for BEGIN\");\n this.db.run(\"BEGIN TRANSACTION\");\n transactionStartedHere = true;\n }\n this.numOpenTransactions++;\n // console.log(\n // \"[SqljsEngine] Transaction opened/nested, numOpenTransactions:\",\n // this.numOpenTransactions\n // );\n });\n\n const transactionalOps = new TransactionalSQLJSOperations(this.db, this);\n\n try {\n const result = await callback(transactionalOps);\n await this.mutex.runExclusive(async () => {\n this.numOpenTransactions--;\n // console.log(\n // \"[SqljsEngine] Transaction finishing, numOpenTransactions:\",\n // this.numOpenTransactions\n // );\n if (this.numOpenTransactions === 0) {\n // console.log(\"[SqljsEngine] Committing transaction...\");\n if (!this.db) throw new Error(\"SQL.js DB not available for COMMIT\");\n this.db.run(\"COMMIT\");\n }\n });\n return result;\n } catch (error) {\n Logger.error(\"[SqljsEngine] Error in transaction, rolling back:\", error);\n await this.mutex.runExclusive(async () => {\n if (this.db && this.numOpenTransactions > 0 && transactionStartedHere) {\n try {\n // console.log(\"[SqljsEngine] Rolling back transaction...\");\n if (!this.db)\n throw new Error(\"SQL.js DB not available for ROLLBACK\");\n this.db.run(\"ROLLBACK\");\n // console.log(\"[SqljsEngine] Rollback successful.\");\n } catch (rollbackError) {\n Logger.error(\"[SqljsEngine] Error during ROLLBACK:\", rollbackError);\n }\n }\n this.numOpenTransactions = 0; // Reset counter for this transaction context\n // console.log(\"[SqljsEngine] Transaction counter reset after error.\");\n });\n throw error;\n }\n }\n\n async close(): Promise<void> {\n await this.readyPromise;\n if (this.db) {\n // console.log(\"[SqljsEngine] Closing SQL.js database...\");\n this.db.close();\n this.db = null;\n SqljsEngine.SQL = null; // Allow re-init if a new instance is made and wasm needs to be reloaded.\n // console.log(\"[SqljsEngine] SQL.js database closed.\");\n }\n }\n\n async getTableSchema(_tableName: string): Promise<any> {\n // Implementation for SQL.js to get table schema (e.g., PRAGMA table_info)\n // This is a placeholder and needs actual implementation\n return undefined; // Placeholder\n }\n\n async destroy(): Promise<void> {\n if (this.db) {\n this.db.close();\n Logger.info(\"[SqljsEngine] Database closed.\");\n // Reset internal state if necessary, e.g., this.db = null;\n // this.db = null; // Assuming sql.js doesn't reuse the instance after close\n // and we'd create a new one upon re-init.\n }\n // No explicit ready state to reset here as ensureReady re-initializes if db is null.\n }\n\n getLastErrorMessage(): string | undefined {\n // SQL.js typically throws errors rather than setting a last error message property.\n // So, this method might not be directly applicable unless we cache errors.\n // For now, returning undefined as per the basic contract.\n return undefined;\n }\n}\n"],"mappings":"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","names":[]}
|