@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
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { T, R } from "./utils.js";
|
|
1
|
+
import { T, R, AS } from "./utils.js";
|
|
2
2
|
export function generateServerPushCode(ctx, pushType, endpoint, reconnectDelayMs) {
|
|
3
3
|
const { ext, ts } = ctx;
|
|
4
4
|
const invalidate = `
|
|
5
5
|
// Forward to SW for cache invalidation
|
|
6
|
-
if (navigator.serviceWorker
|
|
6
|
+
if (navigator.serviceWorker?.controller) {
|
|
7
7
|
for (const tag of tags) {
|
|
8
8
|
navigator.serviceWorker.controller.postMessage({ type: "INVALIDATE_TAG", tag });
|
|
9
9
|
}
|
|
@@ -15,6 +15,8 @@ export function generateServerPushCode(ctx, pushType, endpoint, reconnectDelayMs
|
|
|
15
15
|
credentials: "include",
|
|
16
16
|
signal: options.signal,
|
|
17
17
|
}).then(async (response) => {
|
|
18
|
+
currentFetchController = null;
|
|
19
|
+
if (!active) { resolve(); return; }
|
|
18
20
|
if (!response.ok || !response.body) { resolve(); return; }
|
|
19
21
|
notifyStatus(true);
|
|
20
22
|
const reader = response.body.getReader();
|
|
@@ -51,14 +53,15 @@ export function generateServerPushCode(ctx, pushType, endpoint, reconnectDelayMs
|
|
|
51
53
|
return new Promise((resolve) => {
|
|
52
54
|
try {
|
|
53
55
|
const ws = new WebSocket(API_BASE + "${endpoint}");
|
|
56
|
+
currentWs = ws;
|
|
54
57
|
ws.onopen = () => notifyStatus(true);
|
|
55
58
|
ws.onmessage = (event) => {
|
|
56
59
|
try { const d = JSON.parse(event.data); if (d.type === "invalidate" && d.tags) handleInvalidation(d.tags); } catch {}
|
|
57
60
|
};
|
|
58
|
-
ws.onclose = () => { notifyStatus(false); resolve(); };
|
|
59
|
-
ws.onerror = () => { ws.close(); resolve(); };
|
|
61
|
+
ws.onclose = () => { currentWs = null; notifyStatus(false); resolve(); };
|
|
62
|
+
ws.onerror = () => { currentWs = null; ws.close(); resolve(); };
|
|
60
63
|
if (options.signal) {
|
|
61
|
-
options.signal.addEventListener("abort", () => ws.close());
|
|
64
|
+
options.signal.addEventListener("abort", () => { ws.close(); currentWs = null; });
|
|
62
65
|
}
|
|
63
66
|
} catch { resolve(); }
|
|
64
67
|
});`;
|
|
@@ -70,7 +73,7 @@ export function generateServerPushCode(ctx, pushType, endpoint, reconnectDelayMs
|
|
|
70
73
|
* This client-side helper provides status tracking and a manual start/stop API.
|
|
71
74
|
*
|
|
72
75
|
* Usage:
|
|
73
|
-
* import { startPushEvents, stopPushEvents, isPushConnected } from "./
|
|
76
|
+
* import { startPushEvents, stopPushEvents, isPushConnected } from "./server-push/client.${ext}";
|
|
74
77
|
* startPushEvents();
|
|
75
78
|
*
|
|
76
79
|
* Server sends:
|
|
@@ -87,6 +90,8 @@ type PushEventOptions= {
|
|
|
87
90
|
let active${T(ts, "boolean")} = false;
|
|
88
91
|
let swConnected${T(ts, "boolean")} = false;
|
|
89
92
|
let reconnectTimer${T(ts, "ReturnType<typeof setTimeout> | null")} = null;
|
|
93
|
+
let currentWs${T(ts, "WebSocket | null")} = null;
|
|
94
|
+
let currentFetchController${T(ts, "AbortController | null")} = null;
|
|
90
95
|
|
|
91
96
|
function handleInvalidation(tags${T(ts, "string[]")})${R(ts, "void")}{${invalidate}
|
|
92
97
|
window.dispatchEvent(new CustomEvent("cache-invalidated", { detail: { tags } }));
|
|
@@ -97,7 +102,7 @@ function notifyStatus(connected${T(ts, "boolean")})${R(ts, "void")}{
|
|
|
97
102
|
}
|
|
98
103
|
|
|
99
104
|
// Listen for SSE status from the SW
|
|
100
|
-
if (typeof navigator !== "undefined" && navigator
|
|
105
|
+
if (typeof navigator !== "undefined" && "serviceWorker" in navigator) {
|
|
101
106
|
navigator.serviceWorker.addEventListener("message", (event) => {
|
|
102
107
|
if (event.data?.type === "SSE_STATUS") {
|
|
103
108
|
swConnected = event.data.connected;
|
|
@@ -106,7 +111,10 @@ if (typeof navigator !== "undefined" && navigator.serviceWorker) {
|
|
|
106
111
|
});
|
|
107
112
|
}
|
|
108
113
|
|
|
109
|
-
async function connect(
|
|
114
|
+
async function connect()${R(ts, "Promise<void>")}{
|
|
115
|
+
const controller = new AbortController();
|
|
116
|
+
currentFetchController = controller;
|
|
117
|
+
const options = { signal: controller.signal }${AS(ts, "PushEventOptions")};
|
|
110
118
|
${pushType === "sse" ? sseConnect : wsConnect}
|
|
111
119
|
}
|
|
112
120
|
|
|
@@ -115,14 +123,14 @@ export async function startPushEvents(){
|
|
|
115
123
|
if (active) return;
|
|
116
124
|
|
|
117
125
|
// If SW is already controlling the page, skip client-side connection — the SW handles push events.
|
|
118
|
-
if (navigator.serviceWorker
|
|
126
|
+
if (navigator.serviceWorker?.controller) return;
|
|
119
127
|
|
|
120
128
|
// Listen for SW activation — if SW takes over, disconnect the client fallback.
|
|
121
129
|
const onControllerChange = () => { stopPushEvents(); };
|
|
122
|
-
navigator.serviceWorker
|
|
130
|
+
navigator.serviceWorker?.addEventListener("controllerchange", onControllerChange);
|
|
123
131
|
|
|
124
132
|
active = true;
|
|
125
|
-
let delay = ${reconnectDelayMs};
|
|
133
|
+
let delay = Math.max(1000, ${reconnectDelayMs});
|
|
126
134
|
while (active) {
|
|
127
135
|
await connect();
|
|
128
136
|
if (!active) break;
|
|
@@ -130,13 +138,15 @@ export async function startPushEvents(){
|
|
|
130
138
|
delay = Math.min(delay * 1.5, 30000); // cap at 30s
|
|
131
139
|
}
|
|
132
140
|
|
|
133
|
-
navigator.serviceWorker
|
|
141
|
+
navigator.serviceWorker?.removeEventListener("controllerchange", onControllerChange);
|
|
134
142
|
}
|
|
135
143
|
|
|
136
|
-
/** Stop listening for push events. */
|
|
144
|
+
/** Stop listening for push events and close the active connection. */
|
|
137
145
|
export function stopPushEvents(){
|
|
138
146
|
active = false;
|
|
139
147
|
if (reconnectTimer) { clearTimeout(reconnectTimer); reconnectTimer = null; }
|
|
148
|
+
if (currentWs) { currentWs.close(); currentWs = null; }
|
|
149
|
+
if (currentFetchController) { currentFetchController.abort(); currentFetchController = null; }
|
|
140
150
|
}
|
|
141
151
|
|
|
142
152
|
/** Check if the push connection is currently established. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-push.js","sourceRoot":"","sources":["../../src/runtime/server-push.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"server-push.js","sourceRoot":"","sources":["../../src/runtime/server-push.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,YAAY,CAAC;AAEtC,MAAM,UAAU,sBAAsB,CACpC,GAAmB,EACnB,QAAgB,EAChB,QAAgB,EAChB,gBAAwB;IAExB,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,GAAG,CAAC;IAExB,MAAM,UAAU,GAAG;;;;;;IAMjB,CAAC;IAEH,MAAM,UAAU,GAAG;;wBAEG,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAsC1B,CAAC;IAEL,MAAM,SAAS,GAAG;;;6CAGyB,QAAQ;;;;;;;;;;;;MAY/C,CAAC;IAEL,OAAO;;;oCAG2B,QAAQ;;;;;8FAKkD,GAAG;;;;;;;;sCAQ3D,GAAG;;;UAG/B,CAAC,CAAC,EAAE,EAAE,aAAa,CAAC;;;YAGlB,CAAC,CAAC,EAAE,EAAE,SAAS,CAAC;iBACX,CAAC,CAAC,EAAE,EAAE,SAAS,CAAC;oBACb,CAAC,CAAC,EAAE,EAAE,sCAAsC,CAAC;eAClD,CAAC,CAAC,EAAE,EAAE,kBAAkB,CAAC;4BACZ,CAAC,CAAC,EAAE,EAAE,wBAAwB,CAAC;;kCAEzB,CAAC,CAAC,EAAE,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,UAAU;;;;iCAIjD,CAAC,CAAC,EAAE,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,MAAM,CAAC;;;;;;;;;;;;;;0BAcxC,CAAC,CAAC,EAAE,EAAE,eAAe,CAAC;;;iDAGC,EAAE,CAAC,EAAE,EAAE,kBAAkB,CAAC;IACvE,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;;;;;;;;;;;;;;;+BAehB,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;CAuB9C,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { T, R } from "./utils.js";
|
|
2
|
+
export function generateStorageCode(ctx) {
|
|
3
|
+
const { ext, ts } = ctx;
|
|
4
|
+
return `/**
|
|
5
|
+
* Swoff Storage
|
|
6
|
+
* Pure utility functions for storage estimation and formatting.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* import { getStorageEstimate, formatBytes } from "./swoff/storage.${ext}";
|
|
10
|
+
* const { usage, quota, percentUsed } = await getStorageEstimate();
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** Get raw storage estimate. */
|
|
14
|
+
export async function getStorageEstimate()${R(ts, "Promise<{ usage: number; quota: number; percentUsed: number }>")}{
|
|
15
|
+
if (!navigator.storage?.estimate) {
|
|
16
|
+
return { usage: 0, quota: 0, percentUsed: 0 };
|
|
17
|
+
}
|
|
18
|
+
const { usage = 0, quota = 0 } = await navigator.storage.estimate();
|
|
19
|
+
const percentUsed = quota > 0 ? Math.round((usage / quota) * 100) : 0;
|
|
20
|
+
return { usage, quota, percentUsed };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Format bytes to a human-readable string (e.g. "1.5 MB"). */
|
|
24
|
+
export function formatBytes(bytes${T(ts, "number")})${R(ts, "string")}{
|
|
25
|
+
if (bytes === 0) return "0 B";
|
|
26
|
+
const units = ["B", "KB", "MB", "GB"];
|
|
27
|
+
const i = Math.floor(Math.log(bytes) / Math.log(1024));
|
|
28
|
+
return \`\${(bytes / Math.pow(1024, i)).toFixed(1)} \${units[i]}\`;
|
|
29
|
+
}
|
|
30
|
+
`;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/runtime/storage.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,YAAY,CAAC;AAElC,MAAM,UAAU,mBAAmB,CAAC,GAAmB;IACrD,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,GAAG,CAAC;IACxB,OAAO;;;;;wEAK+D,GAAG;;;;;4CAK/B,CAAC,CAAC,EAAE,EAAE,gEAAgE,CAAC;;;;;;;;;;mCAUhF,CAAC,CAAC,EAAE,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,QAAQ,CAAC;;;;;;CAMpE,CAAC;AACF,CAAC"}
|
|
@@ -1,103 +1,21 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { R } from "./utils.js";
|
|
2
2
|
export function generateSwInjectorCode(ctx) {
|
|
3
|
-
const { ext, ts,
|
|
4
|
-
if (!versionEnabled) {
|
|
5
|
-
return `/**
|
|
6
|
-
* Swoff SW Injector (Simple Mode)
|
|
7
|
-
* Fixed SW URL with hash-based cache name — no versioned URLs or update events.
|
|
8
|
-
*
|
|
9
|
-
* Usage:
|
|
10
|
-
* import { initServiceWorker } from './swoff/sw/injector.${ext}';
|
|
11
|
-
* initServiceWorker();
|
|
12
|
-
*
|
|
13
|
-
* Window events:
|
|
14
|
-
* sw-ready - SW active and controlling page
|
|
15
|
-
* sw-error - SW registration failed
|
|
16
|
-
*
|
|
17
|
-
* Window properties:
|
|
18
|
-
* window.currentSWVersion - "simple"
|
|
19
|
-
* window.swReady - SW is active
|
|
20
|
-
* window.swError - Registration failed
|
|
21
|
-
*/
|
|
22
|
-
async function waitForController()${R(ts, "Promise<void>")}{
|
|
23
|
-
return new Promise<void>((resolve) => {
|
|
24
|
-
if (navigator.serviceWorker.controller) {
|
|
25
|
-
resolve();
|
|
26
|
-
} else {
|
|
27
|
-
const timeout = setTimeout(() => resolve(), 30000);
|
|
28
|
-
navigator.serviceWorker.addEventListener("controllerchange", () => {
|
|
29
|
-
clearTimeout(timeout);
|
|
30
|
-
resolve();
|
|
31
|
-
}, { once: true });
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/** Register the SW with a fixed URL (non-versioned mode). Dispatches sw-ready/sw-error. */
|
|
37
|
-
export async function initServiceWorker()${R(ts, "Promise<void>")}{
|
|
38
|
-
if (!("serviceWorker" in navigator)) {
|
|
39
|
-
console.warn("Service Workers not supported");
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
try {
|
|
43
|
-
const registration = await navigator.serviceWorker.register("/${swFilename}.js");
|
|
44
|
-
window.currentSWVersion = "simple";
|
|
45
|
-
window.dispatchEvent(new CustomEvent("sw-version-detected"));
|
|
46
|
-
await waitForController();
|
|
47
|
-
window.dispatchEvent(new CustomEvent("sw-ready"));
|
|
48
|
-
} catch (error) {
|
|
49
|
-
console.error("Service Worker registration failed:", error);
|
|
50
|
-
window.swError = true;
|
|
51
|
-
window.dispatchEvent(new CustomEvent("sw-error"));
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
`;
|
|
55
|
-
}
|
|
3
|
+
const { ext, ts, autoActivate, swFilename } = ctx;
|
|
56
4
|
return `/**
|
|
57
5
|
* Swoff SW Injector
|
|
58
|
-
*
|
|
6
|
+
* Registers the service worker and tracks installation progress.
|
|
59
7
|
*
|
|
60
8
|
* Usage:
|
|
61
9
|
* import { initServiceWorker } from './swoff/sw/injector.${ext}';
|
|
62
10
|
* initServiceWorker();
|
|
63
11
|
*
|
|
64
12
|
* Window events:
|
|
65
|
-
* sw-version-detected - Version info available on window
|
|
66
|
-
* sw-update-available - New version ready for user consent (detail: { version })
|
|
67
13
|
* sw-progress - Download progress (detail: { percent, downloaded, total })
|
|
68
14
|
* sw-ready - SW active and controlling page
|
|
69
15
|
* sw-error - SW registration failed
|
|
70
|
-
*
|
|
71
|
-
* Window properties:
|
|
72
|
-
* window.latestSWVersion - Latest version from version.json
|
|
73
|
-
* window.currentSWVersion - Active SW version
|
|
74
|
-
* window.swAvailableVersion - Pending update version
|
|
75
|
-
* window.swUpdateRequired - Forced update needed (version < minSupportedVersion)
|
|
76
|
-
* window.swMinSupportedVersion - Minimum supported version
|
|
77
|
-
* window.swReady - SW is active
|
|
78
|
-
* window.swError - Registration failed
|
|
79
16
|
*/
|
|
80
|
-
const AUTO_UPDATE = ${autoUpdate};
|
|
81
17
|
const AUTO_ACTIVATE = ${autoActivate};
|
|
82
18
|
|
|
83
|
-
function semverCompare(a${T(ts, "string")}, b${T(ts, "string")})${R(ts, "number")}{
|
|
84
|
-
const pa = a.split('.').map(Number);
|
|
85
|
-
const pb = b.split('.').map(Number);
|
|
86
|
-
for (let i = 0; i < 3; i++) {
|
|
87
|
-
if (pa[i] > pb[i]) return 1;
|
|
88
|
-
if (pa[i] < pb[i]) return -1;
|
|
89
|
-
}
|
|
90
|
-
return 0;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
async function checkForUpdate() {
|
|
94
|
-
const response = await fetch("/version.json?t=" + Date.now());
|
|
95
|
-
if (!response.ok) {
|
|
96
|
-
throw new Error("Failed to fetch version.json");
|
|
97
|
-
}
|
|
98
|
-
return response.json();
|
|
99
|
-
}
|
|
100
|
-
|
|
101
19
|
async function waitForController()${R(ts, "Promise<void>")}{
|
|
102
20
|
return new Promise<void>((resolve) => {
|
|
103
21
|
if (navigator.serviceWorker.controller) {
|
|
@@ -112,19 +30,7 @@ async function waitForController()${R(ts, "Promise<void>")}{
|
|
|
112
30
|
});
|
|
113
31
|
}
|
|
114
32
|
|
|
115
|
-
|
|
116
|
-
const swUrl = \`/sw-v\${version}.js\`;
|
|
117
|
-
const registration = await navigator.serviceWorker.register(swUrl);
|
|
118
|
-
localStorage.setItem("swRegisteredVersion", version);
|
|
119
|
-
window.currentSWVersion = version;
|
|
120
|
-
window.swRegisteredVersion = version;
|
|
121
|
-
window.dispatchEvent(new CustomEvent("sw-version-detected"));
|
|
122
|
-
await waitForController();
|
|
123
|
-
window.dispatchEvent(new CustomEvent("sw-ready"));
|
|
124
|
-
return registration;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/** Register the SW with version checking and update flow. Checks version.json, handles updates, and dispatches sw-ready/sw-error events. */
|
|
33
|
+
/** Register the SW. The browser detects updates by comparing SW file bytes. */
|
|
128
34
|
export async function initServiceWorker()${R(ts, "Promise<void>")}{
|
|
129
35
|
if (!("serviceWorker" in navigator)) {
|
|
130
36
|
console.warn("Service Workers not supported");
|
|
@@ -132,98 +38,33 @@ export async function initServiceWorker()${R(ts, "Promise<void>")}{
|
|
|
132
38
|
}
|
|
133
39
|
|
|
134
40
|
try {
|
|
135
|
-
const
|
|
136
|
-
const currentVersion = localStorage.getItem("swRegisteredVersion");
|
|
137
|
-
window.latestSWVersion = manifest.version;
|
|
138
|
-
window.swMinSupportedVersion = manifest.minSupportedVersion || "0.0.0";
|
|
139
|
-
|
|
140
|
-
if (currentVersion === manifest.version) {
|
|
141
|
-
const registration = await navigator.serviceWorker.getRegistration();
|
|
142
|
-
if (registration && registration.active) {
|
|
143
|
-
window.currentSWVersion = currentVersion ?? undefined;
|
|
144
|
-
window.dispatchEvent(new CustomEvent("sw-version-detected"));
|
|
145
|
-
await waitForController();
|
|
146
|
-
if (!window.swReady) {
|
|
147
|
-
window.dispatchEvent(new CustomEvent("sw-ready"));
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
} else if (currentVersion && currentVersion !== manifest.version) {
|
|
151
|
-
window.swAvailableVersion = manifest.version;
|
|
152
|
-
window.swUpdateRequired =
|
|
153
|
-
semverCompare(currentVersion, manifest.minSupportedVersion || "0.0.0") < 0;
|
|
41
|
+
const registration = await navigator.serviceWorker.register("/${swFilename}.js");
|
|
154
42
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
43
|
+
var swReadyDispatched = false;
|
|
44
|
+
if (registration.installing) {
|
|
45
|
+
const installingWorker = registration.installing;
|
|
46
|
+
installingWorker.addEventListener("statechange", () => {
|
|
47
|
+
if (installingWorker.state === "installed") {
|
|
158
48
|
if (AUTO_ACTIVATE) {
|
|
159
|
-
registration.waiting
|
|
160
|
-
} else {
|
|
161
|
-
window.dispatchEvent(
|
|
162
|
-
new CustomEvent("sw-update-available", {
|
|
163
|
-
detail: { version: manifest.version },
|
|
164
|
-
})
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
} else {
|
|
168
|
-
const newReg = await doRegisterServiceWorker(manifest.version);
|
|
169
|
-
if (AUTO_ACTIVATE && newReg.waiting) {
|
|
170
|
-
newReg.waiting.postMessage({ type: "SKIP_WAITING" });
|
|
171
|
-
} else {
|
|
172
|
-
window.dispatchEvent(
|
|
173
|
-
new CustomEvent("sw-update-available", {
|
|
174
|
-
detail: { version: manifest.version },
|
|
175
|
-
})
|
|
176
|
-
);
|
|
49
|
+
registration.waiting?.postMessage({ type: "SKIP_WAITING" });
|
|
177
50
|
}
|
|
178
|
-
|
|
179
|
-
} else {
|
|
180
|
-
window.dispatchEvent(
|
|
181
|
-
new CustomEvent("sw-update-available", {
|
|
182
|
-
detail: { version: manifest.version },
|
|
183
|
-
})
|
|
184
|
-
);
|
|
185
|
-
}
|
|
186
|
-
} else {
|
|
187
|
-
await doRegisterServiceWorker(manifest.version);
|
|
188
|
-
}
|
|
189
|
-
} catch (error) {
|
|
190
|
-
try {
|
|
191
|
-
const existing = await navigator.serviceWorker.getRegistration();
|
|
192
|
-
if (existing && existing.active) {
|
|
193
|
-
window.currentSWVersion = localStorage.getItem("swRegisteredVersion") || "unknown";
|
|
194
|
-
window.dispatchEvent(new CustomEvent("sw-version-detected"));
|
|
195
|
-
await waitForController();
|
|
196
|
-
if (!window.swReady) {
|
|
51
|
+
swReadyDispatched = true;
|
|
197
52
|
window.dispatchEvent(new CustomEvent("sw-ready"));
|
|
198
53
|
}
|
|
199
|
-
|
|
200
|
-
}
|
|
201
|
-
} catch {
|
|
202
|
-
// Handle the case where no existing active registration is found
|
|
54
|
+
});
|
|
203
55
|
}
|
|
204
56
|
|
|
205
|
-
|
|
57
|
+
await waitForController();
|
|
58
|
+
if (!swReadyDispatched) {
|
|
59
|
+
window.dispatchEvent(new CustomEvent("sw-ready"));
|
|
60
|
+
}
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error("Service Worker registration failed:", error);
|
|
206
63
|
window.swError = true;
|
|
207
64
|
window.dispatchEvent(new CustomEvent("sw-error"));
|
|
208
65
|
}
|
|
209
66
|
}
|
|
210
67
|
|
|
211
|
-
/** Accept a pending SW update. Reloads the page once the new SW takes control. */
|
|
212
|
-
export async function handleUpdateApproved(newVersion${T(ts, "string")})${R(ts, "Promise<void>")}{
|
|
213
|
-
const registration = await navigator.serviceWorker.getRegistration();
|
|
214
|
-
if (registration && registration.waiting) {
|
|
215
|
-
registration.waiting.postMessage({ type: "SKIP_WAITING" });
|
|
216
|
-
registration.addEventListener("controllerchange", () => {
|
|
217
|
-
window.location.reload();
|
|
218
|
-
});
|
|
219
|
-
} else {
|
|
220
|
-
await doRegisterServiceWorker(newVersion);
|
|
221
|
-
navigator.serviceWorker.addEventListener("controllerchange", () => {
|
|
222
|
-
window.location.reload();
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
68
|
/** Activate a waiting SW without reloading. Useful when you handle the transition yourself. */
|
|
228
69
|
export async function skipWaiting()${R(ts, "Promise<void>")}{
|
|
229
70
|
const registration = await navigator.serviceWorker.ready;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sw-injector.js","sourceRoot":"","sources":["../../src/runtime/sw-injector.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"sw-injector.js","sourceRoot":"","sources":["../../src/runtime/sw-injector.ts"],"names":[],"mappings":"AACA,OAAO,EAAK,CAAC,EAAE,MAAM,YAAY,CAAC;AAElC,MAAM,UAAU,sBAAsB,CACpC,GAAmE;IAEnE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,GAAG,CAAC;IAElD,OAAO;;;;;8DAKqD,GAAG;;;;;;;;wBAQzC,YAAY;;oCAEA,CAAC,CAAC,EAAE,EAAE,eAAe,CAAC;;;;;;;;;;;;;;;2CAef,CAAC,CAAC,EAAE,EAAE,eAAe,CAAC;;;;;;;oEAOG,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;qCA4BzC,CAAC,CAAC,EAAE,EAAE,eAAe,CAAC;;;;;;CAM1D,CAAC;AACF,CAAC"}
|