@serwist/background-sync 9.0.0-preview.2 → 9.0.0-preview.20
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 -1
- package/dist/index.d.ts +2 -23
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -441
- package/package.json +8 -10
- package/src/index.ts +2 -37
- package/dist/BackgroundSyncPlugin.d.ts +0 -23
- package/dist/BackgroundSyncPlugin.d.ts.map +0 -1
- package/dist/Queue.d.ts +0 -170
- package/dist/Queue.d.ts.map +0 -1
- package/dist/QueueDb.d.ts +0 -90
- package/dist/QueueDb.d.ts.map +0 -1
- package/dist/QueueStore.d.ts +0 -75
- package/dist/QueueStore.d.ts.map +0 -1
- package/dist/StorableRequest.d.ts +0 -52
- package/dist/StorableRequest.d.ts.map +0 -1
- package/src/BackgroundSyncPlugin.ts +0 -40
- package/src/Queue.ts +0 -444
- package/src/QueueDb.ts +0 -176
- package/src/QueueStore.ts +0 -161
- package/src/StorableRequest.ts +0 -144
package/README.md
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
This module's documentation can be found at https://
|
|
1
|
+
This module's documentation can be found at https://serwist.pages.dev/docs/background-sync
|
package/dist/index.d.ts
CHANGED
|
@@ -1,24 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { Queue } from "./Queue.js";
|
|
4
|
-
import { QueueStore } from "./QueueStore.js";
|
|
5
|
-
import { StorableRequest } from "./StorableRequest.js";
|
|
6
|
-
interface SyncManager {
|
|
7
|
-
getTags(): Promise<string[]>;
|
|
8
|
-
register(tag: string): Promise<void>;
|
|
9
|
-
}
|
|
10
|
-
declare global {
|
|
11
|
-
interface ServiceWorkerRegistration {
|
|
12
|
-
readonly sync: SyncManager;
|
|
13
|
-
}
|
|
14
|
-
interface SyncEvent extends ExtendableEvent {
|
|
15
|
-
readonly lastChance: boolean;
|
|
16
|
-
readonly tag: string;
|
|
17
|
-
}
|
|
18
|
-
interface ServiceWorkerGlobalScopeEventMap {
|
|
19
|
-
sync: SyncEvent;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
export { BackgroundSyncPlugin, Queue, QueueStore, StorableRequest };
|
|
23
|
-
export type { QueueOptions, QueueEntry };
|
|
1
|
+
export { BackgroundSyncPlugin, BackgroundSyncQueue as Queue, BackgroundSyncQueueStore as QueueStore, StorableRequest } from "@serwist/sw/plugins";
|
|
2
|
+
export type { BackgroundSyncQueueOptions as QueueOptions, BackgroundSyncQueueEntry as QueueEntry } from "@serwist/sw/plugins";
|
|
24
3
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,IAAI,KAAK,EAAE,wBAAwB,IAAI,UAAU,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAClJ,YAAY,EAAE,0BAA0B,IAAI,YAAY,EAAE,wBAAwB,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,441 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { openDB } from 'idb';
|
|
3
|
-
|
|
4
|
-
const DB_VERSION = 3;
|
|
5
|
-
const DB_NAME = "serwist-background-sync";
|
|
6
|
-
const REQUEST_OBJECT_STORE_NAME = "requests";
|
|
7
|
-
const QUEUE_NAME_INDEX = "queueName";
|
|
8
|
-
class QueueDb {
|
|
9
|
-
_db = null;
|
|
10
|
-
async addEntry(entry) {
|
|
11
|
-
const db = await this.getDb();
|
|
12
|
-
const tx = db.transaction(REQUEST_OBJECT_STORE_NAME, "readwrite", {
|
|
13
|
-
durability: "relaxed"
|
|
14
|
-
});
|
|
15
|
-
await tx.store.add(entry);
|
|
16
|
-
await tx.done;
|
|
17
|
-
}
|
|
18
|
-
async getFirstEntryId() {
|
|
19
|
-
const db = await this.getDb();
|
|
20
|
-
const cursor = await db.transaction(REQUEST_OBJECT_STORE_NAME).store.openCursor();
|
|
21
|
-
return cursor?.value.id;
|
|
22
|
-
}
|
|
23
|
-
async getAllEntriesByQueueName(queueName) {
|
|
24
|
-
const db = await this.getDb();
|
|
25
|
-
const results = await db.getAllFromIndex(REQUEST_OBJECT_STORE_NAME, QUEUE_NAME_INDEX, IDBKeyRange.only(queueName));
|
|
26
|
-
return results ? results : new Array();
|
|
27
|
-
}
|
|
28
|
-
async getEntryCountByQueueName(queueName) {
|
|
29
|
-
const db = await this.getDb();
|
|
30
|
-
return db.countFromIndex(REQUEST_OBJECT_STORE_NAME, QUEUE_NAME_INDEX, IDBKeyRange.only(queueName));
|
|
31
|
-
}
|
|
32
|
-
async deleteEntry(id) {
|
|
33
|
-
const db = await this.getDb();
|
|
34
|
-
await db.delete(REQUEST_OBJECT_STORE_NAME, id);
|
|
35
|
-
}
|
|
36
|
-
async getFirstEntryByQueueName(queueName) {
|
|
37
|
-
return await this.getEndEntryFromIndex(IDBKeyRange.only(queueName), "next");
|
|
38
|
-
}
|
|
39
|
-
async getLastEntryByQueueName(queueName) {
|
|
40
|
-
return await this.getEndEntryFromIndex(IDBKeyRange.only(queueName), "prev");
|
|
41
|
-
}
|
|
42
|
-
async getEndEntryFromIndex(query, direction) {
|
|
43
|
-
const db = await this.getDb();
|
|
44
|
-
const cursor = await db.transaction(REQUEST_OBJECT_STORE_NAME).store.index(QUEUE_NAME_INDEX).openCursor(query, direction);
|
|
45
|
-
return cursor?.value;
|
|
46
|
-
}
|
|
47
|
-
async getDb() {
|
|
48
|
-
if (!this._db) {
|
|
49
|
-
this._db = await openDB(DB_NAME, DB_VERSION, {
|
|
50
|
-
upgrade: this._upgradeDb
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
return this._db;
|
|
54
|
-
}
|
|
55
|
-
_upgradeDb(db, oldVersion) {
|
|
56
|
-
if (oldVersion > 0 && oldVersion < DB_VERSION) {
|
|
57
|
-
if (db.objectStoreNames.contains(REQUEST_OBJECT_STORE_NAME)) {
|
|
58
|
-
db.deleteObjectStore(REQUEST_OBJECT_STORE_NAME);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
const objStore = db.createObjectStore(REQUEST_OBJECT_STORE_NAME, {
|
|
62
|
-
autoIncrement: true,
|
|
63
|
-
keyPath: "id"
|
|
64
|
-
});
|
|
65
|
-
objStore.createIndex(QUEUE_NAME_INDEX, QUEUE_NAME_INDEX, {
|
|
66
|
-
unique: false
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
class QueueStore {
|
|
72
|
-
_queueName;
|
|
73
|
-
_queueDb;
|
|
74
|
-
constructor(queueName){
|
|
75
|
-
this._queueName = queueName;
|
|
76
|
-
this._queueDb = new QueueDb();
|
|
77
|
-
}
|
|
78
|
-
async pushEntry(entry) {
|
|
79
|
-
if (process.env.NODE_ENV !== "production") {
|
|
80
|
-
assert.isType(entry, "object", {
|
|
81
|
-
moduleName: "@serwist/background-sync",
|
|
82
|
-
className: "QueueStore",
|
|
83
|
-
funcName: "pushEntry",
|
|
84
|
-
paramName: "entry"
|
|
85
|
-
});
|
|
86
|
-
assert.isType(entry.requestData, "object", {
|
|
87
|
-
moduleName: "@serwist/background-sync",
|
|
88
|
-
className: "QueueStore",
|
|
89
|
-
funcName: "pushEntry",
|
|
90
|
-
paramName: "entry.requestData"
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
delete entry.id;
|
|
94
|
-
entry.queueName = this._queueName;
|
|
95
|
-
await this._queueDb.addEntry(entry);
|
|
96
|
-
}
|
|
97
|
-
async unshiftEntry(entry) {
|
|
98
|
-
if (process.env.NODE_ENV !== "production") {
|
|
99
|
-
assert.isType(entry, "object", {
|
|
100
|
-
moduleName: "@serwist/background-sync",
|
|
101
|
-
className: "QueueStore",
|
|
102
|
-
funcName: "unshiftEntry",
|
|
103
|
-
paramName: "entry"
|
|
104
|
-
});
|
|
105
|
-
assert.isType(entry.requestData, "object", {
|
|
106
|
-
moduleName: "@serwist/background-sync",
|
|
107
|
-
className: "QueueStore",
|
|
108
|
-
funcName: "unshiftEntry",
|
|
109
|
-
paramName: "entry.requestData"
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
const firstId = await this._queueDb.getFirstEntryId();
|
|
113
|
-
if (firstId) {
|
|
114
|
-
entry.id = firstId - 1;
|
|
115
|
-
} else {
|
|
116
|
-
delete entry.id;
|
|
117
|
-
}
|
|
118
|
-
entry.queueName = this._queueName;
|
|
119
|
-
await this._queueDb.addEntry(entry);
|
|
120
|
-
}
|
|
121
|
-
async popEntry() {
|
|
122
|
-
return this._removeEntry(await this._queueDb.getLastEntryByQueueName(this._queueName));
|
|
123
|
-
}
|
|
124
|
-
async shiftEntry() {
|
|
125
|
-
return this._removeEntry(await this._queueDb.getFirstEntryByQueueName(this._queueName));
|
|
126
|
-
}
|
|
127
|
-
async getAll() {
|
|
128
|
-
return await this._queueDb.getAllEntriesByQueueName(this._queueName);
|
|
129
|
-
}
|
|
130
|
-
async size() {
|
|
131
|
-
return await this._queueDb.getEntryCountByQueueName(this._queueName);
|
|
132
|
-
}
|
|
133
|
-
async deleteEntry(id) {
|
|
134
|
-
await this._queueDb.deleteEntry(id);
|
|
135
|
-
}
|
|
136
|
-
async _removeEntry(entry) {
|
|
137
|
-
if (entry) {
|
|
138
|
-
await this.deleteEntry(entry.id);
|
|
139
|
-
}
|
|
140
|
-
return entry;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const serializableProperties = [
|
|
145
|
-
"method",
|
|
146
|
-
"referrer",
|
|
147
|
-
"referrerPolicy",
|
|
148
|
-
"mode",
|
|
149
|
-
"credentials",
|
|
150
|
-
"cache",
|
|
151
|
-
"redirect",
|
|
152
|
-
"integrity",
|
|
153
|
-
"keepalive"
|
|
154
|
-
];
|
|
155
|
-
class StorableRequest {
|
|
156
|
-
_requestData;
|
|
157
|
-
static async fromRequest(request) {
|
|
158
|
-
const requestData = {
|
|
159
|
-
url: request.url,
|
|
160
|
-
headers: {}
|
|
161
|
-
};
|
|
162
|
-
if (request.method !== "GET") {
|
|
163
|
-
requestData.body = await request.clone().arrayBuffer();
|
|
164
|
-
}
|
|
165
|
-
request.headers.forEach((value, key)=>{
|
|
166
|
-
requestData.headers[key] = value;
|
|
167
|
-
});
|
|
168
|
-
for (const prop of serializableProperties){
|
|
169
|
-
if (request[prop] !== undefined) {
|
|
170
|
-
requestData[prop] = request[prop];
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
return new StorableRequest(requestData);
|
|
174
|
-
}
|
|
175
|
-
constructor(requestData){
|
|
176
|
-
if (process.env.NODE_ENV !== "production") {
|
|
177
|
-
assert.isType(requestData, "object", {
|
|
178
|
-
moduleName: "@serwist/background-sync",
|
|
179
|
-
className: "StorableRequest",
|
|
180
|
-
funcName: "constructor",
|
|
181
|
-
paramName: "requestData"
|
|
182
|
-
});
|
|
183
|
-
assert.isType(requestData.url, "string", {
|
|
184
|
-
moduleName: "@serwist/background-sync",
|
|
185
|
-
className: "StorableRequest",
|
|
186
|
-
funcName: "constructor",
|
|
187
|
-
paramName: "requestData.url"
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
if (requestData.mode === "navigate") {
|
|
191
|
-
requestData.mode = "same-origin";
|
|
192
|
-
}
|
|
193
|
-
this._requestData = requestData;
|
|
194
|
-
}
|
|
195
|
-
toObject() {
|
|
196
|
-
const requestData = Object.assign({}, this._requestData);
|
|
197
|
-
requestData.headers = Object.assign({}, this._requestData.headers);
|
|
198
|
-
if (requestData.body) {
|
|
199
|
-
requestData.body = requestData.body.slice(0);
|
|
200
|
-
}
|
|
201
|
-
return requestData;
|
|
202
|
-
}
|
|
203
|
-
toRequest() {
|
|
204
|
-
return new Request(this._requestData.url, this._requestData);
|
|
205
|
-
}
|
|
206
|
-
clone() {
|
|
207
|
-
return new StorableRequest(this.toObject());
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const TAG_PREFIX = "serwist-background-sync";
|
|
212
|
-
const MAX_RETENTION_TIME = 60 * 24 * 7;
|
|
213
|
-
const queueNames = new Set();
|
|
214
|
-
const convertEntry = (queueStoreEntry)=>{
|
|
215
|
-
const queueEntry = {
|
|
216
|
-
request: new StorableRequest(queueStoreEntry.requestData).toRequest(),
|
|
217
|
-
timestamp: queueStoreEntry.timestamp
|
|
218
|
-
};
|
|
219
|
-
if (queueStoreEntry.metadata) {
|
|
220
|
-
queueEntry.metadata = queueStoreEntry.metadata;
|
|
221
|
-
}
|
|
222
|
-
return queueEntry;
|
|
223
|
-
};
|
|
224
|
-
class Queue {
|
|
225
|
-
_name;
|
|
226
|
-
_onSync;
|
|
227
|
-
_maxRetentionTime;
|
|
228
|
-
_queueStore;
|
|
229
|
-
_forceSyncFallback;
|
|
230
|
-
_syncInProgress = false;
|
|
231
|
-
_requestsAddedDuringSync = false;
|
|
232
|
-
constructor(name, { forceSyncFallback, onSync, maxRetentionTime } = {}){
|
|
233
|
-
if (queueNames.has(name)) {
|
|
234
|
-
throw new SerwistError("duplicate-queue-name", {
|
|
235
|
-
name
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
queueNames.add(name);
|
|
239
|
-
this._name = name;
|
|
240
|
-
this._onSync = onSync || this.replayRequests;
|
|
241
|
-
this._maxRetentionTime = maxRetentionTime || MAX_RETENTION_TIME;
|
|
242
|
-
this._forceSyncFallback = Boolean(forceSyncFallback);
|
|
243
|
-
this._queueStore = new QueueStore(this._name);
|
|
244
|
-
this._addSyncListener();
|
|
245
|
-
}
|
|
246
|
-
get name() {
|
|
247
|
-
return this._name;
|
|
248
|
-
}
|
|
249
|
-
async pushRequest(entry) {
|
|
250
|
-
if (process.env.NODE_ENV !== "production") {
|
|
251
|
-
assert.isType(entry, "object", {
|
|
252
|
-
moduleName: "@serwist/background-sync",
|
|
253
|
-
className: "Queue",
|
|
254
|
-
funcName: "pushRequest",
|
|
255
|
-
paramName: "entry"
|
|
256
|
-
});
|
|
257
|
-
assert.isInstance(entry.request, Request, {
|
|
258
|
-
moduleName: "@serwist/background-sync",
|
|
259
|
-
className: "Queue",
|
|
260
|
-
funcName: "pushRequest",
|
|
261
|
-
paramName: "entry.request"
|
|
262
|
-
});
|
|
263
|
-
}
|
|
264
|
-
await this._addRequest(entry, "push");
|
|
265
|
-
}
|
|
266
|
-
async unshiftRequest(entry) {
|
|
267
|
-
if (process.env.NODE_ENV !== "production") {
|
|
268
|
-
assert.isType(entry, "object", {
|
|
269
|
-
moduleName: "@serwist/background-sync",
|
|
270
|
-
className: "Queue",
|
|
271
|
-
funcName: "unshiftRequest",
|
|
272
|
-
paramName: "entry"
|
|
273
|
-
});
|
|
274
|
-
assert.isInstance(entry.request, Request, {
|
|
275
|
-
moduleName: "@serwist/background-sync",
|
|
276
|
-
className: "Queue",
|
|
277
|
-
funcName: "unshiftRequest",
|
|
278
|
-
paramName: "entry.request"
|
|
279
|
-
});
|
|
280
|
-
}
|
|
281
|
-
await this._addRequest(entry, "unshift");
|
|
282
|
-
}
|
|
283
|
-
async popRequest() {
|
|
284
|
-
return this._removeRequest("pop");
|
|
285
|
-
}
|
|
286
|
-
async shiftRequest() {
|
|
287
|
-
return this._removeRequest("shift");
|
|
288
|
-
}
|
|
289
|
-
async getAll() {
|
|
290
|
-
const allEntries = await this._queueStore.getAll();
|
|
291
|
-
const now = Date.now();
|
|
292
|
-
const unexpiredEntries = [];
|
|
293
|
-
for (const entry of allEntries){
|
|
294
|
-
const maxRetentionTimeInMs = this._maxRetentionTime * 60 * 1000;
|
|
295
|
-
if (now - entry.timestamp > maxRetentionTimeInMs) {
|
|
296
|
-
await this._queueStore.deleteEntry(entry.id);
|
|
297
|
-
} else {
|
|
298
|
-
unexpiredEntries.push(convertEntry(entry));
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
return unexpiredEntries;
|
|
302
|
-
}
|
|
303
|
-
async size() {
|
|
304
|
-
return await this._queueStore.size();
|
|
305
|
-
}
|
|
306
|
-
async _addRequest({ request, metadata, timestamp = Date.now() }, operation) {
|
|
307
|
-
const storableRequest = await StorableRequest.fromRequest(request.clone());
|
|
308
|
-
const entry = {
|
|
309
|
-
requestData: storableRequest.toObject(),
|
|
310
|
-
timestamp
|
|
311
|
-
};
|
|
312
|
-
if (metadata) {
|
|
313
|
-
entry.metadata = metadata;
|
|
314
|
-
}
|
|
315
|
-
switch(operation){
|
|
316
|
-
case "push":
|
|
317
|
-
await this._queueStore.pushEntry(entry);
|
|
318
|
-
break;
|
|
319
|
-
case "unshift":
|
|
320
|
-
await this._queueStore.unshiftEntry(entry);
|
|
321
|
-
break;
|
|
322
|
-
}
|
|
323
|
-
if (process.env.NODE_ENV !== "production") {
|
|
324
|
-
logger.log(`Request for '${getFriendlyURL(request.url)}' has ` + `been added to background sync queue '${this._name}'.`);
|
|
325
|
-
}
|
|
326
|
-
if (this._syncInProgress) {
|
|
327
|
-
this._requestsAddedDuringSync = true;
|
|
328
|
-
} else {
|
|
329
|
-
await this.registerSync();
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
async _removeRequest(operation) {
|
|
333
|
-
const now = Date.now();
|
|
334
|
-
let entry;
|
|
335
|
-
switch(operation){
|
|
336
|
-
case "pop":
|
|
337
|
-
entry = await this._queueStore.popEntry();
|
|
338
|
-
break;
|
|
339
|
-
case "shift":
|
|
340
|
-
entry = await this._queueStore.shiftEntry();
|
|
341
|
-
break;
|
|
342
|
-
}
|
|
343
|
-
if (entry) {
|
|
344
|
-
const maxRetentionTimeInMs = this._maxRetentionTime * 60 * 1000;
|
|
345
|
-
if (now - entry.timestamp > maxRetentionTimeInMs) {
|
|
346
|
-
return this._removeRequest(operation);
|
|
347
|
-
}
|
|
348
|
-
return convertEntry(entry);
|
|
349
|
-
}
|
|
350
|
-
return undefined;
|
|
351
|
-
}
|
|
352
|
-
async replayRequests() {
|
|
353
|
-
let entry = undefined;
|
|
354
|
-
while(entry = await this.shiftRequest()){
|
|
355
|
-
try {
|
|
356
|
-
await fetch(entry.request.clone());
|
|
357
|
-
if (process.env.NODE_ENV !== "production") {
|
|
358
|
-
logger.log(`Request for '${getFriendlyURL(entry.request.url)}' ` + `has been replayed in queue '${this._name}'`);
|
|
359
|
-
}
|
|
360
|
-
} catch (error) {
|
|
361
|
-
await this.unshiftRequest(entry);
|
|
362
|
-
if (process.env.NODE_ENV !== "production") {
|
|
363
|
-
logger.log(`Request for '${getFriendlyURL(entry.request.url)}' ` + `failed to replay, putting it back in queue '${this._name}'`);
|
|
364
|
-
}
|
|
365
|
-
throw new SerwistError("queue-replay-failed", {
|
|
366
|
-
name: this._name
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
if (process.env.NODE_ENV !== "production") {
|
|
371
|
-
logger.log(`All requests in queue '${this.name}' have successfully replayed; the queue is now empty!`);
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
async registerSync() {
|
|
375
|
-
if ("sync" in self.registration && !this._forceSyncFallback) {
|
|
376
|
-
try {
|
|
377
|
-
await self.registration.sync.register(`${TAG_PREFIX}:${this._name}`);
|
|
378
|
-
} catch (err) {
|
|
379
|
-
if (process.env.NODE_ENV !== "production") {
|
|
380
|
-
logger.warn(`Unable to register sync event for '${this._name}'.`, err);
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
_addSyncListener() {
|
|
386
|
-
if ("sync" in self.registration && !this._forceSyncFallback) {
|
|
387
|
-
self.addEventListener("sync", (event)=>{
|
|
388
|
-
if (event.tag === `${TAG_PREFIX}:${this._name}`) {
|
|
389
|
-
if (process.env.NODE_ENV !== "production") {
|
|
390
|
-
logger.log(`Background sync for tag '${event.tag}' has been received`);
|
|
391
|
-
}
|
|
392
|
-
const syncComplete = async ()=>{
|
|
393
|
-
this._syncInProgress = true;
|
|
394
|
-
let syncError = undefined;
|
|
395
|
-
try {
|
|
396
|
-
await this._onSync({
|
|
397
|
-
queue: this
|
|
398
|
-
});
|
|
399
|
-
} catch (error) {
|
|
400
|
-
if (error instanceof Error) {
|
|
401
|
-
syncError = error;
|
|
402
|
-
throw syncError;
|
|
403
|
-
}
|
|
404
|
-
} finally{
|
|
405
|
-
if (this._requestsAddedDuringSync && !(syncError && !event.lastChance)) {
|
|
406
|
-
await this.registerSync();
|
|
407
|
-
}
|
|
408
|
-
this._syncInProgress = false;
|
|
409
|
-
this._requestsAddedDuringSync = false;
|
|
410
|
-
}
|
|
411
|
-
};
|
|
412
|
-
event.waitUntil(syncComplete());
|
|
413
|
-
}
|
|
414
|
-
});
|
|
415
|
-
} else {
|
|
416
|
-
if (process.env.NODE_ENV !== "production") {
|
|
417
|
-
logger.log("Background sync replaying without background sync event");
|
|
418
|
-
}
|
|
419
|
-
void this._onSync({
|
|
420
|
-
queue: this
|
|
421
|
-
});
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
static get _queueNames() {
|
|
425
|
-
return queueNames;
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
class BackgroundSyncPlugin {
|
|
430
|
-
_queue;
|
|
431
|
-
constructor(name, options){
|
|
432
|
-
this._queue = new Queue(name, options);
|
|
433
|
-
}
|
|
434
|
-
fetchDidFail = async ({ request })=>{
|
|
435
|
-
await this._queue.pushRequest({
|
|
436
|
-
request
|
|
437
|
-
});
|
|
438
|
-
};
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
export { BackgroundSyncPlugin, Queue, QueueStore, StorableRequest };
|
|
1
|
+
export { BackgroundSyncPlugin, BackgroundSyncQueue as Queue, BackgroundSyncQueueStore as QueueStore, StorableRequest } from '@serwist/sw/plugins';
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@serwist/background-sync",
|
|
3
|
-
"version": "9.0.0-preview.
|
|
3
|
+
"version": "9.0.0-preview.20",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "A module that queues failed requests and uses the Background Synchronization API to replay them when the network is available.",
|
|
6
6
|
"files": [
|
|
7
7
|
"src",
|
|
8
8
|
"dist"
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
],
|
|
19
19
|
"author": "Google's Web DevRel Team, Serwist's Team",
|
|
20
20
|
"license": "MIT",
|
|
21
|
-
"repository": "serwist/serwist",
|
|
22
|
-
"bugs": "https://
|
|
21
|
+
"repository": "https://gitlab.com/serwist/serwist",
|
|
22
|
+
"bugs": "https://gitlab.com/serwist/serwist/issues",
|
|
23
23
|
"homepage": "https://serwist.pages.dev",
|
|
24
24
|
"main": "./dist/index.js",
|
|
25
25
|
"types": "./dist/index.d.ts",
|
|
@@ -30,14 +30,13 @@
|
|
|
30
30
|
}
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"
|
|
34
|
-
"@serwist/core": "9.0.0-preview.2"
|
|
33
|
+
"@serwist/sw": "9.0.0-preview.20"
|
|
35
34
|
},
|
|
36
35
|
"devDependencies": {
|
|
37
36
|
"cross-env": "7.0.3",
|
|
38
|
-
"rollup": "4.
|
|
39
|
-
"typescript": "5.
|
|
40
|
-
"@serwist/constants": "9.0.0-preview.
|
|
37
|
+
"rollup": "4.13.0",
|
|
38
|
+
"typescript": "5.5.0-dev.20240323",
|
|
39
|
+
"@serwist/constants": "9.0.0-preview.20"
|
|
41
40
|
},
|
|
42
41
|
"peerDependencies": {
|
|
43
42
|
"typescript": ">=5.0.0"
|
|
@@ -49,7 +48,6 @@
|
|
|
49
48
|
},
|
|
50
49
|
"scripts": {
|
|
51
50
|
"build": "rimraf dist && cross-env NODE_ENV=production rollup --config rollup.config.js",
|
|
52
|
-
"dev": "rollup --config rollup.config.js --watch",
|
|
53
51
|
"lint": "biome lint ./src",
|
|
54
52
|
"typecheck": "tsc"
|
|
55
53
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,37 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
Use of this source code is governed by an MIT-style
|
|
5
|
-
license that can be found in the LICENSE file or at
|
|
6
|
-
https://opensource.org/licenses/MIT.
|
|
7
|
-
*/
|
|
8
|
-
import { BackgroundSyncPlugin } from "./BackgroundSyncPlugin.js";
|
|
9
|
-
import type { QueueEntry, QueueOptions } from "./Queue.js";
|
|
10
|
-
import { Queue } from "./Queue.js";
|
|
11
|
-
import { QueueStore } from "./QueueStore.js";
|
|
12
|
-
import { StorableRequest } from "./StorableRequest.js";
|
|
13
|
-
|
|
14
|
-
// See https://github.com/GoogleChrome/workbox/issues/2946
|
|
15
|
-
interface SyncManager {
|
|
16
|
-
getTags(): Promise<string[]>;
|
|
17
|
-
register(tag: string): Promise<void>;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
declare global {
|
|
21
|
-
interface ServiceWorkerRegistration {
|
|
22
|
-
readonly sync: SyncManager;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
interface SyncEvent extends ExtendableEvent {
|
|
26
|
-
readonly lastChance: boolean;
|
|
27
|
-
readonly tag: string;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
interface ServiceWorkerGlobalScopeEventMap {
|
|
31
|
-
sync: SyncEvent;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export { BackgroundSyncPlugin, Queue, QueueStore, StorableRequest };
|
|
36
|
-
|
|
37
|
-
export type { QueueOptions, QueueEntry };
|
|
1
|
+
export { BackgroundSyncPlugin, BackgroundSyncQueue as Queue, BackgroundSyncQueueStore as QueueStore, StorableRequest } from "@serwist/sw/plugins";
|
|
2
|
+
export type { BackgroundSyncQueueOptions as QueueOptions, BackgroundSyncQueueEntry as QueueEntry } from "@serwist/sw/plugins";
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { SerwistPlugin } from "@serwist/core";
|
|
2
|
-
import type { QueueOptions } from "./Queue.js";
|
|
3
|
-
/**
|
|
4
|
-
* A class implementing the `fetchDidFail` lifecycle callback. This makes it
|
|
5
|
-
* easier to add failed requests to a background sync Queue.
|
|
6
|
-
*/
|
|
7
|
-
declare class BackgroundSyncPlugin implements SerwistPlugin {
|
|
8
|
-
private readonly _queue;
|
|
9
|
-
/**
|
|
10
|
-
* @param name See the `@serwist/background-sync.Queue`
|
|
11
|
-
* documentation for parameter details.
|
|
12
|
-
* @param options See the `@serwist/background-sync.Queue`
|
|
13
|
-
* documentation for parameter details.
|
|
14
|
-
*/
|
|
15
|
-
constructor(name: string, options?: QueueOptions);
|
|
16
|
-
/**
|
|
17
|
-
* @param options
|
|
18
|
-
* @private
|
|
19
|
-
*/
|
|
20
|
-
fetchDidFail: SerwistPlugin["fetchDidFail"];
|
|
21
|
-
}
|
|
22
|
-
export { BackgroundSyncPlugin };
|
|
23
|
-
//# sourceMappingURL=BackgroundSyncPlugin.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"BackgroundSyncPlugin.d.ts","sourceRoot":"","sources":["../src/BackgroundSyncPlugin.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C;;;GAGG;AACH,cAAM,oBAAqB,YAAW,aAAa;IACjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;IAE/B;;;;;OAKG;gBACS,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;IAIhD;;;OAGG;IACH,YAAY,EAAE,aAAa,CAAC,cAAc,CAAC,CAEzC;CACH;AAED,OAAO,EAAE,oBAAoB,EAAE,CAAC"}
|