@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.
- package/README.md +1 -25
- package/lib/src/db/PowerSyncDatabase.d.ts +2 -2
- package/lib/src/db/PowerSyncDatabase.js +35 -28
- package/lib/src/db/adapters/AbstractWebPowerSyncDatabaseOpenFactory.js +7 -1
- package/lib/src/db/adapters/AbstractWebSQLOpenFactory.js +2 -0
- package/lib/src/db/adapters/SSRDBAdapter.js +28 -48
- package/lib/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.js +105 -124
- package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.js +4 -1
- package/lib/src/db/adapters/web-sql-flags.js +6 -3
- package/lib/src/db/sync/SSRWebStreamingSyncImplementation.js +2 -0
- package/lib/src/db/sync/SharedWebStreamingSyncImplementation.js +66 -95
- package/lib/src/db/sync/WebRemote.d.ts +5 -1
- package/lib/src/db/sync/WebRemote.js +29 -21
- package/lib/src/shared/open-db.js +153 -184
- package/lib/src/worker/db/SharedWASQLiteDB.worker.js +15 -23
- package/lib/src/worker/db/WASQLiteDB.worker.js +1 -10
- package/lib/src/worker/sync/BroadcastLogger.js +16 -19
- package/lib/src/worker/sync/SharedSyncImplementation.js +96 -115
- package/lib/src/worker/sync/SharedSyncImplementation.worker.js +1 -5
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +13 -7
|
@@ -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(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return
|
|
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
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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
|
-
|
|
172
|
-
|
|
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
|
-
|
|
175
|
-
|
|
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
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
|
|
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: () =>
|
|
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) =>
|
|
8
|
+
const openDB = async (dbFileName) => {
|
|
18
9
|
// Prevent multiple simultaneous opens from causing race conditions
|
|
19
|
-
return navigator.locks.request(OPEN_DB_LOCK, () =>
|
|
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 =
|
|
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 =
|
|
33
|
-
|
|
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
|
|
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) =>
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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) =>
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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.
|