@reidelsaltres/pureper 0.2.24 → 0.2.26
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/out/foundation/worker/ServiceWorker.d.ts +18 -0
- package/out/foundation/worker/ServiceWorker.d.ts.map +1 -1
- package/out/foundation/worker/ServiceWorker.js +82 -0
- package/out/foundation/worker/ServiceWorker.js.map +1 -1
- package/out/index.d.ts +1 -1
- package/out/index.d.ts.map +1 -1
- package/out/index.js.map +1 -1
- package/package.json +1 -1
- package/src/foundation/worker/ServiceWorker.ts +100 -0
- package/src/foundation/worker/serviceworker.js +67 -9
- package/src/index.ts +1 -1
|
@@ -3,6 +3,17 @@ export type ServiceWorkerConfig = {
|
|
|
3
3
|
scriptURL?: string;
|
|
4
4
|
scope?: string;
|
|
5
5
|
};
|
|
6
|
+
export interface FetchActivityItem {
|
|
7
|
+
id: number;
|
|
8
|
+
url: string;
|
|
9
|
+
startTime: number;
|
|
10
|
+
size?: number;
|
|
11
|
+
duration?: number;
|
|
12
|
+
fromCache?: boolean;
|
|
13
|
+
status: 'loading' | 'complete' | 'error';
|
|
14
|
+
error?: string;
|
|
15
|
+
}
|
|
16
|
+
export type PageSourceType = 'cache' | 'network' | 'unknown';
|
|
6
17
|
/**
|
|
7
18
|
* Client-side Service Worker manager for Purper SPA.
|
|
8
19
|
*
|
|
@@ -23,6 +34,10 @@ export default class ServiceWorker {
|
|
|
23
34
|
private static _registration?;
|
|
24
35
|
/** Observable connectivity state — subscribe for real-time changes. */
|
|
25
36
|
static readonly online: Observable<boolean>;
|
|
37
|
+
static readonly fetchActivities: Observable<FetchActivityItem[]>;
|
|
38
|
+
static readonly pageSource: Observable<PageSourceType>;
|
|
39
|
+
private static _fetchTrackingEnabled;
|
|
40
|
+
private static _fetchListenerBound;
|
|
26
41
|
private static _connectivityBound;
|
|
27
42
|
private static _bindConnectivity;
|
|
28
43
|
static register(config?: ServiceWorkerConfig): Promise<ServiceWorkerRegistration | undefined>;
|
|
@@ -52,5 +67,8 @@ export default class ServiceWorker {
|
|
|
52
67
|
static isOnline(probeURL?: string): Promise<boolean>;
|
|
53
68
|
/** Current registration, if any. */
|
|
54
69
|
static get registration(): ServiceWorkerRegistration | undefined;
|
|
70
|
+
static enableFetchTracking(): void;
|
|
71
|
+
static disableFetchTracking(): void;
|
|
72
|
+
private static _bindFetchListener;
|
|
55
73
|
}
|
|
56
74
|
//# sourceMappingURL=ServiceWorker.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServiceWorker.d.ts","sourceRoot":"","sources":["../../../src/foundation/worker/ServiceWorker.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,oBAAoB,CAAC;AAE5C,MAAM,MAAM,mBAAmB,GAAG;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,OAAO,OAAO,aAAa;IAC9B,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,CAA4B;IAEzD,uEAAuE;IACvE,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,CAAoC;
|
|
1
|
+
{"version":3,"file":"ServiceWorker.d.ts","sourceRoot":"","sources":["../../../src/foundation/worker/ServiceWorker.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,oBAAoB,CAAC;AAE5C,MAAM,MAAM,mBAAmB,GAAG;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,WAAW,iBAAiB;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;AAE7D;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,OAAO,OAAO,aAAa;IAC9B,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,CAA4B;IAEzD,uEAAuE;IACvE,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,CAAoC;IAE/E,MAAM,CAAC,QAAQ,CAAC,eAAe,EAAE,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAsB;IACtF,MAAM,CAAC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC,cAAc,CAAC,CAA6C;IACnG,OAAO,CAAC,MAAM,CAAC,qBAAqB,CAAS;IAC7C,OAAO,CAAC,MAAM,CAAC,mBAAmB,CAAS;IAG3C,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAS;IAC1C,OAAO,CAAC,MAAM,CAAC,iBAAiB;WAenB,QAAQ,CAAC,MAAM,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,yBAAyB,GAAG,SAAS,CAAC;IA0CnG,OAAO,CAAC,MAAM,CAAC,YAAY;IAI3B,OAAO,CAAC,MAAM,CAAC,QAAQ;IAcvB,wCAAwC;WAC3B,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBnD,sDAAsD;IACtD,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI;IAI1C,gFAAgF;WACnE,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAe3D,iDAAiD;WACpC,YAAY,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAS9C,gCAAgC;WACnB,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IAS3C,kDAAkD;WACrC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAgBpD,kDAAkD;IAClD,MAAM,CAAC,WAAW,IAAI,IAAI;IAI1B,kDAAkD;WACrC,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAO1C;;;;OAIG;WACU,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAuB1D,oCAAoC;IACpC,MAAM,KAAK,YAAY,IAAI,yBAAyB,GAAG,SAAS,CAE/D;IAID,MAAM,CAAC,mBAAmB,IAAI,IAAI;IAQlC,MAAM,CAAC,oBAAoB,IAAI,IAAI;IAOnC,OAAO,CAAC,MAAM,CAAC,kBAAkB;CAgEpC"}
|
|
@@ -19,6 +19,10 @@ export default class ServiceWorker {
|
|
|
19
19
|
static _registration;
|
|
20
20
|
/** Observable connectivity state — subscribe for real-time changes. */
|
|
21
21
|
static online = new Observable(navigator.onLine);
|
|
22
|
+
static fetchActivities = new Observable([]);
|
|
23
|
+
static pageSource = new Observable('unknown');
|
|
24
|
+
static _fetchTrackingEnabled = false;
|
|
25
|
+
static _fetchListenerBound = false;
|
|
22
26
|
// ── Connectivity listeners (bound once) ─────────────────────────
|
|
23
27
|
static _connectivityBound = false;
|
|
24
28
|
static _bindConnectivity() {
|
|
@@ -207,5 +211,83 @@ export default class ServiceWorker {
|
|
|
207
211
|
static get registration() {
|
|
208
212
|
return this._registration;
|
|
209
213
|
}
|
|
214
|
+
// ── Fetch Tracking ──────────────────────────────────────────────
|
|
215
|
+
static enableFetchTracking() {
|
|
216
|
+
if (!this._fetchTrackingEnabled) {
|
|
217
|
+
this._fetchTrackingEnabled = true;
|
|
218
|
+
this._postMessage({ type: 'ENABLE_FETCH_TRACKING' });
|
|
219
|
+
this._bindFetchListener();
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
static disableFetchTracking() {
|
|
223
|
+
if (this._fetchTrackingEnabled) {
|
|
224
|
+
this._fetchTrackingEnabled = false;
|
|
225
|
+
this._postMessage({ type: 'DISABLE_FETCH_TRACKING' });
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
static _bindFetchListener() {
|
|
229
|
+
if (this._fetchListenerBound)
|
|
230
|
+
return;
|
|
231
|
+
this._fetchListenerBound = true;
|
|
232
|
+
navigator.serviceWorker?.addEventListener('message', (event) => {
|
|
233
|
+
const data = event.data;
|
|
234
|
+
if (!data || !data.type)
|
|
235
|
+
return;
|
|
236
|
+
switch (data.type) {
|
|
237
|
+
case 'FETCH_START': {
|
|
238
|
+
const item = {
|
|
239
|
+
id: data.id,
|
|
240
|
+
url: data.url,
|
|
241
|
+
startTime: data.timestamp,
|
|
242
|
+
status: 'loading'
|
|
243
|
+
};
|
|
244
|
+
const current = [...this.fetchActivities.getObject()];
|
|
245
|
+
current.push(item);
|
|
246
|
+
this.fetchActivities.setObject(current);
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
case 'FETCH_COMPLETE': {
|
|
250
|
+
const current = [...this.fetchActivities.getObject()];
|
|
251
|
+
const idx = current.findIndex(i => i.id === data.id);
|
|
252
|
+
if (idx !== -1) {
|
|
253
|
+
current[idx] = {
|
|
254
|
+
...current[idx],
|
|
255
|
+
size: data.size,
|
|
256
|
+
duration: data.duration,
|
|
257
|
+
fromCache: data.fromCache,
|
|
258
|
+
status: 'complete'
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
this.fetchActivities.setObject(current);
|
|
262
|
+
setTimeout(() => {
|
|
263
|
+
const list = this.fetchActivities.getObject().filter(i => i.id !== data.id);
|
|
264
|
+
this.fetchActivities.setObject(list);
|
|
265
|
+
}, 3000);
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
case 'FETCH_ERROR': {
|
|
269
|
+
const current = [...this.fetchActivities.getObject()];
|
|
270
|
+
const idx = current.findIndex(i => i.id === data.id);
|
|
271
|
+
if (idx !== -1) {
|
|
272
|
+
current[idx] = {
|
|
273
|
+
...current[idx],
|
|
274
|
+
status: 'error',
|
|
275
|
+
error: data.error
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
this.fetchActivities.setObject(current);
|
|
279
|
+
setTimeout(() => {
|
|
280
|
+
const list = this.fetchActivities.getObject().filter(i => i.id !== data.id);
|
|
281
|
+
this.fetchActivities.setObject(list);
|
|
282
|
+
}, 5000);
|
|
283
|
+
break;
|
|
284
|
+
}
|
|
285
|
+
case 'PAGE_SOURCE': {
|
|
286
|
+
this.pageSource.setObject(data.source);
|
|
287
|
+
break;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
}
|
|
210
292
|
}
|
|
211
293
|
//# sourceMappingURL=ServiceWorker.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServiceWorker.js","sourceRoot":"","sources":["../../../src/foundation/worker/ServiceWorker.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"ServiceWorker.js","sourceRoot":"","sources":["../../../src/foundation/worker/ServiceWorker.ts"],"names":[],"mappings":"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"}
|
package/out/index.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export { Implementation, ImplementationStruct, Placeholder } from './foundation/
|
|
|
13
13
|
export { default as Fetcher } from './foundation/Fetcher.js';
|
|
14
14
|
export * from './foundation/engine/TemplateEngine.js';
|
|
15
15
|
export { Router } from './foundation/worker/Router.js';
|
|
16
|
-
export { default as ServiceWorker, ServiceWorkerConfig } from './foundation/worker/ServiceWorker.js';
|
|
16
|
+
export { default as ServiceWorker, ServiceWorkerConfig, FetchActivityItem, PageSourceType } from './foundation/worker/ServiceWorker.js';
|
|
17
17
|
export * from './foundation/Hosting.js';
|
|
18
18
|
export * from './foundation/Theme.js';
|
|
19
19
|
//# sourceMappingURL=index.d.ts.map
|
package/out/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AACnF,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAE3D,cAAc,2CAA2C,CAAC;AAC1D,OAAO,EACN,OAAO,IAAI,UAAU,EACrB,SAAS,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,QAAQ,EAAE,gBAAgB,EAAE,WAAW,EAC3F,YAAY,EACZ,MAAM,8BAA8B,CAAA;AAErC,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAE/E,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAClG,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEzF,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC9F,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAE7D,cAAc,uCAAuC,CAAC;AAEtD,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AACnF,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAE3D,cAAc,2CAA2C,CAAC;AAC1D,OAAO,EACN,OAAO,IAAI,UAAU,EACrB,SAAS,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,QAAQ,EAAE,gBAAgB,EAAE,WAAW,EAC3F,YAAY,EACZ,MAAM,8BAA8B,CAAA;AAErC,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAE/E,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAClG,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEzF,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC9F,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAE7D,cAAc,uCAAuC,CAAC;AAEtD,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAExI,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC"}
|
package/out/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAE3D,cAAc,2CAA2C,CAAC;AAC1D,OAAO,EACN,OAAO,IAAI,UAAU,EAC+B,QAAQ,EAAE,gBAAgB,EAAE,WAAW,EAC3F,YAAY,EACZ,MAAM,8BAA8B,CAAA;AAErC,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAE/E,OAAO,EAAE,OAAO,IAAI,OAAO,EAAiB,UAAU,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAClG,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEzF,OAAO,EAAE,cAAc,EAAwB,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC9F,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAE7D,cAAc,uCAAuC,CAAC;AAEtD,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,aAAa,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAE3D,cAAc,2CAA2C,CAAC;AAC1D,OAAO,EACN,OAAO,IAAI,UAAU,EAC+B,QAAQ,EAAE,gBAAgB,EAAE,WAAW,EAC3F,YAAY,EACZ,MAAM,8BAA8B,CAAA;AAErC,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAE/E,OAAO,EAAE,OAAO,IAAI,OAAO,EAAiB,UAAU,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAClG,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEzF,OAAO,EAAE,cAAc,EAAwB,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC9F,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAE7D,cAAc,uCAAuC,CAAC;AAEtD,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,aAAa,EAA0D,MAAM,sCAAsC,CAAC;AAExI,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AAGtC,qEAAqE;AACrE;;WAEQ;AAER,yEAAyE"}
|
package/package.json
CHANGED
|
@@ -5,6 +5,19 @@ export type ServiceWorkerConfig = {
|
|
|
5
5
|
scope?: string;
|
|
6
6
|
};
|
|
7
7
|
|
|
8
|
+
export interface FetchActivityItem {
|
|
9
|
+
id: number;
|
|
10
|
+
url: string;
|
|
11
|
+
startTime: number;
|
|
12
|
+
size?: number;
|
|
13
|
+
duration?: number;
|
|
14
|
+
fromCache?: boolean;
|
|
15
|
+
status: 'loading' | 'complete' | 'error';
|
|
16
|
+
error?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type PageSourceType = 'cache' | 'network' | 'unknown';
|
|
20
|
+
|
|
8
21
|
/**
|
|
9
22
|
* Client-side Service Worker manager for Purper SPA.
|
|
10
23
|
*
|
|
@@ -27,6 +40,11 @@ export default class ServiceWorker {
|
|
|
27
40
|
/** Observable connectivity state — subscribe for real-time changes. */
|
|
28
41
|
static readonly online: Observable<boolean> = new Observable(navigator.onLine);
|
|
29
42
|
|
|
43
|
+
static readonly fetchActivities: Observable<FetchActivityItem[]> = new Observable([]);
|
|
44
|
+
static readonly pageSource: Observable<PageSourceType> = new Observable<PageSourceType>('unknown');
|
|
45
|
+
private static _fetchTrackingEnabled = false;
|
|
46
|
+
private static _fetchListenerBound = false;
|
|
47
|
+
|
|
30
48
|
// ── Connectivity listeners (bound once) ─────────────────────────
|
|
31
49
|
private static _connectivityBound = false;
|
|
32
50
|
private static _bindConnectivity(): void {
|
|
@@ -226,4 +244,86 @@ export default class ServiceWorker {
|
|
|
226
244
|
static get registration(): ServiceWorkerRegistration | undefined {
|
|
227
245
|
return this._registration;
|
|
228
246
|
}
|
|
247
|
+
|
|
248
|
+
// ── Fetch Tracking ──────────────────────────────────────────────
|
|
249
|
+
|
|
250
|
+
static enableFetchTracking(): void {
|
|
251
|
+
if (!this._fetchTrackingEnabled) {
|
|
252
|
+
this._fetchTrackingEnabled = true;
|
|
253
|
+
this._postMessage({ type: 'ENABLE_FETCH_TRACKING' });
|
|
254
|
+
this._bindFetchListener();
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
static disableFetchTracking(): void {
|
|
259
|
+
if (this._fetchTrackingEnabled) {
|
|
260
|
+
this._fetchTrackingEnabled = false;
|
|
261
|
+
this._postMessage({ type: 'DISABLE_FETCH_TRACKING' });
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
private static _bindFetchListener(): void {
|
|
266
|
+
if (this._fetchListenerBound) return;
|
|
267
|
+
this._fetchListenerBound = true;
|
|
268
|
+
|
|
269
|
+
navigator.serviceWorker?.addEventListener('message', (event) => {
|
|
270
|
+
const data = event.data;
|
|
271
|
+
if (!data || !data.type) return;
|
|
272
|
+
|
|
273
|
+
switch (data.type) {
|
|
274
|
+
case 'FETCH_START': {
|
|
275
|
+
const item: FetchActivityItem = {
|
|
276
|
+
id: data.id,
|
|
277
|
+
url: data.url,
|
|
278
|
+
startTime: data.timestamp,
|
|
279
|
+
status: 'loading'
|
|
280
|
+
};
|
|
281
|
+
const current = [...this.fetchActivities.getObject()];
|
|
282
|
+
current.push(item);
|
|
283
|
+
this.fetchActivities.setObject(current);
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
286
|
+
case 'FETCH_COMPLETE': {
|
|
287
|
+
const current = [...this.fetchActivities.getObject()];
|
|
288
|
+
const idx = current.findIndex(i => i.id === data.id);
|
|
289
|
+
if (idx !== -1) {
|
|
290
|
+
current[idx] = {
|
|
291
|
+
...current[idx],
|
|
292
|
+
size: data.size,
|
|
293
|
+
duration: data.duration,
|
|
294
|
+
fromCache: data.fromCache,
|
|
295
|
+
status: 'complete'
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
this.fetchActivities.setObject(current);
|
|
299
|
+
setTimeout(() => {
|
|
300
|
+
const list = this.fetchActivities.getObject().filter(i => i.id !== data.id);
|
|
301
|
+
this.fetchActivities.setObject(list);
|
|
302
|
+
}, 3000);
|
|
303
|
+
break;
|
|
304
|
+
}
|
|
305
|
+
case 'FETCH_ERROR': {
|
|
306
|
+
const current = [...this.fetchActivities.getObject()];
|
|
307
|
+
const idx = current.findIndex(i => i.id === data.id);
|
|
308
|
+
if (idx !== -1) {
|
|
309
|
+
current[idx] = {
|
|
310
|
+
...current[idx],
|
|
311
|
+
status: 'error',
|
|
312
|
+
error: data.error
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
this.fetchActivities.setObject(current);
|
|
316
|
+
setTimeout(() => {
|
|
317
|
+
const list = this.fetchActivities.getObject().filter(i => i.id !== data.id);
|
|
318
|
+
this.fetchActivities.setObject(list);
|
|
319
|
+
}, 5000);
|
|
320
|
+
break;
|
|
321
|
+
}
|
|
322
|
+
case 'PAGE_SOURCE': {
|
|
323
|
+
this.pageSource.setObject(data.source);
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
}
|
|
229
329
|
}
|
|
@@ -17,6 +17,15 @@
|
|
|
17
17
|
const CACHE_VERSION = 'purper-v1';
|
|
18
18
|
const SW_VERSION = '1.0.0';
|
|
19
19
|
|
|
20
|
+
let fetchCounter = 0;
|
|
21
|
+
let fetchTrackingEnabled = false;
|
|
22
|
+
|
|
23
|
+
function broadcastToClients(message) {
|
|
24
|
+
self.clients.matchAll().then((clients) => {
|
|
25
|
+
clients.forEach((c) => c.postMessage(message));
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
20
29
|
// ── Install ─────────────────────────────────────────────────────────
|
|
21
30
|
self.addEventListener('install', (event) => {
|
|
22
31
|
console.log(`[ServiceWorker ${SW_VERSION}]: Installing...`);
|
|
@@ -59,6 +68,14 @@ self.addEventListener('fetch', (event) => {
|
|
|
59
68
|
// Only handle GET requests
|
|
60
69
|
if (request.method !== 'GET') return;
|
|
61
70
|
|
|
71
|
+
const tracking = fetchTrackingEnabled;
|
|
72
|
+
const fetchId = tracking ? ++fetchCounter : 0;
|
|
73
|
+
const startTime = tracking ? Date.now() : 0;
|
|
74
|
+
|
|
75
|
+
if (tracking) {
|
|
76
|
+
broadcastToClients({ type: 'FETCH_START', id: fetchId, url: request.url, timestamp: startTime });
|
|
77
|
+
}
|
|
78
|
+
|
|
62
79
|
// Navigation requests (HTML pages) — network-first, fall back to cache
|
|
63
80
|
if (request.mode === 'navigate') {
|
|
64
81
|
event.respondWith(
|
|
@@ -68,11 +85,23 @@ self.addEventListener('fetch', (event) => {
|
|
|
68
85
|
const clone = response.clone();
|
|
69
86
|
caches.open(CACHE_VERSION).then((cache) => cache.put(request, clone));
|
|
70
87
|
}
|
|
88
|
+
broadcastToClients({ type: 'PAGE_SOURCE', url: request.url, source: 'network' });
|
|
89
|
+
if (tracking) {
|
|
90
|
+
const duration = Date.now() - startTime;
|
|
91
|
+
const size = parseInt(response.headers.get('Content-Length')) || -1;
|
|
92
|
+
broadcastToClients({ type: 'FETCH_COMPLETE', id: fetchId, url: request.url, size, duration, fromCache: false, timestamp: Date.now() });
|
|
93
|
+
}
|
|
71
94
|
return response;
|
|
72
95
|
})
|
|
73
96
|
.catch(() => {
|
|
74
97
|
return caches.match(request).then((cached) => {
|
|
75
|
-
|
|
98
|
+
const result = cached || caches.match('/index.html');
|
|
99
|
+
broadcastToClients({ type: 'PAGE_SOURCE', url: request.url, source: 'cache' });
|
|
100
|
+
if (tracking) {
|
|
101
|
+
const duration = Date.now() - startTime;
|
|
102
|
+
broadcastToClients({ type: 'FETCH_COMPLETE', id: fetchId, url: request.url, size: -1, duration, fromCache: true, timestamp: Date.now() });
|
|
103
|
+
}
|
|
104
|
+
return result;
|
|
76
105
|
});
|
|
77
106
|
})
|
|
78
107
|
);
|
|
@@ -82,15 +111,34 @@ self.addEventListener('fetch', (event) => {
|
|
|
82
111
|
// Sub-resources (CSS, JS, images, fonts, JSON) — cache-first, fall back to network
|
|
83
112
|
event.respondWith(
|
|
84
113
|
caches.match(request).then((cached) => {
|
|
85
|
-
if (cached)
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
caches.open(CACHE_VERSION).then((cache) => cache.put(request, clone));
|
|
114
|
+
if (cached) {
|
|
115
|
+
if (tracking) {
|
|
116
|
+
const duration = Date.now() - startTime;
|
|
117
|
+
const size = parseInt(cached.headers.get('Content-Length')) || -1;
|
|
118
|
+
broadcastToClients({ type: 'FETCH_COMPLETE', id: fetchId, url: request.url, size, duration, fromCache: true, timestamp: Date.now() });
|
|
91
119
|
}
|
|
92
|
-
return
|
|
93
|
-
}
|
|
120
|
+
return cached;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return fetch(request)
|
|
124
|
+
.then((response) => {
|
|
125
|
+
if (response.ok && response.type === 'basic') {
|
|
126
|
+
const clone = response.clone();
|
|
127
|
+
caches.open(CACHE_VERSION).then((cache) => cache.put(request, clone));
|
|
128
|
+
}
|
|
129
|
+
if (tracking) {
|
|
130
|
+
const duration = Date.now() - startTime;
|
|
131
|
+
const size = parseInt(response.headers.get('Content-Length')) || -1;
|
|
132
|
+
broadcastToClients({ type: 'FETCH_COMPLETE', id: fetchId, url: request.url, size, duration, fromCache: false, timestamp: Date.now() });
|
|
133
|
+
}
|
|
134
|
+
return response;
|
|
135
|
+
})
|
|
136
|
+
.catch((err) => {
|
|
137
|
+
if (tracking) {
|
|
138
|
+
broadcastToClients({ type: 'FETCH_ERROR', id: fetchId, url: request.url, error: err.message || String(err), timestamp: Date.now() });
|
|
139
|
+
}
|
|
140
|
+
throw err;
|
|
141
|
+
});
|
|
94
142
|
})
|
|
95
143
|
);
|
|
96
144
|
});
|
|
@@ -185,6 +233,16 @@ self.addEventListener('message', (event) => {
|
|
|
185
233
|
break;
|
|
186
234
|
}
|
|
187
235
|
|
|
236
|
+
case 'ENABLE_FETCH_TRACKING':
|
|
237
|
+
fetchTrackingEnabled = true;
|
|
238
|
+
console.log('[ServiceWorker]: Fetch tracking enabled');
|
|
239
|
+
break;
|
|
240
|
+
|
|
241
|
+
case 'DISABLE_FETCH_TRACKING':
|
|
242
|
+
fetchTrackingEnabled = false;
|
|
243
|
+
console.log('[ServiceWorker]: Fetch tracking disabled');
|
|
244
|
+
break;
|
|
245
|
+
|
|
188
246
|
default:
|
|
189
247
|
console.warn(`[ServiceWorker]: Unknown message type "${type}"`);
|
|
190
248
|
}
|
package/src/index.ts
CHANGED
|
@@ -24,7 +24,7 @@ export { default as Fetcher } from './foundation/Fetcher.js';
|
|
|
24
24
|
export * from './foundation/engine/TemplateEngine.js';
|
|
25
25
|
|
|
26
26
|
export { Router } from './foundation/worker/Router.js';
|
|
27
|
-
export { default as ServiceWorker, ServiceWorkerConfig } from './foundation/worker/ServiceWorker.js';
|
|
27
|
+
export { default as ServiceWorker, ServiceWorkerConfig, FetchActivityItem, PageSourceType } from './foundation/worker/ServiceWorker.js';
|
|
28
28
|
|
|
29
29
|
export * from './foundation/Hosting.js';
|
|
30
30
|
export * from './foundation/Theme.js';
|