@powersync/web 0.0.0-dev-20240723112746 → 0.0.0-dev-20240726145924

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,181 +1,212 @@
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
+ };
1
17
  import * as SQLite from '@journeyapps/wa-sqlite';
2
18
  import '@journeyapps/wa-sqlite';
3
19
  import * as Comlink from 'comlink';
4
20
  import { Mutex } from 'async-mutex';
5
21
  let nextId = 1;
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);
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));
29
38
  });
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;
51
- }
52
- });
53
- sqlite3.reset(stmt);
54
- if (bindings) {
55
- sqlite3.bind_collection(stmt, binding);
56
- }
57
- const rows = [];
58
- while ((await sqlite3.step(stmt)) === SQLite.SQLITE_ROW) {
59
- const row = sqlite3.row(stmt);
60
- rows.push(row);
61
- }
62
- columns = columns ?? sqlite3.column_names(stmt);
63
- if (columns.length) {
64
- results.push({ columns, rows });
65
- }
66
- }
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
- }
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
+ }));
47
+ });
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);
89
54
  };
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);
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 = [];
100
61
  try {
101
- await executeSingleStatement('BEGIN TRANSACTION');
102
- //Prepare statement once
103
- const prepared = await sqlite3.prepare_v2(db, query);
104
- if (prepared === null) {
105
- return {
106
- rowsAffected: 0,
107
- rows: { _array: [], length: 0 }
108
- };
109
- }
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;
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 });
117
87
  }
118
88
  }
119
- //Reset bindings
120
- sqlite3.reset(prepared.stmt);
89
+ // When binding parameters, only a single statement is executed.
121
90
  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);
91
+ break;
128
92
  }
129
93
  }
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,
138
- rows: { _array: [], length: 0 }
139
- };
140
94
  }
95
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
141
96
  finally {
142
- sqlite3.str_finish(str);
97
+ try {
98
+ if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
99
+ }
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);
110
+ }
143
111
  }
144
112
  const result = {
145
- rowsAffected: affectedRows,
146
- rows: { _array: [], length: 0 }
113
+ insertId: sqlite3.last_insert_id(db),
114
+ rowsAffected: sqlite3.changes(db),
115
+ rows: {
116
+ _array: rows,
117
+ length: rows.length
118
+ }
147
119
  };
148
120
  return result;
149
121
  });
150
- };
151
- if (options.useWebWorker) {
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');
166
+ return {
167
+ rowsAffected: 0,
168
+ rows: { _array: [], length: 0 }
169
+ };
170
+ }
171
+ finally {
172
+ sqlite3.str_finish(str);
173
+ }
174
+ const result = {
175
+ rowsAffected: affectedRows,
176
+ rows: { _array: [], length: 0 }
177
+ };
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
+ })
196
+ };
197
+ }
152
198
  const registerOnTableChange = (callback) => {
153
199
  const id = nextId++;
154
200
  listeners.set(id, callback);
155
- return Comlink.proxy(() => {
201
+ return () => {
156
202
  listeners.delete(id);
157
- });
203
+ };
158
204
  };
159
205
  return {
160
- execute: Comlink.proxy(execute),
161
- executeBatch: Comlink.proxy(executeBatch),
162
- registerOnTableChange: Comlink.proxy(registerOnTableChange),
163
- close: Comlink.proxy(() => {
164
- sqlite3.close(db);
165
- })
166
- };
167
- }
168
- const registerOnTableChange = (callback) => {
169
- const id = nextId++;
170
- listeners.set(id, callback);
171
- return () => {
172
- listeners.delete(id);
206
+ execute: execute,
207
+ executeBatch: executeBatch,
208
+ registerOnTableChange: registerOnTableChange,
209
+ close: () => sqlite3.close(db)
173
210
  };
174
- };
175
- return {
176
- execute: execute,
177
- executeBatch: executeBatch,
178
- registerOnTableChange: registerOnTableChange,
179
- close: () => sqlite3.close(db)
180
- };
211
+ });
181
212
  }
@@ -1,3 +1,12 @@
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
+ };
1
10
  import '@journeyapps/wa-sqlite';
2
11
  import * as Comlink from 'comlink';
