@swoff/cli 0.0.2 → 0.2.0

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.
Files changed (100) hide show
  1. package/README.md +49 -0
  2. package/bin/swoff +0 -0
  3. package/dist/__tests__/assemble-sw.test.js +145 -0
  4. package/dist/__tests__/assemble-sw.test.js.map +1 -0
  5. package/dist/__tests__/cli-integration.test.js +128 -0
  6. package/dist/__tests__/cli-integration.test.js.map +1 -0
  7. package/dist/__tests__/config-types.test.js +82 -0
  8. package/dist/__tests__/config-types.test.js.map +1 -0
  9. package/dist/__tests__/detect-language.test.js +51 -0
  10. package/dist/__tests__/detect-language.test.js.map +1 -0
  11. package/dist/__tests__/file-generators.test.js +271 -0
  12. package/dist/__tests__/file-generators.test.js.map +1 -0
  13. package/dist/__tests__/invalidation-tags.test.js +99 -0
  14. package/dist/__tests__/invalidation-tags.test.js.map +1 -0
  15. package/dist/__tests__/loader.test.js +77 -0
  16. package/dist/__tests__/loader.test.js.map +1 -0
  17. package/dist/__tests__/validator.test.js +232 -0
  18. package/dist/__tests__/validator.test.js.map +1 -0
  19. package/dist/index.js +36 -348
  20. package/dist/index.js.map +1 -1
  21. package/dist/lib/cli/colors.js +14 -0
  22. package/dist/lib/cli/colors.js.map +1 -0
  23. package/dist/lib/cli/help.js +63 -0
  24. package/dist/lib/cli/help.js.map +1 -0
  25. package/dist/lib/cli/logger.js +13 -0
  26. package/dist/lib/cli/logger.js.map +1 -0
  27. package/dist/lib/commands/add.js +58 -0
  28. package/dist/lib/commands/add.js.map +1 -0
  29. package/dist/lib/commands/clean.js +39 -0
  30. package/dist/lib/commands/clean.js.map +1 -0
  31. package/dist/lib/commands/generate.js +84 -0
  32. package/dist/lib/commands/generate.js.map +1 -0
  33. package/dist/lib/commands/info.js +44 -0
  34. package/dist/lib/commands/info.js.map +1 -0
  35. package/dist/lib/commands/init.js +46 -0
  36. package/dist/lib/commands/init.js.map +1 -0
  37. package/dist/lib/commands/validate.js +30 -0
  38. package/dist/lib/commands/validate.js.map +1 -0
  39. package/dist/lib/config/loader.js +80 -0
  40. package/dist/lib/config/loader.js.map +1 -0
  41. package/dist/lib/config/validator.js +102 -0
  42. package/dist/lib/config/validator.js.map +1 -0
  43. package/dist/lib/generators/file-generators/background-sync.js +59 -0
  44. package/dist/lib/generators/file-generators/background-sync.js.map +1 -0
  45. package/dist/lib/generators/file-generators/cache.js +55 -0
  46. package/dist/lib/generators/file-generators/cache.js.map +1 -0
  47. package/dist/lib/generators/file-generators/context.js +16 -0
  48. package/dist/lib/generators/file-generators/context.js.map +1 -0
  49. package/dist/lib/generators/file-generators/fetch-wrapper.js +80 -0
  50. package/dist/lib/generators/file-generators/fetch-wrapper.js.map +1 -0
  51. package/dist/lib/generators/file-generators/indexeddb.js +73 -0
  52. package/dist/lib/generators/file-generators/indexeddb.js.map +1 -0
  53. package/dist/lib/generators/file-generators/invalidation-tags.js +91 -0
  54. package/dist/lib/generators/file-generators/invalidation-tags.js.map +1 -0
  55. package/dist/lib/generators/file-generators/manifest.js +26 -0
  56. package/dist/lib/generators/file-generators/manifest.js.map +1 -0
  57. package/dist/lib/generators/file-generators/mutation-queue.js +226 -0
  58. package/dist/lib/generators/file-generators/mutation-queue.js.map +1 -0
  59. package/dist/lib/generators/file-generators/pwa-install.js +102 -0
  60. package/dist/lib/generators/file-generators/pwa-install.js.map +1 -0
  61. package/dist/lib/generators/file-generators/reconcile.js +54 -0
  62. package/dist/lib/generators/file-generators/reconcile.js.map +1 -0
  63. package/dist/lib/generators/file-generators/store.js +75 -0
  64. package/dist/lib/generators/file-generators/store.js.map +1 -0
  65. package/dist/lib/generators/file-generators/sw-generator-build.js +70 -0
  66. package/dist/lib/generators/file-generators/sw-generator-build.js.map +1 -0
  67. package/dist/lib/generators/file-generators/sw-injector.js +195 -0
  68. package/dist/lib/generators/file-generators/sw-injector.js.map +1 -0
  69. package/dist/lib/generators/file-generators/sw-template.js +143 -0
  70. package/dist/lib/generators/file-generators/sw-template.js.map +1 -0
  71. package/dist/lib/generators/file-generators/type-definitions.js +69 -0
  72. package/dist/lib/generators/file-generators/type-definitions.js.map +1 -0
  73. package/dist/lib/generators/sw-generator.js +37 -239
  74. package/dist/lib/generators/sw-generator.js.map +1 -1
  75. package/dist/lib/generators/sw-sections/activate-handler.js +16 -0
  76. package/dist/lib/generators/sw-sections/activate-handler.js.map +1 -0
  77. package/dist/lib/generators/sw-sections/assemble-sw.js +38 -0
  78. package/dist/lib/generators/sw-sections/assemble-sw.js.map +1 -0
  79. package/dist/lib/generators/sw-sections/background-sync-handler.js +106 -0
  80. package/dist/lib/generators/sw-sections/background-sync-handler.js.map +1 -0
  81. package/dist/lib/generators/sw-sections/config-header.js +15 -0
  82. package/dist/lib/generators/sw-sections/config-header.js.map +1 -0
  83. package/dist/lib/generators/sw-sections/default-template.js +51 -0
  84. package/dist/lib/generators/sw-sections/default-template.js.map +1 -0
  85. package/dist/lib/generators/sw-sections/fetch-handler.js +210 -0
  86. package/dist/lib/generators/sw-sections/fetch-handler.js.map +1 -0
  87. package/dist/lib/generators/sw-sections/install-handler.js +35 -0
  88. package/dist/lib/generators/sw-sections/install-handler.js.map +1 -0
  89. package/dist/lib/generators/sw-sections/message-handler.js +20 -0
  90. package/dist/lib/generators/sw-sections/message-handler.js.map +1 -0
  91. package/dist/lib/generators/sw-sections/tag-management.js +69 -0
  92. package/dist/lib/generators/sw-sections/tag-management.js.map +1 -0
  93. package/dist/lib/generators/swoff-files-generator.js +80 -1043
  94. package/dist/lib/generators/swoff-files-generator.js.map +1 -1
  95. package/dist/lib/shared/config-types.js +87 -0
  96. package/dist/lib/shared/config-types.js.map +1 -0
  97. package/dist/lib/utils/detect-language.js +33 -0
  98. package/dist/lib/utils/detect-language.js.map +1 -0
  99. package/package.json +6 -2
  100. package/src/lib/templates/sw-template.js +23 -6
