@swoff/cli 0.3.13 → 0.3.15
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 +28 -32
- package/dist/index.js +4 -15
- package/dist/index.js.map +1 -1
- package/dist/lib/cli/help.js +4 -9
- package/dist/lib/cli/help.js.map +1 -1
- package/dist/lib/commands/clean.js +8 -17
- package/dist/lib/commands/clean.js.map +1 -1
- package/dist/lib/commands/generate-guide.js +16 -30
- package/dist/lib/commands/generate-guide.js.map +1 -1
- package/dist/lib/commands/generate.js +33 -7
- package/dist/lib/commands/generate.js.map +1 -1
- package/dist/lib/commands/init.js +259 -23
- package/dist/lib/commands/init.js.map +1 -1
- package/dist/lib/commands/validate.js +2 -4
- package/dist/lib/commands/validate.js.map +1 -1
- package/dist/lib/config/loader.js +34 -25
- package/dist/lib/config/loader.js.map +1 -1
- package/dist/lib/config/minimal-config.js +64 -0
- package/dist/lib/config/minimal-config.js.map +1 -0
- package/dist/lib/config/validator.js +219 -110
- package/dist/lib/config/validator.js.map +1 -1
- package/dist/lib/generators/file-generators/api-config.js +1 -1
- package/dist/lib/generators/file-generators/api-config.js.map +1 -1
- package/dist/lib/generators/file-generators/auth-adapter.js +13 -0
- package/dist/lib/generators/file-generators/auth-adapter.js.map +1 -0
- package/dist/lib/generators/file-generators/auth-check.js +40 -0
- package/dist/lib/generators/file-generators/auth-check.js.map +1 -0
- package/dist/lib/generators/file-generators/auth-store.js +2 -5
- package/dist/lib/generators/file-generators/auth-store.js.map +1 -1
- package/dist/lib/generators/file-generators/background-sync.js +1 -1
- package/dist/lib/generators/file-generators/background-sync.js.map +1 -1
- package/dist/lib/generators/file-generators/cache.js +2 -1
- package/dist/lib/generators/file-generators/cache.js.map +1 -1
- package/dist/lib/generators/file-generators/client-injector-bundle.js +15 -0
- package/dist/lib/generators/file-generators/client-injector-bundle.js.map +1 -0
- package/dist/lib/generators/file-generators/client-injector.js +2 -1
- package/dist/lib/generators/file-generators/client-injector.js.map +1 -1
- package/dist/lib/generators/file-generators/connectivity.js +12 -0
- package/dist/lib/generators/file-generators/connectivity.js.map +1 -0
- package/dist/lib/generators/file-generators/context.js +7 -0
- package/dist/lib/generators/file-generators/context.js.map +1 -1
- package/dist/lib/generators/file-generators/fetch-wrapper.js +1 -1
- package/dist/lib/generators/file-generators/fetch-wrapper.js.map +1 -1
- package/dist/lib/generators/file-generators/generate-framework-adapters.js +29 -20
- package/dist/lib/generators/file-generators/generate-framework-adapters.js.map +1 -1
- package/dist/lib/generators/file-generators/gql-wrapper.js +2 -2
- package/dist/lib/generators/file-generators/gql-wrapper.js.map +1 -1
- package/dist/lib/generators/file-generators/guide-generator.js +51 -1
- package/dist/lib/generators/file-generators/guide-generator.js.map +1 -1
- package/dist/lib/generators/file-generators/invalidation-tags.js +2 -3
- package/dist/lib/generators/file-generators/invalidation-tags.js.map +1 -1
- package/dist/lib/generators/file-generators/mutation-queue.js +2 -2
- package/dist/lib/generators/file-generators/mutation-queue.js.map +1 -1
- package/dist/lib/generators/file-generators/mutation-state.js +1 -1
- package/dist/lib/generators/file-generators/mutation-state.js.map +1 -1
- package/dist/lib/generators/file-generators/open-db.js +6 -0
- package/dist/lib/generators/file-generators/open-db.js.map +1 -0
- package/dist/lib/generators/file-generators/push.js +1 -2
- package/dist/lib/generators/file-generators/push.js.map +1 -1
- package/dist/lib/generators/file-generators/pwa-install.js +2 -6
- package/dist/lib/generators/file-generators/pwa-install.js.map +1 -1
- package/dist/lib/generators/file-generators/server-push.js +1 -1
- package/dist/lib/generators/file-generators/server-push.js.map +1 -1
- package/dist/lib/generators/file-generators/storage.js +6 -0
- package/dist/lib/generators/file-generators/storage.js.map +1 -0
- package/dist/lib/generators/file-generators/sw-generator-build.js +105 -48
- package/dist/lib/generators/file-generators/sw-generator-build.js.map +1 -1
- package/dist/lib/generators/file-generators/sw-injector.js +0 -4
- package/dist/lib/generators/file-generators/sw-injector.js.map +1 -1
- package/dist/lib/generators/file-generators/sw-template.js +8 -9
- package/dist/lib/generators/file-generators/sw-template.js.map +1 -1
- package/dist/lib/generators/file-generators/swoff-api-bundle.js +51 -0
- package/dist/lib/generators/file-generators/swoff-api-bundle.js.map +1 -0
- package/dist/lib/generators/sw-build-utils.js +69 -0
- package/dist/lib/generators/sw-build-utils.js.map +1 -0
- package/dist/lib/generators/sw-generator.js +23 -34
- package/dist/lib/generators/sw-generator.js.map +1 -1
- package/dist/lib/generators/sw-sections/activate-handler.js +77 -23
- package/dist/lib/generators/sw-sections/activate-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/assemble-sw.js +20 -95
- package/dist/lib/generators/sw-sections/assemble-sw.js.map +1 -1
- package/dist/lib/generators/sw-sections/background-precache.js +126 -0
- package/dist/lib/generators/sw-sections/background-precache.js.map +1 -0
- package/dist/lib/generators/sw-sections/background-sync-handler.js +74 -72
- package/dist/lib/generators/sw-sections/background-sync-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/batch-refresh-queue.js +102 -0
- package/dist/lib/generators/sw-sections/batch-refresh-queue.js.map +1 -0
- package/dist/lib/generators/sw-sections/config-header.js +2 -3
- package/dist/lib/generators/sw-sections/config-header.js.map +1 -1
- package/dist/lib/generators/sw-sections/default-template.js +64 -7
- package/dist/lib/generators/sw-sections/default-template.js.map +1 -1
- package/dist/lib/generators/sw-sections/fetch-handler.js +621 -495
- package/dist/lib/generators/sw-sections/fetch-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/install-handler.js +41 -23
- package/dist/lib/generators/sw-sections/install-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/message-handler.js +34 -8
- package/dist/lib/generators/sw-sections/message-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/server-push-handler.js +10 -14
- package/dist/lib/generators/sw-sections/server-push-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/shared.js +70 -0
- package/dist/lib/generators/sw-sections/shared.js.map +1 -0
- package/dist/lib/generators/sw-sections/sw-push.js +2 -6
- package/dist/lib/generators/sw-sections/sw-push.js.map +1 -1
- package/dist/lib/generators/sw-sections/tag-management.js +55 -86
- package/dist/lib/generators/sw-sections/tag-management.js.map +1 -1
- package/dist/lib/generators/swoff-files-generator.js +183 -59
- package/dist/lib/generators/swoff-files-generator.js.map +1 -1
- package/dist/lib/shared/config-types.js +84 -79
- package/dist/lib/shared/config-types.js.map +1 -1
- package/dist/lib/shared/feature-registry.js +198 -0
- package/dist/lib/shared/feature-registry.js.map +1 -0
- package/dist/lib/utils/detect-framework.js +52 -9
- package/dist/lib/utils/detect-framework.js.map +1 -1
- package/dist/runtime/api-config.js +2 -2
- package/dist/runtime/api-config.js.map +1 -1
- package/dist/runtime/auth-adapter.js +179 -0
- package/dist/runtime/auth-adapter.js.map +1 -0
- package/dist/runtime/auth-state.js +16 -6
- package/dist/runtime/auth-state.js.map +1 -1
- package/dist/runtime/auth-store.js +219 -213
- package/dist/runtime/auth-store.js.map +1 -1
- package/dist/runtime/background-sync.js +5 -2
- package/dist/runtime/background-sync.js.map +1 -1
- package/dist/runtime/cache.js +91 -3
- package/dist/runtime/cache.js.map +1 -1
- package/dist/runtime/client-injector-bundle.js +314 -0
- package/dist/runtime/client-injector-bundle.js.map +1 -0
- package/dist/runtime/client-injector.js +188 -30
- package/dist/runtime/client-injector.js.map +1 -1
- package/dist/runtime/connectivity.js +83 -0
- package/dist/runtime/connectivity.js.map +1 -0
- package/dist/runtime/fetch-wrapper.js +26 -59
- package/dist/runtime/fetch-wrapper.js.map +1 -1
- package/dist/runtime/gql-wrapper.js +15 -9
- package/dist/runtime/gql-wrapper.js.map +1 -1
- package/dist/runtime/invalidation-tags.js +12 -89
- package/dist/runtime/invalidation-tags.js.map +1 -1
- package/dist/runtime/mutation-queue.js +83 -31
- package/dist/runtime/mutation-queue.js.map +1 -1
- package/dist/runtime/mutation-state.js +3 -3
- package/dist/runtime/mutation-state.js.map +1 -1
- package/dist/runtime/open-db.js +41 -0
- package/dist/runtime/open-db.js.map +1 -0
- package/dist/runtime/push.js +15 -27
- package/dist/runtime/push.js.map +1 -1
- package/dist/runtime/pwa-prompt.js +35 -3
- package/dist/runtime/pwa-prompt.js.map +1 -1
- package/dist/runtime/reset.js +39 -42
- package/dist/runtime/reset.js.map +1 -1
- package/dist/runtime/server-push.js +23 -13
- package/dist/runtime/server-push.js.map +1 -1
- package/dist/runtime/storage.js +32 -0
- package/dist/runtime/storage.js.map +1 -0
- package/dist/runtime/sw-injector.js +19 -178
- package/dist/runtime/sw-injector.js.map +1 -1
- package/dist/runtime/swoff-api-bundle.js +1491 -0
- package/dist/runtime/swoff-api-bundle.js.map +1 -0
- package/dist/runtime/type-definitions.js +8 -7
- package/dist/runtime/type-definitions.js.map +1 -1
- package/dist/runtime/utils.js +4 -0
- package/dist/runtime/utils.js.map +1 -1
- package/package.json +9 -3
- package/templates/react/useAuth.jsx +7 -4
- package/templates/react/useAuth.tsx +14 -14
- package/templates/react/useBackgroundSync.jsx +5 -4
- package/templates/react/useBackgroundSync.tsx +5 -4
- package/templates/react/useCachedFetch.jsx +8 -0
- package/templates/react/useCachedFetch.tsx +8 -0
- package/templates/react/useMutation.jsx +60 -56
- package/templates/react/useMutation.tsx +65 -64
- package/templates/react/useMutationQueue.jsx +5 -1
- package/templates/react/useMutationQueue.tsx +8 -2
- package/templates/react/useMutationState.jsx +3 -4
- package/templates/react/useMutationState.tsx +4 -8
- package/templates/react/useNetworkStatus.jsx +57 -17
- package/templates/react/useNetworkStatus.tsx +42 -20
- package/templates/react/useOfflineAnalytics.jsx +42 -0
- package/templates/react/useOfflineAnalytics.tsx +50 -0
- package/templates/react/usePwaInstall.jsx +26 -0
- package/templates/react/usePwaInstall.tsx +26 -0
- package/templates/react/useSWUpdate.jsx +7 -52
- package/templates/react/useSWUpdate.tsx +12 -51
- package/templates/react/useStorageEstimate.jsx +56 -0
- package/templates/react/useStorageEstimate.tsx +67 -0
- package/dist/__tests__/assemble-sw.test.js +0 -145
- package/dist/__tests__/assemble-sw.test.js.map +0 -1
- package/dist/__tests__/cli-integration.test.js +0 -231
- package/dist/__tests__/cli-integration.test.js.map +0 -1
- package/dist/__tests__/config-types.test.js +0 -124
- package/dist/__tests__/config-types.test.js.map +0 -1
- package/dist/__tests__/detect-language.test.js +0 -51
- package/dist/__tests__/detect-language.test.js.map +0 -1
- package/dist/__tests__/file-generators.test.js +0 -228
- package/dist/__tests__/file-generators.test.js.map +0 -1
- package/dist/__tests__/glob-matcher.test.js +0 -86
- package/dist/__tests__/glob-matcher.test.js.map +0 -1
- package/dist/__tests__/invalidation-tags.test.js +0 -283
- package/dist/__tests__/invalidation-tags.test.js.map +0 -1
- package/dist/__tests__/loader.test.js +0 -77
- package/dist/__tests__/loader.test.js.map +0 -1
- package/dist/__tests__/validator.test.js +0 -340
- package/dist/__tests__/validator.test.js.map +0 -1
- package/dist/lib/commands/add.js +0 -120
- package/dist/lib/commands/add.js.map +0 -1
- package/dist/lib/commands/assets.js +0 -45
- package/dist/lib/commands/assets.js.map +0 -1
- package/dist/lib/commands/generate-assets.js +0 -44
- package/dist/lib/commands/generate-assets.js.map +0 -1
- package/dist/lib/commands/info.js +0 -183
- package/dist/lib/commands/info.js.map +0 -1
- package/dist/lib/generators/asset-generator/dependency-resolver.js +0 -85
- package/dist/lib/generators/asset-generator/dependency-resolver.js.map +0 -1
- package/dist/lib/generators/asset-generator/generate.js +0 -111
- package/dist/lib/generators/asset-generator/generate.js.map +0 -1
- package/dist/lib/generators/asset-generator/guide.js +0 -43
- package/dist/lib/generators/asset-generator/guide.js.map +0 -1
- package/dist/lib/generators/asset-generator/html-patcher.js +0 -65
- package/dist/lib/generators/asset-generator/html-patcher.js.map +0 -1
- package/dist/lib/generators/asset-generator/ico-encoder.js +0 -29
- package/dist/lib/generators/asset-generator/ico-encoder.js.map +0 -1
- package/dist/lib/generators/asset-generator/manifest-patcher.js +0 -23
- package/dist/lib/generators/asset-generator/manifest-patcher.js.map +0 -1
- package/dist/lib/generators/asset-generator/maskable.js +0 -15
- package/dist/lib/generators/asset-generator/maskable.js.map +0 -1
- package/dist/lib/generators/asset-generator/rasterize.js +0 -32
- package/dist/lib/generators/asset-generator/rasterize.js.map +0 -1
- package/dist/lib/generators/asset-generator/sizes.js +0 -25
- package/dist/lib/generators/asset-generator/sizes.js.map +0 -1
- package/dist/lib/generators/file-generators/auth-fetch.js +0 -151
- package/dist/lib/generators/file-generators/auth-fetch.js.map +0 -1
- package/dist/lib/generators/file-generators/auth-user.js +0 -13
- package/dist/lib/generators/file-generators/auth-user.js.map +0 -1
- package/dist/lib/generators/file-generators/fetch-state.js +0 -6
- package/dist/lib/generators/file-generators/fetch-state.js.map +0 -1
- package/dist/lib/generators/file-generators/generate-hooks.js +0 -44
- package/dist/lib/generators/file-generators/generate-hooks.js.map +0 -1
- package/dist/lib/generators/file-generators/indexeddb.js +0 -74
- package/dist/lib/generators/file-generators/indexeddb.js.map +0 -1
- package/dist/lib/generators/file-generators/manifest.js +0 -46
- package/dist/lib/generators/file-generators/manifest.js.map +0 -1
- package/dist/lib/generators/file-generators/mutation-reconcile.js +0 -57
- package/dist/lib/generators/file-generators/mutation-reconcile.js.map +0 -1
- package/dist/lib/generators/file-generators/quick-readme.js +0 -21
- package/dist/lib/generators/file-generators/quick-readme.js.map +0 -1
- package/dist/lib/generators/file-generators/reconcile.js +0 -50
- package/dist/lib/generators/file-generators/reconcile.js.map +0 -1
- package/dist/lib/generators/file-generators/store.js +0 -86
- package/dist/lib/generators/file-generators/store.js.map +0 -1
- package/dist/lib/generators/file-generators/sw-push.js +0 -67
- package/dist/lib/generators/file-generators/sw-push.js.map +0 -1
- package/dist/lib/generators/sw-sections/glob-matcher-code.js.map +0 -1
- package/dist/lib/utils/build-script.js +0 -35
- package/dist/lib/utils/build-script.js.map +0 -1
- package/dist/lib/utils/tty-status.js +0 -21
- package/dist/lib/utils/tty-status.js.map +0 -1
- package/dist/runtime/auth-user.js +0 -168
- package/dist/runtime/auth-user.js.map +0 -1
- package/dist/runtime/fetch-state.js +0 -42
- package/dist/runtime/fetch-state.js.map +0 -1
- package/dist/runtime/pwa-index.js +0 -11
- package/dist/runtime/pwa-index.js.map +0 -1
- package/dist/runtime/pwa-injector.js +0 -44
- package/dist/runtime/pwa-injector.js.map +0 -1
- package/dist/runtime/pwa-install.js +0 -83
- package/dist/runtime/pwa-install.js.map +0 -1
- package/templates/react/useCacheInvalidation.jsx +0 -19
- package/templates/react/useCacheInvalidation.tsx +0 -52
- package/templates/react/useIsFetching.jsx +0 -32
- package/templates/react/useIsFetching.tsx +0 -32
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
export function generateClientInjectorBundleCode(ctx, autoActivate, swFilename, pwaEnabled, navMode, authEnabled, mutationQueueEnabled) {
|
|
2
|
+
const pwaCode = pwaEnabled ? `
|
|
3
|
+
// ── PWA Install Prompt ──
|
|
4
|
+
function setupPwaInstall() {
|
|
5
|
+
window.addEventListener("beforeinstallprompt", function (e) {
|
|
6
|
+
window.deferredInstallPrompt = e;
|
|
7
|
+
window.pwaInstallable = true;
|
|
8
|
+
e.preventDefault();
|
|
9
|
+
window.dispatchEvent(new CustomEvent("pwa-installable", { detail: { isInstallable: true } }));
|
|
10
|
+
});
|
|
11
|
+
window.addEventListener("appinstalled", function () {
|
|
12
|
+
window.deferredInstallPrompt = null;
|
|
13
|
+
window.pwaInstallable = false;
|
|
14
|
+
window.dispatchEvent(new CustomEvent("pwa-installed", { detail: { outcome: "accepted" } }));
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
if (typeof window !== "undefined" && typeof document !== "undefined") { setupPwaInstall(); }` : "";
|
|
18
|
+
const ssrPrefetch = navMode === "ssr" ? `
|
|
19
|
+
// ── Auto-prefetch HTML on client-side navigation (SSR mode) ──
|
|
20
|
+
// Guards against missing prefetchCache — only active when the user includes the fetch/core module.
|
|
21
|
+
if (typeof history !== "undefined") {
|
|
22
|
+
var origPushState = history.pushState.bind(history);
|
|
23
|
+
history.pushState = function (data, unused, url) {
|
|
24
|
+
origPushState(data, unused, url);
|
|
25
|
+
if (typeof url === "string" && url.startsWith("/") && typeof prefetchCache === "function") {
|
|
26
|
+
prefetchCache(url);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
var origReplaceState = history.replaceState.bind(history);
|
|
30
|
+
history.replaceState = function (data, unused, url) {
|
|
31
|
+
origReplaceState(data, unused, url);
|
|
32
|
+
if (typeof url === "string" && url.startsWith("/") && typeof prefetchCache === "function") {
|
|
33
|
+
prefetchCache(url);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}` : "";
|
|
37
|
+
return `(function () {
|
|
38
|
+
"use strict";
|
|
39
|
+
|
|
40
|
+
// ── Service Worker Registration ──
|
|
41
|
+
var AUTO_ACTIVATE = ${autoActivate};
|
|
42
|
+
|
|
43
|
+
function waitForController() {
|
|
44
|
+
return new Promise(function (resolve) {
|
|
45
|
+
if (navigator.serviceWorker.controller) {
|
|
46
|
+
resolve();
|
|
47
|
+
} else {
|
|
48
|
+
var timeout = setTimeout(function () { resolve(); }, 30000);
|
|
49
|
+
navigator.serviceWorker.addEventListener("controllerchange", function () {
|
|
50
|
+
clearTimeout(timeout);
|
|
51
|
+
resolve();
|
|
52
|
+
}, { once: true });
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async function registerSW() {
|
|
58
|
+
if (!("serviceWorker" in navigator)) {
|
|
59
|
+
console.warn("Service Workers not supported");
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
var registration = await navigator.serviceWorker.register("/${swFilename}.js");
|
|
64
|
+
var swReadyDispatched = false;
|
|
65
|
+
if (registration.installing) {
|
|
66
|
+
var installingWorker = registration.installing;
|
|
67
|
+
installingWorker.addEventListener("statechange", function () {
|
|
68
|
+
if (installingWorker.state === "installed") {
|
|
69
|
+
if (AUTO_ACTIVATE) {
|
|
70
|
+
if (registration.waiting) {
|
|
71
|
+
registration.waiting.postMessage({ type: "SKIP_WAITING" });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
swReadyDispatched = true;
|
|
75
|
+
window.dispatchEvent(new CustomEvent("sw-ready"));
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
await waitForController();
|
|
80
|
+
if (!swReadyDispatched) {
|
|
81
|
+
window.dispatchEvent(new CustomEvent("sw-ready"));
|
|
82
|
+
}
|
|
83
|
+
} catch (error) {
|
|
84
|
+
console.error("Service Worker registration failed:", error);
|
|
85
|
+
window.swError = true;
|
|
86
|
+
window.dispatchEvent(new CustomEvent("sw-error"));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ── Connectivity ──
|
|
91
|
+
var CONNECTIVITY_EVENT = "app-connectivity-change";
|
|
92
|
+
var heartbeatIntervalId = null;
|
|
93
|
+
var HEARTBEAT_DELAY = 30000;
|
|
94
|
+
var _currentOnlineStatus = typeof navigator !== "undefined" ? navigator.onLine : true;
|
|
95
|
+
|
|
96
|
+
function getCurrentOnlineStatus() {
|
|
97
|
+
return _currentOnlineStatus;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function createTimeoutSignal(ms) {
|
|
101
|
+
if (typeof AbortSignal.timeout === "function") return AbortSignal.timeout(ms);
|
|
102
|
+
var ctrl = new AbortController();
|
|
103
|
+
setTimeout(function () { ctrl.abort(); }, ms);
|
|
104
|
+
return ctrl.signal;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function verifyAndNotify() {
|
|
108
|
+
if (typeof window === "undefined") return false;
|
|
109
|
+
if (!navigator.onLine) {
|
|
110
|
+
dispatchState(false);
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
await fetch("/" + Date.now() + "?hb=1", {
|
|
115
|
+
method: "HEAD",
|
|
116
|
+
cache: "no-cache",
|
|
117
|
+
signal: createTimeoutSignal(5000),
|
|
118
|
+
});
|
|
119
|
+
if (navigator.serviceWorker.controller) {
|
|
120
|
+
navigator.serviceWorker.controller.postMessage({ type: "ONLINE" });
|
|
121
|
+
}
|
|
122
|
+
dispatchState(true);
|
|
123
|
+
return true;
|
|
124
|
+
} catch (error) {
|
|
125
|
+
if (navigator.serviceWorker.controller) {
|
|
126
|
+
navigator.serviceWorker.controller.postMessage({ type: "OFFLINE" });
|
|
127
|
+
}
|
|
128
|
+
dispatchState(false);
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function dispatchState(isTrulyOnline) {
|
|
134
|
+
_currentOnlineStatus = isTrulyOnline;
|
|
135
|
+
window.dispatchEvent(new CustomEvent(CONNECTIVITY_EVENT, { detail: { online: isTrulyOnline } }));
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function startHeartbeat() {
|
|
139
|
+
if (heartbeatIntervalId) return;
|
|
140
|
+
heartbeatIntervalId = setInterval(async function () {
|
|
141
|
+
if (document.hidden) return;
|
|
142
|
+
await verifyAndNotify();
|
|
143
|
+
}, HEARTBEAT_DELAY);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function stopHeartbeat() {
|
|
147
|
+
if (!heartbeatIntervalId) return;
|
|
148
|
+
clearInterval(heartbeatIntervalId);
|
|
149
|
+
heartbeatIntervalId = null;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function forceRetry() {
|
|
153
|
+
stopHeartbeat();
|
|
154
|
+
return verifyAndNotify().then(function () {
|
|
155
|
+
startHeartbeat();
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// ── Storage ──
|
|
160
|
+
async function getStorageEstimate() {
|
|
161
|
+
if (!navigator.storage || !navigator.storage.estimate) {
|
|
162
|
+
return { usage: 0, quota: 0, percentUsed: 0 };
|
|
163
|
+
}
|
|
164
|
+
var est = await navigator.storage.estimate();
|
|
165
|
+
var usage = est.usage || 0;
|
|
166
|
+
var quota = est.quota || 0;
|
|
167
|
+
var percentUsed = quota > 0 ? Math.round((usage / quota) * 100) : 0;
|
|
168
|
+
return { usage: usage, quota: quota, percentUsed: percentUsed };
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function formatBytes(bytes) {
|
|
172
|
+
if (bytes === 0) return "0 B";
|
|
173
|
+
var units = ["B", "KB", "MB", "GB"];
|
|
174
|
+
var i = Math.floor(Math.log(bytes) / Math.log(1024));
|
|
175
|
+
return (bytes / Math.pow(1024, i)).toFixed(1) + " " + units[i];
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// ── Online / Offline / Visibility Listeners ──
|
|
179
|
+
if (typeof window !== "undefined") {
|
|
180
|
+
window.addEventListener("online", async function () {
|
|
181
|
+
await verifyAndNotify();
|
|
182
|
+
startHeartbeat();
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
window.addEventListener("offline", function () {
|
|
186
|
+
stopHeartbeat();
|
|
187
|
+
dispatchState(false);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
document.addEventListener("visibilitychange", function () {
|
|
191
|
+
if (!document.hidden) {
|
|
192
|
+
verifyAndNotify();
|
|
193
|
+
startHeartbeat();
|
|
194
|
+
} else {
|
|
195
|
+
stopHeartbeat();
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
if (navigator.onLine) {
|
|
200
|
+
verifyAndNotify();
|
|
201
|
+
startHeartbeat();
|
|
202
|
+
} else {
|
|
203
|
+
queueMicrotask(function () { dispatchState(false); });
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// ── Focus Listener (reactive strategy) ──
|
|
208
|
+
if (typeof document !== "undefined") {
|
|
209
|
+
document.addEventListener("visibilitychange", function () {
|
|
210
|
+
if (document.visibilityState === "visible" && navigator.serviceWorker.controller) {
|
|
211
|
+
navigator.serviceWorker.controller.postMessage({ type: "FOCUS" });
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
${pwaCode}${ssrPrefetch}
|
|
216
|
+
// ── SW Message Listener ──
|
|
217
|
+
if (typeof window !== "undefined" && "serviceWorker" in navigator) {
|
|
218
|
+
navigator.serviceWorker.addEventListener("message", function (event) {
|
|
219
|
+
if (event.data.type === "CACHE_UPDATED") {
|
|
220
|
+
window.dispatchEvent(new CustomEvent("swoff:cache-updated", { detail: { url: event.data.url } }));
|
|
221
|
+
}
|
|
222
|
+
if (event.data.type === "NAV_RETRY_SUCCESS") {
|
|
223
|
+
window.dispatchEvent(new CustomEvent("swoff:navigation-online", { detail: { url: event.data.url } }));
|
|
224
|
+
}
|
|
225
|
+
if (event.data.type === "OFFLINE_FALLBACK_ACTIVATED") {
|
|
226
|
+
window.dispatchEvent(new CustomEvent("swoff:offline-fallback", { detail: event.data.detail }));
|
|
227
|
+
}
|
|
228
|
+
if (event.data.type === "SW_PROGRESS") {
|
|
229
|
+
window.dispatchEvent(new CustomEvent("sw-progress", {
|
|
230
|
+
detail: { percent: event.data.percent, downloaded: event.data.downloaded, total: event.data.total },
|
|
231
|
+
}));
|
|
232
|
+
}
|
|
233
|
+
if (event.data.type === "SW_NOTIFICATION") {
|
|
234
|
+
window.dispatchEvent(new CustomEvent("swoff:notification", {
|
|
235
|
+
detail: { level: event.data.level, code: event.data.code, message: event.data.message },
|
|
236
|
+
}));
|
|
237
|
+
}
|
|
238
|
+
${mutationQueueEnabled ? `
|
|
239
|
+
if (event.data.type === "BACKGROUND_SYNC_PROGRESS") {
|
|
240
|
+
window.dispatchEvent(new CustomEvent("mutation-sync-progress", { detail: event.data.detail }));
|
|
241
|
+
}
|
|
242
|
+
if (event.data.type === "BACKGROUND_SYNC_COMPLETE") {
|
|
243
|
+
var _d = event.data.detail;
|
|
244
|
+
window.dispatchEvent(new CustomEvent("mutation-sync-complete", { detail: { succeeded: _d.succeeded, failed: _d.failed } }));
|
|
245
|
+
if (_d.tags && _d.tags.length > 0) {
|
|
246
|
+
window.dispatchEvent(new CustomEvent("cache-invalidated", { detail: { tags: _d.tags } }));
|
|
247
|
+
}
|
|
248
|
+
window.dispatchEvent(new CustomEvent("mutation-queue-changed"));
|
|
249
|
+
}
|
|
250
|
+
if (event.data.type === "MUTATION_STORED" && window.swoff && typeof window.swoff.flushMutations === "function") {
|
|
251
|
+
window.swoff.flushMutations();
|
|
252
|
+
}` : ""}
|
|
253
|
+
${authEnabled ? `
|
|
254
|
+
if (event.data.type === "AUTH_CLEARED" && window.swoff && typeof window.swoff.clearMemoryAuth === "function") {
|
|
255
|
+
window.swoff.clearMemoryAuth();
|
|
256
|
+
window.dispatchEvent(new CustomEvent("sw-auth-state-change", { detail: { type: "clear" } }));
|
|
257
|
+
}
|
|
258
|
+
if (event.data.type === "AUTH_FAILURE" && window.swoff && typeof window.swoff.ensureValidAuth === "function") {
|
|
259
|
+
(async function () {
|
|
260
|
+
var _refreshed = await window.swoff.ensureValidAuth();
|
|
261
|
+
if (!_refreshed) {
|
|
262
|
+
if (window.swoff && typeof window.swoff.clearQueue === "function") {
|
|
263
|
+
await window.swoff.clearQueue();
|
|
264
|
+
}
|
|
265
|
+
try {
|
|
266
|
+
var _names = ["swoff-runtime", "swoff-runtime-html"];
|
|
267
|
+
for (var _i = 0; _i < _names.length; _i++) {
|
|
268
|
+
var _cache = await caches.open(_names[_i]);
|
|
269
|
+
var _keys = await _cache.keys();
|
|
270
|
+
await Promise.all(_keys.map(function (k) { return _cache.delete(k); }));
|
|
271
|
+
}
|
|
272
|
+
} catch (e) {}
|
|
273
|
+
window.dispatchEvent(new CustomEvent("sw-auth-unauthorized"));
|
|
274
|
+
}
|
|
275
|
+
})();
|
|
276
|
+
}` : ""}
|
|
277
|
+
if (event.data.type === "TAG_INVALIDATED" && event.data.tag) {
|
|
278
|
+
window.dispatchEvent(new CustomEvent("cache-invalidated", {
|
|
279
|
+
detail: { tags: [event.data.tag] },
|
|
280
|
+
}));
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// ── Main Entry ──
|
|
286
|
+
async function initServiceWorker() {
|
|
287
|
+
await registerSW();
|
|
288
|
+
var storage = await getStorageEstimate();
|
|
289
|
+
if (storage.percentUsed > 80) {
|
|
290
|
+
window.dispatchEvent(new CustomEvent("swoff:notification", {
|
|
291
|
+
detail: {
|
|
292
|
+
level: "warn",
|
|
293
|
+
code: "STORAGE_QUOTA_HIGH",
|
|
294
|
+
message: "Storage at " + storage.percentUsed + "% capacity (" + formatBytes(storage.usage) + " / " + formatBytes(storage.quota) + ")",
|
|
295
|
+
},
|
|
296
|
+
}));
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// ── Bridge for swoff-api-bundle ──
|
|
301
|
+
if (typeof window !== "undefined") {
|
|
302
|
+
window.__SWOFF_FORCE_RETRY = forceRetry;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// ── Auto-initialize ──
|
|
306
|
+
if (typeof window !== "undefined" && "serviceWorker" in navigator) {
|
|
307
|
+
initServiceWorker().catch(function (err) {
|
|
308
|
+
console.warn("Swoff SW registration failed:", err);
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
})();
|
|
312
|
+
`;
|
|
313
|
+
}
|
|
314
|
+
//# sourceMappingURL=client-injector-bundle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-injector-bundle.js","sourceRoot":"","sources":["../../src/runtime/client-injector-bundle.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,gCAAgC,CAC9C,GAAmB,EACnB,YAAqB,EACrB,UAAkB,EAClB,UAAmB,EACnB,OAAgB,EAChB,WAAqB,EACrB,oBAA8B;IAE9B,MAAM,OAAO,GAAG,UAAU,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;+FAegE,CAAC,CAAC,CAAC,EAAE,CAAC;IAEnG,MAAM,WAAW,GAAG,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;IAkBtC,CAAC,CAAC,CAAC,EAAE,CAAC;IAER,OAAO;;;;wBAIe,YAAY;;;;;;;;;;;;;;;;;;;;;;oEAsBgC,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwJ5E,OAAO,GAAG,WAAW;;;;;;;;;;;;;;;;;;;;;;;EAuBrB,oBAAoB,CAAC,CAAC,CAAC;;;;;;;;;;;;;;QAcjB,CAAC,CAAC,CAAC,EAAE;EACX,WAAW,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;QAuBR,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoCZ,CAAC;AACF,CAAC"}
|
|
@@ -1,37 +1,79 @@
|
|
|
1
|
-
export function generateClientInjectorCode(ctx, pwaEnabled, mutationQueueEnabled, serverPushEnabled) {
|
|
1
|
+
export function generateClientInjectorCode(ctx, pwaEnabled, mutationQueueEnabled, serverPushEnabled, navMode, authEnabled, connectivityEnabled, tagInvalidationEnabled) {
|
|
2
2
|
const { ext, ts } = ctx;
|
|
3
|
+
const ssrNav = navMode === "ssr" && tagInvalidationEnabled;
|
|
3
4
|
const pwaImport = pwaEnabled
|
|
4
|
-
? `import { setupPwaInstall } from "./pwa/
|
|
5
|
+
? `import { setupPwaInstall } from "./pwa/prompt.${ext}";
|
|
5
6
|
`
|
|
6
7
|
: "";
|
|
7
|
-
const pwaCall = pwaEnabled
|
|
8
|
+
const pwaCall = pwaEnabled
|
|
9
|
+
? `if (typeof window !== "undefined" && typeof document !== "undefined") { setupPwaInstall(); }\n`
|
|
10
|
+
: "";
|
|
8
11
|
const pushImport = serverPushEnabled
|
|
9
|
-
? `import { startPushEvents } from "./
|
|
12
|
+
? `import { startPushEvents } from "./server-push/client.${ext}";
|
|
10
13
|
`
|
|
11
14
|
: "";
|
|
12
|
-
const pushCall = serverPushEnabled
|
|
15
|
+
const pushCall = serverPushEnabled
|
|
16
|
+
? `if (typeof navigator !== "undefined" && "serviceWorker" in navigator) { startPushEvents(); }\n`
|
|
17
|
+
: "";
|
|
13
18
|
const mutationImport = mutationQueueEnabled
|
|
14
|
-
? `import { processMutationQueue } from "./
|
|
19
|
+
? `import { processMutationQueue, clearQueue } from "./mutation/queue.${ext}";
|
|
15
20
|
`
|
|
16
21
|
: "";
|
|
17
|
-
const
|
|
18
|
-
? `
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
const authImport = authEnabled
|
|
23
|
+
? `import { ensureValidAuth, clearMemoryAuth } from "./auth/store.${ext}";
|
|
24
|
+
`
|
|
25
|
+
: "";
|
|
26
|
+
const storageImport = connectivityEnabled
|
|
27
|
+
? `import { getStorageEstimate, formatBytes } from "./storage.${ext}";
|
|
28
|
+
`
|
|
29
|
+
: "";
|
|
30
|
+
const connectivityImport = connectivityEnabled
|
|
31
|
+
? `import {
|
|
32
|
+
dispatchState,
|
|
33
|
+
startHeartbeat,
|
|
34
|
+
stopHeartbeat,
|
|
35
|
+
verifyAndNotify,
|
|
36
|
+
} from './connectivity.${ext}'
|
|
21
37
|
`
|
|
22
38
|
: "";
|
|
23
|
-
const
|
|
24
|
-
|
|
39
|
+
const onlineListener = connectivityEnabled
|
|
40
|
+
? `
|
|
41
|
+
// --- Online Listener ---
|
|
25
42
|
// When connectivity returns, the SW checks stale cache entries and refetches them.
|
|
26
|
-
if (typeof window !==
|
|
27
|
-
window.addEventListener(
|
|
28
|
-
|
|
29
|
-
|
|
43
|
+
if (typeof window !== 'undefined') {
|
|
44
|
+
window.addEventListener('online', async () => {
|
|
45
|
+
const isOnline = await verifyAndNotify()
|
|
46
|
+
startHeartbeat()
|
|
47
|
+
if (isOnline) {
|
|
48
|
+
${mutationQueueEnabled ? `processMutationQueue()` : ""}
|
|
30
49
|
}
|
|
31
|
-
})
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
window.addEventListener('offline', () => {
|
|
53
|
+
stopHeartbeat()
|
|
54
|
+
dispatchState(false)
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
document.addEventListener('visibilitychange', () => {
|
|
58
|
+
if (!document.hidden) {
|
|
59
|
+
verifyAndNotify()
|
|
60
|
+
startHeartbeat()
|
|
61
|
+
} else {
|
|
62
|
+
stopHeartbeat()
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
if (navigator.onLine) {
|
|
67
|
+
verifyAndNotify()
|
|
68
|
+
startHeartbeat()
|
|
69
|
+
} else {
|
|
70
|
+
queueMicrotask(() => dispatchState(false))
|
|
71
|
+
}
|
|
32
72
|
}
|
|
33
|
-
|
|
34
|
-
|
|
73
|
+
`
|
|
74
|
+
: "";
|
|
75
|
+
const focusListener = tagInvalidationEnabled
|
|
76
|
+
? `
|
|
35
77
|
// --- Focus Listener for Reactive Strategy ---
|
|
36
78
|
// Notifies the SW when the tab gains focus so it can refresh stale reactive entries.
|
|
37
79
|
// Uses visibilitychange only (covers tab switch, window refocus, alt-tab) — single source avoids duplicate FOCUS messages.
|
|
@@ -42,8 +84,10 @@ if (typeof document !== "undefined") {
|
|
|
42
84
|
}
|
|
43
85
|
});
|
|
44
86
|
}
|
|
45
|
-
|
|
46
|
-
|
|
87
|
+
`
|
|
88
|
+
: "";
|
|
89
|
+
const invalidationHandler = tagInvalidationEnabled
|
|
90
|
+
? `
|
|
47
91
|
if (event.data.type === "TAG_INVALIDATED" && event.data.tag) {
|
|
48
92
|
window.dispatchEvent(
|
|
49
93
|
new CustomEvent("cache-invalidated", {
|
|
@@ -51,9 +95,53 @@ if (typeof document !== "undefined") {
|
|
|
51
95
|
})
|
|
52
96
|
);
|
|
53
97
|
}
|
|
54
|
-
|
|
98
|
+
`
|
|
99
|
+
: "";
|
|
55
100
|
const swImport = `import { initServiceWorker as swInit } from "./sw/injector.${ext}";
|
|
56
101
|
`;
|
|
102
|
+
const autoPrefetchImport = ssrNav
|
|
103
|
+
? `import { prefetchCache } from "./fetch/core.${ext}";
|
|
104
|
+
`
|
|
105
|
+
: "";
|
|
106
|
+
const autoPrefetchCode = ssrNav
|
|
107
|
+
? `
|
|
108
|
+
// --- Auto-prefetch HTML on client-side navigation (SSR mode) ---
|
|
109
|
+
// Intercepts history.pushState/replaceState to warm the SW cache with HTML
|
|
110
|
+
// for routes the user navigates to via client-side routing.
|
|
111
|
+
if (typeof history !== "undefined") {
|
|
112
|
+
const origPushState = history.pushState.bind(history);
|
|
113
|
+
history.pushState = function (data, unused, url) {
|
|
114
|
+
origPushState(data, unused, url);
|
|
115
|
+
if (typeof url === "string" && url.startsWith("/")) {
|
|
116
|
+
prefetchCache(url);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
const origReplaceState = history.replaceState.bind(history);
|
|
120
|
+
history.replaceState = function (data, unused, url) {
|
|
121
|
+
origReplaceState(data, unused, url);
|
|
122
|
+
if (typeof url === "string" && url.startsWith("/")) {
|
|
123
|
+
prefetchCache(url);
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
`
|
|
128
|
+
: "";
|
|
129
|
+
const storageInit = connectivityEnabled
|
|
130
|
+
? `
|
|
131
|
+
const storage = await getStorageEstimate();
|
|
132
|
+
if (storage.percentUsed > 80) {
|
|
133
|
+
window.dispatchEvent(
|
|
134
|
+
new CustomEvent("swoff:notification", {
|
|
135
|
+
detail: {
|
|
136
|
+
level: "warn",
|
|
137
|
+
code: "STORAGE_QUOTA_HIGH",
|
|
138
|
+
message: \`Storage at \${storage.percentUsed}% capacity (\${formatBytes(storage.usage)} / \${formatBytes(storage.quota)})\`,
|
|
139
|
+
},
|
|
140
|
+
}),
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
`
|
|
144
|
+
: "";
|
|
57
145
|
return `/**
|
|
58
146
|
* Swoff Client Injector
|
|
59
147
|
* Orchestrates SW registration, PWA install, and cross-tab sync.
|
|
@@ -68,7 +156,9 @@ if (typeof document !== "undefined") {
|
|
|
68
156
|
* sw-ready - SW active and controlling page
|
|
69
157
|
* sw-error - SW registration failed
|
|
70
158
|
* cache-invalidated - Cache entries cleared on SW confirmation (detail: { tags })
|
|
71
|
-
* swoff:cache-updated
|
|
159
|
+
* swoff:cache-updated - Background refresh completed (detail: { url })
|
|
160
|
+
* swoff:offline-fallback - Offline fallback page served (detail: { route, fallbackLevel, timestamp })
|
|
161
|
+
* swoff:notification - SW or storage notification (detail: { level, code, message })
|
|
72
162
|
* mutation-sync-complete - Queued mutations synced (detail: { succeeded, failed })
|
|
73
163
|
* mutation-sync-progress - Batch progress during sync (detail: { succeeded, failed, total, current })
|
|
74
164
|
* mutation-queue-changed - Queue modified
|
|
@@ -78,11 +168,9 @@ if (typeof document !== "undefined") {
|
|
|
78
168
|
* pwa-installed - User accepted install (detail: { outcome: 'accepted' })
|
|
79
169
|
* sw-auth-unauthorized - 401 response received
|
|
80
170
|
* sw-auth-state-change - Login or logout (detail: { authenticated: boolean })
|
|
81
|
-
* sw-update-available - New version ready (detail: { version })
|
|
82
|
-
* sw-version-detected - Version info available
|
|
83
171
|
*/
|
|
84
|
-
${pwaImport}${mutationImport}${swImport}${pushImport}
|
|
85
|
-
${pwaCall}${
|
|
172
|
+
${pwaImport}${mutationImport}${authImport}${swImport}${storageImport}${connectivityImport}${pushImport}${autoPrefetchImport}
|
|
173
|
+
${pwaCall}${pushCall}${onlineListener}${focusListener}${autoPrefetchCode}
|
|
86
174
|
// --- SW Message Listener ---
|
|
87
175
|
if (typeof window !== "undefined" && "serviceWorker" in navigator) {
|
|
88
176
|
navigator.serviceWorker.addEventListener("message", (event) => {
|
|
@@ -93,6 +181,20 @@ if (typeof window !== "undefined" && "serviceWorker" in navigator) {
|
|
|
93
181
|
})
|
|
94
182
|
);
|
|
95
183
|
}
|
|
184
|
+
if (event.data.type === "NAV_RETRY_SUCCESS") {
|
|
185
|
+
window.dispatchEvent(
|
|
186
|
+
new CustomEvent("swoff:navigation-online", {
|
|
187
|
+
detail: { url: event.data.url },
|
|
188
|
+
})
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
if (event.data.type === "OFFLINE_FALLBACK_ACTIVATED") {
|
|
192
|
+
window.dispatchEvent(
|
|
193
|
+
new CustomEvent("swoff:offline-fallback", {
|
|
194
|
+
detail: event.data.detail,
|
|
195
|
+
})
|
|
196
|
+
);
|
|
197
|
+
}
|
|
96
198
|
if (event.data.type === "SW_PROGRESS") {
|
|
97
199
|
const { percent, downloaded, total } = event.data;
|
|
98
200
|
window.dispatchEvent(
|
|
@@ -101,6 +203,17 @@ if (typeof window !== "undefined" && "serviceWorker" in navigator) {
|
|
|
101
203
|
})
|
|
102
204
|
);
|
|
103
205
|
}
|
|
206
|
+
if (event.data.type === "SW_NOTIFICATION") {
|
|
207
|
+
window.dispatchEvent(
|
|
208
|
+
new CustomEvent("swoff:notification", {
|
|
209
|
+
detail: {
|
|
210
|
+
level: event.data.level,
|
|
211
|
+
code: event.data.code,
|
|
212
|
+
message: event.data.message,
|
|
213
|
+
},
|
|
214
|
+
})
|
|
215
|
+
);
|
|
216
|
+
}
|
|
104
217
|
if (event.data.type === "BACKGROUND_SYNC_PROGRESS") {
|
|
105
218
|
window.dispatchEvent(
|
|
106
219
|
new CustomEvent("mutation-sync-progress", {
|
|
@@ -122,14 +235,59 @@ if (typeof window !== "undefined" && "serviceWorker" in navigator) {
|
|
|
122
235
|
}
|
|
123
236
|
window.dispatchEvent(new CustomEvent("mutation-queue-changed"));
|
|
124
237
|
}
|
|
125
|
-
if (event.data.type === "MUTATION_STORED") {
|
|
126
|
-
|
|
238
|
+
if (event.data.type === "MUTATION_STORED" && typeof processMutationQueue !== "undefined") {
|
|
239
|
+
processMutationQueue();
|
|
240
|
+
}
|
|
241
|
+
if (event.data.type === "AUTH_CLEARED") {
|
|
242
|
+
// Another tab cleared auth — clear memory only (IndexedDB + caches already cleaned by initiator)
|
|
243
|
+
if (typeof clearMemoryAuth !== "undefined") {
|
|
244
|
+
clearMemoryAuth();
|
|
245
|
+
}
|
|
246
|
+
window.dispatchEvent(new CustomEvent("sw-auth-state-change", { detail: { type: "clear" } }));
|
|
247
|
+
}
|
|
248
|
+
if (event.data.type === "AUTH_FAILURE") {
|
|
249
|
+
// SW detected 401 during background refetch — check if session is still valid
|
|
250
|
+
(async () => {
|
|
251
|
+
if (typeof ensureValidAuth === "undefined") return;
|
|
252
|
+
const refreshed = await ensureValidAuth();
|
|
253
|
+
if (!refreshed) {
|
|
254
|
+
// Session expired — clear queue and runtime caches
|
|
255
|
+
if (typeof clearQueue !== "undefined") {
|
|
256
|
+
await clearQueue();
|
|
257
|
+
}
|
|
258
|
+
try {
|
|
259
|
+
for (const name of ["swoff-runtime", "swoff-runtime-html"]) {
|
|
260
|
+
const cache = await caches.open(name);
|
|
261
|
+
const keys = await cache.keys();
|
|
262
|
+
await Promise.all(keys.map((k) => cache.delete(k)));
|
|
263
|
+
}
|
|
264
|
+
} catch {
|
|
265
|
+
// Handle cache deletion errors
|
|
266
|
+
}
|
|
267
|
+
window.dispatchEvent(new CustomEvent("sw-auth-unauthorized"));
|
|
268
|
+
}
|
|
269
|
+
})();
|
|
127
270
|
}${invalidationHandler} });
|
|
128
271
|
}
|
|
129
272
|
|
|
273
|
+
// --- Background Precache Resume ---
|
|
274
|
+
// Tells the SW to resume background precaching when the page becomes visible
|
|
275
|
+
// or the browser comes back online. The SW tracks progress via IndexedDB
|
|
276
|
+
// checkpoint so it safely picks up where it left off.
|
|
277
|
+
if (typeof document !== "undefined" && "serviceWorker" in navigator) {
|
|
278
|
+
var _resumeP = function() {
|
|
279
|
+
if (navigator.serviceWorker.controller)
|
|
280
|
+
navigator.serviceWorker.controller.postMessage({ type: "RESUME_PRECACHE" });
|
|
281
|
+
};
|
|
282
|
+
document.addEventListener("visibilitychange", function() {
|
|
283
|
+
if (document.visibilityState === "visible") _resumeP();
|
|
284
|
+
});
|
|
285
|
+
window.addEventListener("online", _resumeP);
|
|
286
|
+
}
|
|
287
|
+
|
|
130
288
|
/** Initialize SW registration and all client-side features (PWA install, mutation queue, cross-tab sync). Call once at app startup. */
|
|
131
289
|
export async function initServiceWorker()${ts ? ": Promise<void>" : " "}{
|
|
132
|
-
await swInit()
|
|
290
|
+
await swInit();${storageInit}
|
|
133
291
|
}
|
|
134
292
|
`;
|
|
135
293
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-injector.js","sourceRoot":"","sources":["../../src/runtime/client-injector.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,0BAA0B,CACxC,GAAmB,EACnB,UAAmB,EACnB,oBAA6B,EAC7B,iBAA0B;
|
|
1
|
+
{"version":3,"file":"client-injector.js","sourceRoot":"","sources":["../../src/runtime/client-injector.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,0BAA0B,CACxC,GAAmB,EACnB,UAAmB,EACnB,oBAA6B,EAC7B,iBAA0B,EAC1B,OAAgB,EAChB,WAAqB,EACrB,mBAA6B,EAC7B,sBAAgC;IAEhC,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,GAAG,CAAC;IACxB,MAAM,MAAM,GAAG,OAAO,KAAK,KAAK,IAAI,sBAAsB,CAAC;IAE3D,MAAM,SAAS,GAAG,UAAU;QAC1B,CAAC,CAAC,iDAAiD,GAAG;CACzD;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,OAAO,GAAG,UAAU;QACxB,CAAC,CAAC,gGAAgG;QAClG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,UAAU,GAAG,iBAAiB;QAClC,CAAC,CAAC,yDAAyD,GAAG;CACjE;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,QAAQ,GAAG,iBAAiB;QAChC,CAAC,CAAC,gGAAgG;QAClG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,cAAc,GAAG,oBAAoB;QACzC,CAAC,CAAC,sEAAsE,GAAG;CAC9E;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,UAAU,GAAG,WAAW;QAC5B,CAAC,CAAC,kEAAkE,GAAG;CAC1E;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,aAAa,GAAG,mBAAmB;QACvC,CAAC,CAAC,8DAA8D,GAAG;CACtE;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,kBAAkB,GAAG,mBAAmB;QAC5C,CAAC,CAAC;;;;;yBAKmB,GAAG;CAC3B;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,cAAc,GAAG,mBAAmB;QACxC,CAAC,CAAC;;;;;;;;QAQE,oBAAoB,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;CAyB3D;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,aAAa,GAAG,sBAAsB;QAC1C,CAAC,CAAC;;;;;;;;;;;CAWL;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,mBAAmB,GAAG,sBAAsB;QAChD,CAAC,CAAC;;;;;;;;CAQL;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,QAAQ,GAAG,8DAA8D,GAAG;CACnF,CAAC;IAEA,MAAM,kBAAkB,GAAG,MAAM;QAC/B,CAAC,CAAC,+CAA+C,GAAG;CACvD;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,gBAAgB,GAAG,MAAM;QAC7B,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;CAoBL;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,WAAW,GAAG,mBAAmB;QACrC,CAAC,CAAC;;;;;;;;;;;;;CAaL;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO;;;;;;kEAMyD,GAAG;;;;;;;;;;;;;;;;;;;;;EAqBnE,SAAS,GAAG,cAAc,GAAG,UAAU,GAAG,QAAQ,GAAG,aAAa,GAAG,kBAAkB,GAAG,UAAU,GAAG,kBAAkB;EACzH,OAAO,GAAG,QAAQ,GAAG,cAAc,GAAG,aAAa,GAAG,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiGjE,mBAAmB;;;;;;;;;;;;;;;;;;;2CAmBiB,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,GAAG;mBACpD,WAAW;;CAE7B,CAAC;AACF,CAAC"}
|