@powersync/web 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,212 +1,181 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- var __asyncValues = (this && this.__asyncValues) || function (o) {
11
- if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
12
- var m = o[Symbol.asyncIterator], i;
13
- return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
14
- function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
15
- function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
16
- };
17
1
  import * as SQLite from '@journeyapps/wa-sqlite';
18
2
  import '@journeyapps/wa-sqlite';
19
3
  import * as Comlink from 'comlink';
20
4
  import { Mutex } from 'async-mutex';
21
5
  let nextId = 1;
22
- export function _openDB(dbFileName_1) {
23
- return __awaiter(this, arguments, void 0, function* (dbFileName, options = { useWebWorker: true }) {
24
- const { default: moduleFactory } = yield import('@journeyapps/wa-sqlite/dist/wa-sqlite-async.mjs');
25
- const module = yield moduleFactory();
26
- const sqlite3 = SQLite.Factory(module);
27
- const { IDBBatchAtomicVFS } = yield import('@journeyapps/wa-sqlite/src/examples/IDBBatchAtomicVFS.js');
28
- const vfs = new IDBBatchAtomicVFS(dbFileName);
29
- sqlite3.vfs_register(vfs, true);
30
- const db = yield sqlite3.open_v2(dbFileName);
31
- const statementMutex = new Mutex();
32
- /**
33
- * Listeners are exclusive to the DB connection.
34
- */
35
- const listeners = new Map();
36
- sqlite3.register_table_onchange_hook(db, (opType, tableName, rowId) => {
37
- Array.from(listeners.values()).forEach((l) => l(opType, tableName, rowId));
38
- });
39
- /**
40
- * This executes single SQL statements inside a requested lock.
41
- */
42
- const execute = (sql, bindings) => __awaiter(this, void 0, void 0, function* () {
43
- // Running multiple statements on the same connection concurrently should not be allowed
44
- return _acquireExecuteLock(() => __awaiter(this, void 0, void 0, function* () {
45
- return executeSingleStatement(sql, bindings);
46
- }));
6
+ export async function _openDB(dbFileName, options = { useWebWorker: true }) {
7
+ const { default: moduleFactory } = await import('@journeyapps/wa-sqlite/dist/wa-sqlite-async.mjs');
8
+ const module = await moduleFactory();
9
+ const sqlite3 = SQLite.Factory(module);
10
+ const { IDBBatchAtomicVFS } = await import('@journeyapps/wa-sqlite/src/examples/IDBBatchAtomicVFS.js');
11
+ const vfs = new IDBBatchAtomicVFS(dbFileName);
12
+ sqlite3.vfs_register(vfs, true);
13
+ const db = await sqlite3.open_v2(dbFileName);
14
+ const statementMutex = new Mutex();
15
+ /**
16
+ * Listeners are exclusive to the DB connection.
17
+ */
18
+ const listeners = new Map();
19
+ sqlite3.register_table_onchange_hook(db, (opType, tableName, rowId) => {
20
+ Array.from(listeners.values()).forEach((l) => l(opType, tableName, rowId));
21
+ });
22
+ /**
23
+ * This executes single SQL statements inside a requested lock.
24
+ */
25
+ const execute = async (sql, bindings) => {
26
+ // Running multiple statements on the same connection concurrently should not be allowed
27
+ return _acquireExecuteLock(async () => {
28
+ return executeSingleStatement(sql, bindings);
47
29
  });
48
- /**
49
- * This requests a lock for executing statements.
50
- * Should only be used internally.
51
- */
52
- const _acquireExecuteLock = (callback) => {
53
- return statementMutex.runExclusive(callback);
54
- };
55
- /**
56
- * This executes a single statement using SQLite3.
57
- */
58
- const executeSingleStatement = (sql, bindings) => __awaiter(this, void 0, void 0, function* () {
59
- var _a, e_1, _b, _c;
60
- const results = [];
61
- try {
62
- for (var _d = true, _e = __asyncValues(sqlite3.statements(db, sql)), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
63
- _c = _f.value;
64
- _d = false;
65
- const stmt = _c;
66
- let columns;
67
- const wrappedBindings = bindings ? [bindings] : [[]];
68
- for (const binding of wrappedBindings) {
69
- // TODO not sure why this is needed currently, but booleans break
70
- binding.forEach((b, index, arr) => {
71
- if (typeof b == 'boolean') {
72
- arr[index] = b ? 1 : 0;
73
- }
74
- });
75
- sqlite3.reset(stmt);
76
- if (bindings) {
77
- sqlite3.bind_collection(stmt, binding);
78
- }
79
- const rows = [];
80
- while ((yield sqlite3.step(stmt)) === SQLite.SQLITE_ROW) {
81
- const row = sqlite3.row(stmt);
82
- rows.push(row);
83
- }
84
- columns = columns !== null && columns !== void 0 ? columns : sqlite3.column_names(stmt);
85
- if (columns.length) {
86
- results.push({ columns, rows });
87
- }
88
- }
89
- // When binding parameters, only a single statement is executed.
90
- if (bindings) {
91
- break;
30
+ };
31
+ /**
32
+ * This requests a lock for executing statements.
33
+ * Should only be used internally.
34
+ */
35
+ const _acquireExecuteLock = (callback) => {
36
+ return statementMutex.runExclusive(callback);
37
+ };
38
+ /**
39
+ * This executes a single statement using SQLite3.
40
+ */
41
+ const executeSingleStatement = async (sql, bindings) => {
42
+ const results = [];
43
+ for await (const stmt of sqlite3.statements(db, sql)) {
44
+ let columns;
45
+ const wrappedBindings = bindings ? [bindings] : [[]];
46
+ for (const binding of wrappedBindings) {
47
+ // TODO not sure why this is needed currently, but booleans break
48
+ binding.forEach((b, index, arr) => {
49
+ if (typeof b == 'boolean') {
50
+ arr[index] = b ? 1 : 0;
92
51
  }
52
+ });
53
+ sqlite3.reset(stmt);
54
+ if (bindings) {
55
+ sqlite3.bind_collection(stmt, binding);
93
56
  }
94
- }
95
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
96
- finally {
97
- try {
98
- if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
57
+ const rows = [];
58
+ while ((await sqlite3.step(stmt)) === SQLite.SQLITE_ROW) {
59
+ const row = sqlite3.row(stmt);
60
+ rows.push(row);
99
61
  }
100
- finally { if (e_1) throw e_1.error; }
101
- }
102
- const rows = [];
103
- for (const resultset of results) {
104
- for (const row of resultset.rows) {
105
- const outRow = {};
106
- resultset.columns.forEach((key, index) => {
107
- outRow[key] = row[index];
108
- });
109
- rows.push(outRow);
62
+ columns = columns ?? sqlite3.column_names(stmt);
63
+ if (columns.length) {
64
+ results.push({ columns, rows });
110
65
  }
111
66
  }
112
- const result = {
113
- insertId: sqlite3.last_insert_id(db),
114
- rowsAffected: sqlite3.changes(db),
115
- rows: {
116
- _array: rows,
117
- length: rows.length
118
- }
119
- };
120
- return result;
121
- });
122
- /**
123
- * This executes SQL statements in a batch.
124
- */
125
- const executeBatch = (sql, bindings) => __awaiter(this, void 0, void 0, function* () {
126
- return _acquireExecuteLock(() => __awaiter(this, void 0, void 0, function* () {
127
- let affectedRows = 0;
128
- const str = sqlite3.str_new(db, sql);
129
- const query = sqlite3.str_value(str);
130
- try {
131
- yield executeSingleStatement('BEGIN TRANSACTION');
132
- //Prepare statement once
133
- const prepared = yield sqlite3.prepare_v2(db, query);
134
- if (prepared === null) {
135
- return {
136
- rowsAffected: 0,
137
- rows: { _array: [], length: 0 }
138
- };
139
- }
140
- const wrappedBindings = bindings ? bindings : [];
141
- for (const binding of wrappedBindings) {
142
- // TODO not sure why this is needed currently, but booleans break
143
- for (let i = 0; i < binding.length; i++) {
144
- const b = binding[i];
145
- if (typeof b == 'boolean') {
146
- binding[i] = b ? 1 : 0;
147
- }
148
- }
149
- //Reset bindings
150
- sqlite3.reset(prepared.stmt);
151
- if (bindings) {
152
- sqlite3.bind_collection(prepared.stmt, binding);
153
- }
154
- const result = yield sqlite3.step(prepared.stmt);
155
- if (result === SQLite.SQLITE_DONE) {
156
- //The value returned by sqlite3_changes() immediately after an INSERT, UPDATE or DELETE statement run on a view is always zero.
157
- affectedRows += sqlite3.changes(db);
158
- }
159
- }
160
- //Finalize prepared statement
161
- yield sqlite3.finalize(prepared.stmt);
162
- yield executeSingleStatement('COMMIT');
163
- }
164
- catch (err) {
165
- yield executeSingleStatement('ROLLBACK');
67
+ // When binding parameters, only a single statement is executed.
68
+ if (bindings) {
69
+ break;
70
+ }
71
+ }
72
+ const rows = [];
73
+ for (const resultset of results) {
74
+ for (const row of resultset.rows) {
75
+ const outRow = {};
76
+ resultset.columns.forEach((key, index) => {
77
+ outRow[key] = row[index];
78
+ });
79
+ rows.push(outRow);
80
+ }
81
+ }
82
+ const result = {
83
+ insertId: sqlite3.last_insert_id(db),
84
+ rowsAffected: sqlite3.changes(db),
85
+ rows: {
86
+ _array: rows,
87
+ length: rows.length
88
+ }
89
+ };
90
+ return result;
91
+ };
92
+ /**
93
+ * This executes SQL statements in a batch.
94
+ */
95
+ const executeBatch = async (sql, bindings) => {
96
+ return _acquireExecuteLock(async () => {
97
+ let affectedRows = 0;
98
+ const str = sqlite3.str_new(db, sql);
99
+ const query = sqlite3.str_value(str);
100
+ try {
101
+ await executeSingleStatement('BEGIN TRANSACTION');
102
+ //Prepare statement once
103
+ const prepared = await sqlite3.prepare_v2(db, query);
104
+ if (prepared === null) {
166
105
  return {
167
106
  rowsAffected: 0,
168
107
  rows: { _array: [], length: 0 }
169
108
  };
170
109
  }
171
- finally {
172
- sqlite3.str_finish(str);
110
+ const wrappedBindings = bindings ? bindings : [];
111
+ for (const binding of wrappedBindings) {
112
+ // TODO not sure why this is needed currently, but booleans break
113
+ for (let i = 0; i < binding.length; i++) {
114
+ const b = binding[i];
115
+ if (typeof b == 'boolean') {
116
+ binding[i] = b ? 1 : 0;
117
+ }
118
+ }
119
+ //Reset bindings
120
+ sqlite3.reset(prepared.stmt);
121
+ if (bindings) {
122
+ sqlite3.bind_collection(prepared.stmt, binding);
123
+ }
124
+ const result = await sqlite3.step(prepared.stmt);
125
+ if (result === SQLite.SQLITE_DONE) {
126
+ //The value returned by sqlite3_changes() immediately after an INSERT, UPDATE or DELETE statement run on a view is always zero.
127
+ affectedRows += sqlite3.changes(db);
128
+ }
173
129
  }
174
- const result = {
175
- rowsAffected: affectedRows,
130
+ //Finalize prepared statement
131
+ await sqlite3.finalize(prepared.stmt);
132
+ await executeSingleStatement('COMMIT');
133
+ }
134
+ catch (err) {
135
+ await executeSingleStatement('ROLLBACK');
136
+ return {
137
+ rowsAffected: 0,
176
138
  rows: { _array: [], length: 0 }
177
139
  };
178
- return result;
179
- }));
180
- });
181
- if (options.useWebWorker) {
182
- const registerOnTableChange = (callback) => {
183
- const id = nextId++;
184
- listeners.set(id, callback);
185
- return Comlink.proxy(() => {
186
- listeners.delete(id);
187
- });
188
- };
189
- return {
190
- execute: Comlink.proxy(execute),
191
- executeBatch: Comlink.proxy(executeBatch),
192
- registerOnTableChange: Comlink.proxy(registerOnTableChange),
193
- close: Comlink.proxy(() => {
194
- sqlite3.close(db);
195
- })
140
+ }
141
+ finally {
142
+ sqlite3.str_finish(str);
143
+ }
144
+ const result = {
145
+ rowsAffected: affectedRows,
146
+ rows: { _array: [], length: 0 }
196
147
  };
197
- }
148
+ return result;
149
+ });
150
+ };
151
+ if (options.useWebWorker) {
198
152
  const registerOnTableChange = (callback) => {
199
153
  const id = nextId++;
200
154
  listeners.set(id, callback);
201
- return () => {
155
+ return Comlink.proxy(() => {
202
156
  listeners.delete(id);
203
- };
157
+ });
204
158
  };
205
159
  return {
206
- execute: execute,
207
- executeBatch: executeBatch,
208
- registerOnTableChange: registerOnTableChange,
209
- close: () => sqlite3.close(db)
160
+ execute: Comlink.proxy(execute),
161
+ executeBatch: Comlink.proxy(executeBatch),
162
+ registerOnTableChange: Comlink.proxy(registerOnTableChange),
163
+ close: Comlink.proxy(() => {
164
+ sqlite3.close(db);
165
+ })
210
166
  };
211
- });
167
+ }
168
+ const registerOnTableChange = (callback) => {
169
+ const id = nextId++;
170
+ listeners.set(id, callback);
171
+ return () => {
172
+ listeners.delete(id);
173
+ };
174
+ };
175
+ return {
176
+ execute: execute,
177
+ executeBatch: executeBatch,
178
+ registerOnTableChange: registerOnTableChange,
179
+ close: () => sqlite3.close(db)
180
+ };
212
181
  }
@@ -1,12 +1,3 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
1
  import '@journeyapps/wa-sqlite';
11
2
  import * as Comlink from 'comlink';
12
3
  import { _openDB } from '../../shared/open-db';
@@ -14,13 +5,13 @@ const _self = self;
14
5
  const DBMap = new Map();
15
6
  const OPEN_DB_LOCK = 'open-wasqlite-db';
16
7
  let nextClientId = 1;
17
- const openDB = (dbFileName) => __awaiter(void 0, void 0, void 0, function* () {
8
+ const openDB = async (dbFileName) => {
18
9
  // Prevent multiple simultaneous opens from causing race conditions
19
- return navigator.locks.request(OPEN_DB_LOCK, () => __awaiter(void 0, void 0, void 0, function* () {
10
+ return navigator.locks.request(OPEN_DB_LOCK, async () => {
20
11
  const clientId = nextClientId++;
21
12
  if (!DBMap.has(dbFileName)) {
22
13
  const clientIds = new Set();
23
- const connection = yield _openDB(dbFileName);
14
+ const connection = await _openDB(dbFileName);
24
15
  DBMap.set(dbFileName, {
25
16
  clientIds,
26
17
  db: connection
@@ -29,29 +20,30 @@ const openDB = (dbFileName) => __awaiter(void 0, void 0, void 0, function* () {
29
20
  const dbEntry = DBMap.get(dbFileName);
30
21
  dbEntry.clientIds.add(clientId);
31
22
  const { db } = dbEntry;
32
- const wrappedConnection = Object.assign(Object.assign({}, db), { close: Comlink.proxy(() => {
33
- var _a;
23
+ const wrappedConnection = {
24
+ ...db,
25
+ close: Comlink.proxy(() => {
34
26
  const { clientIds } = dbEntry;
35
27
  clientIds.delete(clientId);
36
28
  if (clientIds.size == 0) {
37
29
  console.debug(`Closing connection to ${dbFileName}.`);
38
30
  DBMap.delete(dbFileName);
39
- return (_a = db.close) === null || _a === void 0 ? void 0 : _a.call(db);
31
+ return db.close?.();
40
32
  }
41
33
  console.debug(`Connection to ${dbFileName} not closed yet due to active clients.`);
42
- }) });
34
+ })
35
+ };
43
36
  return Comlink.proxy(wrappedConnection);
44
- }));
45
- });
37
+ });
38
+ };
46
39
  _self.onconnect = function (event) {
47
40
  const port = event.ports[0];
48
41
  console.debug('Exposing db on port', port);
49
42
  Comlink.expose(openDB, port);
50
43
  };
51
44
  addEventListener('unload', () => {
52
- Array.from(DBMap.values()).forEach((dbConnection) => __awaiter(void 0, void 0, void 0, function* () {
53
- var _a;
54
- const db = yield dbConnection.db;
55
- (_a = db.close) === null || _a === void 0 ? void 0 : _a.call(db);
56
- }));
45
+ Array.from(DBMap.values()).forEach(async (dbConnection) => {
46
+ const db = await dbConnection.db;
47
+ db.close?.();
48
+ });
57
49
  });
@@ -1,12 +1,3 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
1
  import * as Comlink from 'comlink';
11
2
  import { _openDB } from '../../shared/open-db';
12
- Comlink.expose((dbFileName) => __awaiter(void 0, void 0, void 0, function* () { return Comlink.proxy(yield _openDB(dbFileName)); }));
3
+ Comlink.expose(async (dbFileName) => Comlink.proxy(await _openDB(dbFileName)));
@@ -1,17 +1,16 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
1
  import Logger from 'js-logger';
11
2
  /**
12
3
  * Broadcasts logs to all clients
13
4
  */
14
5
  export class BroadcastLogger {
6
+ clients;
7
+ TRACE;
8
+ DEBUG;
9
+ INFO;
10
+ TIME;
11
+ WARN;
12
+ ERROR;
13
+ OFF;
15
14
  constructor(clients) {
16
15
  this.clients = clients;
17
16
  this.TRACE = Logger.TRACE;
@@ -75,17 +74,15 @@ export class BroadcastLogger {
75
74
  * Iterates all clients, catches individual client exceptions
76
75
  * and proceeds to execute for all clients.
77
76
  */
78
- iterateClients(callback) {
79
- return __awaiter(this, void 0, void 0, function* () {
80
- for (const client of this.clients) {
81
- try {
82
- yield callback(client);
83
- }
84
- catch (ex) {
85
- console.error('Caught exception when iterating client', ex);
86
- }
77
+ async iterateClients(callback) {
78
+ for (const client of this.clients) {
79
+ try {
80
+ await callback(client);
87
81
  }
88
- });
82
+ catch (ex) {
83
+ console.error('Caught exception when iterating client', ex);
84
+ }
85
+ }
89
86
  }
90
87
  /**
91
88
  * Guards against any logging errors.