@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 CHANGED
@@ -1,7 +1,7 @@
1
1
  # @sqlitecloud/drivers
2
2
 
3
3
  [![npm package][npm-img]][npm-url]
4
- [![Build Status][build-img]][build-url]
4
+ [![Test][test-img]][test-url]
5
5
  [![Downloads][downloads-img]][downloads-url]
6
6
  [![Issues][issues-img]][issues-url]
7
7
  [![codecov](https://codecov.io/gh/sqlitecloud/sqlitecloud-js/graph/badge.svg?token=ZOKE9WFH62)](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
- [build-img]: https://github.com/sqlitecloud/sqlitecloud-js/actions/workflows/build-test-deploy.yml/badge.svg
111
- [build-url]: https://github.com/sqlitecloud/sqlitecloud-js/actions/workflows/build-test-deploy.yml
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 (mod) {
22
- if (mod && mod.__esModule) return mod;
23
- var result = {};
24
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
25
- __setModuleDefault(result, mod);
26
- return result;
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
- this.socket.emit('v1/sql', { sql: commands, row: 'array' }, (response) => {
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 preparedSql = '';
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
- preparedSql += string + (i < values.length ? '?' : '');
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
- preparedSql = (0, utilities_1.prepareSql)(preparedSql, ...values);
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
- if (typeof sql === 'string') {
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(preparedSql, (error, results) => {
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.
@@ -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 (mod) {
22
- if (mod && mod.__esModule) return mod;
23
- var result = {};
24
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
25
- __setModuleDefault(result, mod);
26
- return result;
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 preparedSql = (args === null || args === void 0 ? void 0 : args.length) > 0 ? (0, utilities_1.prepareSql)(sql, ...args) : sql;
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(preparedSql, (error, results) => {
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 preparedSql = (args === null || args === void 0 ? void 0 : args.length) > 0 ? (0, utilities_1.prepareSql)(sql, ...args) : sql;
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(preparedSql, (error, results) => {
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 preparedSql = (args === null || args === void 0 ? void 0 : args.length) > 0 ? (0, utilities_1.prepareSql)(sql, ...args) : sql;
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(preparedSql, (error, results) => {
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 preparedSql = (args === null || args === void 0 ? void 0 : args.length) > 0 ? (0, utilities_1.prepareSql)(sql, ...args) : sql;
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(preparedSql, (error, rowset) => {
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
- const { args, callback } = (0, utilities_1.popCallback)(params);
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 preparedSql = '';
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
- preparedSql += string + (i < values.length ? '?' : '');
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
- preparedSql = (0, utilities_1.prepareSql)(preparedSql, ...values);
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
- if (typeof sql === 'string') {
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(preparedSql, (error, results) => {
441
+ connection.sendCommands(commands, (error, results) => {
433
442
  if (error) {
434
443
  reject(error);
435
444
  }
@@ -1,6 +1,6 @@
1
- /// <reference types="node" />
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: string): string;
53
+ export declare function formatCommand(command: SQLiteCloudCommand): string;
@@ -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.formatCommand = exports.popData = exports.parseRowsetChunks = exports.bufferEndsWith = exports.bufferStartsWith = exports.parseRowsetHeader = exports.parseArray = exports.parseError = exports.decompressBuffer = exports.parseCommandLength = exports.hasCommandLength = 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;
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
- const commandLength = buffer_1.Buffer.byteLength(command, 'utf-8');
307
- return `+${commandLength} ${command}`;
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;
@@ -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
  */
@@ -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 = exports.PUBSUB_ENTITY_TYPE || (exports.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(name, failIfExists = true) {
75
- return __awaiter(this, void 0, void 0, function* () {
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 ? ${notExistsCommand}`, name);
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
  /**