@sqlitecloud/drivers 0.0.34

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.
@@ -0,0 +1,398 @@
1
+ "use strict";
2
+ //
3
+ // database.ts - database driver api, implements and extends sqlite3
4
+ //
5
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
6
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
7
+ return new (P || (P = Promise))(function (resolve, reject) {
8
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
9
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
10
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
11
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
12
+ });
13
+ };
14
+ var __importDefault = (this && this.__importDefault) || function (mod) {
15
+ return (mod && mod.__esModule) ? mod : { "default": mod };
16
+ };
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.Database = void 0;
19
+ // Trying as much as possible to be a drop-in replacement for SQLite3 API
20
+ // https://github.com/TryGhost/node-sqlite3/wiki/API
21
+ // https://github.com/TryGhost/node-sqlite3
22
+ // https://github.com/TryGhost/node-sqlite3/blob/master/lib/sqlite3.d.ts
23
+ /* eslint-disable @typescript-eslint/no-unused-vars */
24
+ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */
25
+ const connection_1 = require("./connection");
26
+ const rowset_1 = require("./rowset");
27
+ const types_1 = require("./types");
28
+ const utilities_1 = require("./utilities");
29
+ const statement_1 = require("./statement");
30
+ const eventemitter3_1 = __importDefault(require("eventemitter3"));
31
+ // Uses eventemitter3 instead of node events for browser compatibility
32
+ // https://github.com/primus/eventemitter3
33
+ /**
34
+ * Creating a Database object automatically opens a connection to the SQLite database.
35
+ * When the connection is established the Database object emits an open event and calls
36
+ * the optional provided callback. If the connection cannot be established an error event
37
+ * will be emitted and the optional callback is called with the error information.
38
+ */
39
+ class Database extends eventemitter3_1.default {
40
+ constructor(config, mode, callback) {
41
+ super();
42
+ /** Database connections */
43
+ this.connections = [];
44
+ this.config = typeof config === 'string' ? { connectionString: config } : config;
45
+ // mode is optional and so is callback
46
+ // https://github.com/TryGhost/node-sqlite3/wiki/API#new-sqlite3databasefilename--mode--callback
47
+ if (typeof mode === 'function') {
48
+ callback = mode;
49
+ mode = undefined;
50
+ }
51
+ // mode is ignored for now
52
+ // opens first connection to the database automatically
53
+ this.getConnection(callback);
54
+ }
55
+ //
56
+ // private methods
57
+ //
58
+ /** Returns first available connection from connection pool */
59
+ getConnection(callback) {
60
+ var _a;
61
+ // TODO sqlitecloud-js / implement database connection pool #10
62
+ if (((_a = this.connections) === null || _a === void 0 ? void 0 : _a.length) > 0) {
63
+ callback === null || callback === void 0 ? void 0 : callback.call(this, null, this.connections[0]);
64
+ }
65
+ else {
66
+ this.connections.push(new connection_1.SQLiteCloudConnection(this.config, error => {
67
+ if (error) {
68
+ this.handleError(this.connections[0], error, callback);
69
+ }
70
+ else {
71
+ console.assert;
72
+ callback === null || callback === void 0 ? void 0 : callback.call(this, null, this.connections[0]);
73
+ this.emitEvent('open');
74
+ }
75
+ }));
76
+ }
77
+ }
78
+ /** Handles an error by closing the connection, calling the callback and/or emitting an error event */
79
+ handleError(connection, error, callback) {
80
+ // an errored connection is thrown out
81
+ if (connection) {
82
+ this.connections = this.connections.filter(c => c !== connection);
83
+ connection.close();
84
+ }
85
+ if (callback) {
86
+ callback.call(this, error);
87
+ }
88
+ else {
89
+ this.emitEvent('error', error);
90
+ }
91
+ }
92
+ /**
93
+ * Some queries like inserts or updates processed via run or exec may generate
94
+ * an empty result (eg. no data was selected), but still have some metadata.
95
+ * For example the server may pass the id of the last row that was modified.
96
+ * In this case the callback results should be empty but the context may contain
97
+ * additional information like lastID, etc.
98
+ * @see https://github.com/TryGhost/node-sqlite3/wiki/API#runsql--param---callback
99
+ * @param results Results received from the server
100
+ * @returns A context object if one makes sense, otherwise undefined
101
+ */
102
+ processContext(results) {
103
+ if (results) {
104
+ if (Array.isArray(results) && results.length > 0) {
105
+ switch (results[0]) {
106
+ case types_1.SQLiteCloudArrayType.ARRAY_TYPE_SQLITE_EXEC:
107
+ return {
108
+ lastID: results[2],
109
+ changes: results[3],
110
+ totalChanges: results[4],
111
+ finalized: results[5] // FINALIZED
112
+ };
113
+ }
114
+ }
115
+ }
116
+ return undefined;
117
+ }
118
+ /** Emits given event with optional arguments on the next tick so callbacks can complete first */
119
+ emitEvent(event, ...args) {
120
+ setTimeout(() => {
121
+ this.emit(event, ...args);
122
+ }, 0);
123
+ }
124
+ //
125
+ // public methods
126
+ //
127
+ /**
128
+ * Returns the configuration with which this database was opened.
129
+ * The configuration is readonly and cannot be changed as there may
130
+ * be multiple connections using the same configuration.
131
+ * @returns {SQLiteCloudConfig} A configuration object
132
+ */
133
+ getConfiguration() {
134
+ return JSON.parse(JSON.stringify(this.config));
135
+ }
136
+ /** Enable verbose mode */
137
+ verbose() {
138
+ this.config.verbose = true;
139
+ for (const connection of this.connections) {
140
+ connection.verbose();
141
+ }
142
+ return this;
143
+ }
144
+ /** Set a configuration option for the database */
145
+ configure(_option, _value) {
146
+ // https://github.com/TryGhost/node-sqlite3/wiki/API#configureoption-value
147
+ return this;
148
+ }
149
+ run(sql, ...params) {
150
+ const { args, callback } = (0, utilities_1.popCallback)(params);
151
+ const preparedSql = (args === null || args === void 0 ? void 0 : args.length) > 0 ? (0, utilities_1.prepareSql)(sql, ...args) : sql;
152
+ this.getConnection((error, connection) => {
153
+ if (error || !connection) {
154
+ this.handleError(null, error, callback);
155
+ }
156
+ else {
157
+ connection.sendCommands(preparedSql, (error, results) => {
158
+ if (error) {
159
+ this.handleError(connection, error, callback);
160
+ }
161
+ else {
162
+ // context may include id of last row inserted, total changes, etc...
163
+ const context = this.processContext(results);
164
+ callback === null || callback === void 0 ? void 0 : callback.call(context || this, null, context ? undefined : results);
165
+ }
166
+ });
167
+ }
168
+ });
169
+ return this;
170
+ }
171
+ get(sql, ...params) {
172
+ const { args, callback } = (0, utilities_1.popCallback)(params);
173
+ const preparedSql = (args === null || args === void 0 ? void 0 : args.length) > 0 ? (0, utilities_1.prepareSql)(sql, ...args) : sql;
174
+ this.getConnection((error, connection) => {
175
+ if (error || !connection) {
176
+ this.handleError(null, error, callback);
177
+ }
178
+ else {
179
+ connection.sendCommands(preparedSql, (error, results) => {
180
+ if (error) {
181
+ this.handleError(connection, error, callback);
182
+ }
183
+ else {
184
+ if (results && results instanceof rowset_1.SQLiteCloudRowset && results.length > 0) {
185
+ callback === null || callback === void 0 ? void 0 : callback.call(this, null, results[0]);
186
+ }
187
+ else {
188
+ callback === null || callback === void 0 ? void 0 : callback.call(this, null);
189
+ }
190
+ }
191
+ });
192
+ }
193
+ });
194
+ return this;
195
+ }
196
+ all(sql, ...params) {
197
+ const { args, callback } = (0, utilities_1.popCallback)(params);
198
+ const preparedSql = (args === null || args === void 0 ? void 0 : args.length) > 0 ? (0, utilities_1.prepareSql)(sql, ...args) : sql;
199
+ this.getConnection((error, connection) => {
200
+ if (error || !connection) {
201
+ this.handleError(null, error, callback);
202
+ }
203
+ else {
204
+ connection.sendCommands(preparedSql, (error, results) => {
205
+ if (error) {
206
+ this.handleError(connection, error, callback);
207
+ }
208
+ else {
209
+ if (results && results instanceof rowset_1.SQLiteCloudRowset) {
210
+ callback === null || callback === void 0 ? void 0 : callback.call(this, null, results);
211
+ }
212
+ else {
213
+ callback === null || callback === void 0 ? void 0 : callback.call(this, null);
214
+ }
215
+ }
216
+ });
217
+ }
218
+ });
219
+ return this;
220
+ }
221
+ each(sql, ...params) {
222
+ // extract optional parameters and one or two callbacks
223
+ const { args, callback, complete } = (0, utilities_1.popCallback)(params);
224
+ const preparedSql = (args === null || args === void 0 ? void 0 : args.length) > 0 ? (0, utilities_1.prepareSql)(sql, ...args) : sql;
225
+ this.getConnection((error, connection) => {
226
+ if (error || !connection) {
227
+ this.handleError(null, error, callback);
228
+ }
229
+ else {
230
+ connection.sendCommands(preparedSql, (error, rowset) => {
231
+ if (error) {
232
+ this.handleError(connection, error, callback);
233
+ }
234
+ else {
235
+ if (rowset && rowset instanceof rowset_1.SQLiteCloudRowset) {
236
+ if (callback) {
237
+ for (const row of rowset) {
238
+ callback.call(this, null, row);
239
+ }
240
+ }
241
+ if (complete) {
242
+ ;
243
+ complete.call(this, null, rowset.numberOfRows);
244
+ }
245
+ }
246
+ else {
247
+ callback === null || callback === void 0 ? void 0 : callback.call(this, new types_1.SQLiteCloudError('Invalid rowset'));
248
+ }
249
+ }
250
+ });
251
+ }
252
+ });
253
+ return this;
254
+ }
255
+ /**
256
+ * Prepares the SQL statement and optionally binds the specified parameters and
257
+ * calls the callback when done. The function returns a Statement object.
258
+ * When preparing was successful, the first and only argument to the callback
259
+ * is null, otherwise it is the error object. When bind parameters are supplied,
260
+ * they are bound to the prepared statement before calling the callback.
261
+ */
262
+ prepare(sql, ...params) {
263
+ const { args, callback } = (0, utilities_1.popCallback)(params);
264
+ return new statement_1.Statement(this, sql, ...args, callback);
265
+ }
266
+ /**
267
+ * Runs all SQL queries in the supplied string. No result rows are retrieved.
268
+ * The function returns the Database object to allow for function chaining.
269
+ * If a query fails, no subsequent statements will be executed (wrap it in a
270
+ * transaction if you want all or none to be executed). When all statements
271
+ * have been executed successfully, or when an error occurs, the callback
272
+ * function is called, with the first parameter being either null or an error
273
+ * object. When no callback is provided and an error occurs, an error event
274
+ * will be emitted on the database object.
275
+ */
276
+ exec(sql, callback) {
277
+ this.getConnection((error, connection) => {
278
+ if (error || !connection) {
279
+ this.handleError(null, error, callback);
280
+ }
281
+ else {
282
+ connection.sendCommands(sql, (error, results) => {
283
+ if (error) {
284
+ this.handleError(connection, error, callback);
285
+ }
286
+ else {
287
+ const context = this.processContext(results);
288
+ callback === null || callback === void 0 ? void 0 : callback.call(context ? context : this, null);
289
+ }
290
+ });
291
+ }
292
+ });
293
+ return this;
294
+ }
295
+ /**
296
+ * If the optional callback is provided, this function will be called when the
297
+ * database was closed successfully or when an error occurred. The first argument
298
+ * is an error object. When it is null, closing succeeded. If no callback is provided
299
+ * and an error occurred, an error event with the error object as the only parameter
300
+ * will be emitted on the database object. If closing succeeded, a close event with no
301
+ * parameters is emitted, regardless of whether a callback was provided or not.
302
+ */
303
+ close(callback) {
304
+ var _a;
305
+ if (((_a = this.connections) === null || _a === void 0 ? void 0 : _a.length) > 0) {
306
+ for (const connection of this.connections) {
307
+ connection.close();
308
+ }
309
+ }
310
+ callback === null || callback === void 0 ? void 0 : callback.call(this, null);
311
+ this.emitEvent('close');
312
+ }
313
+ /**
314
+ * Loads a compiled SQLite extension into the database connection object.
315
+ * @param path Filename of the extension to load.
316
+ * @param callback If provided, this function will be called when the extension
317
+ * was loaded successfully or when an error occurred. The first argument is an
318
+ * error object. When it is null, loading succeeded. If no callback is provided
319
+ * and an error occurred, an error event with the error object as the only parameter
320
+ * will be emitted on the database object.
321
+ */
322
+ loadExtension(_path, callback) {
323
+ // TODO sqlitecloud-js / implement database loadExtension #17
324
+ if (callback) {
325
+ callback.call(this, new Error('Database.loadExtension - Not implemented'));
326
+ }
327
+ else {
328
+ this.emitEvent('error', new Error('Database.loadExtension - Not implemented'));
329
+ }
330
+ return this;
331
+ }
332
+ /**
333
+ * Allows the user to interrupt long-running queries. Wrapper around
334
+ * sqlite3_interrupt and causes other data-fetching functions to be
335
+ * passed an err with code = sqlite3.INTERRUPT. The database must be
336
+ * open to use this function.
337
+ */
338
+ interrupt() {
339
+ // TODO sqlitecloud-js / implement database interrupt #13
340
+ }
341
+ //
342
+ // extended APIs
343
+ //
344
+ /**
345
+ * Sql is a promise based API for executing SQL statements. You can
346
+ * pass a simple string with a SQL statement or a template string
347
+ * using backticks and parameters in ${parameter} format. These parameters
348
+ * will be properly escaped and quoted like when using a prepared statement.
349
+ * @param sql A sql string or a template string in `backticks` format
350
+ * @returns An array of rows in case of selections or an object with
351
+ * metadata in case of insert, update, delete.
352
+ */
353
+ sql(sql, ...values) {
354
+ return __awaiter(this, void 0, void 0, function* () {
355
+ let preparedSql = '';
356
+ // sql is a TemplateStringsArray, the 'raw' property is specific to TemplateStringsArray
357
+ if (Array.isArray(sql) && 'raw' in sql) {
358
+ sql.forEach((string, i) => {
359
+ preparedSql += string + (i < values.length ? '?' : '');
360
+ });
361
+ preparedSql = (0, utilities_1.prepareSql)(preparedSql, ...values);
362
+ }
363
+ else {
364
+ if (typeof sql === 'string') {
365
+ if ((values === null || values === void 0 ? void 0 : values.length) > 0) {
366
+ preparedSql = (0, utilities_1.prepareSql)(sql, ...values);
367
+ }
368
+ else {
369
+ preparedSql = sql;
370
+ }
371
+ }
372
+ else {
373
+ throw new Error('Invalid sql');
374
+ }
375
+ }
376
+ return new Promise((resolve, reject) => {
377
+ this.getConnection((error, connection) => {
378
+ if (error || !connection) {
379
+ reject(error);
380
+ }
381
+ else {
382
+ connection.sendCommands(preparedSql, (error, results) => {
383
+ if (error) {
384
+ reject(error);
385
+ }
386
+ else {
387
+ // metadata for operations like insert, update, delete?
388
+ const context = this.processContext(results);
389
+ resolve(context ? context : results);
390
+ }
391
+ });
392
+ }
393
+ });
394
+ });
395
+ });
396
+ }
397
+ }
398
+ exports.Database = Database;
package/lib/index.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ export { Database } from './database';
2
+ export { Statement } from './statement';
3
+ export { SQLiteCloudConfig, SQLCloudRowsetMetadata, SQLiteCloudError, ErrorCallback } from './types';
4
+ export { SQLiteCloudRowset, SQLiteCloudRow } from './rowset';
5
+ export { SQLiteCloudConnection } from './connection';
6
+ export { escapeSqlParameter, prepareSql } from './utilities';
7
+ export { WebSocketTransport } from './transport-ws';
package/lib/index.js ADDED
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ //
3
+ // index.ts - re-export public APIs
4
+ //
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.WebSocketTransport = exports.prepareSql = exports.escapeSqlParameter = exports.SQLiteCloudConnection = exports.SQLiteCloudRow = exports.SQLiteCloudRowset = exports.SQLiteCloudError = exports.Statement = exports.Database = void 0;
7
+ var database_1 = require("./database");
8
+ Object.defineProperty(exports, "Database", { enumerable: true, get: function () { return database_1.Database; } });
9
+ var statement_1 = require("./statement");
10
+ Object.defineProperty(exports, "Statement", { enumerable: true, get: function () { return statement_1.Statement; } });
11
+ var types_1 = require("./types");
12
+ Object.defineProperty(exports, "SQLiteCloudError", { enumerable: true, get: function () { return types_1.SQLiteCloudError; } });
13
+ var rowset_1 = require("./rowset");
14
+ Object.defineProperty(exports, "SQLiteCloudRowset", { enumerable: true, get: function () { return rowset_1.SQLiteCloudRowset; } });
15
+ Object.defineProperty(exports, "SQLiteCloudRow", { enumerable: true, get: function () { return rowset_1.SQLiteCloudRow; } });
16
+ var connection_1 = require("./connection");
17
+ Object.defineProperty(exports, "SQLiteCloudConnection", { enumerable: true, get: function () { return connection_1.SQLiteCloudConnection; } });
18
+ var utilities_1 = require("./utilities");
19
+ Object.defineProperty(exports, "escapeSqlParameter", { enumerable: true, get: function () { return utilities_1.escapeSqlParameter; } });
20
+ Object.defineProperty(exports, "prepareSql", { enumerable: true, get: function () { return utilities_1.prepareSql; } });
21
+ var transport_ws_1 = require("./transport-ws");
22
+ Object.defineProperty(exports, "WebSocketTransport", { enumerable: true, get: function () { return transport_ws_1.WebSocketTransport; } });
@@ -0,0 +1,36 @@
1
+ import { SQLCloudRowsetMetadata, SQLiteCloudDataTypes } from './types';
2
+ /** A single row in a dataset with values accessible by column name */
3
+ export declare class SQLiteCloudRow {
4
+ #private;
5
+ constructor(rowset: SQLiteCloudRowset, columnsNames: string[], data: SQLiteCloudDataTypes[]);
6
+ /** Returns the rowset that this row belongs to */
7
+ getRowset(): SQLiteCloudRowset;
8
+ /** Returns rowset data as a plain array of values */
9
+ getData(): SQLiteCloudDataTypes[];
10
+ /** Column values are accessed by column name */
11
+ [columnName: string]: SQLiteCloudDataTypes;
12
+ }
13
+ export declare class SQLiteCloudRowset extends Array<SQLiteCloudRow> {
14
+ #private;
15
+ constructor(metadata: SQLCloudRowsetMetadata, data: any[]);
16
+ /**
17
+ * Rowset version is 1 for a rowset with simple column names, 2 for extended metadata
18
+ * @see https://github.com/sqlitecloud/sdk/blob/master/PROTOCOL.md
19
+ */
20
+ get version(): number;
21
+ /** Number of rows in row set */
22
+ get numberOfRows(): number;
23
+ /** Number of columns in row set */
24
+ get numberOfColumns(): number;
25
+ /** Array of columns names */
26
+ get columnsNames(): string[];
27
+ /** Get rowset metadata */
28
+ get metadata(): SQLCloudRowsetMetadata;
29
+ /** Return value of item at given row and column */
30
+ getItem(row: number, column: number): any;
31
+ /** Returns a subset of rows from this rowset */
32
+ slice(start?: number, end?: number): SQLiteCloudRow[];
33
+ map(fn: (row: SQLiteCloudRow, index: number, rowset: SQLiteCloudRow[]) => any): any[];
34
+ /** Returns an instance of SQLiteCloudRowset where rows have been filtered via given callback */
35
+ filter(fn: (row: SQLiteCloudRow, index: number, rowset: SQLiteCloudRow[]) => boolean): SQLiteCloudRow[];
36
+ }
package/lib/rowset.js ADDED
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ //
3
+ // rowset.ts
4
+ //
5
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
6
+ if (kind === "m") throw new TypeError("Private method is not writable");
7
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
8
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
9
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
10
+ };
11
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
12
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
13
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
14
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
15
+ };
16
+ var _SQLiteCloudRow_rowset, _SQLiteCloudRow_data, _SQLiteCloudRowset_metadata, _SQLiteCloudRowset_data;
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.SQLiteCloudRowset = exports.SQLiteCloudRow = void 0;
19
+ const types_1 = require("./types");
20
+ /** A single row in a dataset with values accessible by column name */
21
+ class SQLiteCloudRow {
22
+ constructor(rowset, columnsNames, data) {
23
+ // rowset is private
24
+ _SQLiteCloudRow_rowset.set(this, void 0);
25
+ // data is private
26
+ _SQLiteCloudRow_data.set(this, void 0);
27
+ __classPrivateFieldSet(this, _SQLiteCloudRow_rowset, rowset, "f");
28
+ __classPrivateFieldSet(this, _SQLiteCloudRow_data, data, "f");
29
+ for (let i = 0; i < columnsNames.length; i++) {
30
+ this[columnsNames[i]] = data[i];
31
+ }
32
+ }
33
+ /** Returns the rowset that this row belongs to */
34
+ // @ts-expect-error
35
+ getRowset() {
36
+ return __classPrivateFieldGet(this, _SQLiteCloudRow_rowset, "f");
37
+ }
38
+ /** Returns rowset data as a plain array of values */
39
+ // @ts-expect-error
40
+ getData() {
41
+ return __classPrivateFieldGet(this, _SQLiteCloudRow_data, "f");
42
+ }
43
+ }
44
+ exports.SQLiteCloudRow = SQLiteCloudRow;
45
+ _SQLiteCloudRow_rowset = new WeakMap(), _SQLiteCloudRow_data = new WeakMap();
46
+ /* A set of rows returned by a query */
47
+ class SQLiteCloudRowset extends Array {
48
+ constructor(metadata, data) {
49
+ super(metadata.numberOfRows);
50
+ /** Metadata contains number of rows and columns, column names, types, etc. */
51
+ _SQLiteCloudRowset_metadata.set(this, void 0);
52
+ /** Actual data organized in rows */
53
+ _SQLiteCloudRowset_data.set(this, void 0);
54
+ // console.assert(data !== undefined && data.length === metadata.numberOfRows * metadata.numberOfColumns, 'Invalid rowset data')
55
+ // console.assert(metadata !== undefined && metadata.columns.length === metadata.numberOfColumns, 'Invalid columns metadata')
56
+ __classPrivateFieldSet(this, _SQLiteCloudRowset_metadata, metadata, "f");
57
+ __classPrivateFieldSet(this, _SQLiteCloudRowset_data, data, "f");
58
+ // adjust missing column names, duplicate column names, etc.
59
+ const columnNames = this.columnsNames;
60
+ for (let i = 0; i < metadata.numberOfColumns; i++) {
61
+ if (!columnNames[i]) {
62
+ columnNames[i] = `column_${i}`;
63
+ }
64
+ let j = 0;
65
+ while (columnNames.findIndex((name, index) => index !== i && name === columnNames[i]) >= 0) {
66
+ columnNames[i] = `${columnNames[i]}_${j}`;
67
+ j++;
68
+ }
69
+ }
70
+ for (let i = 0, start = 0; i < metadata.numberOfRows; i++, start += metadata.numberOfColumns) {
71
+ this[i] = new SQLiteCloudRow(this, columnNames, data.slice(start, start + metadata.numberOfColumns));
72
+ }
73
+ }
74
+ /**
75
+ * Rowset version is 1 for a rowset with simple column names, 2 for extended metadata
76
+ * @see https://github.com/sqlitecloud/sdk/blob/master/PROTOCOL.md
77
+ */
78
+ get version() {
79
+ return __classPrivateFieldGet(this, _SQLiteCloudRowset_metadata, "f").version;
80
+ }
81
+ /** Number of rows in row set */
82
+ get numberOfRows() {
83
+ return __classPrivateFieldGet(this, _SQLiteCloudRowset_metadata, "f").numberOfRows;
84
+ }
85
+ /** Number of columns in row set */
86
+ get numberOfColumns() {
87
+ return __classPrivateFieldGet(this, _SQLiteCloudRowset_metadata, "f").numberOfColumns;
88
+ }
89
+ /** Array of columns names */
90
+ get columnsNames() {
91
+ return __classPrivateFieldGet(this, _SQLiteCloudRowset_metadata, "f").columns.map(column => column.name);
92
+ }
93
+ /** Get rowset metadata */
94
+ get metadata() {
95
+ return __classPrivateFieldGet(this, _SQLiteCloudRowset_metadata, "f");
96
+ }
97
+ /** Return value of item at given row and column */
98
+ getItem(row, column) {
99
+ if (row < 0 || row >= this.numberOfRows || column < 0 || column >= this.numberOfColumns) {
100
+ throw new types_1.SQLiteCloudError(`This rowset has ${this.numberOfColumns} columns by ${this.numberOfRows} rows, requested column ${column} and row ${row} is invalid.`);
101
+ }
102
+ return __classPrivateFieldGet(this, _SQLiteCloudRowset_data, "f")[row * this.numberOfColumns + column];
103
+ }
104
+ /** Returns a subset of rows from this rowset */
105
+ slice(start, end) {
106
+ // validate and apply boundaries
107
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice
108
+ start = start === undefined ? 0 : start < 0 ? this.numberOfRows + start : start;
109
+ start = Math.min(Math.max(start, 0), this.numberOfRows);
110
+ end = end === undefined ? this.numberOfRows : end < 0 ? this.numberOfRows + end : end;
111
+ end = Math.min(Math.max(start, end), this.numberOfRows);
112
+ const slicedMetadata = Object.assign(Object.assign({}, __classPrivateFieldGet(this, _SQLiteCloudRowset_metadata, "f")), { numberOfRows: end - start });
113
+ const slicedData = __classPrivateFieldGet(this, _SQLiteCloudRowset_data, "f").slice(start * this.numberOfColumns, end * this.numberOfColumns);
114
+ console.assert(slicedData && slicedData.length === slicedMetadata.numberOfRows * slicedMetadata.numberOfColumns, 'SQLiteCloudRowset.slice - invalid rowset data');
115
+ return new SQLiteCloudRowset(slicedMetadata, slicedData);
116
+ }
117
+ map(fn) {
118
+ const results = [];
119
+ for (let i = 0; i < this.numberOfRows; i++) {
120
+ const row = this[i];
121
+ results.push(fn(row, i, this));
122
+ }
123
+ return results;
124
+ }
125
+ /** Returns an instance of SQLiteCloudRowset where rows have been filtered via given callback */
126
+ filter(fn) {
127
+ const filteredData = [];
128
+ for (let i = 0; i < this.numberOfRows; i++) {
129
+ const row = this[i];
130
+ if (fn(row, i, this)) {
131
+ filteredData.push(...__classPrivateFieldGet(this, _SQLiteCloudRowset_data, "f").slice(i * this.numberOfColumns, (i + 1) * this.numberOfColumns));
132
+ }
133
+ }
134
+ return new SQLiteCloudRowset(Object.assign(Object.assign({}, __classPrivateFieldGet(this, _SQLiteCloudRowset_metadata, "f")), { numberOfRows: filteredData.length / this.numberOfColumns }), filteredData);
135
+ }
136
+ }
137
+ exports.SQLiteCloudRowset = SQLiteCloudRowset;
138
+ _SQLiteCloudRowset_metadata = new WeakMap(), _SQLiteCloudRowset_data = new WeakMap();