@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.
Files changed (224) hide show
  1. package/README.md +28 -32
  2. package/dist/index.js +2 -13
  3. package/dist/index.js.map +1 -1
  4. package/dist/lib/cli/help.js +3 -8
  5. package/dist/lib/cli/help.js.map +1 -1
  6. package/dist/lib/commands/add.js +29 -87
  7. package/dist/lib/commands/add.js.map +1 -1
  8. package/dist/lib/commands/generate-guide.js +16 -30
  9. package/dist/lib/commands/generate-guide.js.map +1 -1
  10. package/dist/lib/commands/generate.js +31 -6
  11. package/dist/lib/commands/generate.js.map +1 -1
  12. package/dist/lib/commands/init.js +188 -11
  13. package/dist/lib/commands/init.js.map +1 -1
  14. package/dist/lib/commands/validate.js +2 -4
  15. package/dist/lib/commands/validate.js.map +1 -1
  16. package/dist/lib/config/loader.js +34 -25
  17. package/dist/lib/config/loader.js.map +1 -1
  18. package/dist/lib/config/validator.js +202 -96
  19. package/dist/lib/config/validator.js.map +1 -1
  20. package/dist/lib/generators/file-generators/api-config.js +1 -1
  21. package/dist/lib/generators/file-generators/api-config.js.map +1 -1
  22. package/dist/lib/generators/file-generators/auth-adapter.js +13 -0
  23. package/dist/lib/generators/file-generators/auth-adapter.js.map +1 -0
  24. package/dist/lib/generators/file-generators/auth-check.js +40 -0
  25. package/dist/lib/generators/file-generators/auth-check.js.map +1 -0
  26. package/dist/lib/generators/file-generators/auth-store.js +2 -5
  27. package/dist/lib/generators/file-generators/auth-store.js.map +1 -1
  28. package/dist/lib/generators/file-generators/background-sync.js +1 -1
  29. package/dist/lib/generators/file-generators/background-sync.js.map +1 -1
  30. package/dist/lib/generators/file-generators/cache.js +2 -1
  31. package/dist/lib/generators/file-generators/cache.js.map +1 -1
  32. package/dist/lib/generators/file-generators/client-injector-bundle.js +15 -0
  33. package/dist/lib/generators/file-generators/client-injector-bundle.js.map +1 -0
  34. package/dist/lib/generators/file-generators/client-injector.js +2 -1
  35. package/dist/lib/generators/file-generators/client-injector.js.map +1 -1
  36. package/dist/lib/generators/file-generators/connectivity-manager.js +12 -0
  37. package/dist/lib/generators/file-generators/connectivity-manager.js.map +1 -0
  38. package/dist/lib/generators/file-generators/connectivity.js +12 -0
  39. package/dist/lib/generators/file-generators/connectivity.js.map +1 -0
  40. package/dist/lib/generators/file-generators/context.js +7 -0
  41. package/dist/lib/generators/file-generators/context.js.map +1 -1
  42. package/dist/lib/generators/file-generators/fetch-wrapper.js +1 -1
  43. package/dist/lib/generators/file-generators/fetch-wrapper.js.map +1 -1
  44. package/dist/lib/generators/file-generators/generate-framework-adapters.js +29 -20
  45. package/dist/lib/generators/file-generators/generate-framework-adapters.js.map +1 -1
  46. package/dist/lib/generators/file-generators/gql-wrapper.js +2 -2
  47. package/dist/lib/generators/file-generators/gql-wrapper.js.map +1 -1
  48. package/dist/lib/generators/file-generators/guide-generator.js +51 -1
  49. package/dist/lib/generators/file-generators/guide-generator.js.map +1 -1
  50. package/dist/lib/generators/file-generators/invalidation-tags.js +2 -3
  51. package/dist/lib/generators/file-generators/invalidation-tags.js.map +1 -1
  52. package/dist/lib/generators/file-generators/mutation-queue.js +2 -2
  53. package/dist/lib/generators/file-generators/mutation-queue.js.map +1 -1
  54. package/dist/lib/generators/file-generators/mutation-state.js +1 -1
  55. package/dist/lib/generators/file-generators/mutation-state.js.map +1 -1
  56. package/dist/lib/generators/file-generators/notification-generator.js +6 -0
  57. package/dist/lib/generators/file-generators/notification-generator.js.map +1 -0
  58. package/dist/lib/generators/file-generators/open-db.js +6 -0
  59. package/dist/lib/generators/file-generators/open-db.js.map +1 -0
  60. package/dist/lib/generators/file-generators/push.js +1 -2
  61. package/dist/lib/generators/file-generators/push.js.map +1 -1
  62. package/dist/lib/generators/file-generators/pwa-install.js +2 -6
  63. package/dist/lib/generators/file-generators/pwa-install.js.map +1 -1
  64. package/dist/lib/generators/file-generators/server-push.js +1 -1
  65. package/dist/lib/generators/file-generators/server-push.js.map +1 -1
  66. package/dist/lib/generators/file-generators/storage-generator.js +6 -0
  67. package/dist/lib/generators/file-generators/storage-generator.js.map +1 -0
  68. package/dist/lib/generators/file-generators/storage-notify.js +6 -0
  69. package/dist/lib/generators/file-generators/storage-notify.js.map +1 -0
  70. package/dist/lib/generators/file-generators/storage.js +6 -0
  71. package/dist/lib/generators/file-generators/storage.js.map +1 -0
  72. package/dist/lib/generators/file-generators/sw-generator-build.js +96 -45
  73. package/dist/lib/generators/file-generators/sw-generator-build.js.map +1 -1
  74. package/dist/lib/generators/file-generators/sw-injector.js +0 -4
  75. package/dist/lib/generators/file-generators/sw-injector.js.map +1 -1
  76. package/dist/lib/generators/file-generators/sw-template.js +8 -9
  77. package/dist/lib/generators/file-generators/sw-template.js.map +1 -1
  78. package/dist/lib/generators/file-generators/sw-version-gen.js +32 -0
  79. package/dist/lib/generators/file-generators/sw-version-gen.js.map +1 -0
  80. package/dist/lib/generators/file-generators/swoff-api-bundle.js +51 -0
  81. package/dist/lib/generators/file-generators/swoff-api-bundle.js.map +1 -0
  82. package/dist/lib/generators/sw-build-utils.js +69 -0
  83. package/dist/lib/generators/sw-build-utils.js.map +1 -0
  84. package/dist/lib/generators/sw-generator.js +23 -34
  85. package/dist/lib/generators/sw-generator.js.map +1 -1
  86. package/dist/lib/generators/sw-sections/activate-handler.js +74 -23
  87. package/dist/lib/generators/sw-sections/activate-handler.js.map +1 -1
  88. package/dist/lib/generators/sw-sections/assemble-sw.js +15 -94
  89. package/dist/lib/generators/sw-sections/assemble-sw.js.map +1 -1
  90. package/dist/lib/generators/sw-sections/background-sync-handler.js +74 -72
  91. package/dist/lib/generators/sw-sections/background-sync-handler.js.map +1 -1
  92. package/dist/lib/generators/sw-sections/batch-refresh-queue.js +102 -0
  93. package/dist/lib/generators/sw-sections/batch-refresh-queue.js.map +1 -0
  94. package/dist/lib/generators/sw-sections/config-header.js +2 -3
  95. package/dist/lib/generators/sw-sections/config-header.js.map +1 -1
  96. package/dist/lib/generators/sw-sections/default-template.js +59 -6
  97. package/dist/lib/generators/sw-sections/default-template.js.map +1 -1
  98. package/dist/lib/generators/sw-sections/fetch-handler.js +621 -495
  99. package/dist/lib/generators/sw-sections/fetch-handler.js.map +1 -1
  100. package/dist/lib/generators/sw-sections/install-handler.js +40 -23
  101. package/dist/lib/generators/sw-sections/install-handler.js.map +1 -1
  102. package/dist/lib/generators/sw-sections/message-handler.js +25 -8
  103. package/dist/lib/generators/sw-sections/message-handler.js.map +1 -1
  104. package/dist/lib/generators/sw-sections/server-push-handler.js +10 -14
  105. package/dist/lib/generators/sw-sections/server-push-handler.js.map +1 -1
  106. package/dist/lib/generators/sw-sections/shared.js +68 -0
  107. package/dist/lib/generators/sw-sections/shared.js.map +1 -0
  108. package/dist/lib/generators/sw-sections/sw-push.js +2 -6
  109. package/dist/lib/generators/sw-sections/sw-push.js.map +1 -1
  110. package/dist/lib/generators/sw-sections/tag-management.js +55 -86
  111. package/dist/lib/generators/sw-sections/tag-management.js.map +1 -1
  112. package/dist/lib/generators/swoff-files-generator.js +183 -59
  113. package/dist/lib/generators/swoff-files-generator.js.map +1 -1
  114. package/dist/lib/shared/config-types.js +67 -63
  115. package/dist/lib/shared/config-types.js.map +1 -1
  116. package/dist/lib/shared/feature-registry.js +198 -0
  117. package/dist/lib/shared/feature-registry.js.map +1 -0
  118. package/dist/lib/utils/detect-framework.js +52 -9
  119. package/dist/lib/utils/detect-framework.js.map +1 -1
  120. package/dist/runtime/api-config.js +2 -2
  121. package/dist/runtime/api-config.js.map +1 -1
  122. package/dist/runtime/auth-adapter.js +179 -0
  123. package/dist/runtime/auth-adapter.js.map +1 -0
  124. package/dist/runtime/auth-state.js +16 -6
  125. package/dist/runtime/auth-state.js.map +1 -1
  126. package/dist/runtime/auth-store.js +219 -213
  127. package/dist/runtime/auth-store.js.map +1 -1
  128. package/dist/runtime/auth-user.js +5 -19
  129. package/dist/runtime/auth-user.js.map +1 -1
  130. package/dist/runtime/background-sync.js +5 -2
  131. package/dist/runtime/background-sync.js.map +1 -1
  132. package/dist/runtime/cache.js +91 -3
  133. package/dist/runtime/cache.js.map +1 -1
  134. package/dist/runtime/client-injector-bundle.js +314 -0
  135. package/dist/runtime/client-injector-bundle.js.map +1 -0
  136. package/dist/runtime/client-injector.js +173 -30
  137. package/dist/runtime/client-injector.js.map +1 -1
  138. package/dist/runtime/connectivity-manager.js +83 -0
  139. package/dist/runtime/connectivity-manager.js.map +1 -0
  140. package/dist/runtime/connectivity.js +83 -0
  141. package/dist/runtime/connectivity.js.map +1 -0
  142. package/dist/runtime/fetch-wrapper.js +26 -59
  143. package/dist/runtime/fetch-wrapper.js.map +1 -1
  144. package/dist/runtime/gql-wrapper.js +15 -9
  145. package/dist/runtime/gql-wrapper.js.map +1 -1
  146. package/dist/runtime/invalidation-tags.js +12 -89
  147. package/dist/runtime/invalidation-tags.js.map +1 -1
  148. package/dist/runtime/mutation-queue.js +83 -31
  149. package/dist/runtime/mutation-queue.js.map +1 -1
  150. package/dist/runtime/mutation-state.js +3 -3
  151. package/dist/runtime/mutation-state.js.map +1 -1
  152. package/dist/runtime/notification.js +65 -0
  153. package/dist/runtime/notification.js.map +1 -0
  154. package/dist/runtime/open-db.js +41 -0
  155. package/dist/runtime/open-db.js.map +1 -0
  156. package/dist/runtime/push.js +15 -27
  157. package/dist/runtime/push.js.map +1 -1
  158. package/dist/runtime/pwa-injector.js +3 -32
  159. package/dist/runtime/pwa-injector.js.map +1 -1
  160. package/dist/runtime/pwa-prompt.js +35 -3
  161. package/dist/runtime/pwa-prompt.js.map +1 -1
  162. package/dist/runtime/reset.js +39 -42
  163. package/dist/runtime/reset.js.map +1 -1
  164. package/dist/runtime/server-push.js +23 -13
  165. package/dist/runtime/server-push.js.map +1 -1
  166. package/dist/runtime/storage.js +32 -0
  167. package/dist/runtime/storage.js.map +1 -0
  168. package/dist/runtime/sw-injector.js +19 -178
  169. package/dist/runtime/sw-injector.js.map +1 -1
  170. package/dist/runtime/sw-version.js +13 -0
  171. package/dist/runtime/sw-version.js.map +1 -0
  172. package/dist/runtime/swoff-api-bundle.js +1491 -0
  173. package/dist/runtime/swoff-api-bundle.js.map +1 -0
  174. package/dist/runtime/type-definitions.js +8 -7
  175. package/dist/runtime/type-definitions.js.map +1 -1
  176. package/dist/runtime/utils.js +4 -0
  177. package/dist/runtime/utils.js.map +1 -1
  178. package/dist/swoff-nkdhhmw8. +18 -0
  179. package/dist/swoff.js +5 -0
  180. package/package.json +1 -1
  181. package/templates/react/useAuth.jsx +7 -4
  182. package/templates/react/useAuth.tsx +14 -14
  183. package/templates/react/useBackgroundSync.jsx +5 -4
  184. package/templates/react/useBackgroundSync.tsx +5 -4
  185. package/templates/react/useCachedFetch.jsx +8 -0
  186. package/templates/react/useCachedFetch.tsx +8 -0
  187. package/templates/react/useMutation.jsx +60 -56
  188. package/templates/react/useMutation.tsx +65 -64
  189. package/templates/react/useMutationQueue.jsx +5 -1
  190. package/templates/react/useMutationQueue.tsx +8 -2
  191. package/templates/react/useMutationState.jsx +3 -4
  192. package/templates/react/useMutationState.tsx +4 -8
  193. package/templates/react/useNetworkStatus.jsx +57 -17
  194. package/templates/react/useNetworkStatus.tsx +42 -20
  195. package/templates/react/useOfflineAnalytics.jsx +42 -0
  196. package/templates/react/useOfflineAnalytics.tsx +50 -0
  197. package/templates/react/usePwaInstall.jsx +26 -0
  198. package/templates/react/usePwaInstall.tsx +26 -0
  199. package/templates/react/useSWUpdate.jsx +7 -52
  200. package/templates/react/useSWUpdate.tsx +12 -51
  201. package/templates/react/useStorageEstimate.jsx +56 -0
  202. package/templates/react/useStorageEstimate.tsx +67 -0
  203. package/dist/__tests__/assemble-sw.test.js +0 -145
  204. package/dist/__tests__/assemble-sw.test.js.map +0 -1
  205. package/dist/__tests__/cli-integration.test.js +0 -231
  206. package/dist/__tests__/cli-integration.test.js.map +0 -1
  207. package/dist/__tests__/config-types.test.js +0 -124
  208. package/dist/__tests__/config-types.test.js.map +0 -1
  209. package/dist/__tests__/detect-language.test.js +0 -51
  210. package/dist/__tests__/detect-language.test.js.map +0 -1
  211. package/dist/__tests__/file-generators.test.js +0 -228
  212. package/dist/__tests__/file-generators.test.js.map +0 -1
  213. package/dist/__tests__/glob-matcher.test.js +0 -86
  214. package/dist/__tests__/glob-matcher.test.js.map +0 -1
  215. package/dist/__tests__/invalidation-tags.test.js +0 -283
  216. package/dist/__tests__/invalidation-tags.test.js.map +0 -1
  217. package/dist/__tests__/loader.test.js +0 -77
  218. package/dist/__tests__/loader.test.js.map +0 -1
  219. package/dist/__tests__/validator.test.js +0 -340
  220. package/dist/__tests__/validator.test.js.map +0 -1
  221. package/templates/react/useCacheInvalidation.jsx +0 -19
  222. package/templates/react/useCacheInvalidation.tsx +0 -52
  223. package/templates/react/useIsFetching.jsx +0 -32
  224. package/templates/react/useIsFetching.tsx +0 -32
