@swoff/cli 0.3.13 → 0.3.14
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 +2 -13
- package/dist/index.js.map +1 -1
- package/dist/lib/cli/help.js +3 -8
- package/dist/lib/cli/help.js.map +1 -1
- package/dist/lib/commands/add.js +29 -87
- package/dist/lib/commands/add.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 +31 -6
- package/dist/lib/commands/generate.js.map +1 -1
- package/dist/lib/commands/init.js +188 -11
- 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/validator.js +202 -96
- 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-manager.js +12 -0
- package/dist/lib/generators/file-generators/connectivity-manager.js.map +1 -0
- 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/notification-generator.js +6 -0
- package/dist/lib/generators/file-generators/notification-generator.js.map +1 -0
- 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-generator.js +6 -0
- package/dist/lib/generators/file-generators/storage-generator.js.map +1 -0
- package/dist/lib/generators/file-generators/storage-notify.js +6 -0
- package/dist/lib/generators/file-generators/storage-notify.js.map +1 -0
- 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 +96 -45
- 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/sw-version-gen.js +32 -0
- package/dist/lib/generators/file-generators/sw-version-gen.js.map +1 -0
- 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 +74 -23
- package/dist/lib/generators/sw-sections/activate-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/assemble-sw.js +15 -94
- package/dist/lib/generators/sw-sections/assemble-sw.js.map +1 -1
- 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 +59 -6
- 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 +40 -23
- package/dist/lib/generators/sw-sections/install-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/message-handler.js +25 -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 +68 -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 +67 -63
- 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/auth-user.js +5 -19
- package/dist/runtime/auth-user.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 +173 -30
- package/dist/runtime/client-injector.js.map +1 -1
- package/dist/runtime/connectivity-manager.js +83 -0
- package/dist/runtime/connectivity-manager.js.map +1 -0
- 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/notification.js +65 -0
- package/dist/runtime/notification.js.map +1 -0
- 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-injector.js +3 -32
- package/dist/runtime/pwa-injector.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/sw-version.js +13 -0
- package/dist/runtime/sw-version.js.map +1 -0
- 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/dist/swoff-nkdhhmw8. +18 -0
- package/dist/swoff.js +5 -0
- package/package.json +1 -1
- 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/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,259 +1,177 @@
|
|
|
1
|
-
import { T, R, PT
|
|
2
|
-
|
|
3
|
-
const hd = T(ts, "Headers");
|
|
4
|
-
const a = T(ts, "AuthData | null");
|
|
5
|
-
switch (authType) {
|
|
6
|
-
case "cookie":
|
|
7
|
-
return `/** Inject auth headers. For cookie auth, credentials are handled via AUTH_WITH_CREDENTIALS. */
|
|
8
|
-
export function withAuthHeaders(headers${hd}, _auth${a})${hd}{
|
|
9
|
-
return headers;
|
|
10
|
-
}`;
|
|
11
|
-
case "bearer":
|
|
12
|
-
return `/** Inject Bearer token into request headers. */
|
|
13
|
-
export function withAuthHeaders(headers${hd}, auth${a})${hd}{
|
|
14
|
-
if (auth?.token) {
|
|
15
|
-
headers.set("Authorization", \`Bearer \${auth.token}\`);
|
|
16
|
-
}
|
|
17
|
-
return headers;
|
|
18
|
-
}`;
|
|
19
|
-
case "custom":
|
|
20
|
-
return `/** Inject custom auth headers. Edit this function to match your backend. */
|
|
21
|
-
export function withAuthHeaders(headers${hd}, auth${a})${hd}{
|
|
22
|
-
// --- EDIT THIS BLOCK FOR YOUR BACKEND ---
|
|
23
|
-
// if (auth?.token) {
|
|
24
|
-
// headers.set("X-Auth-Token", auth.token);
|
|
25
|
-
// }
|
|
26
|
-
// --- END OF EDITABLE BLOCK ---
|
|
27
|
-
return headers;
|
|
28
|
-
}`;
|
|
29
|
-
default:
|
|
30
|
-
return `export function withAuthHeaders(headers${hd}, auth${a})${hd}{
|
|
31
|
-
if (auth?.token) {
|
|
32
|
-
headers.set("Authorization", \`Bearer \${auth.token}\`);
|
|
33
|
-
}
|
|
34
|
-
return headers;
|
|
35
|
-
}`;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
function generateIsAuthUrl(refreshPath, userEndpoint, ts) {
|
|
39
|
-
return `/** Check if a URL is an auth endpoint that should bypass the SW cache. */
|
|
40
|
-
export function isAuthUrl(url${T(ts, "string")})${R(ts, "boolean")}{
|
|
41
|
-
const authPaths = [
|
|
1
|
+
import { T, R, PT } from "./utils.js";
|
|
2
|
+
const DEFAULT_AUTH_ROUTES = [
|
|
42
3
|
"/login",
|
|
43
4
|
"/logout",
|
|
44
5
|
"/register",
|
|
45
6
|
"/api/login",
|
|
46
7
|
"/api/logout",
|
|
47
8
|
"/api/register",
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}`;
|
|
53
|
-
}
|
|
54
|
-
function generateEnsureValidAuth(cookieAuth, ts, refreshPath, ext) {
|
|
55
|
-
const tokenArg = cookieAuth ? "" : "auth?.token";
|
|
56
|
-
return `/** Try to restore the session after page refresh — delegates to refreshSession() in ./user.${ext}. */
|
|
57
|
-
let restorePromise${T(ts, "Promise<AuthData | null> | null")} = null;
|
|
58
|
-
|
|
59
|
-
async function tryRestoreSession()${R(ts, "Promise<AuthData | null>")}{
|
|
60
|
-
if (restorePromise) {
|
|
61
|
-
try { return await restorePromise; } finally { restorePromise = null; }
|
|
62
|
-
}
|
|
63
|
-
restorePromise = (async () => {
|
|
64
|
-
try {
|
|
65
|
-
const response = await refreshSession();
|
|
66
|
-
if (!response.ok) return null;
|
|
67
|
-
const data = await response.json();
|
|
68
|
-
const userData = await loadUserData();
|
|
69
|
-
const auth = { ...userData, token: data.token, expiresAt: data.expiresAt };
|
|
70
|
-
await setAuth(auth);
|
|
71
|
-
return auth;
|
|
72
|
-
} catch { return null; }
|
|
73
|
-
})();
|
|
74
|
-
try { return await restorePromise; } finally { restorePromise = null; }
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
let refreshPromise${T(ts, "Promise<AuthData | null> | null")} = null;
|
|
78
|
-
|
|
79
|
-
export async function ensureValidAuth()${R(ts, "Promise<AuthData | null>")}{
|
|
80
|
-
const auth = await getAuth();
|
|
81
|
-
if (!auth) return null;
|
|
82
|
-
|
|
83
|
-
// Token missing after page refresh — try silent session restoration
|
|
84
|
-
if (!auth.token) {
|
|
85
|
-
return tryRestoreSession();
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (!auth.expiresAt || Date.now() < auth.expiresAt) return auth;
|
|
89
|
-
|
|
90
|
-
if (!refreshPromise) {
|
|
91
|
-
refreshPromise = (async () => {
|
|
92
|
-
try {
|
|
93
|
-
const response = await refreshSession(${tokenArg});
|
|
94
|
-
if (!response.ok) {
|
|
95
|
-
await clearAuth();
|
|
96
|
-
window.dispatchEvent(new CustomEvent("sw-auth-unauthorized"));
|
|
97
|
-
return null;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const data = await response.json();
|
|
101
|
-
const updated = { ...auth, token: data.token, expiresAt: data.expiresAt };
|
|
102
|
-
await setAuth(updated);
|
|
103
|
-
return updated;
|
|
104
|
-
} catch {
|
|
105
|
-
await clearAuth();
|
|
106
|
-
window.dispatchEvent(new CustomEvent("sw-auth-unauthorized"));
|
|
107
|
-
return null;
|
|
108
|
-
}
|
|
109
|
-
})();
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
try {
|
|
113
|
-
return await refreshPromise;
|
|
114
|
-
} finally {
|
|
115
|
-
refreshPromise = null;
|
|
116
|
-
}
|
|
117
|
-
}`;
|
|
118
|
-
}
|
|
119
|
-
export function generateAuthStoreCode(ctx, authType, refreshPath, userEndpoint) {
|
|
9
|
+
"/api/refresh",
|
|
10
|
+
"/api/me",
|
|
11
|
+
];
|
|
12
|
+
export function generateAuthStoreCode(ctx, authType, authRoutePaths = DEFAULT_AUTH_ROUTES, mutationQueueEnabled = false) {
|
|
120
13
|
const { ext, ts } = ctx;
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
// token: string;
|
|
131
|
-
// user: Record<string, unknown>;
|
|
132
|
-
// expiresAt?: number;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
`
|
|
136
|
-
: "";
|
|
137
|
-
const createAuthFromResponseBlock = ts
|
|
138
|
-
? `/** Extract AuthData from your backend's login response. Edit this function to match your backend's response shape. */
|
|
139
|
-
export function createAuthFromResponse(response: AuthResponse): AuthData {
|
|
140
|
-
// --- EDIT THIS TO MATCH YOUR BACKEND ---
|
|
141
|
-
const data = response as Record<string, unknown>;
|
|
142
|
-
return {
|
|
143
|
-
token: data.token as string,
|
|
144
|
-
user: data.user as Record<string, unknown> | undefined,
|
|
145
|
-
expiresAt: data.expiresAt as number | undefined,
|
|
146
|
-
};
|
|
147
|
-
// --- END OF EDITABLE BLOCK ---
|
|
148
|
-
}
|
|
149
|
-
`
|
|
150
|
-
: `/** Extract AuthData from your backend's login response. Edit this function to match your backend's response shape. */
|
|
151
|
-
export function createAuthFromResponse(response) {
|
|
152
|
-
// --- EDIT THIS TO MATCH YOUR BACKEND ---
|
|
153
|
-
return {
|
|
154
|
-
token: response.token,
|
|
155
|
-
user: response.user,
|
|
156
|
-
expiresAt: response.expiresAt,
|
|
157
|
-
};
|
|
158
|
-
// --- END OF EDITABLE BLOCK ---
|
|
159
|
-
}
|
|
160
|
-
`;
|
|
14
|
+
const isCookie = authType === "cookie";
|
|
15
|
+
const cookieAuthComment = isCookie
|
|
16
|
+
? ` *
|
|
17
|
+
* Cookie auth: the server manages the session. setAuth() stores user info
|
|
18
|
+
* for offline display. The browser sends the session cookie automatically.`
|
|
19
|
+
: ` *
|
|
20
|
+
* Bearer auth: token lives in memory only — cleared on page refresh.
|
|
21
|
+
* ensureValidAuth() calls adapter.refresh() when the token expires.
|
|
22
|
+
* Only { user, expiresAt } persists to IndexedDB for offline display.`;
|
|
161
23
|
return `/**
|
|
162
|
-
* Auth Store — Token in memory only; user info in IndexedDB for offline access
|
|
24
|
+
* Auth Store — Token in memory only; user info in IndexedDB for offline access.${cookieAuthComment}
|
|
163
25
|
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
*
|
|
26
|
+
* Public API (functions listed here):
|
|
27
|
+
* setAuth, getAuth, clearAuth, clearMemoryAuth, isAuthValid,
|
|
28
|
+
* ensureValidAuth, withAuthHeaders,
|
|
29
|
+
* AUTH_WITH_CREDENTIALS, isAuthUrl
|
|
30
|
+
*
|
|
31
|
+
* Internal helpers (not exported — used by Swoff internally):
|
|
32
|
+
* persistUserData, loadUserData, clearPersistedData
|
|
168
33
|
*
|
|
169
34
|
* Usage:
|
|
170
|
-
* import { setAuth, getAuth, clearAuth, isAuthValid } from "./auth/store.${ext}";
|
|
35
|
+
* import { setAuth, getAuth, clearAuth, clearMemoryAuth, isAuthValid, ensureValidAuth, withAuthHeaders } from "./auth/store.${ext}";
|
|
171
36
|
*
|
|
172
|
-
* await setAuth({
|
|
37
|
+
* await setAuth({ user });
|
|
173
38
|
* const auth = await getAuth();
|
|
174
39
|
* await clearAuth();
|
|
40
|
+
* await clearMemoryAuth();
|
|
41
|
+
* await ensureValidAuth();
|
|
175
42
|
*/
|
|
176
43
|
|
|
177
|
-
import {
|
|
44
|
+
import { adapter } from "./adapter.${ext}";
|
|
45
|
+
${ts ? `import type { AuthData } from "./adapter.${ext}";` : ""}
|
|
46
|
+
import { openDB } from "../db.${ext}";
|
|
47
|
+
${mutationQueueEnabled ? `import { clearQueue } from "../mutation/queue.${ext}";\n` : ""}
|
|
178
48
|
|
|
179
|
-
|
|
49
|
+
const DB_NAME = "swoff-auth";
|
|
180
50
|
const STORE_NAME = "auth";
|
|
181
|
-
// Bump this when adding new indexes/stores for schema migration
|
|
182
|
-
const DB_VERSION = 1;
|
|
183
|
-
|
|
184
51
|
let memoryAuth${T(ts, "AuthData | null")} = null;
|
|
52
|
+
let _fetchingUser = false;
|
|
185
53
|
|
|
186
|
-
|
|
187
|
-
function openAuthDB()${R(ts, "Promise<IDBDatabase>")}{
|
|
188
|
-
return new Promise${PT(ts, "IDBDatabase")}((resolve, reject) => {
|
|
189
|
-
const request = indexedDB.open(DB_NAME, DB_VERSION);
|
|
190
|
-
request.onupgradeneeded = (e) => {
|
|
191
|
-
const db = (e.target${AS(ts, "IDBOpenDBRequest")}).result;
|
|
192
|
-
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
|
193
|
-
db.createObjectStore(STORE_NAME, { keyPath: "key" });
|
|
194
|
-
}
|
|
195
|
-
};
|
|
196
|
-
request.onsuccess = (e) => resolve((e.target${AS(ts, "IDBOpenDBRequest")}).result);
|
|
197
|
-
request.onerror = (e) => reject((e.target${AS(ts, "IDBRequest")}).error);
|
|
198
|
-
});
|
|
199
|
-
}
|
|
54
|
+
// ── Internal: persistence helpers ────────────────────────────────────
|
|
200
55
|
|
|
201
56
|
async function persistUserData(authData${T(ts, "AuthData | null")})${R(ts, "Promise<void>")}{
|
|
202
|
-
// Only persist { user, expiresAt } — never the token
|
|
203
57
|
const userData = { user: authData?.user, expiresAt: authData?.expiresAt };
|
|
204
|
-
const db = await
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
58
|
+
const db = await openDB(DB_NAME, STORE_NAME, "key");
|
|
59
|
+
try {
|
|
60
|
+
await new Promise${PT(ts, "void")}((resolve, reject) => {
|
|
61
|
+
const tx = db.transaction(STORE_NAME, "readwrite");
|
|
62
|
+
const store = tx.objectStore(STORE_NAME);
|
|
63
|
+
const request = store.put({ key: "session", value: userData });
|
|
64
|
+
request.onsuccess = () => resolve();
|
|
65
|
+
request.onerror = () => reject(request.error);
|
|
66
|
+
});
|
|
67
|
+
} finally {
|
|
68
|
+
db.close();
|
|
69
|
+
}
|
|
212
70
|
}
|
|
213
71
|
|
|
214
|
-
async function loadUserData()${R(ts, "Promise<
|
|
215
|
-
const db = await
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
72
|
+
async function loadUserData()${R(ts, "Promise<AuthData | null>")}{
|
|
73
|
+
const db = await openDB(DB_NAME, STORE_NAME, "key");
|
|
74
|
+
try {
|
|
75
|
+
return await new Promise((resolve, reject) => {
|
|
76
|
+
const tx = db.transaction(STORE_NAME, "readonly");
|
|
77
|
+
const store = tx.objectStore(STORE_NAME);
|
|
78
|
+
const request = store.get("session");
|
|
79
|
+
request.onsuccess = () => resolve(request.result?.value ?? null);
|
|
80
|
+
request.onerror = () => reject(request.error);
|
|
81
|
+
});
|
|
82
|
+
} finally {
|
|
83
|
+
db.close();
|
|
84
|
+
}
|
|
223
85
|
}
|
|
224
86
|
|
|
225
87
|
async function clearPersistedData()${R(ts, "Promise<void>")}{
|
|
226
|
-
const db = await
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
88
|
+
const db = await openDB(DB_NAME, STORE_NAME, "key");
|
|
89
|
+
try {
|
|
90
|
+
await new Promise${PT(ts, "void")}((resolve, reject) => {
|
|
91
|
+
const tx = db.transaction(STORE_NAME, "readwrite");
|
|
92
|
+
const store = tx.objectStore(STORE_NAME);
|
|
93
|
+
const request = store.delete("session");
|
|
94
|
+
request.onsuccess = () => resolve();
|
|
95
|
+
request.onerror = () => reject(request.error);
|
|
96
|
+
});
|
|
97
|
+
} finally {
|
|
98
|
+
db.close();
|
|
99
|
+
}
|
|
234
100
|
}
|
|
235
101
|
|
|
102
|
+
// ── Public API: auth data operations ─────────────────────────────────
|
|
103
|
+
|
|
236
104
|
/** Store auth data in memory and persist user info to IndexedDB for offline access. */
|
|
237
105
|
export async function setAuth(authData${T(ts, "AuthData")})${R(ts, "Promise<void>")}{
|
|
238
106
|
memoryAuth = authData;
|
|
239
107
|
await persistUserData(authData);
|
|
240
108
|
}
|
|
241
109
|
|
|
242
|
-
/** Get auth data from memory
|
|
110
|
+
/** Get auth data from memory, then adapter, then IndexedDB fallback (user info only). */
|
|
243
111
|
export async function getAuth()${R(ts, "Promise<AuthData | null>")}{
|
|
244
112
|
if (memoryAuth) return memoryAuth;
|
|
245
113
|
|
|
114
|
+
// Try adapter first (for provider-managed auth like Better Auth)
|
|
115
|
+
try {
|
|
116
|
+
const adapterAuth = await adapter.getAuth();
|
|
117
|
+
if (adapterAuth) {
|
|
118
|
+
memoryAuth = adapterAuth;
|
|
119
|
+
await persistUserData(adapterAuth);
|
|
120
|
+
return memoryAuth;
|
|
121
|
+
}
|
|
122
|
+
// Adapter confirmed no session — don't fall through to stale IDB
|
|
123
|
+
return null;
|
|
124
|
+
} catch {
|
|
125
|
+
// Adapter error (network failure) — fall through to IndexedDB
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Fall back to IndexedDB user cache (only reached on adapter error)
|
|
246
129
|
const userData = await loadUserData();
|
|
247
130
|
if (userData) {
|
|
248
131
|
memoryAuth = userData;
|
|
132
|
+
return memoryAuth;
|
|
249
133
|
}
|
|
250
|
-
|
|
134
|
+
|
|
135
|
+
// Last resort — try server fetch
|
|
136
|
+
if (_fetchingUser) return null;
|
|
137
|
+
_fetchingUser = true;
|
|
138
|
+
try {
|
|
139
|
+
const fetched = await adapter.fetchUser();
|
|
140
|
+
if (fetched) {
|
|
141
|
+
memoryAuth = fetched;
|
|
142
|
+
await persistUserData(fetched);
|
|
143
|
+
return memoryAuth;
|
|
144
|
+
}
|
|
145
|
+
} catch {
|
|
146
|
+
// Server unreachable — no auth data available
|
|
147
|
+
} finally {
|
|
148
|
+
_fetchingUser = false;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** Null memory auth only. Use for cross-tab sync — SW broadcasts AUTH_CLEARED, other tabs call this. */
|
|
155
|
+
export function clearMemoryAuth()${R(ts, "void")}{
|
|
156
|
+
memoryAuth = null;
|
|
251
157
|
}
|
|
252
158
|
|
|
253
|
-
/** Clear auth from memory and
|
|
254
|
-
export async function clearAuth()${R(ts, "Promise<void>")}{
|
|
159
|
+
/** Clear auth from memory, IndexedDB, runtime caches, and dispatch event. Sends AUTH_CLEARED to SW so other tabs clear memory too. Call once on logout. */
|
|
160
|
+
export async function clearAuth(options${T(ts, "{ broadcast?: boolean }")} = {})${R(ts, "Promise<void>")}{
|
|
161
|
+
if (options.broadcast !== false) {
|
|
162
|
+
navigator.serviceWorker.controller?.postMessage({ type: "AUTH_CLEARED" });
|
|
163
|
+
}
|
|
255
164
|
memoryAuth = null;
|
|
256
165
|
await clearPersistedData();
|
|
166
|
+
try {
|
|
167
|
+
const cacheNames = await caches.keys();
|
|
168
|
+
await Promise.all(
|
|
169
|
+
cacheNames
|
|
170
|
+
.filter(name => name.startsWith("swoff-runtime"))
|
|
171
|
+
.map(name => caches.delete(name))
|
|
172
|
+
);
|
|
173
|
+
} catch { /* caches API unavailable */ }
|
|
174
|
+
${mutationQueueEnabled ? `await clearQueue();\n` : ""} window.dispatchEvent(new CustomEvent("sw-auth-state-change", { detail: { type: "clear" } }));
|
|
257
175
|
}
|
|
258
176
|
|
|
259
177
|
/** Check if auth exists and has not expired. Returns true if no expiresAt is set. */
|
|
@@ -263,11 +181,99 @@ export function isAuthValid(auth${T(ts, "AuthData | null")})${R(ts, "boolean")}{
|
|
|
263
181
|
return Date.now() < auth.expiresAt;
|
|
264
182
|
}
|
|
265
183
|
|
|
266
|
-
|
|
184
|
+
// ── Public API: adapter-delegated ────────────────────────────────────
|
|
185
|
+
|
|
186
|
+
/** Whether to use credentials: "include" for fetch requests. True for cookie-based auth. */
|
|
187
|
+
export const AUTH_WITH_CREDENTIALS = adapter.type === "cookie";
|
|
188
|
+
|
|
189
|
+
/** Inject auth headers into a Headers object. Delegates to the auth adapter. */
|
|
190
|
+
export function withAuthHeaders(headers${T(ts, "Headers")}, auth${T(ts, "AuthData | null")})${R(ts, "Headers")}{
|
|
191
|
+
const adapterHeaders = adapter.getHeaders(auth);
|
|
192
|
+
for (const [key, value] of Object.entries(adapterHeaders)) {
|
|
193
|
+
headers.set(key, value);
|
|
194
|
+
}
|
|
195
|
+
return headers;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/** Check if a URL is an auth endpoint that should bypass the SW cache. */
|
|
199
|
+
export function isAuthUrl(url${T(ts, "string")})${R(ts, "boolean")}{
|
|
200
|
+
var urlPath = url.indexOf("://") !== -1 ? new URL(url).pathname.replace(/\/$/, "") : url.replace(/\/$/, "");
|
|
201
|
+
return ${JSON.stringify(authRoutePaths)}.some(function(path) { return urlPath === path; });
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// ── Public API: session refresh ──────────────────────────────────────
|
|
205
|
+
|
|
206
|
+
${isCookie
|
|
207
|
+
? `
|
|
208
|
+
/**
|
|
209
|
+
* Cookie auth: the server manages the session. No token to restore or refresh.
|
|
210
|
+
* The browser sends the session cookie automatically.
|
|
211
|
+
* getAuth() + IndexedDB user cache provides offline access.
|
|
212
|
+
*/
|
|
213
|
+
export async function ensureValidAuth()${R(ts, "Promise<AuthData | null>")}{
|
|
214
|
+
return getAuth();
|
|
215
|
+
}
|
|
216
|
+
`
|
|
217
|
+
: `
|
|
218
|
+
/** Try to restore session after page refresh. Delegates to adapter.refresh(). */
|
|
219
|
+
async function tryRestoreSession()${R(ts, "Promise<AuthData | null>")}{
|
|
220
|
+
try {
|
|
221
|
+
const auth = await getAuth();
|
|
222
|
+
if (!auth) return null;
|
|
223
|
+
const refreshed = await adapter.refresh(auth);
|
|
224
|
+
if (refreshed) {
|
|
225
|
+
await setAuth(refreshed);
|
|
226
|
+
return refreshed;
|
|
227
|
+
}
|
|
228
|
+
return null;
|
|
229
|
+
} catch { return null; }
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
let restorePromise${T(ts, "Promise<AuthData | null> | null")} = null;
|
|
233
|
+
let refreshPromise${T(ts, "Promise<AuthData | null> | null")} = null;
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Bearer auth: token expires — try silent refresh via adapter.refresh().
|
|
237
|
+
* If refresh fails, auth is cleared and sw-auth-unauthorized is dispatched.
|
|
238
|
+
*/
|
|
239
|
+
export async function ensureValidAuth()${R(ts, "Promise<AuthData | null>")}{
|
|
240
|
+
const auth = await getAuth();
|
|
241
|
+
if (!auth) return null;
|
|
242
|
+
|
|
243
|
+
// No token after page refresh — try silent session restoration
|
|
244
|
+
if (!auth.token) {
|
|
245
|
+
if (restorePromise) {
|
|
246
|
+
try { return await restorePromise; } finally { restorePromise = null; }
|
|
247
|
+
}
|
|
248
|
+
restorePromise = tryRestoreSession();
|
|
249
|
+
try { return await restorePromise; } finally { restorePromise = null; }
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Not expired yet
|
|
253
|
+
if (!auth.expiresAt || Date.now() < auth.expiresAt) return auth;
|
|
254
|
+
|
|
255
|
+
// Token expired — try refresh via adapter
|
|
256
|
+
if (!refreshPromise) {
|
|
257
|
+
refreshPromise = (async () => {
|
|
258
|
+
try {
|
|
259
|
+
const refreshed = await adapter.refresh(auth);
|
|
260
|
+
if (refreshed) {
|
|
261
|
+
await setAuth(refreshed);
|
|
262
|
+
return refreshed;
|
|
263
|
+
}
|
|
264
|
+
await clearAuth();
|
|
265
|
+
return null;
|
|
266
|
+
} catch {
|
|
267
|
+
await clearAuth();
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
})();
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
try { return await refreshPromise; } finally { refreshPromise = null; }
|
|
274
|
+
}
|
|
275
|
+
`}
|
|
267
276
|
|
|
268
|
-
${generateWithAuthHeaders(authType, ts)}
|
|
269
|
-
${generateIsAuthUrl(refreshPath, userEndpoint, ts)}
|
|
270
|
-
${generateEnsureValidAuth(authType === "cookie", ts, refreshPath, ext)}
|
|
271
277
|
`;
|
|
272
278
|
}
|
|
273
279
|
//# sourceMappingURL=auth-store.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-store.js","sourceRoot":"","sources":["../../src/runtime/auth-store.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"auth-store.js","sourceRoot":"","sources":["../../src/runtime/auth-store.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,YAAY,CAAC;AAEtC,MAAM,mBAAmB,GAAG;IAC1B,QAAQ;IACR,SAAS;IACT,WAAW;IACX,YAAY;IACZ,aAAa;IACb,eAAe;IACf,cAAc;IACd,SAAS;CACV,CAAC;AAEF,MAAM,UAAU,qBAAqB,CACnC,GAAmB,EACnB,QAAgB,EAChB,iBAA2B,mBAAmB,EAC9C,uBAAgC,KAAK;IAErC,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,GAAG,CAAC;IACxB,MAAM,QAAQ,GAAG,QAAQ,KAAK,QAAQ,CAAC;IAEvC,MAAM,iBAAiB,GAAG,QAAQ;QAChC,CAAC,CAAC;;4EAEsE;QACxE,CAAC,CAAC;;;uEAGiE,CAAC;IAEtE,OAAO;kFACyE,iBAAiB;;;;;;;;;;;iIAW8B,GAAG;;;;;;;;;qCAS/F,GAAG;EACtC,EAAE,CAAC,CAAC,CAAC,4CAA4C,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE;gCAC/B,GAAG;EACjC,oBAAoB,CAAC,CAAC,CAAC,iDAAiD,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE;;;;gBAIxE,CAAC,CAAC,EAAE,EAAE,iBAAiB,CAAC;;;;;yCAKC,CAAC,CAAC,EAAE,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,eAAe,CAAC;;;;uBAIpE,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC;;;;;;;;;;;;+BAYN,CAAC,CAAC,EAAE,EAAE,0BAA0B,CAAC;;;;;;;;;;;;;;;qCAe3B,CAAC,CAAC,EAAE,EAAE,eAAe,CAAC;;;uBAGpC,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC;;;;;;;;;;;;;;;wCAeG,CAAC,CAAC,EAAE,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,eAAe,CAAC;;;;;;iCAMlD,CAAC,CAAC,EAAE,EAAE,0BAA0B,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mCA4C/B,CAAC,CAAC,EAAE,EAAE,MAAM,CAAC;;;;;yCAKP,CAAC,CAAC,EAAE,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,eAAe,CAAC;;;;;;;;;;;;;;IAcpG,oBAAoB,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,EAAE;;;;kCAIrB,CAAC,CAAC,EAAE,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,SAAS,CAAC;;;;;;;;;;;;yCAYrC,CAAC,CAAC,EAAE,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,SAAS,CAAC;;;;;;;;;+BAS/E,CAAC,CAAC,EAAE,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,SAAS,CAAC;;WAEvD,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC;;;;;EAMvC,QAAQ;QACN,CAAC,CAAC;;;;;;yCAMmC,CAAC,CAAC,EAAE,EAAE,0BAA0B,CAAC;;;CAGzE;QACG,CAAC,CAAC;;oCAE8B,CAAC,CAAC,EAAE,EAAE,0BAA0B,CAAC;;;;;;;;;;;;;oBAajD,CAAC,CAAC,EAAE,EAAE,iCAAiC,CAAC;oBACxC,CAAC,CAAC,EAAE,EAAE,iCAAiC,CAAC;;;;;;yCAMnB,CAAC,CAAC,EAAE,EAAE,0BAA0B,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqC1E;;CAEC,CAAC;AACF,CAAC"}
|
|
@@ -68,24 +68,10 @@ export function generateAuthUserCode(ctx, refreshPath, userEndpoint, authType) {
|
|
|
68
68
|
|
|
69
69
|
import { API_BASE } from "../config.${ext}";
|
|
70
70
|
|
|
71
|
+
import { openDB } from "../db.${ext}";
|
|
72
|
+
|
|
71
73
|
const DB_NAME = "swoff-auth-user";
|
|
72
74
|
const STORE_NAME = "current-user";
|
|
73
|
-
// Bump this when adding new indexes/stores for schema migration
|
|
74
|
-
const DB_VERSION = 1;
|
|
75
|
-
|
|
76
|
-
function openAuthDB()${R(ts, "Promise<IDBDatabase>")}{
|
|
77
|
-
return new Promise${PT(ts, "IDBDatabase")}((resolve, reject) => {
|
|
78
|
-
const request = indexedDB.open(DB_NAME, DB_VERSION);
|
|
79
|
-
request.onupgradeneeded = (e) => {
|
|
80
|
-
const db = (e.target${AS(ts, "IDBOpenDBRequest")}).result;
|
|
81
|
-
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
|
82
|
-
db.createObjectStore(STORE_NAME, { keyPath: "key" });
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
request.onsuccess = (e) => resolve((e.target${AS(ts, "IDBOpenDBRequest")}).result);
|
|
86
|
-
request.onerror = (e) => reject((e.target${AS(ts, "IDBRequest")}).error);
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
75
|
|
|
90
76
|
/**
|
|
91
77
|
* Refresh the auth session.
|
|
@@ -130,7 +116,7 @@ export async function fetchCurrentUser()${R(ts, "Promise<Record<string, unknown>
|
|
|
130
116
|
|
|
131
117
|
/** Persist user data to IndexedDB for offline access. */
|
|
132
118
|
export async function cacheUser(user${T(ts, "Record<string, unknown>")})${R(ts, "Promise<void>")}{
|
|
133
|
-
const db = await
|
|
119
|
+
const db = await openDB(DB_NAME, STORE_NAME, "key");
|
|
134
120
|
return new Promise<void>((resolve, reject) => {
|
|
135
121
|
const tx = db.transaction(STORE_NAME, "readwrite");
|
|
136
122
|
const store = tx.objectStore(STORE_NAME);
|
|
@@ -142,7 +128,7 @@ export async function cacheUser(user${T(ts, "Record<string, unknown>")})${R(ts,
|
|
|
142
128
|
|
|
143
129
|
/** Load user data from IndexedDB cache (no token — only user object survives refresh). */
|
|
144
130
|
export async function getCachedUser()${R(ts, "Promise<Record<string, unknown> | null>")}{
|
|
145
|
-
const db = await
|
|
131
|
+
const db = await openDB(DB_NAME, STORE_NAME, "key");
|
|
146
132
|
return new Promise${PT(ts, "Record<string, unknown> | null")}((resolve, reject) => {
|
|
147
133
|
const tx = db.transaction(STORE_NAME, "readonly");
|
|
148
134
|
const store = tx.objectStore(STORE_NAME);
|
|
@@ -154,7 +140,7 @@ export async function getCachedUser()${R(ts, "Promise<Record<string, unknown> |
|
|
|
154
140
|
|
|
155
141
|
/** Remove user data from IndexedDB cache. Call on logout. */
|
|
156
142
|
export async function clearCachedUser()${R(ts, "Promise<void>")}{
|
|
157
|
-
const db = await
|
|
143
|
+
const db = await openDB(DB_NAME, STORE_NAME, "key");
|
|
158
144
|
return new Promise${PT(ts, "void")}((resolve, reject) => {
|
|
159
145
|
const tx = db.transaction(STORE_NAME, "readwrite");
|
|
160
146
|
const store = tx.objectStore(STORE_NAME);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-user.js","sourceRoot":"","sources":["../../src/runtime/auth-user.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,UAAU,oBAAoB,CAClC,GAAmB,EACnB,WAAmB,EACnB,YAAoB,EACpB,QAAgB;IAEhB,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,GAAG,CAAC;IACxB,MAAM,UAAU,GAAG,QAAQ,KAAK,QAAQ,CAAC;IACzC,MAAM,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;IAEtD,MAAM,WAAW,GAAG,UAAU;QAC5B,CAAC,CAAC;;;;;;;sBAOgB;QAClB,CAAC,CAAC;;;;;;;;yEAQmE,CAAC;IAExE,MAAM,QAAQ,GAAG,UAAU;QACzB,CAAC,CAAC;;;;;;;WAOK;QACP,CAAC,CAAC;;;0CAGoC,GAAG;;kDAEK,YAAY;;;+EAGiB,CAAC;IAE9E,OAAO;;;;;;;mEAO0D,GAAG;;;;gHAI0C,GAAG;;;;;;;;;;;;;;;;sCAgB7E,GAAG
|
|
1
|
+
{"version":3,"file":"auth-user.js","sourceRoot":"","sources":["../../src/runtime/auth-user.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,UAAU,oBAAoB,CAClC,GAAmB,EACnB,WAAmB,EACnB,YAAoB,EACpB,QAAgB;IAEhB,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,GAAG,CAAC;IACxB,MAAM,UAAU,GAAG,QAAQ,KAAK,QAAQ,CAAC;IACzC,MAAM,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;IAEtD,MAAM,WAAW,GAAG,UAAU;QAC5B,CAAC,CAAC;;;;;;;sBAOgB;QAClB,CAAC,CAAC;;;;;;;;yEAQmE,CAAC;IAExE,MAAM,QAAQ,GAAG,UAAU;QACzB,CAAC,CAAC;;;;;;;WAOK;QACP,CAAC,CAAC;;;0CAGoC,GAAG;;kDAEK,YAAY;;;+EAGiB,CAAC;IAE9E,OAAO;;;;;;;mEAO0D,GAAG;;;;gHAI0C,GAAG;;;;;;;;;;;;;;;;sCAgB7E,GAAG;;gCAET,GAAG;;;;;;;;;;;KAW9B,YAAY,aAAa,WAAW;;KAEpC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,sFAAsF;;;;uCAItE,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,GAAC,CAAC,CAAC,EAAE,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,mBAAmB,CAAC;IAC1G,UAAU;QACV,CAAC,CAAC,4BAA4B,WAAW;;;MAGvC;QACF,CAAC,CAAC,gBAAgB,CAAC,CAAC,EAAE,EAAE,wBAAwB,CAAC;;6BAExB,WAAW;;;MAGlC;;;KAGD,QAAQ;;0CAE6B,CAAC,CAAC,EAAE,EAAE,kCAAkC,CAAC;IAC/E,UAAU;QACV,CAAC,CAAC,4CAA4C,YAAY;;MAExD;QACF,CAAC,CAAC,4CAA4C,YAAY,KAAK;;;;;;;;;sCAS7B,CAAC,CAAC,EAAE,EAAE,yBAAyB,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,eAAe,CAAC;;;;;;;;;;;;uCAYzD,CAAC,CAAC,EAAE,EAAE,yCAAyC,CAAC;;sBAEjE,EAAE,CAAC,EAAE,EAAE,gCAAgC,CAAC;;;;gDAId,EAAE,CAAC,EAAE,EAAE,YAAY,CAAC;6CACvB,EAAE,CAAC,EAAE,EAAE,YAAY,CAAC;;;;;yCAKxB,CAAC,CAAC,EAAE,EAAE,eAAe,CAAC;;sBAEzC,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC;;;;;mCAKD,EAAE,CAAC,EAAE,EAAE,gBAAgB,CAAC;;;CAG1D,CAAC;AACF,CAAC"}
|
|
@@ -14,7 +14,6 @@ export function generateBackgroundSyncCode(ctx) {
|
|
|
14
14
|
* url: "/api/todos",
|
|
15
15
|
* body: { title: "Grocery" },
|
|
16
16
|
* tags: ["todos"],
|
|
17
|
-
* tags: ["todos"],
|
|
18
17
|
* });
|
|
19
18
|
*/
|
|
20
19
|
|
|
@@ -44,6 +43,10 @@ export async function syncWhenPossible(mutation${T(ts, "object")})${R(ts, "Promi
|
|
|
44
43
|
|
|
45
44
|
/** Re-register a background sync if mutations are still pending. Called automatically after each sync cycle. */
|
|
46
45
|
export async function retrySync()${R(ts, "Promise<void>")}{
|
|
46
|
+
// Re-register self-cleaning listener for next cycle
|
|
47
|
+
if (typeof window !== "undefined") {
|
|
48
|
+
window.addEventListener("mutation-sync-complete", retrySync, { once: true });
|
|
49
|
+
}
|
|
47
50
|
if (!("serviceWorker" in navigator) || !("SyncManager" in window)) return;
|
|
48
51
|
const count = await getPendingCount();
|
|
49
52
|
if (count > 0) {
|
|
@@ -52,7 +55,7 @@ export async function retrySync()${R(ts, "Promise<void>")}{
|
|
|
52
55
|
}
|
|
53
56
|
|
|
54
57
|
if (typeof window !== "undefined") {
|
|
55
|
-
window.addEventListener("mutation-sync-complete", retrySync);
|
|
58
|
+
window.addEventListener("mutation-sync-complete", retrySync, { once: true });
|
|
56
59
|
}
|
|
57
60
|
`;
|
|
58
61
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"background-sync.js","sourceRoot":"","sources":["../../src/runtime/background-sync.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,YAAY,CAAC;AAElC,MAAM,UAAU,0BAA0B,CAAC,GAAmB;IAC5D,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,GAAG,CAAC;IACxB,OAAO;;;;;;iEAMwD,GAAG
|
|
1
|
+
{"version":3,"file":"background-sync.js","sourceRoot":"","sources":["../../src/runtime/background-sync.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,YAAY,CAAC;AAElC,MAAM,UAAU,0BAA0B,CAAC,GAAmB;IAC5D,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,GAAG,CAAC;IACxB,OAAO;;;;;;iEAMwD,GAAG;;;;;;;;;;gFAUY,GAAG;;;;+BAIpD,CAAC,CAAC,EAAE,EAAE,eAAe,CAAC;;;;;;;;;;;;;;;iDAeJ,CAAC,CAAC,EAAE,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,eAAe,CAAC;;;;;;mCAMvD,CAAC,CAAC,EAAE,EAAE,eAAe,CAAC;;;;;;;;;;;;;;;CAexD,CAAC;AACF,CAAC"}
|