3
12
  import { _openDB } from '../../shared/open-db';
@@ -5,13 +14,13 @@ const _self = self;
5
14
  const DBMap = new Map();
6
15
  const OPEN_DB_LOCK = 'open-wasqlite-db';
7
16
  let nextClientId = 1;
8
- const openDB = async (dbFileName) => {
17
+ const openDB = (dbFileName) => __awaiter(void 0, void 0, void 0, function* () {
9
18
  // Prevent multiple simultaneous opens from causing race conditions
10
- return navigator.locks.request(OPEN_DB_LOCK, async () => {
19
+ return navigator.locks.request(OPEN_DB_LOCK, () => __awaiter(void 0, void 0, void 0, function* () {
11
20
  const clientId = nextClientId++;
12
21
  if (!DBMap.has(dbFileName)) {
13
22
  const clientIds = new Set();
14
- const connection = await _openDB(dbFileName);
23
+ const connection = yield _openDB(dbFileName);
15
24
  DBMap.set(dbFileName, {
16
25
  clientIds,
17
26
  db: connection
@@ -20,30 +29,29 @@ const openDB = async (dbFileName) => {
20
29
  const dbEntry = DBMap.get(dbFileName);
21
30
  dbEntry.clientIds.add(clientId);
22
31
  const { db } = dbEntry;
23
- const wrappedConnection = {
24
- ...db,
25
- close: Comlink.proxy(() => {
32
+ const wrappedConnection = Object.assign(Object.assign({}, db), { close: Comlink.proxy(() => {
33
+ var _a;
26
34
  const { clientIds } = dbEntry;
27
35
  clientIds.delete(clientId);
28
36
  if (clientIds.size == 0) {
29
37
  console.debug(`Closing connection to ${dbFileName}.`);
30
38
  DBMap.delete(dbFileName);
31
- return db.close?.();
39
+ return (_a = db.close) === null || _a === void 0 ? void 0 : _a.call(db);
32
40
  }
33
41
  console.debug(`Connection to ${dbFileName} not closed yet due to active clients.`);
34
- })
35
- };
42
+ }) });
36
43
  return Comlink.proxy(wrappedConnection);
37
- });
38
- };
44
+ }));
45
+ });
39
46
  _self.onconnect = function (event) {
40
47
  const port = event.ports[0];
41
48
  console.debug('Exposing db on port', port);
42
49
  Comlink.expose(openDB, port);
43
50
  };
44
51
  addEventListener('unload', () => {
45
- Array.from(DBMap.values()).forEach(async (dbConnection) => {
46
- const db = await dbConnection.db;
47
- db.close?.();
48
- });
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
+ }));
49
57
  });
@@ -1,3 +1,12 @@
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
+ };
1
10
  import * as Comlink from 'comlink';
2
11
  import { _openDB } from '../../shared/open-db';
3
- Comlink.expose(async (dbFileName) => Comlink.proxy(await _openDB(dbFileName)));
12
+ Comlink.expose((dbFileName) => __awaiter(void 0, void 0, void 0, function* () { return Comlink.proxy(yield _openDB(dbFileName)); }));
@@ -1,16 +1,17 @@
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
+ };
1
10
  import Logger from 'js-logger';
2
11
  /**
3
12
  * Broadcasts logs to all clients
4
13
  */
5
14
  export class BroadcastLogger {
6
- clients;
7
- TRACE;
8
- DEBUG;
9
- INFO;
10
- TIME;
11
- WARN;
12
- ERROR;
13
- OFF;
14
15
  constructor(clients) {
15
16
  this.clients = clients;
16
17
  this.TRACE = Logger.TRACE;
@@ -74,15 +75,17 @@ export class BroadcastLogger {
74
75
  * Iterates all clients, catches individual client exceptions
75
76
  * and proceeds to execute for all clients.
76
77
  */
77
- async iterateClients(callback) {
78
- for (const client of this.clients) {
79
- try {
80
- await callback(client);
81
- }
82
- catch (ex) {
83
- console.error('Caught exception when iterating client', ex);
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
+ }
84
87
  }
85
- }
88
+ });
86
89
  }
87
90
  /**
88
91
  * Guards against any logging errors.