@@ -2,53 +2,30 @@
2
2
  * Swoff Service Worker Generator
3
3
  *
4
4
  * Generates a service worker based on swoff.config.json configuration.
5
- * Can be run as CLI or imported as a module.
5
+ * Thin orchestrator - delegates to sw-sections for code generation.
6
6
  *
7
7
  * CLI Usage:
8
- * node sw-generator.js [--project-root <path>] [--package-dir <path>]
8
+ * node sw-generator.js [--project-root <path>] [--package-dir <path>] [--config-path <path>]
9
9
  *
10
10
  * Module Usage:
11
- * import { generate } from './sw-generator.js';
12
- * generate({ projectRoot: '/path/to/project' });
11
+ * import { generateSW } from './sw-generator.js';
12
+ * await generateSW({ projectRoot: '/path/to/project', onStatus: (msg) => {...} });
13
13
  */
14
14
  import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
15
+ import { join } from "path";
15
16
  import { fileURLToPath } from "url";
16
- import { join, dirname } from "path";
17
+ import { loadConfig } from "../config/loader.js";
18
+ import { assembleSW } from "./sw-sections/assemble-sw.js";
17
19
  const args = process.argv.slice(2);
18
20
  const projectRootArg = args.findIndex((arg) => arg === "--project-root");
