@sqlitecloud/drivers 1.0.276 → 1.0.345
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 +3 -3
- package/lib/drivers/connection-tls.d.ts +2 -2
- package/lib/drivers/connection-tls.js +20 -8
- package/lib/drivers/connection-ws.d.ts +2 -2
- package/lib/drivers/connection-ws.js +4 -2
- package/lib/drivers/connection.d.ts +5 -4
- package/lib/drivers/connection.js +16 -15
- package/lib/drivers/database.d.ts +3 -3
- package/lib/drivers/database.js +45 -36
- package/lib/drivers/protocol.d.ts +3 -3
- package/lib/drivers/protocol.js +58 -15
- package/lib/drivers/pubsub.d.ts +5 -0
- package/lib/drivers/pubsub.js +14 -5
- package/lib/drivers/statement.d.ts +12 -6
- package/lib/drivers/statement.js +53 -56
- package/lib/drivers/types.d.ts +11 -9
- package/lib/drivers/types.js +1 -1
- package/lib/drivers/utilities.d.ts +2 -4
- package/lib/drivers/utilities.js +27 -82
- package/lib/index.d.ts +3 -3
- package/lib/index.js +37 -5
- package/lib/sqlitecloud.drivers.dev.js +67 -78
- package/lib/sqlitecloud.drivers.js +1 -1
- package/package.json +16 -27
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @sqlitecloud/drivers
|
|
2
2
|
|
|
3
3
|
[![npm package][npm-img]][npm-url]
|
|
4
|
-
[![
|
|
4
|
+
[![Test][test-img]][test-url]
|
|
5
5
|
[![Downloads][downloads-img]][downloads-url]
|
|
6
6
|
[![Issues][issues-img]][issues-url]
|
|
7
7
|
[](https://codecov.io/gh/sqlitecloud/sqlitecloud-js)
|
|
@@ -107,8 +107,8 @@ How do I connect SQLite cloud with Javascript?
|
|
|
107
107
|
How can I contribute or suggest features?
|
|
108
108
|
[https://github.com/sqlitecloud/sqlitecloud-js/issues](https://github.com/sqlitecloud/sqlitecloud-js/issues)
|
|
109
109
|
|
|
110
|
-
[
|
|
111
|
-
[
|
|
110
|
+
[test-img]: https://img.shields.io/github/actions/workflow/status/sqlitecloud/sqlitecloud-js/test.yml?label=Android%20%7C%20iOS%20%7C%20Web%20%7C%20Windows%20%7C%20MacOS%20%7C%20Linux
|
|
111
|
+
[test-url]: https://github.com/sqlitecloud/sqlitecloud-js/actions/workflows/test.yml
|
|
112
112
|
[downloads-img]: https://img.shields.io/npm/dt/@sqlitecloud/drivers
|
|
113
113
|
[downloads-url]: https://www.npmtrends.com/@sqlitecloud/drivers
|
|
114
114
|
[npm-img]: https://img.shields.io/npm/v/@sqlitecloud/drivers
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* connection-tls.ts - connection via tls socket and sqlitecloud protocol
|
|
3
3
|
*/
|
|
4
|
-
import { type SQLiteCloudConfig, type ErrorCallback, type ResultsCallback } from './types';
|
|
4
|
+
import { type SQLiteCloudConfig, type ErrorCallback, type ResultsCallback, SQLiteCloudCommand } from './types';
|
|
5
5
|
import { SQLiteCloudConnection } from './connection';
|
|
6
6
|
/**
|
|
7
7
|
* Implementation of SQLiteCloudConnection that connects to the database using specific tls APIs
|
|
@@ -14,7 +14,7 @@ export declare class SQLiteCloudTlsConnection extends SQLiteCloudConnection {
|
|
|
14
14
|
get connected(): boolean;
|
|
15
15
|
connectTransport(config: SQLiteCloudConfig, callback?: ErrorCallback): this;
|
|
16
16
|
/** Will send a command immediately (no queueing), return the rowset/result or throw an error */
|
|
17
|
-
transportCommands(commands: string, callback?: ResultsCallback): this;
|
|
17
|
+
transportCommands(commands: string | SQLiteCloudCommand, callback?: ResultsCallback): this;
|
|
18
18
|
private buffer;
|
|
19
19
|
private startedOn;
|
|
20
20
|
private executingCommands?;
|
|
@@ -18,13 +18,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
18
18
|
}) : function(o, v) {
|
|
19
19
|
o["default"] = v;
|
|
20
20
|
});
|
|
21
|
-
var __importStar = (this && this.__importStar) || function (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
};
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
28
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
39
|
exports.SQLiteCloudTlsConnection = void 0;
|
|
30
40
|
const types_1 = require("./types");
|
|
@@ -54,7 +64,6 @@ class SQLiteCloudTlsConnection extends connection_1.SQLiteCloudConnection {
|
|
|
54
64
|
return !!this.socket;
|
|
55
65
|
}
|
|
56
66
|
/* Opens a connection with the server and sends the initialization commands. Will throw in case of errors. */
|
|
57
|
-
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
58
67
|
connectTransport(config, callback) {
|
|
59
68
|
console.assert(!this.connected, 'SQLiteCloudTlsConnection.connect - connection already established');
|
|
60
69
|
if (this.config.verbose) {
|
|
@@ -118,6 +127,9 @@ class SQLiteCloudTlsConnection extends connection_1.SQLiteCloudConnection {
|
|
|
118
127
|
callback === null || callback === void 0 ? void 0 : callback.call(this, new types_1.SQLiteCloudError('Connection not established', { errorCode: 'ERR_CONNECTION_NOT_ESTABLISHED' }));
|
|
119
128
|
return this;
|
|
120
129
|
}
|
|
130
|
+
if (typeof commands === 'string') {
|
|
131
|
+
commands = { query: commands };
|
|
132
|
+
}
|
|
121
133
|
// reset buffer and rowset chunks, define response callback
|
|
122
134
|
this.buffer = buffer_1.Buffer.alloc(0);
|
|
123
135
|
this.startedOn = new Date();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* transport-ws.ts - handles low level communication with sqlitecloud server via socket.io websocket
|
|
3
3
|
*/
|
|
4
|
-
import { SQLiteCloudConfig, ErrorCallback, ResultsCallback } from './types';
|
|
4
|
+
import { SQLiteCloudConfig, ErrorCallback, ResultsCallback, SQLiteCloudCommand } from './types';
|
|
5
5
|
import { SQLiteCloudConnection } from './connection';
|
|
6
6
|
/**
|
|
7
7
|
* Implementation of TransportConnection that connects to the database indirectly
|
|
@@ -16,7 +16,7 @@ export declare class SQLiteCloudWebsocketConnection extends SQLiteCloudConnectio
|
|
|
16
16
|
get connected(): boolean;
|
|
17
17
|
connectTransport(config: SQLiteCloudConfig, callback?: ErrorCallback): this;
|
|
18
18
|
/** Will send a command immediately (no queueing), return the rowset/result or throw an error */
|
|
19
|
-
transportCommands(commands: string, callback?: ResultsCallback): this;
|
|
19
|
+
transportCommands(commands: string | SQLiteCloudCommand, callback?: ResultsCallback): this;
|
|
20
20
|
/** Disconnect socket.io from server */
|
|
21
21
|
close(): this;
|
|
22
22
|
}
|
|
@@ -45,7 +45,10 @@ class SQLiteCloudWebsocketConnection extends connection_1.SQLiteCloudConnection
|
|
|
45
45
|
callback === null || callback === void 0 ? void 0 : callback.call(this, new types_1.SQLiteCloudError('Connection not established', { errorCode: 'ERR_CONNECTION_NOT_ESTABLISHED' }));
|
|
46
46
|
return this;
|
|
47
47
|
}
|
|
48
|
-
|
|
48
|
+
if (typeof commands === 'string') {
|
|
49
|
+
commands = { query: commands };
|
|
50
|
+
}
|
|
51
|
+
this.socket.emit('GET /v2/weblite/sql', { sql: commands.query, bind: commands.parameters, row: 'array' }, (response) => {
|
|
49
52
|
if (response === null || response === void 0 ? void 0 : response.error) {
|
|
50
53
|
const error = new types_1.SQLiteCloudError(response.error.detail, Object.assign({}, response.error));
|
|
51
54
|
callback === null || callback === void 0 ? void 0 : callback.call(this, error);
|
|
@@ -56,7 +59,6 @@ class SQLiteCloudWebsocketConnection extends connection_1.SQLiteCloudConnection
|
|
|
56
59
|
if (metadata.numberOfRows !== undefined && metadata.numberOfColumns !== undefined && metadata.columns !== undefined) {
|
|
57
60
|
console.assert(Array.isArray(data), 'SQLiteCloudWebsocketConnection.transportCommands - data is not an array');
|
|
58
61
|
// we can recreate a SQLiteCloudRowset from the response which we know to be an array of arrays
|
|
59
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
60
62
|
const rowset = new rowset_1.SQLiteCloudRowset(metadata, data.flat());
|
|
61
63
|
callback === null || callback === void 0 ? void 0 : callback.call(this, null, rowset);
|
|
62
64
|
return;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* connection.ts - base abstract class for sqlitecloud server connections
|
|
3
3
|
*/
|
|
4
|
-
import { SQLiteCloudConfig, ErrorCallback, ResultsCallback } from './types';
|
|
4
|
+
import { SQLiteCloudConfig, ErrorCallback, ResultsCallback, SQLiteCloudCommand } from './types';
|
|
5
5
|
import { OperationsQueue } from './queue';
|
|
6
6
|
/**
|
|
7
7
|
* Base class for SQLiteCloudConnection handles basics and defines methods.
|
|
@@ -20,7 +20,7 @@ export declare abstract class SQLiteCloudConnection {
|
|
|
20
20
|
protected connect(callback?: ErrorCallback): this;
|
|
21
21
|
protected abstract connectTransport(config: SQLiteCloudConfig, callback?: ErrorCallback): this;
|
|
22
22
|
/** Send a command, return the rowset/result or throw an error */
|
|
23
|
-
protected abstract transportCommands(commands: string, callback?: ResultsCallback): this;
|
|
23
|
+
protected abstract transportCommands(commands: string | SQLiteCloudCommand, callback?: ResultsCallback): this;
|
|
24
24
|
/** Will log to console if verbose mode is enabled */
|
|
25
25
|
protected log(message: string, ...optionalParams: any[]): void;
|
|
26
26
|
/** Returns true if connection is open */
|
|
@@ -28,17 +28,18 @@ export declare abstract class SQLiteCloudConnection {
|
|
|
28
28
|
/** Enable verbose logging for debug purposes */
|
|
29
29
|
verbose(): void;
|
|
30
30
|
/** Will enquee a command to be executed and callback with the resulting rowset/result/error */
|
|
31
|
-
sendCommands(commands: string, callback?: ResultsCallback): this;
|
|
31
|
+
sendCommands(commands: string | SQLiteCloudCommand, callback?: ResultsCallback): this;
|
|
32
32
|
/**
|
|
33
33
|
* Sql is a promise based API for executing SQL statements. You can
|
|
34
34
|
* pass a simple string with a SQL statement or a template string
|
|
35
35
|
* using backticks and parameters in ${parameter} format. These parameters
|
|
36
36
|
* will be properly escaped and quoted like when using a prepared statement.
|
|
37
37
|
* @param sql A sql string or a template string in `backticks` format
|
|
38
|
+
* A SQLiteCloudCommand when the query is defined with question marks and bindings.
|
|
38
39
|
* @returns An array of rows in case of selections or an object with
|
|
39
40
|
* metadata in case of insert, update, delete.
|
|
40
41
|
*/
|
|
41
|
-
sql(sql: TemplateStringsArray | string, ...values: any[]): Promise<any>;
|
|
42
|
+
sql(sql: TemplateStringsArray | string | SQLiteCloudCommand, ...values: any[]): Promise<any>;
|
|
42
43
|
/** Disconnect from server, release transport. */
|
|
43
44
|
abstract close(): this;
|
|
44
45
|
}
|
|
@@ -92,34 +92,35 @@ class SQLiteCloudConnection {
|
|
|
92
92
|
* using backticks and parameters in ${parameter} format. These parameters
|
|
93
93
|
* will be properly escaped and quoted like when using a prepared statement.
|
|
94
94
|
* @param sql A sql string or a template string in `backticks` format
|
|
95
|
+
* A SQLiteCloudCommand when the query is defined with question marks and bindings.
|
|
95
96
|
* @returns An array of rows in case of selections or an object with
|
|
96
97
|
* metadata in case of insert, update, delete.
|
|
97
98
|
*/
|
|
98
99
|
sql(sql, ...values) {
|
|
99
100
|
return __awaiter(this, void 0, void 0, function* () {
|
|
100
|
-
let
|
|
101
|
+
let commands = { query: '' };
|
|
101
102
|
// sql is a TemplateStringsArray, the 'raw' property is specific to TemplateStringsArray
|
|
102
103
|
if (Array.isArray(sql) && 'raw' in sql) {
|
|
104
|
+
let query = '';
|
|
103
105
|
sql.forEach((string, i) => {
|
|
104
|
-
|
|
106
|
+
// TemplateStringsArray splits the string before each variable
|
|
107
|
+
// used in the template. Add the question mark
|
|
108
|
+
// to the end of the string for the number of used variables.
|
|
109
|
+
query += string + (i < values.length ? '?' : '');
|
|
105
110
|
});
|
|
106
|
-
|
|
111
|
+
commands = { query, parameters: values };
|
|
112
|
+
}
|
|
113
|
+
else if (typeof sql === 'string') {
|
|
114
|
+
commands = { query: sql, parameters: values };
|
|
115
|
+
}
|
|
116
|
+
else if (typeof sql === 'object') {
|
|
117
|
+
commands = sql;
|
|
107
118
|
}
|
|
108
119
|
else {
|
|
109
|
-
|
|
110
|
-
if ((values === null || values === void 0 ? void 0 : values.length) > 0) {
|
|
111
|
-
preparedSql = (0, utilities_1.prepareSql)(sql, ...values);
|
|
112
|
-
}
|
|
113
|
-
else {
|
|
114
|
-
preparedSql = sql;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
else {
|
|
118
|
-
throw new Error('Invalid sql');
|
|
119
|
-
}
|
|
120
|
+
throw new Error('Invalid sql');
|
|
120
121
|
}
|
|
121
122
|
return new Promise((resolve, reject) => {
|
|
122
|
-
this.sendCommands(
|
|
123
|
+
this.sendCommands(commands, (error, results) => {
|
|
123
124
|
if (error) {
|
|
124
125
|
reject(error);
|
|
125
126
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { SQLiteCloudConfig, RowCountCallback } from './types';
|
|
2
|
-
import { Statement } from './statement';
|
|
1
|
+
import { SQLiteCloudConfig, RowCountCallback, SQLiteCloudCommand } from './types';
|
|
3
2
|
import { ErrorCallback, ResultsCallback, RowCallback, RowsCallback } from './types';
|
|
4
3
|
import EventEmitter from 'eventemitter3';
|
|
5
4
|
import { PubSub } from './pubsub';
|
|
5
|
+
import { Statement } from './statement';
|
|
6
6
|
/**
|
|
7
7
|
* Creating a Database object automatically opens a connection to the SQLite database.
|
|
8
8
|
* When the connection is established the Database object emits an open event and calls
|
|
@@ -151,7 +151,7 @@ export declare class Database extends EventEmitter {
|
|
|
151
151
|
* @returns An array of rows in case of selections or an object with
|
|
152
152
|
* metadata in case of insert, update, delete.
|
|
153
153
|
*/
|
|
154
|
-
sql(sql: TemplateStringsArray | string, ...values: any[]): Promise<any>;
|
|
154
|
+
sql(sql: TemplateStringsArray | string | SQLiteCloudCommand, ...values: any[]): Promise<any>;
|
|
155
155
|
/**
|
|
156
156
|
* PubSub class provides a Pub/Sub real-time updates and notifications system to
|
|
157
157
|
* allow multiple applications to communicate with each other asynchronously.
|
package/lib/drivers/database.js
CHANGED
|
@@ -18,13 +18,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
18
18
|
}) : function(o, v) {
|
|
19
19
|
o["default"] = v;
|
|
20
20
|
});
|
|
21
|
-
var __importStar = (this && this.__importStar) || function (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
};
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
28
38
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
29
39
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
30
40
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -42,10 +52,10 @@ exports.Database = void 0;
|
|
|
42
52
|
const rowset_1 = require("./rowset");
|
|
43
53
|
const types_1 = require("./types");
|
|
44
54
|
const utilities_1 = require("./utilities");
|
|
45
|
-
const statement_1 = require("./statement");
|
|
46
55
|
const eventemitter3_1 = __importDefault(require("eventemitter3"));
|
|
47
56
|
const utilities_2 = require("./utilities");
|
|
48
57
|
const pubsub_1 = require("./pubsub");
|
|
58
|
+
const statement_1 = require("./statement");
|
|
49
59
|
// Uses eventemitter3 instead of node events for browser compatibility
|
|
50
60
|
// https://github.com/primus/eventemitter3
|
|
51
61
|
/**
|
|
@@ -155,9 +165,9 @@ class Database extends eventemitter3_1.default {
|
|
|
155
165
|
switch (results[0]) {
|
|
156
166
|
case types_1.SQLiteCloudArrayType.ARRAY_TYPE_SQLITE_EXEC:
|
|
157
167
|
return {
|
|
158
|
-
lastID: results[2],
|
|
159
|
-
changes: results[3],
|
|
160
|
-
totalChanges: results[4],
|
|
168
|
+
lastID: results[2], // ROWID (sqlite3_last_insert_rowid)
|
|
169
|
+
changes: results[3], // CHANGES(sqlite3_changes)
|
|
170
|
+
totalChanges: results[4], // TOTAL_CHANGES (sqlite3_total_changes)
|
|
161
171
|
finalized: results[5] // FINALIZED
|
|
162
172
|
};
|
|
163
173
|
}
|
|
@@ -198,13 +208,13 @@ class Database extends eventemitter3_1.default {
|
|
|
198
208
|
}
|
|
199
209
|
run(sql, ...params) {
|
|
200
210
|
const { args, callback } = (0, utilities_1.popCallback)(params);
|
|
201
|
-
const
|
|
211
|
+
const command = { query: sql, parameters: args };
|
|
202
212
|
this.getConnection((error, connection) => {
|
|
203
213
|
if (error || !connection) {
|
|
204
214
|
this.handleError(null, error, callback);
|
|
205
215
|
}
|
|
206
216
|
else {
|
|
207
|
-
connection.sendCommands(
|
|
217
|
+
connection.sendCommands(command, (error, results) => {
|
|
208
218
|
if (error) {
|
|
209
219
|
this.handleError(connection, error, callback);
|
|
210
220
|
}
|
|
@@ -220,13 +230,13 @@ class Database extends eventemitter3_1.default {
|
|
|
220
230
|
}
|
|
221
231
|
get(sql, ...params) {
|
|
222
232
|
const { args, callback } = (0, utilities_1.popCallback)(params);
|
|
223
|
-
const
|
|
233
|
+
const command = { query: sql, parameters: args };
|
|
224
234
|
this.getConnection((error, connection) => {
|
|
225
235
|
if (error || !connection) {
|
|
226
236
|
this.handleError(null, error, callback);
|
|
227
237
|
}
|
|
228
238
|
else {
|
|
229
|
-
connection.sendCommands(
|
|
239
|
+
connection.sendCommands(command, (error, results) => {
|
|
230
240
|
if (error) {
|
|
231
241
|
this.handleError(connection, error, callback);
|
|
232
242
|
}
|
|
@@ -245,13 +255,13 @@ class Database extends eventemitter3_1.default {
|
|
|
245
255
|
}
|
|
246
256
|
all(sql, ...params) {
|
|
247
257
|
const { args, callback } = (0, utilities_1.popCallback)(params);
|
|
248
|
-
const
|
|
258
|
+
const command = { query: sql, parameters: args };
|
|
249
259
|
this.getConnection((error, connection) => {
|
|
250
260
|
if (error || !connection) {
|
|
251
261
|
this.handleError(null, error, callback);
|
|
252
262
|
}
|
|
253
263
|
else {
|
|
254
|
-
connection.sendCommands(
|
|
264
|
+
connection.sendCommands(command, (error, results) => {
|
|
255
265
|
if (error) {
|
|
256
266
|
this.handleError(connection, error, callback);
|
|
257
267
|
}
|
|
@@ -271,13 +281,13 @@ class Database extends eventemitter3_1.default {
|
|
|
271
281
|
each(sql, ...params) {
|
|
272
282
|
// extract optional parameters and one or two callbacks
|
|
273
283
|
const { args, callback, complete } = (0, utilities_1.popCallback)(params);
|
|
274
|
-
const
|
|
284
|
+
const command = { query: sql, parameters: args };
|
|
275
285
|
this.getConnection((error, connection) => {
|
|
276
286
|
if (error || !connection) {
|
|
277
287
|
this.handleError(null, error, callback);
|
|
278
288
|
}
|
|
279
289
|
else {
|
|
280
|
-
connection.sendCommands(
|
|
290
|
+
connection.sendCommands(command, (error, rowset) => {
|
|
281
291
|
if (error) {
|
|
282
292
|
this.handleError(connection, error, callback);
|
|
283
293
|
}
|
|
@@ -310,8 +320,7 @@ class Database extends eventemitter3_1.default {
|
|
|
310
320
|
* they are bound to the prepared statement before calling the callback.
|
|
311
321
|
*/
|
|
312
322
|
prepare(sql, ...params) {
|
|
313
|
-
|
|
314
|
-
return new statement_1.Statement(this, sql, ...args, callback);
|
|
323
|
+
return new statement_1.Statement(this, sql, ...params);
|
|
315
324
|
}
|
|
316
325
|
/**
|
|
317
326
|
* Runs all SQL queries in the supplied string. No result rows are retrieved.
|
|
@@ -402,26 +411,26 @@ class Database extends eventemitter3_1.default {
|
|
|
402
411
|
*/
|
|
403
412
|
sql(sql, ...values) {
|
|
404
413
|
return __awaiter(this, void 0, void 0, function* () {
|
|
405
|
-
let
|
|
414
|
+
let commands = { query: '' };
|
|
406
415
|
// sql is a TemplateStringsArray, the 'raw' property is specific to TemplateStringsArray
|
|
407
416
|
if (Array.isArray(sql) && 'raw' in sql) {
|
|
417
|
+
let query = '';
|
|
408
418
|
sql.forEach((string, i) => {
|
|
409
|
-
|
|
419
|
+
// TemplateStringsArray splits the string before each variable
|
|
420
|
+
// used in the template. Add the question mark
|
|
421
|
+
// to the end of the string for the number of used variables.
|
|
422
|
+
query += string + (i < values.length ? '?' : '');
|
|
410
423
|
});
|
|
411
|
-
|
|
424
|
+
commands = { query, parameters: values };
|
|
425
|
+
}
|
|
426
|
+
else if (typeof sql === 'string') {
|
|
427
|
+
commands = { query: sql, parameters: values };
|
|
428
|
+
}
|
|
429
|
+
else if (typeof sql === 'object') {
|
|
430
|
+
commands = sql;
|
|
412
431
|
}
|
|
413
432
|
else {
|
|
414
|
-
|
|
415
|
-
if ((values === null || values === void 0 ? void 0 : values.length) > 0) {
|
|
416
|
-
preparedSql = (0, utilities_1.prepareSql)(sql, ...values);
|
|
417
|
-
}
|
|
418
|
-
else {
|
|
419
|
-
preparedSql = sql;
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
else {
|
|
423
|
-
throw new Error('Invalid sql');
|
|
424
|
-
}
|
|
433
|
+
throw new Error('Invalid sql');
|
|
425
434
|
}
|
|
426
435
|
return new Promise((resolve, reject) => {
|
|
427
436
|
this.getConnection((error, connection) => {
|
|
@@ -429,7 +438,7 @@ class Database extends eventemitter3_1.default {
|
|
|
429
438
|
reject(error);
|
|
430
439
|
}
|
|
431
440
|
else {
|
|
432
|
-
connection.sendCommands(
|
|
441
|
+
connection.sendCommands(commands, (error, results) => {
|
|
433
442
|
if (error) {
|
|
434
443
|
reject(error);
|
|
435
444
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
import { type SQLCloudRowsetMetadata, type SQLiteCloudDataTypes } from './types';
|
|
1
|
+
import { SQLiteCloudCommand, type SQLCloudRowsetMetadata, type SQLiteCloudDataTypes } from './types';
|
|
3
2
|
import { SQLiteCloudRowset } from './rowset';
|
|
3
|
+
import { Buffer } from 'buffer';
|
|
4
4
|
export declare const CMD_STRING = "+";
|
|
5
5
|
export declare const CMD_ZEROSTRING = "!";
|
|
6
6
|
export declare const CMD_ERROR = "-";
|
|
@@ -50,4 +50,4 @@ export declare function popData(buffer: Buffer): {
|
|
|
50
50
|
fwdBuffer: Buffer;
|
|
51
51
|
};
|
|
52
52
|
/** Format a command to be sent via SCSP protocol */
|
|
53
|
-
export declare function formatCommand(command:
|
|
53
|
+
export declare function formatCommand(command: SQLiteCloudCommand): string;
|
package/lib/drivers/protocol.js
CHANGED
|
@@ -3,7 +3,18 @@
|
|
|
3
3
|
// protocol.ts - low level protocol handling for SQLiteCloud transport
|
|
4
4
|
//
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.ROWSET_CHUNKS_END = exports.CMD_PUBSUB = exports.CMD_ARRAY = exports.CMD_COMMAND = exports.CMD_COMPRESSED = exports.CMD_BLOB = exports.CMD_NULL = exports.CMD_JSON = exports.CMD_ROWSET_CHUNK = exports.CMD_ROWSET = exports.CMD_FLOAT = exports.CMD_INT = exports.CMD_ERROR = exports.CMD_ZEROSTRING = exports.CMD_STRING = void 0;
|
|
7
|
+
exports.hasCommandLength = hasCommandLength;
|
|
8
|
+
exports.parseCommandLength = parseCommandLength;
|
|
9
|
+
exports.decompressBuffer = decompressBuffer;
|
|
10
|
+
exports.parseError = parseError;
|
|
11
|
+
exports.parseArray = parseArray;
|
|
12
|
+
exports.parseRowsetHeader = parseRowsetHeader;
|
|
13
|
+
exports.bufferStartsWith = bufferStartsWith;
|
|
14
|
+
exports.bufferEndsWith = bufferEndsWith;
|
|
15
|
+
exports.parseRowsetChunks = parseRowsetChunks;
|
|
16
|
+
exports.popData = popData;
|
|
17
|
+
exports.formatCommand = formatCommand;
|
|
7
18
|
const types_1 = require("./types");
|
|
8
19
|
const rowset_1 = require("./rowset");
|
|
9
20
|
// explicitly importing buffer library to allow cross-platform support by replacing it
|
|
@@ -39,12 +50,10 @@ exports.ROWSET_CHUNKS_END = '/6 0 0 0 ';
|
|
|
39
50
|
function hasCommandLength(firstCharacter) {
|
|
40
51
|
return firstCharacter == exports.CMD_INT || firstCharacter == exports.CMD_FLOAT || firstCharacter == exports.CMD_NULL ? false : true;
|
|
41
52
|
}
|
|
42
|
-
exports.hasCommandLength = hasCommandLength;
|
|
43
53
|
/** Analyze a command with explict LEN and extract it */
|
|
44
54
|
function parseCommandLength(data) {
|
|
45
55
|
return parseInt(data.subarray(1, data.indexOf(' ')).toString('utf8'));
|
|
46
56
|
}
|
|
47
|
-
exports.parseCommandLength = parseCommandLength;
|
|
48
57
|
/** Receive a compressed buffer, decompress with lz4, return buffer and datatype */
|
|
49
58
|
function decompressBuffer(buffer) {
|
|
50
59
|
// https://github.com/sqlitecloud/sdk/blob/master/PROTOCOL.md#scsp-compression
|
|
@@ -64,7 +73,6 @@ function decompressBuffer(buffer) {
|
|
|
64
73
|
let decompressedBuffer = buffer_1.Buffer.alloc(decompressedSize);
|
|
65
74
|
const compressedBuffer = commandBuffer.subarray(commandBuffer.length - compressedSize);
|
|
66
75
|
// lz4js library is javascript and doesn't have types so we silence the type check
|
|
67
|
-
// eslint-disable-next-line
|
|
68
76
|
const decompressionResult = lz4.decompressBlock(compressedBuffer, decompressedBuffer, 0, compressedSize, 0);
|
|
69
77
|
// the entire command is composed of the header (which is not compressed) + the decompressed block
|
|
70
78
|
decompressedBuffer = buffer_1.Buffer.concat([commandBuffer.subarray(0, commandBuffer.length - compressedSize), decompressedBuffer]);
|
|
@@ -73,7 +81,6 @@ function decompressBuffer(buffer) {
|
|
|
73
81
|
}
|
|
74
82
|
return { buffer: decompressedBuffer, dataType, remainingBuffer };
|
|
75
83
|
}
|
|
76
|
-
exports.decompressBuffer = decompressBuffer;
|
|
77
84
|
/** Parse error message or extended error message */
|
|
78
85
|
function parseError(buffer, spaceIndex) {
|
|
79
86
|
const errorBuffer = buffer.subarray(spaceIndex + 1);
|
|
@@ -104,7 +111,6 @@ function parseError(buffer, spaceIndex) {
|
|
|
104
111
|
offsetCode
|
|
105
112
|
});
|
|
106
113
|
}
|
|
107
|
-
exports.parseError = parseError;
|
|
108
114
|
/** Parse an array of items (each of which will be parsed by type separately) */
|
|
109
115
|
function parseArray(buffer, spaceIndex) {
|
|
110
116
|
const parsedData = [];
|
|
@@ -118,7 +124,6 @@ function parseArray(buffer, spaceIndex) {
|
|
|
118
124
|
}
|
|
119
125
|
return parsedData;
|
|
120
126
|
}
|
|
121
|
-
exports.parseArray = parseArray;
|
|
122
127
|
/** Parse header in a rowset or chunk of a chunked rowset */
|
|
123
128
|
function parseRowsetHeader(buffer) {
|
|
124
129
|
const index = parseInt(buffer.subarray(0, buffer.indexOf(':') + 1).toString());
|
|
@@ -138,7 +143,6 @@ function parseRowsetHeader(buffer) {
|
|
|
138
143
|
// console.debug(`parseRowsetHeader`, result)
|
|
139
144
|
return result;
|
|
140
145
|
}
|
|
141
|
-
exports.parseRowsetHeader = parseRowsetHeader;
|
|
142
146
|
/** Extract column names and, optionally, more metadata out of a rowset's header */
|
|
143
147
|
function parseRowsetColumnsMetadata(buffer, metadata) {
|
|
144
148
|
function popForward() {
|
|
@@ -186,11 +190,9 @@ function parseRowset(buffer, spaceIndex) {
|
|
|
186
190
|
function bufferStartsWith(buffer, prefix) {
|
|
187
191
|
return buffer.length >= prefix.length && buffer.subarray(0, prefix.length).toString('utf8') === prefix;
|
|
188
192
|
}
|
|
189
|
-
exports.bufferStartsWith = bufferStartsWith;
|
|
190
193
|
function bufferEndsWith(buffer, suffix) {
|
|
191
194
|
return buffer.length >= suffix.length && buffer.subarray(buffer.length - suffix.length, buffer.length).toString('utf8') === suffix;
|
|
192
195
|
}
|
|
193
|
-
exports.bufferEndsWith = bufferEndsWith;
|
|
194
196
|
/**
|
|
195
197
|
* Parse a chunk of a chunked rowset command, eg:
|
|
196
198
|
* *LEN 0:VERS NROWS NCOLS DATA
|
|
@@ -232,7 +234,6 @@ function parseRowsetChunks(buffers) {
|
|
|
232
234
|
// console.debug(`parseRowsetChunks - ${rowset.numberOfRows} rows, ${rowset.numberOfColumns} columns`)
|
|
233
235
|
return rowset;
|
|
234
236
|
}
|
|
235
|
-
exports.parseRowsetChunks = parseRowsetChunks;
|
|
236
237
|
/** Pop one or more space separated integers from beginning of buffer, move buffer forward */
|
|
237
238
|
function popIntegers(buffer, numberOfIntegers = 1) {
|
|
238
239
|
const data = [];
|
|
@@ -300,10 +301,52 @@ function popData(buffer) {
|
|
|
300
301
|
console.error(msg);
|
|
301
302
|
throw new TypeError(msg);
|
|
302
303
|
}
|
|
303
|
-
exports.popData = popData;
|
|
304
304
|
/** Format a command to be sent via SCSP protocol */
|
|
305
305
|
function formatCommand(command) {
|
|
306
|
-
|
|
307
|
-
|
|
306
|
+
if (command.parameters && command.parameters.length > 0) {
|
|
307
|
+
// by SCSP the string paramenters in the array are zero-terminated
|
|
308
|
+
return serializeCommand([command.query, ...(command.parameters || [])], true);
|
|
309
|
+
}
|
|
310
|
+
return serializeData(command.query, false);
|
|
311
|
+
}
|
|
312
|
+
function serializeCommand(data, zeroString = false) {
|
|
313
|
+
const n = data.length;
|
|
314
|
+
let serializedData = `${n} `;
|
|
315
|
+
for (let i = 0; i < n; i++) {
|
|
316
|
+
// the first string is the sql and it must be zero-terminated
|
|
317
|
+
const zs = i == 0 || zeroString;
|
|
318
|
+
serializedData += serializeData(data[i], zs);
|
|
319
|
+
}
|
|
320
|
+
const header = `${exports.CMD_ARRAY}${serializedData.length} `;
|
|
321
|
+
return header + serializedData;
|
|
322
|
+
}
|
|
323
|
+
function serializeData(data, zeroString = false) {
|
|
324
|
+
if (typeof data === 'string') {
|
|
325
|
+
let cmd = exports.CMD_STRING;
|
|
326
|
+
if (zeroString) {
|
|
327
|
+
cmd = exports.CMD_ZEROSTRING;
|
|
328
|
+
data += '\0';
|
|
329
|
+
}
|
|
330
|
+
const header = `${cmd}${buffer_1.Buffer.byteLength(data, 'utf-8')} `;
|
|
331
|
+
return header + data;
|
|
332
|
+
}
|
|
333
|
+
if (typeof data === 'number') {
|
|
334
|
+
if (Number.isInteger(data)) {
|
|
335
|
+
return `${exports.CMD_INT}${data} `;
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
return `${exports.CMD_FLOAT}${data} `;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
if (buffer_1.Buffer.isBuffer(data)) {
|
|
342
|
+
const header = `${exports.CMD_BLOB}${data.length} `;
|
|
343
|
+
return header + data.toString('utf-8');
|
|
344
|
+
}
|
|
345
|
+
if (data === null || data === undefined) {
|
|
346
|
+
return `${exports.CMD_NULL} `;
|
|
347
|
+
}
|
|
348
|
+
if (Array.isArray(data)) {
|
|
349
|
+
return serializeCommand(data, zeroString);
|
|
350
|
+
}
|
|
351
|
+
throw new Error(`Unsupported data type for serialization: ${typeof data}`);
|
|
308
352
|
}
|
|
309
|
-
exports.formatCommand = formatCommand;
|
package/lib/drivers/pubsub.d.ts
CHANGED
|
@@ -31,6 +31,11 @@ export declare class PubSub {
|
|
|
31
31
|
* @param failIfExists Raise an error if the channel already exists
|
|
32
32
|
*/
|
|
33
33
|
createChannel(name: string, failIfExists?: boolean): Promise<any>;
|
|
34
|
+
/**
|
|
35
|
+
* Deletes a Pub/Sub channel.
|
|
36
|
+
* @param name Channel name
|
|
37
|
+
*/
|
|
38
|
+
removeChannel(name: string): Promise<any>;
|
|
34
39
|
/**
|
|
35
40
|
* Send a message to the channel.
|
|
36
41
|
*/
|
package/lib/drivers/pubsub.js
CHANGED
|
@@ -18,7 +18,7 @@ var PUBSUB_ENTITY_TYPE;
|
|
|
18
18
|
(function (PUBSUB_ENTITY_TYPE) {
|
|
19
19
|
PUBSUB_ENTITY_TYPE["TABLE"] = "TABLE";
|
|
20
20
|
PUBSUB_ENTITY_TYPE["CHANNEL"] = "CHANNEL";
|
|
21
|
-
})(PUBSUB_ENTITY_TYPE
|
|
21
|
+
})(PUBSUB_ENTITY_TYPE || (exports.PUBSUB_ENTITY_TYPE = PUBSUB_ENTITY_TYPE = {}));
|
|
22
22
|
/**
|
|
23
23
|
* Pub/Sub class to receive changes on database tables or to send messages to channels.
|
|
24
24
|
*/
|
|
@@ -71,13 +71,22 @@ class PubSub {
|
|
|
71
71
|
* @param name Channel name
|
|
72
72
|
* @param failIfExists Raise an error if the channel already exists
|
|
73
73
|
*/
|
|
74
|
-
createChannel(
|
|
75
|
-
return __awaiter(this,
|
|
74
|
+
createChannel(name_1) {
|
|
75
|
+
return __awaiter(this, arguments, void 0, function* (name, failIfExists = true) {
|
|
76
76
|
let notExistsCommand = '';
|
|
77
77
|
if (!failIfExists) {
|
|
78
|
-
notExistsCommand = 'IF NOT EXISTS
|
|
78
|
+
notExistsCommand = ' IF NOT EXISTS';
|
|
79
79
|
}
|
|
80
|
-
return this.connection.sql(`CREATE CHANNEL
|
|
80
|
+
return this.connection.sql(`CREATE CHANNEL ?${notExistsCommand};`, name);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Deletes a Pub/Sub channel.
|
|
85
|
+
* @param name Channel name
|
|
86
|
+
*/
|
|
87
|
+
removeChannel(name) {
|
|
88
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
89
|
+
return this.connection.sql(`REMOVE CHANNEL ?;`, name);
|
|
81
90
|
});
|
|
82
91
|
}
|
|
83
92
|
/**
|