@sqb/sqljs 4.0.10 → 4.0.14
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/SqljsAdapter.d.ts +11 -0
- package/dist/SqljsAdapter.js +71 -0
- package/dist/SqljsConnection.d.ts +16 -0
- package/dist/SqljsConnection.js +146 -0
- package/dist/SqljsCursor.d.ts +12 -0
- package/dist/SqljsCursor.js +32 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +5 -0
- package/package.json +3 -3
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Adapter, ClientConfiguration } from '@sqb/connect';
|
|
2
|
+
import '@sqb/sqlite-dialect';
|
|
3
|
+
export declare class SqljsAdapter implements Adapter {
|
|
4
|
+
driver: string;
|
|
5
|
+
dialect: string;
|
|
6
|
+
features: {
|
|
7
|
+
cursor: boolean;
|
|
8
|
+
};
|
|
9
|
+
connect(config: ClientConfiguration): Promise<Adapter.Connection>;
|
|
10
|
+
}
|
|
11
|
+
export declare function closeMemoryDatabase(name?: string): Promise<void>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.closeMemoryDatabase = exports.SqljsAdapter = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const fs_1 = tslib_1.__importDefault(require("fs"));
|
|
6
|
+
require("@sqb/sqlite-dialect");
|
|
7
|
+
const sql_js_1 = tslib_1.__importDefault(require("sql.js"));
|
|
8
|
+
const SqljsConnection_1 = require("./SqljsConnection");
|
|
9
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
10
|
+
const putil_promisify_1 = tslib_1.__importDefault(require("putil-promisify"));
|
|
11
|
+
const dbCache = new Map();
|
|
12
|
+
class SqljsAdapter {
|
|
13
|
+
constructor() {
|
|
14
|
+
this.driver = 'sqljs';
|
|
15
|
+
this.dialect = 'sqlite';
|
|
16
|
+
this.features = {
|
|
17
|
+
cursor: true,
|
|
18
|
+
// fetchAsString: [DataType.DATE, DataType.TIMESTAMP, DataType.TIMESTAMPTZ]
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
async connect(config) {
|
|
22
|
+
if (!config.database)
|
|
23
|
+
throw new Error('You must provide sqlite database file for sql.js driver');
|
|
24
|
+
let dbName = '';
|
|
25
|
+
let isMemory = false;
|
|
26
|
+
const m = config.database.match(/^(:memory:)(\w+)?$/);
|
|
27
|
+
if (m) {
|
|
28
|
+
isMemory = true;
|
|
29
|
+
dbName = config.database;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
dbName = path_1.default.resolve(config.database);
|
|
33
|
+
}
|
|
34
|
+
let intlDb = dbCache.get(dbName);
|
|
35
|
+
if (intlDb) {
|
|
36
|
+
intlDb._refCount++;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
const SQL = await (0, sql_js_1.default)();
|
|
40
|
+
if (isMemory) {
|
|
41
|
+
intlDb = new SQL.Database();
|
|
42
|
+
intlDb._refCount = 0;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
const buf = await putil_promisify_1.default.fromCallback(cb => fs_1.default.readFile(dbName, cb));
|
|
46
|
+
intlDb = new SQL.Database(buf);
|
|
47
|
+
intlDb._refCount = 1;
|
|
48
|
+
}
|
|
49
|
+
dbCache.set(dbName, intlDb);
|
|
50
|
+
}
|
|
51
|
+
const _intlDb = intlDb;
|
|
52
|
+
return new SqljsConnection_1.SqljsConnection(_intlDb, () => {
|
|
53
|
+
if (isMemory)
|
|
54
|
+
return;
|
|
55
|
+
if (--_intlDb._refCount <= 0) {
|
|
56
|
+
_intlDb.close();
|
|
57
|
+
dbCache.delete(dbName);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
exports.SqljsAdapter = SqljsAdapter;
|
|
63
|
+
async function closeMemoryDatabase(name) {
|
|
64
|
+
const memoryDbName = name || ':memory:';
|
|
65
|
+
const memDb = dbCache.get(memoryDbName);
|
|
66
|
+
if (memDb) {
|
|
67
|
+
dbCache.delete(memoryDbName);
|
|
68
|
+
memDb.close();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
exports.closeMemoryDatabase = closeMemoryDatabase;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Database } from 'sql.js';
|
|
2
|
+
import { Adapter, QueryRequest } from '@sqb/connect';
|
|
3
|
+
export declare class SqljsConnection implements Adapter.Connection {
|
|
4
|
+
private _onClose;
|
|
5
|
+
private intlcon?;
|
|
6
|
+
constructor(db: Database, _onClose: Function);
|
|
7
|
+
get sessionId(): any;
|
|
8
|
+
close(): Promise<void>;
|
|
9
|
+
reset(): Promise<void>;
|
|
10
|
+
startTransaction(): Promise<void>;
|
|
11
|
+
commit(): Promise<void>;
|
|
12
|
+
rollback(): Promise<void>;
|
|
13
|
+
test(): Promise<void>;
|
|
14
|
+
execute(query: QueryRequest): Promise<Adapter.Response>;
|
|
15
|
+
private _convertFields;
|
|
16
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SqljsConnection = void 0;
|
|
4
|
+
const SqljsCursor_1 = require("./SqljsCursor");
|
|
5
|
+
class SqljsConnection {
|
|
6
|
+
constructor(db, _onClose) {
|
|
7
|
+
this._onClose = _onClose;
|
|
8
|
+
this.intlcon = db;
|
|
9
|
+
}
|
|
10
|
+
get sessionId() {
|
|
11
|
+
return 0;
|
|
12
|
+
}
|
|
13
|
+
async close() {
|
|
14
|
+
if (this.intlcon) {
|
|
15
|
+
this.intlcon = undefined;
|
|
16
|
+
await this._onClose();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
async reset() {
|
|
20
|
+
return this.rollback();
|
|
21
|
+
}
|
|
22
|
+
async startTransaction() {
|
|
23
|
+
assertDefined(this.intlcon);
|
|
24
|
+
try {
|
|
25
|
+
this.intlcon.exec('BEGIN TRANSACTION;');
|
|
26
|
+
}
|
|
27
|
+
catch (e) {
|
|
28
|
+
if (e instanceof Error && e.message.match(/within a transaction/))
|
|
29
|
+
return;
|
|
30
|
+
throw e;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async commit() {
|
|
34
|
+
assertDefined(this.intlcon);
|
|
35
|
+
try {
|
|
36
|
+
this.intlcon.exec('COMMIT;');
|
|
37
|
+
}
|
|
38
|
+
catch (e) {
|
|
39
|
+
if (e instanceof Error && e.message.match(/no transaction/))
|
|
40
|
+
return;
|
|
41
|
+
throw e;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async rollback() {
|
|
45
|
+
assertDefined(this.intlcon);
|
|
46
|
+
try {
|
|
47
|
+
this.intlcon.exec('ROLLBACK;');
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
if (e instanceof Error && e.message.match(/no transaction/))
|
|
51
|
+
return;
|
|
52
|
+
throw e;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async test() {
|
|
56
|
+
assertDefined(this.intlcon);
|
|
57
|
+
this.intlcon.exec('select 1');
|
|
58
|
+
}
|
|
59
|
+
async execute(query) {
|
|
60
|
+
assertDefined(this.intlcon);
|
|
61
|
+
if (!query.autoCommit)
|
|
62
|
+
await this.startTransaction();
|
|
63
|
+
const out = {};
|
|
64
|
+
let params;
|
|
65
|
+
if (query.params) {
|
|
66
|
+
const prms = query.params;
|
|
67
|
+
params = Object.keys(prms).reduce((obj, k) => {
|
|
68
|
+
obj[':' + k] = prms[k];
|
|
69
|
+
return obj;
|
|
70
|
+
}, {});
|
|
71
|
+
}
|
|
72
|
+
const m = query.sql.match(/\b(insert into|update|delete from)\b ("?\w+"?)/i);
|
|
73
|
+
if (m) {
|
|
74
|
+
const stmt = this.intlcon.prepare(query.sql);
|
|
75
|
+
stmt.run(params);
|
|
76
|
+
stmt.free();
|
|
77
|
+
out.rowsAffected = this.intlcon.getRowsModified();
|
|
78
|
+
if (query.autoCommit)
|
|
79
|
+
await this.commit();
|
|
80
|
+
if (out.rowsAffected === 1 && query.returningFields) {
|
|
81
|
+
const selectFields = query.returningFields.map(x => x.field + (x.alias ? ' as ' + x.alias : ''));
|
|
82
|
+
let sql = `select ${selectFields.join(',')} from ${m[2]}\n`;
|
|
83
|
+
// Emulate insert into ... returning
|
|
84
|
+
if (m[1].toLowerCase() === 'insert into') {
|
|
85
|
+
sql += 'where rowid=last_insert_rowid();';
|
|
86
|
+
const r = this.intlcon.exec(sql);
|
|
87
|
+
if (r.length) {
|
|
88
|
+
out.fields = this._convertFields(r[0].columns);
|
|
89
|
+
out.rows = r[0].values;
|
|
90
|
+
out.rowType = 'array';
|
|
91
|
+
}
|
|
92
|
+
return out;
|
|
93
|
+
}
|
|
94
|
+
else
|
|
95
|
+
// Emulate update ... returning
|
|
96
|
+
if (m[1].toLowerCase() === 'update') {
|
|
97
|
+
const m2 = query.sql.match(/where (.+)/);
|
|
98
|
+
query = { ...query };
|
|
99
|
+
query.sql = sql + (m2 ? ' where ' + m2[1] : '');
|
|
100
|
+
}
|
|
101
|
+
else
|
|
102
|
+
return out;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
let stmt = this.intlcon.prepare(query.sql, query.params);
|
|
106
|
+
try {
|
|
107
|
+
const colNames = stmt.getColumnNames();
|
|
108
|
+
if (colNames && colNames.length) {
|
|
109
|
+
out.fields = this._convertFields(colNames);
|
|
110
|
+
const rowType = query.objectRows ? 'object' : 'array';
|
|
111
|
+
out.rowType = rowType;
|
|
112
|
+
const cursor = new SqljsCursor_1.SqljsCursor(stmt, { rowType });
|
|
113
|
+
if (query.cursor) {
|
|
114
|
+
out.cursor = cursor;
|
|
115
|
+
stmt = undefined;
|
|
116
|
+
}
|
|
117
|
+
else
|
|
118
|
+
out.rows = await cursor.fetch(query.fetchRows || 100);
|
|
119
|
+
}
|
|
120
|
+
return out;
|
|
121
|
+
}
|
|
122
|
+
finally {
|
|
123
|
+
if (stmt)
|
|
124
|
+
stmt.free();
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
_convertFields(fields) {
|
|
128
|
+
const result = [];
|
|
129
|
+
for (let i = 0; i < fields.length; i++) {
|
|
130
|
+
const v = fields[i];
|
|
131
|
+
const o = {
|
|
132
|
+
fieldName: v,
|
|
133
|
+
dataType: 'any',
|
|
134
|
+
jsType: 'any',
|
|
135
|
+
_inf: { name: v }
|
|
136
|
+
};
|
|
137
|
+
result.push(o);
|
|
138
|
+
}
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
exports.SqljsConnection = SqljsConnection;
|
|
143
|
+
function assertDefined(d) {
|
|
144
|
+
if (d == null)
|
|
145
|
+
throw new Error("Invalid data");
|
|
146
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Adapter, RowType } from '@sqb/connect';
|
|
2
|
+
export declare class SqljsCursor implements Adapter.Cursor {
|
|
3
|
+
private _stmt?;
|
|
4
|
+
private readonly _rowType;
|
|
5
|
+
constructor(stmt: any, opts: {
|
|
6
|
+
rowType: RowType;
|
|
7
|
+
});
|
|
8
|
+
get isClosed(): boolean;
|
|
9
|
+
get rowType(): RowType;
|
|
10
|
+
close(): Promise<void>;
|
|
11
|
+
fetch(nRows: number): Promise<any[] | undefined>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SqljsCursor = void 0;
|
|
4
|
+
class SqljsCursor {
|
|
5
|
+
constructor(stmt, opts) {
|
|
6
|
+
this._rowType = opts.rowType;
|
|
7
|
+
this._stmt = stmt;
|
|
8
|
+
}
|
|
9
|
+
get isClosed() {
|
|
10
|
+
return !this._stmt;
|
|
11
|
+
}
|
|
12
|
+
get rowType() {
|
|
13
|
+
return this._rowType;
|
|
14
|
+
}
|
|
15
|
+
async close() {
|
|
16
|
+
if (!this._stmt)
|
|
17
|
+
return;
|
|
18
|
+
this._stmt.free();
|
|
19
|
+
this._stmt = undefined;
|
|
20
|
+
}
|
|
21
|
+
async fetch(nRows) {
|
|
22
|
+
if (!this._stmt)
|
|
23
|
+
return;
|
|
24
|
+
const stmt = this._stmt;
|
|
25
|
+
const rows = [];
|
|
26
|
+
while (nRows-- && stmt.step()) {
|
|
27
|
+
rows.push(this.rowType === 'object' ? stmt.getAsObject() : stmt.get());
|
|
28
|
+
}
|
|
29
|
+
return rows;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.SqljsCursor = SqljsCursor;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.js
ADDED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sqb/sqljs",
|
|
3
3
|
"description": "SQB serialization extension for sql.js driver",
|
|
4
|
-
"version": "4.0.
|
|
4
|
+
"version": "4.0.14",
|
|
5
5
|
"author": "Panates",
|
|
6
6
|
"contributors": [
|
|
7
7
|
"Eray Hanoglu <e.hanoglu@panates.com>"
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
"putil-promisify": "^1.8.5"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@types/sql.js": "^1.4.
|
|
30
|
-
"sql.js": "^1.
|
|
29
|
+
"@types/sql.js": "^1.4.3",
|
|
30
|
+
"sql.js": "^1.6.2"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"sql.js": "^1.4.0",
|