jsql-neo 4.5.1 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/mysql_server.js +1 -1
- package/lib/native_client.js +102 -13
- package/lib/sql.js +394 -40
- package/lib/sqlite_compat.js +323 -0
- package/lib/sqlite_worker.js +260 -0
- package/lib/wasm_client.js +85 -1
- package/package.json +3 -2
package/lib/mysql_server.js
CHANGED
|
@@ -909,7 +909,7 @@ class MysqlServer {
|
|
|
909
909
|
this._engine = null;
|
|
910
910
|
this._ownEngine = false;
|
|
911
911
|
this._databases = new Map();
|
|
912
|
-
this._dbDir = options.dataDir ? path.resolve(options.dataDir) : null;
|
|
912
|
+
this._dbDir = options.dataDir && options.dataDir !== ':memory:' ? path.resolve(options.dataDir) : null;
|
|
913
913
|
this._defaultDbName = options.defaultDatabase || 'default';
|
|
914
914
|
this._connectionCounter = 0;
|
|
915
915
|
this._sockets = new Set();
|
package/lib/native_client.js
CHANGED
|
@@ -7,6 +7,69 @@ const STR_TAG = 3;
|
|
|
7
7
|
const BOOL_TAG = 4;
|
|
8
8
|
const INT32_TAG = 5;
|
|
9
9
|
|
|
10
|
+
function safeParse(str, fallback) {
|
|
11
|
+
if (typeof str !== 'string') return fallback;
|
|
12
|
+
try { return JSON.parse(str); } catch (e) { return fallback; }
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const NATIVE_TYPE_MAP = {
|
|
16
|
+
text: 'string',
|
|
17
|
+
varchar: 'string',
|
|
18
|
+
double: 'float',
|
|
19
|
+
number: 'float',
|
|
20
|
+
numeric: 'float',
|
|
21
|
+
decimal: 'float',
|
|
22
|
+
date: 'string',
|
|
23
|
+
timestamp: 'string',
|
|
24
|
+
datetime: 'string',
|
|
25
|
+
json: 'string',
|
|
26
|
+
array: 'string',
|
|
27
|
+
object: 'string',
|
|
28
|
+
bool: 'boolean',
|
|
29
|
+
bigint: 'string',
|
|
30
|
+
int: 'integer',
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
function mapNativeSchema(schema) {
|
|
34
|
+
const mapped = {};
|
|
35
|
+
for (const [field, def] of Object.entries(schema || {})) {
|
|
36
|
+
if (typeof def === 'string') {
|
|
37
|
+
mapped[field] = { type: NATIVE_TYPE_MAP[def.toLowerCase()] || def.toLowerCase() };
|
|
38
|
+
} else if (def && typeof def === 'object') {
|
|
39
|
+
const t = (def.type || 'string').toLowerCase();
|
|
40
|
+
mapped[field] = { ...def, type: NATIVE_TYPE_MAP[t] || t };
|
|
41
|
+
} else {
|
|
42
|
+
mapped[field] = { type: 'string' };
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return mapped;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function restoreRow(row, schema) {
|
|
49
|
+
if (!schema || typeof row !== 'object' || row === null) return row;
|
|
50
|
+
const out = {};
|
|
51
|
+
for (const [field, def] of Object.entries(row)) {
|
|
52
|
+
if (field === 'fields' && typeof row[field] === 'object' && row[field] !== null) {
|
|
53
|
+
out[field] = restoreRow(row[field], schema);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
const colDef = schema[field];
|
|
57
|
+
let t = null;
|
|
58
|
+
if (typeof colDef === 'string') t = colDef.toLowerCase();
|
|
59
|
+
else if (colDef && typeof colDef === 'object' && colDef.type) t = String(colDef.type).toLowerCase();
|
|
60
|
+
if (['json', 'array', 'object'].includes(t) && typeof row[field] === 'string') {
|
|
61
|
+
try { out[field] = JSON.parse(row[field]); } catch (e) { out[field] = row[field]; }
|
|
62
|
+
} else if ((t === 'integer' || t === 'int' || t === 'bigint') && typeof row[field] === 'string' && /^-?\d+$/.test(row[field])) {
|
|
63
|
+
out[field] = Number(row[field]);
|
|
64
|
+
} else if ((t === 'float' || t === 'double' || t === 'number') && typeof row[field] === 'string' && !Number.isNaN(Number(row[field]))) {
|
|
65
|
+
out[field] = Number(row[field]);
|
|
66
|
+
} else {
|
|
67
|
+
out[field] = row[field];
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return out;
|
|
71
|
+
}
|
|
72
|
+
|
|
10
73
|
function encodeBatch(rows) {
|
|
11
74
|
if (rows.length === 0) return new Uint8Array(0);
|
|
12
75
|
const fieldNames = Object.keys(rows[0]);
|
|
@@ -279,14 +342,23 @@ class JSQL {
|
|
|
279
342
|
async start() {
|
|
280
343
|
if (this._mode !== 'memory') {
|
|
281
344
|
if (!this._path) throw new Error('hybrid/disk mode requires a directory path');
|
|
282
|
-
|
|
345
|
+
let r;
|
|
346
|
+
try {
|
|
347
|
+
r = safeParse(native.jsqlOpen(this._path, this._mode));
|
|
348
|
+
} catch (e) {
|
|
349
|
+
throw new Error('failed to open native storage: ' + e.message);
|
|
350
|
+
}
|
|
283
351
|
if (r && r.ok === false) throw new Error(r.error || 'open storage failed');
|
|
284
352
|
if (r && Array.isArray(r.tables)) {
|
|
285
353
|
this._tableNames = new Set(r.tables);
|
|
286
354
|
if (r.schemas) this._schemas = r.schemas;
|
|
287
355
|
}
|
|
288
356
|
} else {
|
|
289
|
-
|
|
357
|
+
try {
|
|
358
|
+
JSON.parse(native.jsqlOpen('', 'memory'));
|
|
359
|
+
} catch (e) {
|
|
360
|
+
throw new Error('failed to open native memory storage: ' + e.message);
|
|
361
|
+
}
|
|
290
362
|
}
|
|
291
363
|
if (this._mode !== 'memory') {
|
|
292
364
|
if (this._flushInterval > 0) {
|
|
@@ -319,8 +391,19 @@ class JSQL {
|
|
|
319
391
|
}
|
|
320
392
|
|
|
321
393
|
async _insertBatch(table, rows) {
|
|
394
|
+
const schema = this._schemas[table];
|
|
395
|
+
if (schema) {
|
|
396
|
+
rows = rows.map(row => {
|
|
397
|
+
const out = {};
|
|
398
|
+
for (const [k, v] of Object.entries(row)) {
|
|
399
|
+
if (v instanceof Date) out[k] = v.toISOString();
|
|
400
|
+
else out[k] = v;
|
|
401
|
+
}
|
|
402
|
+
return out;
|
|
403
|
+
});
|
|
404
|
+
}
|
|
322
405
|
const bin = encodeBatch(rows);
|
|
323
|
-
const r =
|
|
406
|
+
const r = safeParse(native.jsqlInsertBuf(table, bin));
|
|
324
407
|
if (r && r.error) throw new Error(r.error);
|
|
325
408
|
return r;
|
|
326
409
|
}
|
|
@@ -340,13 +423,13 @@ class JSQL {
|
|
|
340
423
|
var ids = remove[table];
|
|
341
424
|
if (ids.size === 0) continue;
|
|
342
425
|
var idsArr = Array.from(ids);
|
|
343
|
-
var r =
|
|
426
|
+
var r = safeParse(native.jsqlRemoveByIds(table, JSON.stringify(idsArr)));
|
|
344
427
|
this._emit('delete', { table, ids: idsArr, result: r });
|
|
345
428
|
}
|
|
346
429
|
for (var table in update) {
|
|
347
430
|
var entries = update[table];
|
|
348
431
|
if (entries.length === 0) continue;
|
|
349
|
-
var r =
|
|
432
|
+
var r = safeParse(native.jsqlUpdateByIds(table, JSON.stringify(entries)));
|
|
350
433
|
this._emit('update', { table, entries, result: r });
|
|
351
434
|
}
|
|
352
435
|
this._opBuffer = { remove: {}, update: {} };
|
|
@@ -410,7 +493,7 @@ class JSQL {
|
|
|
410
493
|
async createTable(name, schema) {
|
|
411
494
|
await this._flush();
|
|
412
495
|
if (!this._runHooks('beforeCreateTable', [name, schema])) return null;
|
|
413
|
-
const r =
|
|
496
|
+
const r = safeParse(native.jsqlCreateTable(name, JSON.stringify(mapNativeSchema(schema))));
|
|
414
497
|
if (r && r.ok === false) throw new Error(r.error || 'create table failed');
|
|
415
498
|
this._tableNames.add(name);
|
|
416
499
|
this._schemas[name] = schema;
|
|
@@ -422,7 +505,7 @@ class JSQL {
|
|
|
422
505
|
async dropTable(name) {
|
|
423
506
|
await this._flush();
|
|
424
507
|
if (!this._runHooks('beforeDropTable', [name])) return null;
|
|
425
|
-
const r =
|
|
508
|
+
const r = safeParse(native.jsqlDropTable(name));
|
|
426
509
|
if (r && r.ok === false) throw new Error(r.error || 'drop table failed');
|
|
427
510
|
this._tableNames.delete(name);
|
|
428
511
|
delete this._schemas[name];
|
|
@@ -434,9 +517,11 @@ class JSQL {
|
|
|
434
517
|
findById(table, id) {
|
|
435
518
|
this._flushOpsNow();
|
|
436
519
|
if (!this._runHooks('beforeFind', [table, { id }])) return null;
|
|
437
|
-
const raw =
|
|
520
|
+
const raw = safeParse(native.jsqlFindById(table, Number(id)));
|
|
438
521
|
if (raw && raw.error) throw new Error(raw.error);
|
|
439
522
|
this._runHooks('afterFind', [table, { id }, raw]);
|
|
523
|
+
const schema = this._schemas[table];
|
|
524
|
+
if (schema && raw && typeof raw === 'object') return restoreRow(raw, schema);
|
|
440
525
|
return raw;
|
|
441
526
|
}
|
|
442
527
|
|
|
@@ -444,9 +529,11 @@ class JSQL {
|
|
|
444
529
|
this._flushOpsNow();
|
|
445
530
|
if (!this._runHooks('beforeFind', [table, { ids }])) return null;
|
|
446
531
|
const resultStr = native.jsqlFindByIds(table, JSON.stringify(ids));
|
|
447
|
-
const r =
|
|
532
|
+
const r = safeParse(resultStr);
|
|
448
533
|
if (r && r.error) throw new Error(r.error);
|
|
449
534
|
this._runHooks('afterFind', [table, { ids }, r]);
|
|
535
|
+
const schema = this._schemas[table];
|
|
536
|
+
if (schema && Array.isArray(r)) return r.map(row => restoreRow(row, schema));
|
|
450
537
|
return r;
|
|
451
538
|
}
|
|
452
539
|
|
|
@@ -459,9 +546,11 @@ class JSQL {
|
|
|
459
546
|
if (!this._runHooks('beforeFind', [table, { filter, opts }])) return [];
|
|
460
547
|
const filterStr = filter ? JSON.stringify(filter) : '';
|
|
461
548
|
const { limit = 100, offset = 0 } = opts;
|
|
462
|
-
const r =
|
|
549
|
+
const r = safeParse(native.jsqlFind(table, filterStr, limit, offset));
|
|
463
550
|
if (r && r.error) throw new Error(r.error);
|
|
464
551
|
this._runHooks('afterFind', [table, { filter, opts }, r]);
|
|
552
|
+
const schema = this._schemas[table];
|
|
553
|
+
if (schema && Array.isArray(r)) return r.map(row => restoreRow(row, schema));
|
|
465
554
|
return r;
|
|
466
555
|
}
|
|
467
556
|
|
|
@@ -529,19 +618,19 @@ class JSQL {
|
|
|
529
618
|
|
|
530
619
|
async beginTx() {
|
|
531
620
|
this._flushOpsNow();
|
|
532
|
-
const r =
|
|
621
|
+
const r = safeParse(native.jsqlBeginTx());
|
|
533
622
|
if (r && r.ok === false) throw new Error(r.error || 'begin transaction failed');
|
|
534
623
|
return r.txId;
|
|
535
624
|
}
|
|
536
625
|
|
|
537
626
|
async commitTx(txId) {
|
|
538
|
-
const r =
|
|
627
|
+
const r = safeParse(native.jsqlCommitTx(String(txId)));
|
|
539
628
|
if (r && r.ok === false) throw new Error(r.error || 'commit transaction failed');
|
|
540
629
|
return true;
|
|
541
630
|
}
|
|
542
631
|
|
|
543
632
|
async rollbackTx(txId) {
|
|
544
|
-
const r =
|
|
633
|
+
const r = safeParse(native.jsqlRollbackTx(String(txId)));
|
|
545
634
|
if (r && r.ok === false) throw new Error(r.error || 'rollback transaction failed');
|
|
546
635
|
return true;
|
|
547
636
|
}
|