19
- const packageDirArg = args.findIndex((arg) => arg === "--package-dir");
21
+ const configPathArg = args.findIndex((arg) => arg === "--config-path");
20
22
  const passedProjectRoot = projectRootArg !== -1 ? args[projectRootArg + 1] : null;
21
- const passedPackageDir = packageDirArg !== -1 ? args[packageDirArg + 1] : null;
22
- const scriptDir = dirname(fileURLToPath(import.meta.url));
23
- const packageDir = passedPackageDir || join(scriptDir, "..");
23
+ const passedConfigPath = configPathArg !== -1 ? args[configPathArg + 1] : null;
24
24
  const projectRoot = passedProjectRoot || process.cwd();
25
- const defaultConfig = {
26
- enabled: true,
27
- version: "from-package",
28
- minSupportedVersion: "0.0.0",
29
- serviceWorker: {
30
- autoUpdate: false,
31
- defaultStrategy: "cache-first",
32
- strategies: {},
33
- },
34
- features: {
35
- versionedSw: true,
36
- offlineReads: true,
37
- mutationQueue: false,
38
- backgroundSync: false,
39
- pwa: true,
40
- auth: false,
41
- crossTabSync: true,
42
- tagInvalidation: true,
43
- },
44
- build: {
45
- outputDir: "dist",
46
- swFilename: "sw",
47
- },
48
- };
49
- export async function generate(options = {}) {
25
+ export async function generateSW(options = {}) {
50
26
  const optProjectRoot = options.projectRoot || projectRoot;
51
- const optPackageDir = options.packageDir || packageDir;
27
+ const optConfigPath = options.configPath || passedConfigPath || undefined;
28
+ const status = options.onStatus || console.log;
52
29
  const pkgPath = join(optProjectRoot, "package.json");
53
30
  let pkg = { version: "1.0.0" };
54
31
  if (existsSync(pkgPath)) {
@@ -56,232 +33,53 @@ export async function generate(options = {}) {
56
33
  pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
57
34
  }
58
35
  catch {
59
- console.warn("Could not read package.json, using default version");
36
+ status("Could not read package.json, using default version");
60
37
  }
61
38
  }
62
- const templatePath = join(optPackageDir, "src/lib/templates/sw-template.js");
63
- let template;
64
- if (existsSync(templatePath)) {
65
- template = readFileSync(templatePath, "utf8");
66
- }
67
- else {
68
- template = getDefaultTemplate();
69
- }
70
- let userConfig = {};
71
- let configSource = "defaults";
72
- const configPath = join(optProjectRoot, "swoff.config.json");
73
- if (existsSync(configPath)) {
74
- try {
75
- userConfig = JSON.parse(readFileSync(configPath, "utf8"));
76
- configSource = "JSON";
77
- }
78
- catch {
79
- console.warn("Could not parse swoff.config.json, using defaults");
80
- }
81
- }
82
- else {
83
- const jsConfigPath = join(optProjectRoot, "swoff.config.js");
84
- if (existsSync(jsConfigPath)) {
85
- try {
86
- const mod = await import(jsConfigPath);
87
- userConfig = (mod.default || mod);
88
- configSource = "JavaScript";
89
- }
90
- catch {
91
- console.warn("Could not load swoff.config.js, using defaults");
92
- }
93
- }
94
- }
95
- const config = { ...defaultConfig, ...userConfig };
39
+ const { config, configSource } = loadConfig(optProjectRoot, optConfigPath);
96
40
  if (!config.enabled) {
97
- console.log("Swoff config generation disabled. Using custom code mode.");
98
- return;
41
+ status("Swoff config generation disabled. Using custom code mode.");
42
+ return { version: "", outputFile: "" };
99
43
  }
100
44
  const version = config.version === "from-package" ? pkg.version || "1.0.0" : config.version;
101
- const sw = generateServiceWorker(config, version);
45
+ const sw = assembleSW(config, version);
102
46
  const outputDir = join(optProjectRoot, config.build.outputDir);
103
47
  const swFilename = config.build.swFilename;
104
48
  if (!existsSync(outputDir)) {
105
49
  mkdirSync(outputDir, { recursive: true });
106
50
  }
51
+ const outputFile = `${swFilename}-v${version}.js`;
107
52
  try {
108
- writeFileSync(join(outputDir, `${swFilename}-v${version}.js`), sw);
53
+ writeFileSync(join(outputDir, outputFile), sw);
109
54
  writeFileSync(join(outputDir, "version.json"), JSON.stringify({
110
- version: version,
55
+ version,
111
56
  minSupportedVersion: config.minSupportedVersion,
112
57
  generatedAt: new Date().toISOString(),
113
58
  configEnabled: config.enabled,
114
- configSource: configSource,
59
+ configSource,
115
60
  }, null, 2));
116
- console.log(`✅ Swoff service worker generated successfully!`);
117
- console.log(`📁 Output: ${outputDir}/${swFilename}-v${version}.js`);
118
- console.log(`📄 Version info: ${outputDir}/version.json`);
119
- console.log(`ℹ️ Configuration source: ${configSource}`);
61
+ status(`✓ ${outputDir}/${outputFile}`);
120
62
  }
121
63
  catch (err) {
122
- console.error(`Error writing files: ${err instanceof Error ? err.message : String(err)}`);
123
- console.log("Make sure the output directory exists:");
124
- console.log(` mkdir -p ${outputDir}`);
64
+ status(`Error writing files: ${err instanceof Error ? err.message : String(err)}`);
125
65
  }
66
+ return { version, outputFile };
126
67
  }
127
- function generateServiceWorker(config, version) {
128
- const { serviceWorker, features } = config;
129
- const baseAssets = ["/", "/index.html"];
130
- const pwaAssets = features.pwa ? ["/manifest.json"] : [];
131
- const assetsToCache = [...baseAssets, ...pwaAssets];
132
- let sw = getDefaultTemplate();
133
- sw = sw.replace("// [[CACHE_NAME]]", `CACHE_NAME = 'sw-v${version}'`);
134
- sw = sw.replace("// [[ASSETS_LIST]]", `ASSETS_TO_CACHE = ${JSON.stringify(assetsToCache, null, 2)}`);
135
- sw = sw.replace("// [[FETCH_HANDLER]]", generateFetchHandler(serviceWorker, features));
136
- sw = sw.replace("// [[ACTIVATE_HANDLER]]", generateActivateHandler(features.versionedSw));
137
- sw = sw.replace("// [[INSTALL_HANDLER]]", generateInstallHandler(features));
138
- sw = `// [[CONFIG_HEADER]]\n\n${sw}`;
139
- sw = sw.replace("// [[CONFIG_HEADER]]", generateConfigHeader(config));
140
- return sw;
141
- }
142
- function generateFetchHandler(swConfig, features) {
143
- const { defaultStrategy, strategies } = swConfig;
144
- return `
145
- self.addEventListener("fetch", (event) => {
146
- if (event.request.method !== "GET") return;
147
-
148
- const strategy = determineCacheStrategy(event.request.url, ${JSON.stringify(strategies || {})}, "${defaultStrategy}");
149
-
150
- event.respondWith(handleRequestWithStrategy(event.request, strategy));
151
- });
152
-
153
- function determineCacheStrategy(url, customStrategies, defaultStrategy) {
154
- for (const [pattern, strategy] of Object.entries(customStrategies)) {
155
- if (url.includes(pattern)) return strategy;
156
- }
157
- return defaultStrategy;
158
- }
159
-
160
- async function handleRequestWithStrategy(request, strategy) {
161
- const cache = await caches.open(CACHE_NAME);
162
-
163
- switch (strategy) {
164
- case "cache-first": return cacheFirstStrategy(request, cache);
165
- case "network-first": return networkFirstStrategy(request, cache);
166
- case "stale-while-revalidate": return staleWhileRevalidateStrategy(request, cache);
167
- case "cache-only": return cacheOnlyStrategy(request, cache);
168
- case "network-only": return networkOnlyStrategy(request, cache);
169
- default: return cacheFirstStrategy(request, cache);
170
- }
171
- }
172
-
173
- async function cacheFirstStrategy(request, cache) {
174
- const cached = await cache.match(request);
175
- if (cached) return cached;
176
- try {
177
- const response = await fetch(request);
178
- if (response.ok) await cache.put(request, response.clone());
179
- return response;
180
- } catch {
181
- return new Response("Offline", { status: 503 });
182
- }
183
- }
184
-
185
- async function networkFirstStrategy(request, cache) {
186
- try {
187
- const response = await fetch(request);
188
- if (response.ok) await cache.put(request, response.clone());
189
- return response;
190
- } catch {
191
- const cached = await cache.match(request);
192
- return cached || new Response("Offline", { status: 503 });
193
- }
194
- }
195
-
196
- async function staleWhileRevalidateStrategy(request, cache) {
197
- const cached = await cache.match(request);
198
- fetch(request).then((response) => {
199
- if (response.ok) cache.put(request, response.clone());
200
- });
201
- return cached || fetch(request);
202
- }
203
-
204
- async function cacheOnlyStrategy(request, cache) {
205
- return (await cache.match(request)) || new Response("Not in cache", { status: 404 });
206
- }
207
-
208
- async function networkOnlyStrategy(request, _cache) {
209
- try {
210
- return await fetch(request);
211
- } catch {
212
- return new Response("Network error", { status: 503 });
213
- }
214
- }`;
215
- }
216
- function generateActivateHandler(versionedSw) {
217
- if (versionedSw) {
218
- return `
219
- self.addEventListener("activate", (event) => {
220
- event.waitUntil(
221
- caches.keys().then((keys) =>
222
- Promise.all(keys.filter((k) => k !== CACHE_NAME).map((k) => caches.delete(k)))
223
- )
224
- );
225
- });`;
226
- }
227
- return `
228
- self.addEventListener("activate", (event) => {
229
- event.waitUntil(Promise.resolve());
230
- });`;
231
- }
232
- function generateInstallHandler(features) {
233
- let code = `
234
- self.addEventListener("install", (event) => {
235
- event.waitUntil(
236
- caches.open(CACHE_NAME).then((cache) => cache.addAll(ASSETS_TO_CACHE))
237
- );
238
- }`;
239
- if (features.offlineReads || features.mutationQueue) {
240
- code += `\n event.waitUntil(initializeOfflineSupport());`;
241
- }
242
- return code;
243
- }
244
- function generateConfigHeader(config) {
245
- return `/**
246
- * Swoff Service Worker - Auto-Generated
247
- * Generated from swoff.config.json
248
- * DO NOT EDIT MANUALLY
249
- * Version: ${config.version}
250
- * Features: versionedSw=${config.features.versionedSw}, offlineReads=${config.features.offlineReads}, mutationQueue=${config.features.mutationQueue}
251
- * Default Strategy: ${config.serviceWorker.defaultStrategy}
252
- * See: https://swoff.netlify.app/docs
253
- */`;
254
- }
255
- function getDefaultTemplate() {
256
- return `let CACHE_NAME = "";
257
- let ASSETS_TO_CACHE = [];
258
-
259
- // [[INSTALL_HANDLER]]
260
- // [[ACTIVATE_HANDLER]]
261
- // [[FETCH_HANDLER]]
262
-
263
- const SWOFF = {
264
- cache: {
265
- async get(key) {
266
- const cache = await caches.open(CACHE_NAME);
267
- return cache.match(key);
268
- },
269
- async put(request, response) {
270
- const cache = await caches.open(CACHE_NAME);
271
- await cache.put(request, response);
272
- }
273
- }
274
- };
275
-
276
- if (typeof self !== 'undefined') {
277
- self.SWOFF = SWOFF;
278
- }`;
279
- }
280
- if (import.meta.url === `file://${process.argv[1]}`) {
281
- generate().catch((err) => {
68
+ if (fileURLToPath(import.meta.url) === fileURLToPath(new URL(process.argv[1], "file:"))) {
69
+ (async () => {
70
+ const ttyStatus = process.stdout.isTTY
71
+ ? (msg) => {
72
+ const cols = process.stdout.columns || 80;
73
+ process.stdout.write(`\r${" ".repeat(cols - 1)}\r ${msg}`);
74
+ }
75
+ : (msg) => console.log(` ${msg}`);
76
+ console.log("Generating service worker...");
77
+ await generateSW({ onStatus: ttyStatus });
78
+ process.stdout.write("\n");
79
+ })().catch((err) => {
282
80
  console.error(err);
283
81
  process.exit(1);
284
82
  });
285
83
  }
286
- export default { generate };
84
+ export default { generateSW };
287
85
  //# sourceMappingURL=sw-generator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sw-generator.js","sourceRoot":"","sources":["../../../src/lib/generators/sw-generator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sw-generator.js","sourceRoot":"","sources":["../../../src/lib/generators/sw-generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Generates the SW activate event handler (old cache cleanup).
3
+ */
4
+ export function generateActivateHandler() {
5
+ return `
6
+ self.addEventListener("activate", (event) => {
7
+ event.waitUntil(
8
+ caches.keys().then((keys) =>
9
+ Promise.all(
10
+ keys.filter((key) => key !== CACHE_NAME && key !== CACHE_NAME_RUNTIME).map((key) => caches.delete(key))
11
+ )
12
+ )
13
+ );
14
+ });`;
15
+ }
16
+ //# sourceMappingURL=activate-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activate-handler.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/activate-handler.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,uBAAuB;IACrC,OAAO;;;;;;;;;IASL,CAAC;AACL,CAAC"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Assembles the complete service worker string from config and version.
3
+ * Calls individual section generators and performs placeholder replacement.
4
+ */
5
+ import { getDefaultTemplate } from "./default-template.js";
6
+ import { generateConfigHeader } from "./config-header.js";
7
+ import { generateInstallHandler } from "./install-handler.js";
8
+ import { generateActivateHandler } from "./activate-handler.js";
9
+ import { generateMessageHandler } from "./message-handler.js";
10
+ import { generateFetchHandler } from "./fetch-handler.js";
11
+ import { generateTagManagement } from "./tag-management.js";
12
+ import { generateBackgroundSyncHandler } from "./background-sync-handler.js";
13
+ export function assembleSW(config, version) {
14
+ const { serviceWorker, features } = config;
15
+ const baseAssets = ["/", "/index.html"];
16
+ const pwaAssets = features.pwa ? ["/manifest.json"] : [];
17
+ const assetsToCache = [...baseAssets, ...pwaAssets];
18
+ let sw = getDefaultTemplate();
19
+ sw = sw.replace("// [[CACHE_NAME]]", `CACHE_NAME = 'sw-v${version}'`);
20
+ sw = sw.replace("// [[ASSETS_LIST]]", `ASSETS_TO_CACHE = ${JSON.stringify(assetsToCache.map((url) => ({ url, options: {} })), null, 2)}`);
21
+ sw = sw.replace("// [[AUTO_SKIP_WAITING]]", `const AUTO_SKIP_WAITING = ${config.serviceWorker.autoUpdate};`);
22
+ sw = sw.replace("// [[FETCH_HANDLER]]", generateFetchHandler(serviceWorker, features.tagInvalidation));
23
+ sw = sw.replace("// [[ACTIVATE_HANDLER]]", generateActivateHandler());
24
+ sw = sw.replace("// [[INSTALL_HANDLER]]", generateInstallHandler());
25
+ sw = sw.replace("// [[MESSAGE_HANDLER]]", generateMessageHandler(features.tagInvalidation));
26
+ if (features.tagInvalidation) {
27
+ sw = sw.replace("// [[TAG_MANAGEMENT]]", generateTagManagement());
28
+ }
29
+ else {
30
+ sw = sw.replace("// [[TAG_MANAGEMENT]]", "");
31
+ }
32
+ sw = `${generateConfigHeader(config, version)}\n\n${sw}`;
33
+ if (features.backgroundSync) {
34
+ sw += `\n\n${generateBackgroundSyncHandler()}`;
35
+ }
36
+ return sw;
37
+ }
38
+ //# sourceMappingURL=assemble-sw.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assemble-sw.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/assemble-sw.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,6BAA6B,EAAE,MAAM,8BAA8B,CAAC;AAE7E,MAAM,UAAU,UAAU,CAAC,MAAmB,EAAE,OAAe;IAC7D,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC;IAE3C,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;IACxC,MAAM,SAAS,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACzD,MAAM,aAAa,GAAG,CAAC,GAAG,UAAU,EAAE,GAAG,SAAS,CAAC,CAAC;IAEpD,IAAI,EAAE,GAAG,kBAAkB,EAAE,CAAC;IAE9B,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,mBAAmB,EAAE,qBAAqB,OAAO,GAAG,CAAC,CAAC;IACtE,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,oBAAoB,EAAE,qBAAqB,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IAC1I,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,0BAA0B,EAAE,6BAA6B,MAAM,CAAC,aAAa,CAAC,UAAU,GAAG,CAAC,CAAC;IAE7G,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,sBAAsB,EAAE,oBAAoB,CAAC,aAAa,EAAE,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC;IACvG,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,yBAAyB,EAAE,uBAAuB,EAAE,CAAC,CAAC;IACtE,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,wBAAwB,EAAE,sBAAsB,EAAE,CAAC,CAAC;IACpE,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,wBAAwB,EAAE,sBAAsB,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC;IAE5F,IAAI,QAAQ,CAAC,eAAe,EAAE,CAAC;QAC7B,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,uBAAuB,EAAE,qBAAqB,EAAE,CAAC,CAAC;IACpE,CAAC;SAAM,CAAC;QACN,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,EAAE,GAAG,GAAG,oBAAoB,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;IAEzD,IAAI,QAAQ,CAAC,cAAc,EAAE,CAAC;QAC5B,EAAE,IAAI,OAAO,6BAA6B,EAAE,EAAE,CAAC;IACjD,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Generates Background Sync event handler for the SW.
3
+ * Processes mutation queue when browser sync fires.
4
+ */
5
+ export function generateBackgroundSyncHandler() {
6
+ return `
7
+ self.addEventListener("sync", (event) => {
8
+ if (event.tag === "sync-mutations") {
9
+ event.waitUntil(processMutationQueueInSW());
10
+ }
11
+ });
12
+
13
+ async function processMutationQueueInSW() {
14
+ const SW_DB_NAME = "swoff-queue";
15
+ const SW_STORE_NAME = "mutations";
16
+ const SW_MAX_RETRIES = 5;
17
+
18
+ let succeeded = 0;
19
+ let failed = 0;
20
+ const tagsToInvalidate = new Set();
21
+
22
+ try {
23
+ const db = await new Promise((resolve, reject) => {
24
+ const request = indexedDB.open(SW_DB_NAME, 1);
25
+ request.onupgradeneeded = (e) => {
26
+ const db = e.target.result;
27
+ if (!db.objectStoreNames.contains(SW_STORE_NAME)) {
28
+ const store = db.createObjectStore(SW_STORE_NAME, { keyPath: "id" });
29
+ store.createIndex("by-timestamp", "timestamp");
30
+ }
31
+ };
32
+ request.onsuccess = (e) => resolve(e.target.result);
33
+ request.onerror = (e) => reject(e.target.error);
34
+ });
35
+
36
+ const tx = db.transaction(SW_STORE_NAME, "readonly");
37
+ const store = tx.objectStore(SW_STORE_NAME);
38
+ const index = store.index("by-timestamp");
39
+ const queue = await new Promise((resolve, reject) => {
40
+ const request = index.getAll();
41
+ request.onsuccess = () => resolve(request.result);
42
+ request.onerror = () => reject(request.error);
43
+ });
44
+
45
+ for (const item of queue) {
46
+ if (item.retryCount >= SW_MAX_RETRIES) {
47
+ await removeFromSWQueue(db, item.id);
48
+ failed++;
49
+ continue;
50
+ }
51
+ try {
52
+ const response = await fetch(item.url, {
53
+ method: item.method,
54
+ headers: { "Content-Type": "application/json", ...item.headers },
55
+ body: JSON.stringify(item.body),
56
+ });
57
+ if (!response.ok) throw new Error(\`HTTP \${response.status}\`);
58
+
59
+ if (item.tags) {
60
+ item.tags.forEach((tag) => tagsToInvalidate.add(tag));
61
+ }
62
+
63
+ await removeFromSWQueue(db, item.id);
64
+ succeeded++;
65
+ } catch {
66
+ item.retryCount++;
67
+ await updateInSWQueue(db, item);
68
+ failed++;
69
+ }
70
+ }
71
+ } catch (err) {
72
+ console.error("Background sync failed:", err);
73
+ }
74
+
75
+ for (const tag of tagsToInvalidate) {
76
+ await invalidateByTag(tag);
77
+ }
78
+
79
+ const clients = await self.clients.matchAll();
80
+ for (const client of clients) {
81
+ client.postMessage({
82
+ type: "BACKGROUND_SYNC_COMPLETE",
83
+ detail: { succeeded, failed, tags: [...tagsToInvalidate] },
84
+ });
85
+ }
86
+ }
87
+
88
+ async function removeFromSWQueue(db, id) {
89
+ const tx = db.transaction(SW_STORE_NAME, "readwrite");
90
+ tx.objectStore(SW_STORE_NAME).delete(id);
91
+ await new Promise((resolve, reject) => {
92
+ tx.oncomplete = () => resolve();
93
+ tx.onerror = () => reject(tx.error);
94
+ });
95
+ }
96
+
97
+ async function updateInSWQueue(db, item) {
98
+ const tx = db.transaction(SW_STORE_NAME, "readwrite");
99
+ tx.objectStore(SW_STORE_NAME).put(item);
100
+ await new Promise((resolve, reject) => {
101
+ tx.oncomplete = () => resolve();
102
+ tx.onerror = () => reject(tx.error);
103
+ });
104
+ }`;
105
+ }
106
+ //# sourceMappingURL=background-sync-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"background-sync-handler.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/background-sync-handler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,UAAU,6BAA6B;IAC3C,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkGP,CAAC;AACH,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Generates the SW file header comment with config metadata.
3
+ */
4
+ export function generateConfigHeader(config, resolvedVersion) {
5
+ return `/**
6
+ * Swoff Service Worker - Auto-Generated
7
+ * Generated from swoff.config.json
8
+ * DO NOT EDIT MANUALLY
9
+ * Version: ${resolvedVersion}
10
+ * Features: versionedSw=${config.features.versionedSw}, offlineReads=${config.features.offlineReads}, mutationQueue=${config.features.mutationQueue}, backgroundSync=${config.features.backgroundSync}, tagInvalidation=${config.features.tagInvalidation}
11
+ * Default Strategy: ${config.serviceWorker.defaultStrategy}
12
+ * See: https://swoff.netlify.app/docs
13
+ */`;
14
+ }
15
+ //# sourceMappingURL=config-header.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-header.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/config-header.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,UAAU,oBAAoB,CAAC,MAAmB,EAAE,eAAuB;IAC/E,OAAO;;;;cAIK,eAAe;2BACF,MAAM,CAAC,QAAQ,CAAC,WAAW,kBAAkB,MAAM,CAAC,QAAQ,CAAC,YAAY,mBAAmB,MAAM,CAAC,QAAQ,CAAC,aAAa,oBAAoB,MAAM,CAAC,QAAQ,CAAC,cAAc,qBAAqB,MAAM,CAAC,QAAQ,CAAC,eAAe;uBACnO,MAAM,CAAC,aAAa,CAAC,eAAe;;IAEvD,CAAC;AACL,CAAC"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Default SW template with placeholder markers.
3
+ * Placeholders are replaced during generation with feature-specific code.
4
+ */
5
+ export function getDefaultTemplate() {
6
+ return `let CACHE_NAME = "";
7
+ let ASSETS_TO_CACHE = [];
8
+
9
+ // [[CACHE_NAME]]
10
+ // [[ASSETS_LIST]]
11
+ // [[AUTO_SKIP_WAITING]]
12
+
13
+ const CACHE_NAME_RUNTIME = "swoff-runtime";
14
+
15
+ // [[INSTALL_HANDLER]]
16
+ // [[ACTIVATE_HANDLER]]
17
+ // [[MESSAGE_HANDLER]]
18
+ // [[FETCH_HANDLER]]
19
+ // [[TAG_MANAGEMENT]]
20
+
21
+ const SWOFF = {
22
+ cache: {
23
+ async get(key) {
24
+ const cache = await caches.open(CACHE_NAME);
25
+ return cache.match(key);
26
+ },
27
+ async put(request, response) {
28
+ const cache = await caches.open(CACHE_NAME);
29
+ await cache.put(request, response);
30
+ },
31
+ async delete(request) {
32
+ const cache = await caches.open(CACHE_NAME);
33
+ return cache.delete(request);
34
+ }
35
+ },
36
+ network: {
37
+ async fetch(request, options = {}) {
38
+ try {
39
+ return await fetch(request, options);
40
+ } catch (error) {
41
+ throw new Error(\`Network request failed: \${error.message}\`);
42
+ }
43
+ }
44
+ }
45
+ };
46
+
47
+ if (typeof self !== 'undefined') {
48
+ self.SWOFF = SWOFF;
49
+ }`;
50
+ }
51
+ //# sourceMappingURL=default-template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-template.js","sourceRoot":"","sources":["../../../../src/lib/generators/sw-sections/default-template.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,UAAU,kBAAkB;IAChC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2CP,CAAC;AACH,CAAC"}