@@ -1,228 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
- import { existsSync, rmSync, readFileSync, mkdirSync } from "fs";
3
- import { join } from "path";
4
- import { defaultConfig } from "../lib/shared/config-types.js";
5
- import { generateSwTemplate } from "../lib/generators/file-generators/sw-template.js";
6
- import { generateSwInjector } from "../lib/generators/file-generators/sw-injector.js";
7
- import { generateClientInjector } from "../lib/generators/file-generators/client-injector.js";
8
- import { generateFetchWrapper } from "../lib/generators/file-generators/fetch-wrapper.js";
9
- import { generateCache } from "../lib/generators/file-generators/cache.js";
10
- import { generateMutationQueue } from "../lib/generators/file-generators/mutation-queue.js";
11
- import { generateBackgroundSync } from "../lib/generators/file-generators/background-sync.js";
12
- import { generateSwGeneratorBuild } from "../lib/generators/file-generators/sw-generator-build.js";
13
- import { generateTypeDefinitions } from "../lib/generators/file-generators/type-definitions.js";
14
- const testDir = "/tmp/swoff-test-generators";
15
- function makeContext(overrides) {
16
- const config = {
17
- ...defaultConfig,
18
- ...overrides,
19
- features: {
20
- ...defaultConfig.features,
21
- ...overrides?.features,
22
- pwa: { ...defaultConfig.features.pwa, ...overrides?.features?.pwa },
23
- serviceWorker: { ...defaultConfig.features.serviceWorker, ...overrides?.features?.serviceWorker },
24
- },
25
- build: { ...defaultConfig.build, ...overrides?.build },
26
- };
27
- return {
28
- config,
29
- projectRoot: testDir,
30
- swoffDir: join(testDir, "swoff"),
31
- ext: "js",
32
- generatedFiles: [],
33
- frameworkName: "vanilla",
34
- };
35
- }
36
- beforeEach(() => {
37
- if (existsSync(testDir))
38
- rmSync(testDir, { recursive: true });
39
- mkdirSync(testDir, { recursive: true });
40
- });
41
- afterEach(() => {
42
- if (existsSync(testDir))
43
- rmSync(testDir, { recursive: true });
44
- });
45
- describe("generateSwTemplate", () => {
46
- it("produces a template with placeholders", () => {
47
- const ctx = makeContext();
48
- generateSwTemplate(ctx);
49
- const content = readFileSync(join(ctx.swoffDir, "sw", "template.js"), "utf8");
50
- expect(content).toContain("// [[CACHE_NAME]]");
51
- expect(content).toContain("// [[ASSETS_LIST]]");
52
- expect(content).toContain("// [[AUTO_SKIP_WAITING]]");
53
- expect(content).toContain("CACHE_NAME_RUNTIME");
54
- expect(content).toContain("self.addEventListener");
55
- expect(content).toContain("fromPrecache");
56
- });
57
- it("includes config-driven strategy code", () => {
58
- const ctx = makeContext({
59
- features: { ...defaultConfig.features, serviceWorker: { ...defaultConfig.features.serviceWorker, strategy: { ...defaultConfig.features.serviceWorker.strategy, patterns: { "/api/*": "network-first" } } } },
60
- });
61
- generateSwTemplate(ctx);
62
- const content = readFileSync(join(ctx.swoffDir, "sw", "template.js"), "utf8");
63
- expect(content).toContain("determineCacheStrategy");
64
- expect(content).toContain("fromPrecache");
65
- expect(content).toContain("network-first");
66
- expect(content).toContain("invalidateByTag");
67
- });
68
- });
69
- describe("generateSwInjector", () => {
70
- it("generates JS registration with correct config values", () => {
71
- const ctx = makeContext({
72
- features: { ...defaultConfig.features, serviceWorker: { ...defaultConfig.features.serviceWorker, autoUpdate: true, autoActivate: true } },
73
- });
74
- generateSwInjector(ctx);
75
- const content = readFileSync(join(ctx.swoffDir, "sw", "injector.js"), "utf8");
76
- expect(content).toContain("AUTO_UPDATE = true");
77
- expect(content).toContain("AUTO_ACTIVATE = true");
78
- expect(content).toContain("initServiceWorker");
79
- expect(content).toContain("checkForUpdate");
80
- expect(content).toContain("handleUpdateApproved");
81
- expect(content).toContain("skipWaiting");
82
- expect(content).toContain("waitForController");
83
- expect(content).toContain("semverCompare");
84
- });
85
- it("generates TS when ext is ts", () => {
86
- const ctx = makeContext();
87
- ctx.ext = "ts";
88
- generateSwInjector(ctx);
89
- expect(existsSync(join(ctx.swoffDir, "sw", "injector.ts"))).toBe(true);
90
- });
91
- it("reflects autoUpdate false", () => {
92
- const ctx = makeContext({
93
- features: { ...defaultConfig.features, serviceWorker: { ...defaultConfig.features.serviceWorker, autoUpdate: false } },
94
- });
95
- generateSwInjector(ctx);
96
- const content = readFileSync(join(ctx.swoffDir, "sw", "injector.js"), "utf8");
97
- expect(content).toContain("AUTO_UPDATE = false");
98
- });
99
- it("generates simple injector when version mode is 'hash'", () => {
100
- const ctx = makeContext({
101
- features: { ...defaultConfig.features, serviceWorker: { ...defaultConfig.features.serviceWorker, version: "hash" } },
102
- });
103
- generateSwInjector(ctx);
104
- const content = readFileSync(join(ctx.swoffDir, "sw", "injector.js"), "utf8");
105
- expect(content).toContain("Simple Mode");
106
- expect(content).toContain("navigator.serviceWorker.register(\"/sw.js\")");
107
- expect(content).not.toContain("checkForUpdate");
108
- expect(content).not.toContain("AUTO_UPDATE");
109
- });
110
- });
111
- describe("generateClientInjector", () => {
112
- it("generates orchestrator with PWA setup and SW message listener when pwa enabled", () => {
113
- const ctx = makeContext({
114
- features: { ...defaultConfig.features },
115
- });
116
- generateClientInjector(ctx);
117
- const content = readFileSync(join(ctx.swoffDir, "client-injector.js"), "utf8");
118
- expect(content).toContain("initServiceWorker");
119
- expect(content).toContain("setupPwaInstall");
120
- expect(content).toContain("SW_PROGRESS");
121
- expect(content).toContain("BACKGROUND_SYNC_COMPLETE");
122
- });
123
- it("includes TAG_INVALIDATED handler when crossTabSync is enabled", () => {
124
- const ctx = makeContext({
125
- features: { ...defaultConfig.features, crossTabSync: true },
126
- });
127
- generateClientInjector(ctx);
128
- const content = readFileSync(join(ctx.swoffDir, "client-injector.js"), "utf8");
129
- expect(content).toContain("TAG_INVALIDATED");
130
- expect(content).toContain('"cache-invalidated"');
131
- });
132
- it("includes setupPwaInstall and beforeinstallprompt import when pwa enabled", () => {
133
- const ctx = makeContext({
134
- features: { ...defaultConfig.features },
135
- });
136
- generateClientInjector(ctx);
137
- const content = readFileSync(join(ctx.swoffDir, "client-injector.js"), "utf8");
138
- expect(content).toContain("setupPwaInstall");
139
- expect(content).toContain("./pwa/install");
140
- });
141
- it("always imports sw/injector", () => {
142
- const ctx = makeContext({
143
- features: { ...defaultConfig.features, pwa: { ...defaultConfig.features.pwa, enabled: true } },
144
- });
145
- generateClientInjector(ctx);
146
- const content = readFileSync(join(ctx.swoffDir, "client-injector.js"), "utf8");
147
- expect(content).toContain("swInit");
148
- expect(content).toContain("./sw/injector");
149
- expect(content).toContain("setupPwaInstall");
150
- expect(content).not.toContain("No SW registration configured");
151
- });
152
- });
153
- describe("generateFetchWrapper", () => {
154
- it("exports fetchWithCache", () => {
155
- const ctx = makeContext();
156
- generateFetchWrapper(ctx);
157
- const content = readFileSync(join(ctx.swoffDir, "fetch-wrapper.js"), "utf8");
158
- expect(content).toContain("fetchWithCache");
159
- });
160
- });
161
- describe("generateCache", () => {
162
- it("exports cache invalidation functions", () => {
163
- const ctx = makeContext();
164
- generateCache(ctx);
165
- const content = readFileSync(join(ctx.swoffDir, "cache.js"), "utf8");
166
- expect(content).toContain("invalidateByTag");
167
- expect(content).toContain("invalidateByTags");
168
- expect(content).toContain("INVALIDATE_TAG");
169
- expect(content).not.toContain("initCrossTabSync");
170
- expect(content).not.toContain("TAG_INVALIDATED");
171
- });
172
- });
173
- describe("generateMutationQueue", () => {
174
- it("contains mutation queue functions", () => {
175
- const ctx = makeContext();
176
- generateMutationQueue(ctx);
177
- const content = readFileSync(join(ctx.swoffDir, "mutation-queue.js"), "utf8");
178
- expect(content).toContain("queueMutation");
179
- expect(content).toContain("processMutationQueue");
180
- expect(content).toContain("getPendingCount");
181
- expect(content).toContain("MAX_RETRIES");
182
- expect(content).toContain("swoff-queue");
183
- });
184
- });
185
- describe("generateBackgroundSync", () => {
186
- it("contains background sync utilities", () => {
187
- const ctx = makeContext();
188
- generateBackgroundSync(ctx);
189
- const content = readFileSync(join(ctx.swoffDir, "background-sync.js"), "utf8");
190
- expect(content).toContain("syncWhenPossible");
191
- expect(content).toContain("retrySync");
192
- expect(content).toContain("SYNC_TAG");
193
- expect(content).toContain("SyncManager");
194
- expect(content).toContain("sync-mutations");
195
- });
196
- });
197
- describe("generateSwGeneratorBuild", () => {
198
- it("generates build script with correct imports", () => {
199
- const ctx = makeContext();
200
- generateSwGeneratorBuild(ctx);
201
- const content = readFileSync(join(ctx.swoffDir, "sw", "generator.js"), "utf8");
202
- expect(content).toContain("#!/usr/bin/env node");
203
- expect(content).toContain("readFileSync");
204
- expect(content).toContain("writeFileSync");
205
- expect(content).toContain("mkdirSync");
206
- expect(content).toContain("template.js");
207
- expect(content).toContain("createHash");
208
- expect(content).not.toContain("import('fs').then");
209
- });
210
- });
211
- describe("generateTypeDefinitions", () => {
212
- it("generates type declarations when ext is ts", () => {
213
- const ctx = makeContext();
214
- ctx.ext = "ts";
215
- generateTypeDefinitions(ctx);
216
- const content = readFileSync(join(ctx.swoffDir, "swoff.d.ts"), "utf8");
217
- expect(content).toContain("BeforeInstallPromptEvent");
218
- expect(content).toContain("FetchWithCacheOptions");
219
- expect(content).toContain("MutationQueueItem");
220
- expect(content).toContain("MutationQueueResult");
221
- });
222
- it("skips generation when ext is js", () => {
223
- const ctx = makeContext();
224
- generateTypeDefinitions(ctx);
225
- expect(ctx.generatedFiles).not.toContain("swoff/swoff.d.ts");
226
- });
227
- });
228
- //# sourceMappingURL=file-generators.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"file-generators.test.js","sourceRoot":"","sources":["../../src/__tests__/file-generators.test.ts"],"names":[],"mappings":"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"}
@@ -1,86 +0,0 @@
1
- import { describe, it, expect, beforeEach } from "vitest";
2
- import { matchGlob, clearGlobCache } from "../lib/shared/glob-matcher";
3
- beforeEach(() => {
4
- clearGlobCache();
5
- });
6
- describe("matchGlob", () => {
7
- describe("wildcard (*)", () => {
8
- it("matches single segment", () => {
9
- expect(matchGlob("/api/users", "/api/*")).toBe(true);
10
- });
11
- it("does not cross segment boundary", () => {
12
- expect(matchGlob("/api/users/123", "/api/*")).toBe(false);
13
- });
14
- it("matches within segment", () => {
15
- expect(matchGlob("/api/users/123", "/api/users/*")).toBe(true);
16
- });
17
- });
18
- describe("globstar (**)", () => {
19
- it("matches across segments", () => {
20
- expect(matchGlob("/api/users/123/posts", "/api/users/**")).toBe(true);
21
- });
22
- it("matches deep nesting", () => {
23
- expect(matchGlob("/api/v1/users/123/posts/456", "/api/**")).toBe(true);
24
- });
25
- it("matches zero segments", () => {
26
- expect(matchGlob("/api", "/api/**")).toBe(true);
27
- });
28
- });
29
- describe("single char (?)", () => {
30
- it("matches exactly one char", () => {
31
- expect(matchGlob("/api/users/123", "/api/users/???")).toBe(true);
32
- });
33
- it("fails if wrong length", () => {
34
- expect(matchGlob("/api/users/12", "/api/users/???")).toBe(false);
35
- });
36
- it("does not cross segments", () => {
37
- expect(matchGlob("/api/users/1/2", "/api/users/?")).toBe(false);
38
- });
39
- });
40
- describe("alternation ({a,b})", () => {
41
- it("matches any alternative", () => {
42
- expect(matchGlob("/api/users", "/api/{users,posts}")).toBe(true);
43
- expect(matchGlob("/api/posts", "/api/{users,posts}")).toBe(true);
44
- });
45
- it("rejects non-matching", () => {
46
- expect(matchGlob("/api/comments", "/api/{users,posts}")).toBe(false);
47
- });
48
- });
49
- describe("negation (!)", () => {
50
- it("inverts match result", () => {
51
- expect(matchGlob("/api/internal/health", "!/api/internal/**")).toBe(false);
52
- });
53
- it("allows non-matching paths", () => {
54
- expect(matchGlob("/api/users/123", "!/api/internal/**")).toBe(true);
55
- });
56
- });
57
- describe("concrete paths", () => {
58
- it("matches exact path", () => {
59
- expect(matchGlob("/api/users", "/api/users")).toBe(true);
60
- });
61
- it("rejects different path", () => {
62
- expect(matchGlob("/api/users/123", "/api/users")).toBe(false);
63
- });
64
- });
65
- describe("complex patterns", () => {
66
- it("matches nested with wildcards", () => {
67
- expect(matchGlob("/api/v2/users/123", "/api/**/users/*")).toBe(true);
68
- });
69
- it("matches deep nested with globstar", () => {
70
- expect(matchGlob("/a/b/c/d/e", "/a/**/e")).toBe(true);
71
- });
72
- it("matches with multiple wildcards", () => {
73
- expect(matchGlob("/api/users/123/posts/456", "/api/*/123/*/456")).toBe(true);
74
- });
75
- });
76
- describe("alternation in nested paths", () => {
77
- it("matches with globstar and alternation", () => {
78
- expect(matchGlob("/api/v1/users/123", "/api/**/{users,posts}/*")).toBe(true);
79
- expect(matchGlob("/api/v1/posts/456", "/api/**/{users,posts}/*")).toBe(true);
80
- });
81
- it("rejects when alternation does not match", () => {
82
- expect(matchGlob("/api/v1/comments/789", "/api/**/{users,posts}/*")).toBe(false);
83
- });
84
- });
85
- });
86
- //# sourceMappingURL=glob-matcher.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"glob-matcher.test.js","sourceRoot":"","sources":["../../src/__tests__/glob-matcher.test.ts"],"names":[],"mappings":"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"}
@@ -1,283 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- // Replicate the segment-based generateTags logic for testing fallback
3
- const SKIP_PREFIXES = ["api", "v1", "v2", "v3", "rest", "graphql", "gql"];
4
- const SINGULARIZATION = {};
5
- function generateTagsFallback(url) {
6
- const parsed = new URL(url, "http://example.com");
7
- const segments = parsed.pathname.split("/").filter(Boolean);
8
- if (segments.length === 0)
9
- return ["root"];
10
- let startIdx = 0;
11
- while (startIdx < segments.length && SKIP_PREFIXES.includes(segments[startIdx])) {
12
- startIdx++;
13
- }
14
- const resourceSegments = segments.slice(startIdx);
15
- if (resourceSegments.length === 0)
16
- return ["root"];
17
- const tags = [];
18
- tags.push(resourceSegments[0]);
19
- if (resourceSegments.length >= 2 && !isNaN(Number(resourceSegments[1]))) {
20
- const collection = resourceSegments[0];
21
- const id = resourceSegments[1];
22
- const singular = SINGULARIZATION[collection] !== undefined
23
- ? SINGULARIZATION[collection]
24
- : collection.replace(/s$/, "");
25
- tags.push(`${singular}:${id}`);
26
- }
27
- for (let i = 2; i < resourceSegments.length; i++) {
28
- if (isNaN(Number(resourceSegments[i]))) {
29
- tags.push(resourceSegments[i]);
30
- }
31
- }
32
- return tags;
33
- }
34
- describe("generateTags (segment-based fallback)", () => {
35
- describe("basic URLs", () => {
36
- it("returns root tag for root path", () => {
37
- expect(generateTagsFallback("/")).toEqual(["root"]);
38
- });
39
- it("generates collection tag from simple path", () => {
40
- expect(generateTagsFallback("/todos")).toEqual(["todos"]);
41
- });
42
- it("generates collection tag from API path", () => {
43
- expect(generateTagsFallback("/api/todos")).toEqual(["todos"]);
44
- });
45
- it("generates resource tag with ID", () => {
46
- expect(generateTagsFallback("/api/todos/42")).toEqual(["todos", "todo:42"]);
47
- });
48
- it("generates sub-resource tags", () => {
49
- expect(generateTagsFallback("/api/todos/42/comments")).toEqual(["todos", "todo:42", "comments"]);
50
- });
51
- });
52
- describe("API prefix skipping", () => {
53
- it("skips /api prefix", () => {
54
- expect(generateTagsFallback("/api/users/123")).toEqual(["users", "user:123"]);
55
- });
56
- it("skips /v1 prefix", () => {
57
- expect(generateTagsFallback("/v1/users/123")).toEqual(["users", "user:123"]);
58
- });
59
- it("skips /v2 prefix", () => {
60
- expect(generateTagsFallback("/v2/users/123")).toEqual(["users", "user:123"]);
61
- });
62
- it("skips multiple prefixes", () => {
63
- expect(generateTagsFallback("/api/v1/users/123")).toEqual(["users", "user:123"]);
64
- });
65
- it("skips /graphql prefix", () => {
66
- expect(generateTagsFallback("/graphql")).toEqual(["root"]);
67
- });
68
- it("skips /rest prefix", () => {
69
- expect(generateTagsFallback("/rest/items/456")).toEqual(["items", "item:456"]);
70
- });
71
- });
72
- describe("pluralization", () => {
73
- it("singularizes collection name for resource tag", () => {
74
- expect(generateTagsFallback("/api/posts/1")).toEqual(["posts", "post:1"]);
75
- });
76
- it("handles non-plural collection names", () => {
77
- expect(generateTagsFallback("/api/data/1")).toEqual(["data", "data:1"]);
78
- });
79
- it("handles nested resources", () => {
80
- expect(generateTagsFallback("/api/users/123/posts/456")).toEqual([
81
- "users",
82
- "user:123",
83
- "posts",
84
- ]);
85
- });
86
- });
87
- describe("edge cases", () => {
88
- it("handles query parameters", () => {
89
- expect(generateTagsFallback("/api/todos?status=active")).toEqual(["todos"]);
90
- });
91
- it("handles trailing slashes", () => {
92
- expect(generateTagsFallback("/api/todos/42/")).toEqual(["todos", "todo:42"]);
93
- });
94
- it("handles full URLs", () => {
95
- expect(generateTagsFallback("https://example.com/api/todos/42")).toEqual([
96
- "todos",
97
- "todo:42",
98
- ]);
99
- });
100
- });
101
- });
102
- // Test compilePatternEntry (used by the generator)
103
- describe("compilePatternEntry", () => {
104
- // We import and test the actual function from the generator
105
- // For unit testing purposes, we replicate the logic
106
- function compileEntry(pattern, templates) {
107
- const rawParts = pattern.split("/");
108
- const parts = rawParts.filter((p) => p !== "");
109
- const paramNames = [];
110
- const regexParts = [];
111
- for (let i = 0; i < parts.length; i++) {
112
- const part = parts[i];
113
- if (part === "**") {
114
- regexParts.push("(?:\\/[^/]+)*");
115
- continue;
116
- }
117
- if (regexParts.length > 0) {
118
- regexParts.push("\\/");
119
- }
120
- if (part === "*") {
121
- regexParts.push("[^/]+");
122
- }
123
- else if (part.startsWith(":")) {
124
- paramNames.push(part.slice(1));
125
- regexParts.push("([^/]+)");
126
- }
127
- else if (part.includes("{")) {
128
- const close = part.indexOf("}");
129
- if (close !== -1) {
130
- const inner = part.slice(part.indexOf("{") + 1, close);
131
- const alternatives = inner.split(",").map((s) => s.trim().replace(/[.+^${}()|[\]\\]/g, "\\$&"));
132
- regexParts.push("(?:" + alternatives.join("|") + ")");
133
- }
134
- else {
135
- regexParts.push(part.replace(/[.+^${}()|[\]\\]/g, "\\$&"));
136
- }
137
- }
138
- else {
139
- regexParts.push(part.replace(/[.+^${}()|[\]\\]/g, "\\$&"));
140
- }
141
- }
142
- if (regexParts.length === 0)
143
- return null;
144
- const hasLeadingSlash = pattern.startsWith("/");
145
- const regex = (hasLeadingSlash ? "^\\/" : "^") + regexParts.join("") + "$";
146
- // Validate template params match captured params
147
- const templatePlaceholders = new Set();
148
- for (const tmpl of templates) {
149
- const matches = tmpl.match(/\{(\w+)\}/g);
150
- if (matches) {
151
- for (const m of matches) {
152
- templatePlaceholders.add(m.slice(1, -1));
153
- }
154
- }
155
- }
156
- for (const ph of templatePlaceholders) {
157
- if (!paramNames.includes(ph))
158
- return null;
159
- }
160
- return { regex, params: paramNames, templates };
161
- }
162
- function testMatch(regex, url) {
163
- const parsed = new URL(url, "http://example.com");
164
- return parsed.pathname.match(new RegExp(regex));
165
- }
166
- function generateTagsWithPatterns(url, patterns) {
167
- const parsed = new URL(url, "http://example.com");
168
- for (const entry of patterns) {
169
- const match = parsed.pathname.match(new RegExp(entry.regex));
170
- if (match) {
171
- const params = {};
172
- for (let i = 0; i < entry.params.length; i++) {
173
- params[entry.params[i]] = match[i + 1];
174
- }
175
- return entry.templates.map((tmpl) => tmpl.replace(/\{(\w+)\}/g, (_, key) => params[key] ?? ""));
176
- }
177
- }
178
- return generateTagsFallback(url);
179
- }
180
- it("compiles :param pattern", () => {
181
- const entry = compileEntry("/api/users/:id", ["users", "user:{id}"]);
182
- expect(entry).not.toBeNull();
183
- expect(entry.params).toEqual(["id"]);
184
- const match = testMatch(entry.regex, "/api/users/42");
185
- expect(match).not.toBeNull();
186
- expect(match[1]).toBe("42");
187
- });
188
- it("compiles * glob pattern", () => {
189
- const entry = compileEntry("/api/users/*", ["users", "user"]);
190
- expect(entry).not.toBeNull();
191
- expect(testMatch(entry.regex, "/api/users/42")).not.toBeNull();
192
- expect(testMatch(entry.regex, "/api/users/abc")).not.toBeNull();
193
- expect(testMatch(entry.regex, "/api/users/42/posts")).toBeNull();
194
- });
195
- it("compiles ** globstar pattern", () => {
196
- const entry = compileEntry("/api/**", ["api"]);
197
- expect(entry).not.toBeNull();
198
- expect(testMatch(entry.regex, "/api/users")).not.toBeNull();
199
- expect(testMatch(entry.regex, "/api/users/123/posts")).not.toBeNull();
200
- });
201
- it("compiles {alternation} pattern", () => {
202
- const entry = compileEntry("/api/{users,posts}/:id", ["entry", "entry:{id}"]);
203
- expect(entry).not.toBeNull();
204
- expect(entry.params).toEqual(["id"]);
205
- expect(testMatch(entry.regex, "/api/users/42")).not.toBeNull();
206
- expect(testMatch(entry.regex, "/api/posts/42")).not.toBeNull();
207
- expect(testMatch(entry.regex, "/api/comments/42")).toBeNull();
208
- });
209
- it("generates tags from matched pattern", () => {
210
- const patterns = [
211
- compileEntry("/api/users/:id", ["users", "user:{id}"]),
212
- ];
213
- expect(generateTagsWithPatterns("/api/users/42", patterns)).toEqual(["users", "user:42"]);
214
- expect(generateTagsWithPatterns("/api/users/abc", patterns)).toEqual(["users", "user:abc"]);
215
- });
216
- it("falls back to segment-based when no pattern matches", () => {
217
- const patterns = [
218
- compileEntry("/api/users/:id", ["users", "user:{id}"]),
219
- ];
220
- expect(generateTagsWithPatterns("/api/todos/42", patterns)).toEqual(["todos", "todo:42"]);
221
- expect(generateTagsWithPatterns("/api/todos", patterns)).toEqual(["todos"]);
222
- });
223
- it("handles multiple named params", () => {
224
- const entry = compileEntry("/api/:resource/:id", ["{resource}", "{resource}:{id}"]);
225
- expect(entry).not.toBeNull();
226
- expect(entry.params).toEqual(["resource", "id"]);
227
- const match = testMatch(entry.regex, "/api/todos/42");
228
- expect(match).not.toBeNull();
229
- expect(match[1]).toBe("todos");
230
- expect(match[2]).toBe("42");
231
- expect(generateTagsWithPatterns("/api/todos/42", [entry])).toEqual(["todos", "todos:42"]);
232
- });
233
- it("handles deeply nested patterns", () => {
234
- const entry = compileEntry("/api/users/:userId/posts/:postId", ["users", "user:{userId}", "posts", "post:{postId}"]);
235
- expect(entry).not.toBeNull();
236
- expect(entry.params).toEqual(["userId", "postId"]);
237
- const match = testMatch(entry.regex, "/api/users/42/posts/99");
238
- expect(match).not.toBeNull();
239
- expect(match[1]).toBe("42");
240
- expect(match[2]).toBe("99");
241
- expect(generateTagsWithPatterns("/api/users/42/posts/99", [entry]))
242
- .toEqual(["users", "user:42", "posts", "post:99"]);
243
- });
244
- it("returns null when template uses undeclared param", () => {
245
- const entry = compileEntry("/api/users/:id", ["users", "user:{id}", "extra:{missing}"]);
246
- expect(entry).toBeNull();
247
- });
248
- });
249
- // Test the generated output contains expected code
250
- describe("generated output", () => {
251
- it("generated file exports expected functions", () => {
252
- // We test what the generator produces by reading it indirectly
253
- // through the file-generators test which invokes the generator
254
- const code = `
255
- import { invalidateByTags } from "./cache.js";
256
- const TAG_PATTERNS = [];
257
- const SKIP_PREFIXES = ["api","v1","v2","v3","rest","graphql","gql"];
258
- const SINGULARIZATION = null;
259
- const CASCADING = null;
260
- export function generateTags(url) {}
261
- export function generateTagsFromMethod(method, url) {}
262
- export async function invalidateUrl(url) {}
263
- export async function invalidateByMethod(method, url) {}
264
- function expandCascading(tags) {}
265
- `;
266
- expect(code).toContain("generateTags");
267
- expect(code).toContain("invalidateUrl");
268
- expect(code).toContain("invalidateByMethod");
269
- expect(code).toContain("CASCADING");
270
- expect(code).toContain("expandCascading");
271
- });
272
- it("generated code with patterns includes compiled entries", () => {
273
- // Simulate what the generator would produce for a config with patterns
274
- const patternCode = `[
275
- { re: new RegExp("^\\\\/api\\\\/users\\\\([^/]+\\\\)$"), params: ["id"], templates: ["users","user:{id}"] }
276
- ]`;
277
- const code = `const TAG_PATTERNS = ${patternCode};`;
278
- expect(code).toContain("TAG_PATTERNS");
279
- expect(code).toContain("users");
280
- expect(code).toContain("user:{id}");
281
- });
282
- });
283
- //# sourceMappingURL=invalidation-tags.test.js.map