@swoff/cli 0.3.6 → 0.3.7
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 +375 -91
- package/bin/swoff +8 -14
- package/dist/__tests__/assemble-sw.test.js +2 -2
- package/dist/__tests__/assemble-sw.test.js.map +1 -1
- package/dist/__tests__/cli-integration.test.js +0 -1
- package/dist/__tests__/cli-integration.test.js.map +1 -1
- package/dist/__tests__/config-types.test.js +4 -3
- package/dist/__tests__/config-types.test.js.map +1 -1
- package/dist/__tests__/file-generators.test.js +12 -23
- package/dist/__tests__/file-generators.test.js.map +1 -1
- package/dist/__tests__/loader.test.js +0 -1
- package/dist/__tests__/loader.test.js.map +1 -1
- package/dist/__tests__/validator.test.js +0 -1
- package/dist/__tests__/validator.test.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/commands/add.js +4 -4
- package/dist/lib/commands/add.js.map +1 -1
- package/dist/lib/commands/generate-guide.js +33 -6
- package/dist/lib/commands/generate-guide.js.map +1 -1
- package/dist/lib/commands/info.js +18 -4
- package/dist/lib/commands/info.js.map +1 -1
- package/dist/lib/commands/init.js +6 -2
- package/dist/lib/commands/init.js.map +1 -1
- package/dist/lib/generators/file-generators/auth-fetch.js +3 -3
- package/dist/lib/generators/file-generators/auth-fetch.js.map +1 -1
- package/dist/lib/generators/file-generators/auth-store.js +114 -5
- package/dist/lib/generators/file-generators/auth-store.js.map +1 -1
- package/dist/lib/generators/file-generators/auth-user.js +2 -2
- package/dist/lib/generators/file-generators/auth-user.js.map +1 -1
- package/dist/lib/generators/file-generators/cache.js +1 -3
- package/dist/lib/generators/file-generators/cache.js.map +1 -1
- package/dist/lib/generators/file-generators/client-injector.js +4 -16
- package/dist/lib/generators/file-generators/client-injector.js.map +1 -1
- package/dist/lib/generators/file-generators/fetch-wrapper.js +40 -15
- package/dist/lib/generators/file-generators/fetch-wrapper.js.map +1 -1
- package/dist/lib/generators/file-generators/generate-hooks.js +23 -209
- package/dist/lib/generators/file-generators/generate-hooks.js.map +1 -1
- package/dist/lib/generators/file-generators/guide-generator.js +153 -36
- package/dist/lib/generators/file-generators/guide-generator.js.map +1 -1
- package/dist/lib/generators/file-generators/mutation-queue.js +31 -3
- package/dist/lib/generators/file-generators/mutation-queue.js.map +1 -1
- package/dist/lib/generators/file-generators/push.js +143 -0
- package/dist/lib/generators/file-generators/push.js.map +1 -0
- package/dist/lib/generators/file-generators/quick-readme.js +13 -3
- package/dist/lib/generators/file-generators/quick-readme.js.map +1 -1
- package/dist/lib/generators/file-generators/sw-generator-build.js +1 -1
- package/dist/lib/generators/file-generators/sw-injector.js +1 -1
- package/dist/lib/generators/file-generators/sw-push.js +67 -0
- package/dist/lib/generators/file-generators/sw-push.js.map +1 -0
- package/dist/lib/generators/file-generators/sw-template.js +2 -0
- package/dist/lib/generators/file-generators/sw-template.js.map +1 -1
- package/dist/lib/generators/file-generators/type-definitions.js +13 -13
- package/dist/lib/generators/sw-generator.js +8 -9
- package/dist/lib/generators/sw-generator.js.map +1 -1
- package/dist/lib/generators/sw-sections/activate-handler.js +6 -2
- package/dist/lib/generators/sw-sections/activate-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/assemble-sw.js +5 -1
- package/dist/lib/generators/sw-sections/assemble-sw.js.map +1 -1
- package/dist/lib/generators/sw-sections/default-template.js +1 -30
- package/dist/lib/generators/sw-sections/default-template.js.map +1 -1
- package/dist/lib/generators/sw-sections/fetch-handler.js +157 -86
- package/dist/lib/generators/sw-sections/fetch-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/install-handler.js +12 -10
- package/dist/lib/generators/sw-sections/install-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/tag-management.js +11 -0
- package/dist/lib/generators/sw-sections/tag-management.js.map +1 -1
- package/dist/lib/generators/swoff-files-generator.js +9 -9
- package/dist/lib/generators/swoff-files-generator.js.map +1 -1
- package/dist/lib/shared/config-types.js +5 -3
- package/dist/lib/shared/config-types.js.map +1 -1
- package/package.json +3 -2
- package/templates/hooks/useAuth.jsx +30 -0
- package/templates/hooks/useAuth.tsx +30 -0
- package/templates/hooks/useBackgroundSync.jsx +31 -0
- package/templates/hooks/useBackgroundSync.tsx +31 -0
- package/templates/hooks/useCacheInvalidation.jsx +19 -0
- package/templates/hooks/useCacheInvalidation.tsx +19 -0
- package/templates/hooks/useCachedFetch.jsx +55 -0
- package/templates/hooks/useCachedFetch.tsx +69 -0
- package/templates/hooks/useMutationQueue.jsx +34 -0
- package/templates/hooks/useMutationQueue.tsx +34 -0
- package/templates/hooks/useNetworkStatus.jsx +19 -0
- package/templates/hooks/useNetworkStatus.tsx +19 -0
- package/templates/hooks/usePushSubscription.jsx +67 -0
- package/templates/hooks/usePushSubscription.tsx +67 -0
- package/templates/hooks/useSWUpdate.jsx +76 -0
- package/templates/hooks/useSWUpdate.tsx +76 -0
|
@@ -33,12 +33,12 @@ const FEATURES = {
|
|
|
33
33
|
auth: {
|
|
34
34
|
label: "Auth",
|
|
35
35
|
description: "Token-based authentication with memory-only tokens, IndexedDB user caching, and auth-aware fetch with automatic 401 handling.",
|
|
36
|
-
files: ["auth/store.ts", "auth/
|
|
36
|
+
files: ["auth/store.ts", "auth/user.ts", "auth/state.ts"],
|
|
37
37
|
functions: [
|
|
38
38
|
"setAuth(authData) / getAuth() / clearAuth() — manage auth state",
|
|
39
39
|
"isAuthValid(auth) — check expiry",
|
|
40
40
|
"createAuthFromResponse(response) — extract AuthData from login response (edit this)",
|
|
41
|
-
"
|
|
41
|
+
"fetchWithCache(input, { auth: true }) — auth-aware fetch (handles bearer, cookie, custom)",
|
|
42
42
|
"ensureValidAuth() — check expiry and refresh token",
|
|
43
43
|
"fetchCurrentUser() / getCachedUser() / cacheUser(user) / clearCachedUser() — user caching",
|
|
44
44
|
"getAuthState() — detect 4-state matrix (online/offline × authenticated/not)",
|
|
@@ -61,6 +61,18 @@ const FEATURES = {
|
|
|
61
61
|
files: ["client-injector.ts (internal handling)"],
|
|
62
62
|
functions: ["No separate imports needed — handled automatically by client-injector.ts"],
|
|
63
63
|
},
|
|
64
|
+
"push-notification": {
|
|
65
|
+
label: "Push Notifications",
|
|
66
|
+
description: "Push notification subscription management with IndexedDB persistence, VAPID key support, and service worker push/notificationclick event handlers.",
|
|
67
|
+
files: ["push.ts"],
|
|
68
|
+
functions: [
|
|
69
|
+
"subscribeToPush(vapidPublicKey) — request permission and subscribe",
|
|
70
|
+
"unsubscribeFromPush() — unsubscribe and clear stored subscription",
|
|
71
|
+
"isSubscribed() — check subscription status",
|
|
72
|
+
"getPushSubscription() — get current PushSubscription object",
|
|
73
|
+
"requestNotificationPermission() — request permission only",
|
|
74
|
+
],
|
|
75
|
+
},
|
|
64
76
|
pwa: {
|
|
65
77
|
label: "PWA",
|
|
66
78
|
description: "Install prompt handling, manifest generation, and React hooks for update management.",
|
|
@@ -103,6 +115,8 @@ export async function infoCommand(projectRoot, feature) {
|
|
|
103
115
|
enabled.push("cross-tab");
|
|
104
116
|
if (config.features.tagInvalidation)
|
|
105
117
|
enabled.push("tag-invalidation");
|
|
118
|
+
if (config.features.pushNotifications?.enabled)
|
|
119
|
+
enabled.push("push-notification");
|
|
106
120
|
if (config.features.pwa.enabled)
|
|
107
121
|
enabled.push("pwa");
|
|
108
122
|
if (enabled.length > 0) {
|
|
@@ -118,7 +132,7 @@ export async function infoCommand(projectRoot, feature) {
|
|
|
118
132
|
log.normal(`Generated files: ${count} in swoff/`);
|
|
119
133
|
}
|
|
120
134
|
log.help("\n swoff info <feature> — detailed info for a feature");
|
|
121
|
-
log.help(" Features: mutation-queue, background-sync, auth, tag-invalidation, cross-tab, pwa");
|
|
135
|
+
log.help(" Features: mutation-queue, background-sync, auth, tag-invalidation, cross-tab, push-notification, pwa");
|
|
122
136
|
log.help(" Read swoff/GUIDE.md for the full integration guide");
|
|
123
137
|
}
|
|
124
138
|
function showFeatureDetail(feature) {
|
|
@@ -126,7 +140,7 @@ function showFeatureDetail(feature) {
|
|
|
126
140
|
const info = FEATURES[key];
|
|
127
141
|
if (!info) {
|
|
128
142
|
log.error(`Unknown feature: ${feature}`);
|
|
129
|
-
log.info("Available: mutation-queue, background-sync, auth, tag-invalidation, cross-tab, pwa");
|
|
143
|
+
log.info("Available: mutation-queue, background-sync, auth, tag-invalidation, cross-tab, push-notification, pwa");
|
|
130
144
|
return;
|
|
131
145
|
}
|
|
132
146
|
log.header(info.label);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"info.js","sourceRoot":"","sources":["../../../src/lib/commands/info.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAStD,MAAM,QAAQ,GAAgC;IAC5C,gBAAgB,EAAE;QAChB,KAAK,EAAE,gBAAgB;QACvB,WAAW,EACT,uJAAuJ;QACzJ,KAAK,EAAE,CAAC,mBAAmB,CAAC;QAC5B,SAAS,EAAE;YACT,wDAAwD;YACxD,mDAAmD;YACnD,sEAAsE;YACtE,yDAAyD;SAC1D;KACF;IACD,iBAAiB,EAAE;QACjB,KAAK,EAAE,iBAAiB;QACxB,WAAW,EACT,8KAA8K;QAChL,KAAK,EAAE,CAAC,oBAAoB,CAAC;QAC7B,SAAS,EAAE;YACT,iEAAiE;YACjE,+DAA+D;SAChE;KACF;IACD,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM;QACb,WAAW,EACT,+HAA+H;QACjI,KAAK,EAAE,CAAC,eAAe,EAAE,
|
|
1
|
+
{"version":3,"file":"info.js","sourceRoot":"","sources":["../../../src/lib/commands/info.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,9 +15,13 @@ export async function initCommand(projectRoot, framework) {
|
|
|
15
15
|
log.info("To reinitialize, delete the config file first.");
|
|
16
16
|
return;
|
|
17
17
|
}
|
|
18
|
+
const detected = framework || detectFramework(projectRoot);
|
|
18
19
|
const config = {
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
$schema: defaultInitConfig.$schema,
|
|
21
|
+
enabled: defaultInitConfig.enabled,
|
|
22
|
+
framework: detected,
|
|
23
|
+
build: defaultInitConfig.build,
|
|
24
|
+
features: defaultInitConfig.features,
|
|
21
25
|
};
|
|
22
26
|
const configPath = join(projectRoot, "swoff.config.json");
|
|
23
27
|
writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/lib/commands/init.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAC1D,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAoB,MAAM,2BAA2B,CAAC;AAChF,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAE/D,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,WAAmB,EAAE,SAAkB;IACvE,GAAG,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAEjC,MAAM,WAAW,GAAG,CAAC,mBAAmB,EAAE,iBAAiB,CAAC,CAAC;IAC7D,MAAM,cAAc,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAC5C,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CACjC,CAAC;IAEF,IAAI,cAAc,EAAE,CAAC;QACnB,GAAG,CAAC,IAAI,CAAC,kBAAkB,cAAc,kBAAkB,CAAC,CAAC;QAC7D,GAAG,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;QAC3D,OAAO;IACT,CAAC;IAED,MAAM,
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/lib/commands/init.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAC1D,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAoB,MAAM,2BAA2B,CAAC;AAChF,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAE/D,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,WAAmB,EAAE,SAAkB;IACvE,GAAG,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAEjC,MAAM,WAAW,GAAG,CAAC,mBAAmB,EAAE,iBAAiB,CAAC,CAAC;IAC7D,MAAM,cAAc,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAC5C,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CACjC,CAAC;IAEF,IAAI,cAAc,EAAE,CAAC;QACnB,GAAG,CAAC,IAAI,CAAC,kBAAkB,cAAc,kBAAkB,CAAC,CAAC;QAC7D,GAAG,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;QAC3D,OAAO;IACT,CAAC;IAED,MAAM,QAAQ,GAAG,SAAS,IAAI,eAAe,CAAC,WAAW,CAAC,CAAC;IAC3D,MAAM,MAAM,GAAG;QACb,OAAO,EAAE,iBAAiB,CAAC,OAAO;QAClC,OAAO,EAAE,iBAAiB,CAAC,OAAO;QAClC,SAAS,EAAE,QAAoC;QAC/C,KAAK,EAAE,iBAAiB,CAAC,KAAK;QAC9B,QAAQ,EAAE,iBAAiB,CAAC,QAAQ;KACrC,CAAC;IAEF,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC;IAC1D,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3D,GAAG,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IAEtC,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IACtC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;QACvC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACzB,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACxC,GAAG,CAAC,IAAI,CAAC,WAAW,GAAG,GAAG,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,GAAG,CAAC,OAAO,CAAC,iCAAiC,CAAC,CAAC;IAC/C,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;IAC5B,GAAG,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC;IAChE,GAAG,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;IAC5C,GAAG,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;AAC/D,CAAC"}
|
|
@@ -44,7 +44,7 @@ export function generateAuthFetch(ctx) {
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
const credentialsLine = type === "cookie"
|
|
47
|
-
? `
|
|
47
|
+
? `const fetchOptions = { ...options, headers, credentials: "include" as RequestCredentials };`
|
|
48
48
|
: ` const fetchOptions = { ...options, headers };`;
|
|
49
49
|
const code = `/**
|
|
50
50
|
* Auth-Fetch — attaches auth headers, excludes auth endpoints from cache,
|
|
@@ -82,8 +82,8 @@ function isAuthUrl(url${T("string")})${R("boolean")}{
|
|
|
82
82
|
return authPaths.some((path) => url.includes(path));
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
/** Auth-aware fetch. Delegates to fetchWithCache with auth headers, cache bypass for auth endpoints, and 401 handling. */
|
|
86
|
-
export async function authenticatedFetch(input${T("RequestInfo")}, options${T("RequestInit")} = {})${R("Promise<Response>")}{
|
|
85
|
+
/** Auth-aware fetch. Delegates to fetchWithCache with auth headers, cache bypass for auth endpoints, and 401 handling. Options may include \`type: 'read' | 'mutation'\` to override method-based caching. */
|
|
86
|
+
export async function authenticatedFetch(input${T("RequestInfo")}, options${T("RequestInit & { type?: 'read' | 'mutation' }")} = {})${R("Promise<Response>")}{
|
|
87
87
|
const auth = await getAuth();
|
|
88
88
|
const headers = new Headers(options.headers);
|
|
89
89
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-fetch.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/auth-fetch.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAoB,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,UAAU,iBAAiB,CAAC,GAAqB;IACrD,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;IACpB,MAAM,EAAE,GAAG,GAAG,KAAK,IAAI,CAAC;IACxB,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACpD,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAEtD,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;IAC5C,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,IAAI,EAAE,GAAG,UAAU,CAAC;IAEvD,SAAS,uBAAuB;QAC9B,MAAM,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAAC,CAAC;QAC/B,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;QACvB,MAAM,EAAE,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;QACxB,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,QAAQ;gBACX,OAAO,mCAAmC,EAAE,UAAU,CAAC,IAAI,CAAC;;EAElE,CAAC;YACG,KAAK,QAAQ;gBACX,OAAO,mCAAmC,EAAE,SAAS,CAAC,IAAI,CAAC;;;;;EAKjE,CAAC;YACG,KAAK,QAAQ;gBACX,OAAO,mCAAmC,EAAE,SAAS,CAAC,IAAI,CAAC;;;;;;;EAOjE,CAAC;YACG;gBACE,OAAO,mCAAmC,EAAE,SAAS,CAAC,IAAI,CAAC;;;;;EAKjE,CAAC;QACC,CAAC;IACH,CAAC;IAED,MAAM,eAAe,GACnB,IAAI,KAAK,QAAQ;QACf,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"auth-fetch.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/auth-fetch.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAoB,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,UAAU,iBAAiB,CAAC,GAAqB;IACrD,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;IACpB,MAAM,EAAE,GAAG,GAAG,KAAK,IAAI,CAAC;IACxB,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACpD,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAEtD,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;IAC5C,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,IAAI,EAAE,GAAG,UAAU,CAAC;IAEvD,SAAS,uBAAuB;QAC9B,MAAM,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAAC,CAAC;QAC/B,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;QACvB,MAAM,EAAE,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;QACxB,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,QAAQ;gBACX,OAAO,mCAAmC,EAAE,UAAU,CAAC,IAAI,CAAC;;EAElE,CAAC;YACG,KAAK,QAAQ;gBACX,OAAO,mCAAmC,EAAE,SAAS,CAAC,IAAI,CAAC;;;;;EAKjE,CAAC;YACG,KAAK,QAAQ;gBACX,OAAO,mCAAmC,EAAE,SAAS,CAAC,IAAI,CAAC;;;;;;;EAOjE,CAAC;YACG;gBACE,OAAO,mCAAmC,EAAE,SAAS,CAAC,IAAI,CAAC;;;;;EAKjE,CAAC;QACC,CAAC;IACH,CAAC;IAED,MAAM,eAAe,GACnB,IAAI,KAAK,QAAQ;QACf,CAAC,CAAC,6FAA6F;QAC/F,CAAC,CAAC,iDAAiD,CAAC;IAExD,MAAM,IAAI,GAAG;;;;;wDAKyC,GAAG;;;;wDAIH,GAAG;;;;mDAIR,GAAG;sCAChB,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,oBAAoB,GAAG;;EAEtF,uBAAuB,EAAE;;;;;;wBAMH,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC;;;;;;;;OAQ5C,WAAW;OACX,YAAY;;;;;;gDAM6B,CAAC,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,8CAA8C,CAAC,SAAS,CAAC,CAAC,mBAAmB,CAAC;;;;;;;;;;;;;IAaxJ,eAAe;;;;;;;;;;;;;;;;oBAgBC,CAAC,CAAC,iCAAiC,CAAC;;yCAEf,CAAC,CAAC,0BAA0B,CAAC;;;;;;;mDAOnB,WAAW;;;;;;;;;;;;;;;;;;;;;;;;CAwB7D,CAAC;IAEA,SAAS,CAAC,GAAG,EAAE,cAAc,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;AAC5C,CAAC"}
|
|
@@ -1,12 +1,111 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Generates auth-store.ts/js — token storage
|
|
3
|
-
*
|
|
2
|
+
* Generates auth-store.ts/js — token storage, auth headers, auth URL detection,
|
|
3
|
+
* and token refresh. All auth logic lives here so fetch-wrapper can import it
|
|
4
|
+
* without circular dependencies.
|
|
4
5
|
*
|
|
5
6
|
* Security: the Bearer token lives in memory only and is cleared on page
|
|
6
7
|
* refresh. Only { user, expiresAt } is persisted to IndexedDB for offline
|
|
7
8
|
* user display. After a page refresh, re-login is required.
|
|
8
9
|
*/
|
|
9
10
|
import { writeFile } from "./context.js";
|
|
11
|
+
function generateWithAuthHeaders(authType, ts, R, T) {
|
|
12
|
+
const a = T("AuthData | null");
|
|
13
|
+
const h = T("Headers");
|
|
14
|
+
const hd = T("Headers");
|
|
15
|
+
switch (authType) {
|
|
16
|
+
case "cookie":
|
|
17
|
+
return `/** Inject auth headers. For cookie auth, credentials are handled via AUTH_WITH_CREDENTIALS. */
|
|
18
|
+
export function withAuthHeaders(headers${hd}, _auth${a})${h}{
|
|
19
|
+
return headers;
|
|
20
|
+
}`;
|
|
21
|
+
case "bearer":
|
|
22
|
+
return `/** Inject Bearer token into request headers. */
|
|
23
|
+
export function withAuthHeaders(headers${hd}, auth${a})${h}{
|
|
24
|
+
if (auth?.token) {
|
|
25
|
+
headers.set("Authorization", \`Bearer \${auth.token}\`);
|
|
26
|
+
}
|
|
27
|
+
return headers;
|
|
28
|
+
}`;
|
|
29
|
+
case "custom":
|
|
30
|
+
return `/** Inject custom auth headers. Edit this function to match your backend. */
|
|
31
|
+
export function withAuthHeaders(headers${hd}, auth${a})${h}{
|
|
32
|
+
// --- EDIT THIS BLOCK FOR YOUR BACKEND ---
|
|
33
|
+
// if (auth?.token) {
|
|
34
|
+
// headers.set("X-Auth-Token", auth.token);
|
|
35
|
+
// }
|
|
36
|
+
// --- END OF EDITABLE BLOCK ---
|
|
37
|
+
return headers;
|
|
38
|
+
}`;
|
|
39
|
+
default:
|
|
40
|
+
return `export function withAuthHeaders(headers${hd}, auth${a})${h}{
|
|
41
|
+
if (auth?.token) {
|
|
42
|
+
headers.set("Authorization", \`Bearer \${auth.token}\`);
|
|
43
|
+
}
|
|
44
|
+
return headers;
|
|
45
|
+
}`;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function generateIsAuthUrl(refreshPath, userEndpoint, ts, R, T) {
|
|
49
|
+
return `/** Check if a URL is an auth endpoint that should bypass the SW cache. */
|
|
50
|
+
export function isAuthUrl(url${T("string")})${R("boolean")}{
|
|
51
|
+
const authPaths = [
|
|
52
|
+
"/login",
|
|
53
|
+
"/logout",
|
|
54
|
+
"/register",
|
|
55
|
+
"/api/login",
|
|
56
|
+
"/api/logout",
|
|
57
|
+
"/api/register",
|
|
58
|
+
"${refreshPath}",
|
|
59
|
+
"${userEndpoint}",
|
|
60
|
+
];
|
|
61
|
+
return authPaths.some((path) => url.includes(path));
|
|
62
|
+
}`;
|
|
63
|
+
}
|
|
64
|
+
function generateEnsureValidAuth(cookieAuth, ts, R, T, PT, refreshPath, ext) {
|
|
65
|
+
const cr = cookieAuth ? ` credentials: "include" as RequestCredentials,` : "";
|
|
66
|
+
return `/** Refresh the auth token via the refresh endpoint. Uses plain fetch to bypass SW cache. */
|
|
67
|
+
let refreshPromise${T("Promise<AuthData | null> | null")} = null;
|
|
68
|
+
|
|
69
|
+
export async function ensureValidAuth()${R("Promise<AuthData | null>")}{
|
|
70
|
+
const auth = await getAuth();
|
|
71
|
+
if (!auth) return null;
|
|
72
|
+
if (!auth.expiresAt || Date.now() < auth.expiresAt) return auth;
|
|
73
|
+
|
|
74
|
+
if (!refreshPromise) {
|
|
75
|
+
refreshPromise = (async () => {
|
|
76
|
+
const headers = new Headers({ "Content-Type": "application/json" });
|
|
77
|
+
withAuthHeaders(headers, auth);
|
|
78
|
+
try {
|
|
79
|
+
const response = await fetch("${refreshPath}", {
|
|
80
|
+
method: "POST",
|
|
81
|
+
headers,
|
|
82
|
+
${cr} });
|
|
83
|
+
|
|
84
|
+
if (!response.ok) {
|
|
85
|
+
await clearAuth();
|
|
86
|
+
window.dispatchEvent(new CustomEvent("sw-auth-unauthorized"));
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const data = await response.json();
|
|
91
|
+
const updated = { ...auth, token: data.token, expiresAt: data.expiresAt };
|
|
92
|
+
await setAuth(updated);
|
|
93
|
+
return updated;
|
|
94
|
+
} catch {
|
|
95
|
+
await clearAuth();
|
|
96
|
+
window.dispatchEvent(new CustomEvent("sw-auth-unauthorized"));
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
})();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
return await refreshPromise;
|
|
104
|
+
} finally {
|
|
105
|
+
refreshPromise = null;
|
|
106
|
+
}
|
|
107
|
+
}`;
|
|
108
|
+
}
|
|
10
109
|
export function generateAuthStore(ctx) {
|
|
11
110
|
const ext = ctx.ext;
|
|
12
111
|
const ts = ext === "ts";
|
|
@@ -14,7 +113,10 @@ export function generateAuthStore(ctx) {
|
|
|
14
113
|
const R = (type) => (ts ? `: ${type} ` : " ");
|
|
15
114
|
const PT = (type) => (ts ? `<${type}>` : "");
|
|
16
115
|
const AS = (type) => (ts ? ` as ${type}` : "");
|
|
17
|
-
const
|
|
116
|
+
const authConfig = ctx.config.features.auth;
|
|
117
|
+
const { refreshPath, userEndpoint, type } = authConfig;
|
|
118
|
+
const authDataInterface = ts
|
|
119
|
+
? `export interface AuthData {
|
|
18
120
|
token?: string;
|
|
19
121
|
user?: Record<string, unknown>;
|
|
20
122
|
expiresAt?: number;
|
|
@@ -27,7 +129,8 @@ export interface AuthResponse extends Record<string, unknown> {
|
|
|
27
129
|
// expiresAt?: number;
|
|
28
130
|
}
|
|
29
131
|
|
|
30
|
-
`
|
|
132
|
+
`
|
|
133
|
+
: "";
|
|
31
134
|
const createAuthFromResponseBlock = ts
|
|
32
135
|
? `/** Extract AuthData from your backend's login response. Edit this function to match your backend's response shape. */
|
|
33
136
|
export function createAuthFromResponse(response: AuthResponse): AuthData {
|
|
@@ -103,7 +206,7 @@ async function persistUserData(authData${T("AuthData | null")})${R("Promise<void
|
|
|
103
206
|
|
|
104
207
|
async function loadUserData()${R("Promise<{ user?: Record<string, unknown>; expiresAt?: number } | null>")}{
|
|
105
208
|
const db = await openAuthDB();
|
|
106
|
-
return new Promise
|
|
209
|
+
return new Promise((resolve, reject) => {
|
|
107
210
|
const tx = db.transaction(STORE_NAME, "readonly");
|
|
108
211
|
const store = tx.objectStore(STORE_NAME);
|
|
109
212
|
const request = store.get("session");
|
|
@@ -152,6 +255,12 @@ export function isAuthValid(auth${T("AuthData | null")})${R("boolean")}{
|
|
|
152
255
|
if (!auth.expiresAt) return true;
|
|
153
256
|
return Date.now() < auth.expiresAt;
|
|
154
257
|
}
|
|
258
|
+
|
|
259
|
+
${type === "cookie" ? `export const AUTH_WITH_CREDENTIALS = true;` : `export const AUTH_WITH_CREDENTIALS = false;`}
|
|
260
|
+
|
|
261
|
+
${generateWithAuthHeaders(type, ts, R, T)}
|
|
262
|
+
${generateIsAuthUrl(refreshPath, userEndpoint, ts, R, T)}
|
|
263
|
+
${generateEnsureValidAuth(type === "cookie", ts, R, T, PT, refreshPath, ext)}
|
|
155
264
|
`;
|
|
156
265
|
writeFile(ctx, `auth/store.${ext}`, code);
|
|
157
266
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-store.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/auth-store.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"auth-store.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/auth-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,7 +21,7 @@ export function generateAuthUser(ctx) {
|
|
|
21
21
|
* await clearCachedUser(); // Clear on logout
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import {
|
|
24
|
+
import { fetchWithCache } from "../fetch-wrapper.${ext}";
|
|
25
25
|
|
|
26
26
|
const DB_NAME = "swoff-auth-user";
|
|
27
27
|
const STORE_NAME = "current-user";
|
|
@@ -42,7 +42,7 @@ function openAuthDB()${R("Promise<IDBDatabase>")}{
|
|
|
42
42
|
|
|
43
43
|
/** Fetch current user from the user endpoint and cache the result in IndexedDB. */
|
|
44
44
|
export async function fetchCurrentUser()${R("Promise<Record<string, unknown>>")}{
|
|
45
|
-
const response = await
|
|
45
|
+
const { response } = await fetchWithCache("${userEndpoint}", { auth: true });
|
|
46
46
|
if (!response.ok) throw new Error("Failed to fetch user");
|
|
47
47
|
|
|
48
48
|
const user = await response.json();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-user.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/auth-user.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAoB,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,UAAU,gBAAgB,CAAC,GAAqB;IACpD,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;IACpB,MAAM,EAAE,GAAG,GAAG,KAAK,IAAI,CAAC;IACxB,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACpD,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACtD,MAAM,EAAE,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACrD,MAAM,EAAE,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACvD,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC;IAE3D,MAAM,IAAI,GAAG;;;;gGAIiF,GAAG;;;;;;;
|
|
1
|
+
{"version":3,"file":"auth-user.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/auth-user.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAoB,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,UAAU,gBAAgB,CAAC,GAAqB;IACpD,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;IACpB,MAAM,EAAE,GAAG,GAAG,KAAK,IAAI,CAAC;IACxB,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACpD,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACtD,MAAM,EAAE,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACrD,MAAM,EAAE,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACvD,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC;IAE3D,MAAM,IAAI,GAAG;;;;gGAIiF,GAAG;;;;;;;mDAOhD,GAAG;;;;;uBAK/B,CAAC,CAAC,sBAAsB,CAAC;sBAC1B,EAAE,CAAC,aAAa,CAAC;;;4BAGX,EAAE,CAAC,kBAAkB,CAAC;;;;;kDAKA,EAAE,CAAC,kBAAkB,CAAC;+CACzB,EAAE,CAAC,YAAY,CAAC;;;;;0CAKrB,CAAC,CAAC,kCAAkC,CAAC;+CAChC,YAAY;;;;;;;;;sCASrB,CAAC,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC,eAAe,CAAC;;;;;;;;;;;;uCAYjD,CAAC,CAAC,yCAAyC,CAAC;;sBAE7D,EAAE,CAAC,gCAAgC,CAAC;;;;gDAIV,EAAE,CAAC,YAAY,CAAC;6CACnB,EAAE,CAAC,YAAY,CAAC;;;;;yCAKpB,CAAC,CAAC,eAAe,CAAC;;sBAErC,EAAE,CAAC,MAAM,CAAC;;;;;mCAKG,EAAE,CAAC,gBAAgB,CAAC;;;CAGtD,CAAC;IAEA,SAAS,CAAC,GAAG,EAAE,aAAa,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;AAC3C,CAAC"}
|
|
@@ -34,9 +34,7 @@ export async function invalidateByTag(tag${T("string")})${R("Promise<void>")}{
|
|
|
34
34
|
|
|
35
35
|
/** Invalidate all cached responses matching any of the given tags. */
|
|
36
36
|
export async function invalidateByTags(tags${T("string[]")})${R("Promise<void>")}{
|
|
37
|
-
|
|
38
|
-
await invalidateByTag(tag);
|
|
39
|
-
}
|
|
37
|
+
await Promise.all(tags.map((tag) => invalidateByTag(tag)));
|
|
40
38
|
}
|
|
41
39
|
`;
|
|
42
40
|
writeFile(ctx, `cache.${ext}`, code);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/cache.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAoB,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,UAAU,aAAa,CAAC,GAAqB;IACjD,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;IACpB,MAAM,EAAE,GAAG,GAAG,KAAK,IAAI,CAAC;IACxB,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACpD,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAEtD,MAAM,IAAI,GAAG;;;;;sDAKuC,GAAG;;;;;;;2CAOd,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,eAAe,CAAC;;;;;;;;;;;;;;6CAc/B,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,eAAe,CAAC
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/cache.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAoB,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,UAAU,aAAa,CAAC,GAAqB;IACjD,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;IACpB,MAAM,EAAE,GAAG,GAAG,KAAK,IAAI,CAAC;IACxB,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACpD,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAEtD,MAAM,IAAI,GAAG;;;;;sDAKuC,GAAG;;;;;;;2CAOd,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,eAAe,CAAC;;;;;;;;;;;;;;6CAc/B,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,eAAe,CAAC;;;CAG/E,CAAC;IAEA,SAAS,CAAC,GAAG,EAAE,SAAS,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;AACvC,CAAC"}
|
|
@@ -8,7 +8,6 @@ export function generateClientInjector(ctx) {
|
|
|
8
8
|
const pwaEnabled = ctx.config.features.pwa.enabled;
|
|
9
9
|
const mutationQueueEnabled = ctx.config.features.mutationQueue;
|
|
10
10
|
const crossTabSync = ctx.config.features.crossTabSync;
|
|
11
|
-
const clientRegistration = ctx.config.features.clientRegistration;
|
|
12
11
|
const pwaImport = pwaEnabled
|
|
13
12
|
? `import { setupPwaInstall } from "./pwa/install.${ext}";
|
|
14
13
|
`
|
|
@@ -35,19 +34,8 @@ window.addEventListener("online", processMutationQueue);
|
|
|
35
34
|
}
|
|
36
35
|
`
|
|
37
36
|
: "";
|
|
38
|
-
const swImport =
|
|
39
|
-
|
|
40
|
-
initServiceWorker as swInit,
|
|
41
|
-
handleUpdateApproved,
|
|
42
|
-
skipWaiting,
|
|
43
|
-
} from "./sw/injector.${ext}";
|
|
44
|
-
`
|
|
45
|
-
: "";
|
|
46
|
-
const swExports = clientRegistration
|
|
47
|
-
? `
|
|
48
|
-
export { handleUpdateApproved, skipWaiting };
|
|
49
|
-
`
|
|
50
|
-
: "";
|
|
37
|
+
const swImport = `import { initServiceWorker as swInit } from "./sw/injector.${ext}";
|
|
38
|
+
`;
|
|
51
39
|
const code = `/**
|
|
52
40
|
* Swoff Client Injector
|
|
53
41
|
* Orchestrates SW registration, PWA install, and cross-tab sync.
|
|
@@ -105,8 +93,8 @@ if (typeof window !== "undefined" && "serviceWorker" in navigator) {
|
|
|
105
93
|
|
|
106
94
|
/** Initialize SW registration and all client-side features (PWA install, mutation queue, cross-tab sync). Call once at app startup. */
|
|
107
95
|
export async function initServiceWorker()${ts ? ": Promise<void>" : " "}{
|
|
108
|
-
|
|
109
|
-
}
|
|
96
|
+
await swInit();
|
|
97
|
+
}
|
|
110
98
|
`;
|
|
111
99
|
writeFile(ctx, `client-injector.${ext}`, code);
|
|
112
100
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-injector.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/client-injector.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAoB,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,UAAU,sBAAsB,CAAC,GAAqB;IAC1D,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;IACpB,MAAM,EAAE,GAAG,GAAG,KAAK,IAAI,CAAC;IACxB,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC;IACnD,MAAM,oBAAoB,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC;IAC/D,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"client-injector.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/client-injector.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAoB,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,UAAU,sBAAsB,CAAC,GAAqB;IAC1D,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;IACpB,MAAM,EAAE,GAAG,GAAG,KAAK,IAAI,CAAC;IACxB,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC;IACnD,MAAM,oBAAoB,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC;IAC/D,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC;IAEtD,MAAM,SAAS,GAAG,UAAU;QAC1B,CAAC,CAAC,kDAAkD,GAAG;CAC1D;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,OAAO,GAAG,UAAU,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE,CAAC;IAEzD,MAAM,cAAc,GAAG,oBAAoB;QACzC,CAAC,CAAC,0DAA0D,GAAG;CAClE;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,sBAAsB,GAAG,oBAAoB;QACjD,CAAC,CAAC;;;CAGL;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,eAAe,GAAG,YAAY;QAClC,CAAC,CAAC;;;;;;;;CAQL;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,QAAQ,GAAG,8DAA8D,GAAG;CACnF,CAAC;IAEA,MAAM,IAAI,GAAG;;;;;;kEAMmD,GAAG;;;;;;;;;;;;;;;;;;;;EAoBnE,SAAS,GAAG,cAAc,GAAG,QAAQ;EACrC,OAAO,GAAG,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;OAyB3B,eAAe;;;;2CAIqB,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,GAAG;;;CAGtE,CAAC;IAEA,SAAS,CAAC,GAAG,EAAE,mBAAmB,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;AACjD,CAAC"}
|
|
@@ -17,7 +17,7 @@ export function generateFetchWrapper(ctx) {
|
|
|
17
17
|
: "",
|
|
18
18
|
tagInvalidation ? `import { invalidateByTags } from "./cache.${ext}";` : "",
|
|
19
19
|
authEnabled
|
|
20
|
-
? `import { getAuth, clearAuth } from "./auth/store.${ext}";`
|
|
20
|
+
? `import { getAuth, clearAuth, withAuthHeaders, isAuthUrl, AUTH_WITH_CREDENTIALS } from "./auth/store.${ext}";`
|
|
21
21
|
: "",
|
|
22
22
|
mutationQueue
|
|
23
23
|
? `import { queueMutation } from "./mutation-queue.${ext}";`
|
|
@@ -27,8 +27,8 @@ export function generateFetchWrapper(ctx) {
|
|
|
27
27
|
.join("\n");
|
|
28
28
|
const interfaceBlock = ts
|
|
29
29
|
? `
|
|
30
|
-
export interface FetchWithCacheResult {
|
|
31
|
-
response${T("Response")};
|
|
30
|
+
export interface FetchWithCacheResult${G("T")} {
|
|
31
|
+
response${T("Response & { json(): Promise<T> }")};
|
|
32
32
|
fromCache${T("boolean")};
|
|
33
33
|
}
|
|
34
34
|
`
|
|
@@ -42,6 +42,8 @@ export interface FetchWithCacheOptions extends RequestInit {
|
|
|
42
42
|
auth?: boolean;
|
|
43
43
|
queueOffline?: boolean;
|
|
44
44
|
invalidate?: 'auto' | string[] | false;
|
|
45
|
+
type?: 'read' | 'mutation';
|
|
46
|
+
strategy?: 'cache-first' | 'network-first' | 'stale-while-revalidate' | 'cache-only' | 'network-only';
|
|
45
47
|
}
|
|
46
48
|
`
|
|
47
49
|
: "";
|
|
@@ -49,17 +51,20 @@ export interface FetchWithCacheOptions extends RequestInit {
|
|
|
49
51
|
? `
|
|
50
52
|
if (options.auth) {
|
|
51
53
|
const auth = await getAuth();
|
|
52
|
-
|
|
53
|
-
headers.set("Authorization", \`Bearer \${auth.token}\`);
|
|
54
|
-
}
|
|
54
|
+
withAuthHeaders(headers, auth);
|
|
55
55
|
}`
|
|
56
56
|
: "";
|
|
57
57
|
const authUrlsBlock = authEnabled
|
|
58
58
|
? `
|
|
59
59
|
// Auth endpoints bypass SW cache
|
|
60
|
-
|
|
61
|
-
if (options.auth && authPaths.some((p) => url.includes(p)) && !headers.has("X-SW-Cache-Strategy")) {
|
|
60
|
+
if (options.auth && isAuthUrl(url) && !headers.has("X-SW-Cache-Strategy")) {
|
|
62
61
|
headers.set("X-SW-Cache-Strategy", "mutation");
|
|
62
|
+
}`
|
|
63
|
+
: "";
|
|
64
|
+
const authCredentialsBlock = authEnabled
|
|
65
|
+
? `
|
|
66
|
+
if (AUTH_WITH_CREDENTIALS) {
|
|
67
|
+
fetchOptions.credentials = "include";
|
|
63
68
|
}`
|
|
64
69
|
: "";
|
|
65
70
|
const auth401Block = authEnabled
|
|
@@ -123,7 +128,8 @@ export interface FetchWithCacheOptions extends RequestInit {
|
|
|
123
128
|
: "";
|
|
124
129
|
const code = `/**
|
|
125
130
|
* Swoff Fetch Wrapper
|
|
126
|
-
* Unified fetch with caching, auth, offline queue,
|
|
131
|
+
* Unified fetch with caching, auth, offline queue, auto-invalidation, and
|
|
132
|
+
* per-request strategy override.
|
|
127
133
|
*
|
|
128
134
|
* Usage:
|
|
129
135
|
* import { fetchWithCache } from './swoff/fetch-wrapper.${ext}';
|
|
@@ -138,7 +144,7 @@ export interface FetchWithCacheOptions extends RequestInit {
|
|
|
138
144
|
* body: JSON.stringify({ title: "New task" }),
|
|
139
145
|
* });
|
|
140
146
|
*
|
|
141
|
-
* // Authenticated request
|
|
147
|
+
* // Authenticated request (works with bearer, cookie, custom)
|
|
142
148
|
* const { response: userRes } = await fetchWithCache("/api/me", { auth: true });
|
|
143
149
|
*
|
|
144
150
|
* // Custom tags + stale-while-revalidate
|
|
@@ -147,6 +153,21 @@ export interface FetchWithCacheOptions extends RequestInit {
|
|
|
147
153
|
* staleWhileRevalidate: true,
|
|
148
154
|
* });
|
|
149
155
|
*
|
|
156
|
+
* // Override caching strategy per-request (highest priority)
|
|
157
|
+
* await fetchWithCache("/api/checkout", {
|
|
158
|
+
* method: "POST",
|
|
159
|
+
* type: "read",
|
|
160
|
+
* strategy: "network-only",
|
|
161
|
+
* });
|
|
162
|
+
*
|
|
163
|
+
* // Override method-based caching with explicit type
|
|
164
|
+
* // Use type: "mutation" for POST-based reads (search, GraphQL)
|
|
165
|
+
* await fetchWithCache("/api/search", {
|
|
166
|
+
* method: "POST",
|
|
167
|
+
* type: "read",
|
|
168
|
+
* body: JSON.stringify({ query: "hello" }),
|
|
169
|
+
* });
|
|
170
|
+
*
|
|
150
171
|
* // Offline: auto-queues writes (disable with queueOffline: false)
|
|
151
172
|
* await fetchWithCache("/api/todos", {
|
|
152
173
|
* method: "POST",
|
|
@@ -159,10 +180,10 @@ ${importLines}
|
|
|
159
180
|
${interfaceBlock}${optionsInterface}
|
|
160
181
|
const inFlightRequests = new Map${G("string, Promise<Response>")}();
|
|
161
182
|
|
|
162
|
-
/** Fetch with caching, auth, offline queue, and
|
|
163
|
-
export async function fetchWithCache(input${T("RequestInfo")}, options${T("RequestInit & { tags?: string[]; staleWhileRevalidate?: boolean; auth?: boolean; queueOffline?: boolean; invalidate?: 'auto' | string[] | false }")} = {})${R("Promise<FetchWithCacheResult
|
|
183
|
+
/** Fetch with caching, auth, offline queue, auto-invalidation, and per-request strategy override. Returns { response, fromCache }. Use { auth: true } for authenticated requests — works with bearer, cookie, and custom auth types. */
|
|
184
|
+
export async function fetchWithCache${G("T")}(input${T("RequestInfo")}, options${T("RequestInit & { tags?: string[]; staleWhileRevalidate?: boolean; auth?: boolean; queueOffline?: boolean; invalidate?: 'auto' | string[] | false; type?: 'read' | 'mutation'; strategy?: 'cache-first' | 'network-first' | 'stale-while-revalidate' | 'cache-only' | 'network-only' }")} = {})${R("Promise<FetchWithCacheResult<T>>")}{
|
|
164
185
|
const method = (options.method || "GET").toUpperCase();
|
|
165
|
-
const isRead = method === "GET" || method === "HEAD";
|
|
186
|
+
const isRead = options.type === "read" || (options.type !== "mutation" && (method === "GET" || method === "HEAD"));
|
|
166
187
|
const url = typeof input === "string" ? input : input.url;
|
|
167
188
|
|
|
168
189
|
const headers = new Headers(options.headers);
|
|
@@ -177,11 +198,15 @@ ${autoTagsBlock}
|
|
|
177
198
|
headers.set("X-SW-Cache-Tags", options.tags.join(","));
|
|
178
199
|
}
|
|
179
200
|
|
|
180
|
-
if (options.staleWhileRevalidate) {
|
|
181
|
-
headers.set("X-SW-
|
|
201
|
+
if (options.staleWhileRevalidate && !options.strategy) {
|
|
202
|
+
headers.set("X-SW-Strategy", "stale-while-revalidate");
|
|
203
|
+
}
|
|
204
|
+
if (options.strategy) {
|
|
205
|
+
headers.set("X-SW-Strategy", options.strategy);
|
|
182
206
|
}
|
|
183
207
|
${authBlock}${authUrlsBlock}
|
|
184
208
|
const fetchOptions${T("RequestInit")} = { ...options, headers };
|
|
209
|
+
${authCredentialsBlock}
|
|
185
210
|
|
|
186
211
|
// Offline handling
|
|
187
212
|
if (!navigator.onLine) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch-wrapper.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/fetch-wrapper.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAoB,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,UAAU,oBAAoB,CAAC,GAAqB;IACxD,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;IACpB,MAAM,EAAE,GAAG,GAAG,KAAK,IAAI,CAAC;IACxB,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACpD,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACtD,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACpD,MAAM,eAAe,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC;IAC5D,MAAM,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC;IACrD,MAAM,aAAa,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC;IAExD,MAAM,WAAW,GAAG;QAClB,eAAe;YACb,CAAC,CAAC,qDAAqD,GAAG,IAAI;YAC9D,CAAC,CAAC,EAAE;QACN,eAAe,CAAC,CAAC,CAAC,6CAA6C,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE;QAC3E,WAAW;YACT,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"fetch-wrapper.js","sourceRoot":"","sources":["../../../../src/lib/generators/file-generators/fetch-wrapper.ts"],"names":[],"mappings":"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"}
|