@swoff/cli 0.3.5 → 0.3.6
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 +327 -25
- package/dist/__tests__/assemble-sw.test.js +15 -1
- package/dist/__tests__/assemble-sw.test.js.map +1 -1
- package/dist/__tests__/cli-integration.test.js +9 -8
- package/dist/__tests__/cli-integration.test.js.map +1 -1
- package/dist/__tests__/config-types.test.js +6 -6
- package/dist/__tests__/config-types.test.js.map +1 -1
- package/dist/__tests__/file-generators.test.js +67 -59
- package/dist/__tests__/file-generators.test.js.map +1 -1
- package/dist/__tests__/loader.test.js +12 -13
- package/dist/__tests__/loader.test.js.map +1 -1
- package/dist/__tests__/validator.test.js +41 -21
- 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/cli/help.js +3 -3
- package/dist/lib/cli/help.js.map +1 -1
- package/dist/lib/commands/add.js +7 -1
- package/dist/lib/commands/add.js.map +1 -1
- package/dist/lib/commands/clean.js +5 -0
- package/dist/lib/commands/clean.js.map +1 -1
- package/dist/lib/commands/generate-guide.js +12 -9
- package/dist/lib/commands/generate-guide.js.map +1 -1
- package/dist/lib/commands/generate.js +7 -3
- package/dist/lib/commands/generate.js.map +1 -1
- package/dist/lib/commands/info.js +135 -32
- package/dist/lib/commands/info.js.map +1 -1
- package/dist/lib/commands/validate.js +3 -1
- package/dist/lib/commands/validate.js.map +1 -1
- package/dist/lib/config/validator.js +25 -16
- package/dist/lib/config/validator.js.map +1 -1
- package/dist/lib/generators/file-generators/auth-fetch.js +29 -34
- package/dist/lib/generators/file-generators/auth-fetch.js.map +1 -1
- package/dist/lib/generators/file-generators/auth-state.js +8 -5
- package/dist/lib/generators/file-generators/auth-state.js.map +1 -1
- package/dist/lib/generators/file-generators/auth-store.js +71 -40
- package/dist/lib/generators/file-generators/auth-store.js.map +1 -1
- package/dist/lib/generators/file-generators/auth-user.js +27 -31
- package/dist/lib/generators/file-generators/auth-user.js.map +1 -1
- package/dist/lib/generators/file-generators/background-sync.js +9 -5
- package/dist/lib/generators/file-generators/background-sync.js.map +1 -1
- package/dist/lib/generators/file-generators/cache.js +7 -2
- package/dist/lib/generators/file-generators/cache.js.map +1 -1
- package/dist/lib/generators/file-generators/client-injector.js +113 -0
- package/dist/lib/generators/file-generators/client-injector.js.map +1 -0
- package/dist/lib/generators/file-generators/context.js +7 -6
- package/dist/lib/generators/file-generators/context.js.map +1 -1
- package/dist/lib/generators/file-generators/fetch-wrapper.js +170 -40
- package/dist/lib/generators/file-generators/fetch-wrapper.js.map +1 -1
- package/dist/lib/generators/file-generators/generate-hooks.js +61 -3
- package/dist/lib/generators/file-generators/generate-hooks.js.map +1 -1
- package/dist/lib/generators/file-generators/guide-generator.js +333 -0
- package/dist/lib/generators/file-generators/guide-generator.js.map +1 -0
- package/dist/lib/generators/file-generators/invalidation-tags.js +12 -10
- package/dist/lib/generators/file-generators/invalidation-tags.js.map +1 -1
- package/dist/lib/generators/file-generators/mutation-queue.js +34 -84
- package/dist/lib/generators/file-generators/mutation-queue.js.map +1 -1
- package/dist/lib/generators/file-generators/mutation-reconcile.js +57 -0
- package/dist/lib/generators/file-generators/mutation-reconcile.js.map +1 -0
- package/dist/lib/generators/file-generators/pwa-install.js +41 -9
- package/dist/lib/generators/file-generators/pwa-install.js.map +1 -1
- package/dist/lib/generators/file-generators/quick-readme.js +78 -0
- package/dist/lib/generators/file-generators/quick-readme.js.map +1 -0
- package/dist/lib/generators/file-generators/reconcile.js +7 -12
- package/dist/lib/generators/file-generators/reconcile.js.map +1 -1
- package/dist/lib/generators/file-generators/store.js +30 -20
- package/dist/lib/generators/file-generators/store.js.map +1 -1
- package/dist/lib/generators/file-generators/sw-generator-build.js +37 -16
- package/dist/lib/generators/file-generators/sw-generator-build.js.map +1 -1
- package/dist/lib/generators/file-generators/sw-injector.js +81 -110
- package/dist/lib/generators/file-generators/sw-injector.js.map +1 -1
- package/dist/lib/generators/file-generators/sw-template.js +1 -1
- package/dist/lib/generators/file-generators/type-definitions.js +33 -10
- package/dist/lib/generators/file-generators/type-definitions.js.map +1 -1
- package/dist/lib/generators/sw-generator.js +19 -10
- package/dist/lib/generators/sw-generator.js.map +1 -1
- package/dist/lib/generators/sw-sections/assemble-sw.js +32 -12
- package/dist/lib/generators/sw-sections/assemble-sw.js.map +1 -1
- package/dist/lib/generators/sw-sections/config-header.js +1 -1
- package/dist/lib/generators/sw-sections/config-header.js.map +1 -1
- package/dist/lib/generators/sw-sections/fetch-handler.js +25 -10
- package/dist/lib/generators/sw-sections/fetch-handler.js.map +1 -1
- package/dist/lib/generators/sw-sections/tag-management.js +25 -5
- package/dist/lib/generators/sw-sections/tag-management.js.map +1 -1
- package/dist/lib/generators/swoff-files-generator.js +7 -5
- package/dist/lib/generators/swoff-files-generator.js.map +1 -1
- package/dist/lib/shared/config-types.js +21 -6
- package/dist/lib/shared/config-types.js.map +1 -1
- package/dist/lib/utils/build-script.js +35 -0
- package/dist/lib/utils/build-script.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,55 +2,357 @@
|
|
|
2
2
|
|
|
3
3
|
CLI for [Swoff](https://swoff.netlify.app) — offline-first web apps made easy.
|
|
4
4
|
|
|
5
|
+
Swoff generates a **service worker** and **client-side utilities** that give your web app:
|
|
6
|
+
|
|
7
|
+
- **Offline support** — cached API responses work without a connection
|
|
8
|
+
- **Mutation queue** — writes performed offline replay when back online
|
|
9
|
+
- **Auth** — token management with automatic 401 handling
|
|
10
|
+
- **Cache invalidation** — tag-based cache busting after mutations
|
|
11
|
+
- **PWA** — install prompt and manifest
|
|
12
|
+
- **Cross-tab sync** — broadcast changes across open tabs
|
|
13
|
+
- **Background Sync API** — process mutations even after tab close
|
|
14
|
+
|
|
15
|
+
It lives in your project as a `swoff/` directory — everything is generated, auditable, and editable.
|
|
16
|
+
|
|
17
|
+
Source: [github.com/iamsuudi/swoff](https://github.com/iamsuudi/swoff)
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
5
21
|
## Quick Start
|
|
6
22
|
|
|
7
23
|
```bash
|
|
24
|
+
# Initialize configuration (creates swoff.config.json)
|
|
8
25
|
npx @swoff/cli init
|
|
26
|
+
|
|
27
|
+
# Generate service worker and supporting files
|
|
9
28
|
npx @swoff/cli generate
|
|
10
|
-
```
|
|
11
29
|
|
|
12
|
-
Import the generated
|
|
30
|
+
# Import the generated entry point in your app
|
|
31
|
+
```
|
|
13
32
|
|
|
14
33
|
```js
|
|
15
|
-
import { initServiceWorker } from
|
|
34
|
+
import { initServiceWorker } from "./swoff/client-injector.js";
|
|
16
35
|
|
|
17
36
|
initServiceWorker();
|
|
18
37
|
```
|
|
19
38
|
|
|
39
|
+
Then build your app:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm run build
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The build script auto-appends `node swoff/sw/generator.js` to finalize the service worker with your asset hashes.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
20
49
|
## Commands
|
|
21
50
|
|
|
22
51
|
| Command | Description |
|
|
23
52
|
|---------|-------------|
|
|
24
|
-
| `init` | Create `swoff.config.json` and
|
|
25
|
-
| `generate` | Generate service worker and supporting files |
|
|
26
|
-
| `validate` | Validate `swoff.config.json` |
|
|
53
|
+
| `init` | Create `swoff.config.json` with auto-detected framework and language |
|
|
54
|
+
| `generate` | Generate service worker and all supporting files |
|
|
27
55
|
| `add <feature>` | Enable a feature and regenerate |
|
|
28
|
-
| `
|
|
29
|
-
| `
|
|
30
|
-
| `
|
|
56
|
+
| `validate` | Validate `swoff.config.json` |
|
|
57
|
+
| `info [feature]` | Show summary or per-feature details |
|
|
58
|
+
| `clean` | Remove all Swoff files (`swoff/`, config, `version.json`) |
|
|
59
|
+
| `help [command]` | Show help for a specific command |
|
|
31
60
|
|
|
32
|
-
###
|
|
61
|
+
### `init`
|
|
33
62
|
|
|
34
|
-
|
|
35
|
-
|------|-------------|
|
|
36
|
-
| `--sw-only` | Regenerate only the service worker |
|
|
37
|
-
| `--files-only` | Regenerate only supporting files (sw-template, sw-injector, etc.) |
|
|
63
|
+
Creates `swoff.config.json` in your project root. Auto-detects:
|
|
38
64
|
|
|
39
|
-
|
|
65
|
+
- **Framework**: react, vue, svelte, or vanilla
|
|
66
|
+
- **Language**: TypeScript or JavaScript
|
|
67
|
+
- **Build tool**: Uses existing `package.json` build script
|
|
40
68
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
69
|
+
```bash
|
|
70
|
+
swoff init
|
|
71
|
+
swoff init --framework react # override detection
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### `generate`
|
|
75
|
+
|
|
76
|
+
Generates the service worker (`dist/sw-<version>.js`) and all supporting files into `swoff/`. Also auto-appends the SW generator to your `package.json` build script.
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
swoff generate
|
|
80
|
+
swoff generate --sw-only # regenerate only the service worker
|
|
81
|
+
swoff generate --files-only # regenerate only supporting files
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
After generation, read `swoff/GUIDE.md` for the full integration guide for your project.
|
|
85
|
+
|
|
86
|
+
### `add <feature>`
|
|
87
|
+
|
|
88
|
+
Enables a feature in `swoff.config.json` and regenerates.
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
swoff add pwa
|
|
92
|
+
swoff add mutation-queue
|
|
93
|
+
swoff add auth
|
|
94
|
+
swoff add tag-invalidation
|
|
95
|
+
swoff add cross-tab
|
|
96
|
+
swoff add background-sync
|
|
97
|
+
swoff add client-registration
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### `info`
|
|
101
|
+
|
|
102
|
+
Shows enabled features and file count, or detailed docs for a specific feature.
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
swoff info # summary
|
|
106
|
+
swoff info auth # auth details and functions
|
|
107
|
+
swoff info mutation-queue # mutation queue details
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### `clean`
|
|
111
|
+
|
|
112
|
+
Removes every generated file:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
swoff clean
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
This deletes `swoff/`, `swoff.config.json`, `version.json`, and removes the SW generator from your build script.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Configuration (`swoff.config.json`)
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
"framework": "react",
|
|
127
|
+
"language": "ts",
|
|
128
|
+
"buildCommand": "vite build",
|
|
129
|
+
"features": {
|
|
130
|
+
"mutationQueue": true,
|
|
131
|
+
"backgroundSync": false,
|
|
132
|
+
"crossTabSync": false,
|
|
133
|
+
"tagInvalidation": true,
|
|
134
|
+
"clientRegistration": true,
|
|
135
|
+
"pwa": {
|
|
136
|
+
"enabled": false
|
|
137
|
+
},
|
|
138
|
+
"auth": {
|
|
139
|
+
"enabled": true,
|
|
140
|
+
"type": "bearer",
|
|
141
|
+
"refreshPath": "/api/refresh",
|
|
142
|
+
"userEndpoint": "/api/me"
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
| Field | Type | Default | Description |
|
|
149
|
+
|-------|------|---------|-------------|
|
|
150
|
+
| `framework` | `"react"` \| `"vue"` \| `"svelte"` \| `"vanilla"` | auto | Your UI framework |
|
|
151
|
+
| `language` | `"ts"` \| `"js"` | auto | TypeScript or JavaScript output |
|
|
152
|
+
| `buildCommand` | `string` | auto | Your build command (detected from `package.json`) |
|
|
153
|
+
| `features.mutationQueue` | `boolean` | `false` | Offline write queue |
|
|
154
|
+
| `features.backgroundSync` | `boolean` | `false` | Background Sync API |
|
|
155
|
+
| `features.crossTabSync` | `boolean` | `false` | Cross-tab broadcast |
|
|
156
|
+
| `features.tagInvalidation` | `boolean` | `false` | Tag-based cache invalidation |
|
|
157
|
+
| `features.clientRegistration` | `boolean` | `false` | SW registration lifecycle |
|
|
158
|
+
| `features.pwa.enabled` | `boolean` | `false` | PWA install + manifest |
|
|
159
|
+
| `features.auth.enabled` | `boolean` | `false` | Auth module |
|
|
160
|
+
| `features.auth.type` | `"bearer"` \| `"cookie"` \| `"custom"` | — | Auth strategy |
|
|
161
|
+
| `features.auth.refreshPath` | `string` | `"/api/refresh"` | Token refresh endpoint |
|
|
162
|
+
| `features.auth.userEndpoint` | `string` | `"/api/me"` | Current user endpoint |
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Generated File Structure
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
swoff/
|
|
170
|
+
├── client-injector.ts # Single entry point — import and call initServiceWorker()
|
|
171
|
+
├── fetch-wrapper.ts # Unified fetch with caching, auth, offline queue
|
|
172
|
+
├── cache.ts # Low-level cache invalidation (tagInvalidation)
|
|
173
|
+
├── invalidation-tags.ts # Tag generation helpers (tagInvalidation)
|
|
174
|
+
├── mutation-queue.ts # Offline write queue (mutationQueue)
|
|
175
|
+
├── background-sync.ts # Background Sync API (backgroundSync)
|
|
176
|
+
├── swoff.d.ts # TypeScript declarations
|
|
177
|
+
│
|
|
178
|
+
├── auth/
|
|
179
|
+
│ ├── store.ts # Auth token/user persistence
|
|
180
|
+
│ ├── fetch.ts # Authenticated fetch wrapper
|
|
181
|
+
│ ├── user.ts # User data caching
|
|
182
|
+
│ └── state.ts # Online/offline × auth state detection
|
|
183
|
+
│
|
|
184
|
+
├── hooks/ # React hooks (if framework = react)
|
|
185
|
+
│ ├── useAuth.tsx
|
|
186
|
+
│ ├── useCachedFetch.tsx
|
|
187
|
+
│ ├── useMutationQueue.tsx
|
|
188
|
+
│ └── usePWAUpdate.tsx
|
|
189
|
+
│
|
|
190
|
+
├── pwa/
|
|
191
|
+
│ └── install.ts
|
|
192
|
+
│
|
|
193
|
+
├── sw/
|
|
194
|
+
│ ├── template.js # Service worker source
|
|
195
|
+
│ ├── injector.ts # SW registration logic
|
|
196
|
+
│ └── generator.js # Build-time SW generator
|
|
197
|
+
│
|
|
198
|
+
├── manifest.json
|
|
199
|
+
├── GUIDE.md # Full integration walkthrough
|
|
200
|
+
└── README.md # Quick reference
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Feature Deep-Dive
|
|
206
|
+
|
|
207
|
+
### Mutation Queue
|
|
208
|
+
|
|
209
|
+
When the user is offline, write operations (POST/PUT/DELETE) are stored in IndexedDB. They replay automatically when the connection returns.
|
|
210
|
+
|
|
211
|
+
```js
|
|
212
|
+
import { queueMutation, getPendingCount } from "./swoff/mutation-queue.js";
|
|
213
|
+
|
|
214
|
+
// Offline write — stored and replayed when online
|
|
215
|
+
await queueMutation({
|
|
216
|
+
method: "POST",
|
|
217
|
+
url: "/api/todos",
|
|
218
|
+
body: { title: "Buy milk" },
|
|
219
|
+
tags: ["todos"],
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
// Show sync badge
|
|
223
|
+
const count = await getPendingCount();
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
The queue processes automatically on the `online` event. Call `flushMutations()` after re-login to retry mutations that failed due to auth expiry.
|
|
227
|
+
|
|
228
|
+
### Fetch Wrapper
|
|
229
|
+
|
|
230
|
+
Drop-in replacement for `fetch()` that communicates with the service worker about caching strategy.
|
|
231
|
+
|
|
232
|
+
```js
|
|
233
|
+
import { fetchWithCache } from "./swoff/fetch-wrapper.js";
|
|
234
|
+
|
|
235
|
+
// Reads are cached for offline access
|
|
236
|
+
const { response, fromCache } = await fetchWithCache("/api/todos");
|
|
237
|
+
const data = await response.json();
|
|
238
|
+
|
|
239
|
+
// Writes auto-invalidate related cache tags
|
|
240
|
+
await fetchWithCache("/api/todos", {
|
|
241
|
+
method: "POST",
|
|
242
|
+
body: JSON.stringify({ title: "New task" }),
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// Auth requests
|
|
246
|
+
const { response: user } = await fetchWithCache("/api/me", { auth: true });
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Returns `{ response: Response, fromCache: boolean }`.
|
|
250
|
+
|
|
251
|
+
### Auth
|
|
252
|
+
|
|
253
|
+
Token-based authentication with memory-only tokens and automatic 401 handling.
|
|
254
|
+
|
|
255
|
+
```js
|
|
256
|
+
import { authenticatedFetch } from "./swoff/auth/fetch.js";
|
|
257
|
+
|
|
258
|
+
// Attaches Bearer token, handles 401
|
|
259
|
+
const user = await authenticatedFetch("/api/me").then((r) => r.json());
|
|
260
|
+
|
|
261
|
+
// For mutations too — no separate wrapper needed
|
|
262
|
+
await authenticatedFetch("/api/todos", {
|
|
263
|
+
method: "POST",
|
|
264
|
+
body: JSON.stringify({ title: "New" }),
|
|
265
|
+
});
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Auth endpoints (`/login`, `/logout`, `/register`) automatically bypass the SW cache. On 401, `sw-auth-unauthorized` is dispatched and the token is cleared.
|
|
269
|
+
|
|
270
|
+
### Cache Invalidation
|
|
271
|
+
|
|
272
|
+
Tag-based invalidation keeps the service worker cache fresh after mutations.
|
|
273
|
+
|
|
274
|
+
```js
|
|
275
|
+
import { generateTags, invalidateUrl } from "./swoff/invalidation-tags.js";
|
|
276
|
+
|
|
277
|
+
// Tag reads automatically
|
|
278
|
+
const data = await fetchWithCache("/api/todos", {
|
|
279
|
+
tags: generateTags("/api/todos"),
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
// Invalidate after writing
|
|
283
|
+
await invalidateUrl("/api/todos/42");
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
When the SW receives an invalidation, it removes matching cache entries and attempts to background-refetch them. If the refetch fails (network error), the old cached entry is served with a stale-while-revalidate fallback.
|
|
287
|
+
|
|
288
|
+
### PWA
|
|
289
|
+
|
|
290
|
+
Install prompt handling and manifest generation.
|
|
291
|
+
|
|
292
|
+
```js
|
|
293
|
+
import { isInstallable, promptInstall } from "./swoff/pwa/install.js";
|
|
294
|
+
|
|
295
|
+
// Show install button conditionally
|
|
296
|
+
if (isInstallable()) {
|
|
297
|
+
const { outcome } = await promptInstall();
|
|
298
|
+
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### React Hooks
|
|
302
|
+
|
|
303
|
+
When `framework` is `"react"`, generated hooks provide reactive state:
|
|
304
|
+
|
|
305
|
+
| Hook | Returns | Description |
|
|
306
|
+
|------|---------|-------------|
|
|
307
|
+
| `useAuth()` | `{ authenticated, user, online }` | Auth + connectivity state |
|
|
308
|
+
| `useCachedFetch(url, options?)` | `{ data, error, loading, refetch }` | Auto-refetches on tag invalidation |
|
|
309
|
+
| `useMutationQueue()` | `{ pending, lastSync }` | Queue status and sync results |
|
|
310
|
+
| `usePWAUpdate()` | `{ updateStatus, progress, forceUpdate, acceptUpdate, dismissUpdate }` | SW update management |
|
|
311
|
+
| `useSWProgress()` | `{ status, progress }` | Download progress during SW update |
|
|
312
|
+
|
|
313
|
+
```tsx
|
|
314
|
+
import { useCachedFetch } from "./swoff/hooks/useCachedFetch.tsx";
|
|
315
|
+
|
|
316
|
+
function TodosList() {
|
|
317
|
+
const { data, loading } = useCachedFetch("/api/todos");
|
|
318
|
+
|
|
319
|
+
if (loading) return <Spinner />;
|
|
320
|
+
return <TodoList data={data} />;
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### Build Script
|
|
325
|
+
|
|
326
|
+
After `swoff generate`, your `package.json` build script is updated to:
|
|
327
|
+
|
|
328
|
+
```json
|
|
329
|
+
"build": "vite build && node swoff/sw/generator.js"
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
The generator learns your build output and precaches all assets in the service worker. Running `swoff clean` removes this suffix.
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
336
|
+
## Service Worker Architecture
|
|
337
|
+
|
|
338
|
+
The generated service worker (`sw/template.js`) implements:
|
|
339
|
+
|
|
340
|
+
- **Cache strategies**: network-first for API routes, cache-first for assets
|
|
341
|
+
- **Tag invalidation**: removes stale cache entries and background-refetches
|
|
342
|
+
- **Stale-while-revalidate**: on refetch failure, serves cached content with a stale indicator
|
|
343
|
+
- **Offline fallback**: returns cached responses when the network is unavailable
|
|
344
|
+
- **Cross-tab sync**: forwards invalidation events to all open clients
|
|
345
|
+
- **PWA lifecycle**: skip-waiting, activate, and install event handling
|
|
346
|
+
|
|
347
|
+
The build-time generator (`sw/generator.js`) collects your built asset files and embeds their hashes into the service worker, so cached assets are versioned and updated when they change.
|
|
348
|
+
|
|
349
|
+
---
|
|
50
350
|
|
|
51
351
|
## Requirements
|
|
52
352
|
|
|
53
|
-
Node.js >= 18
|
|
353
|
+
- Node.js >= 18
|
|
354
|
+
- A build tool with a `package.json` build script (Vite, Webpack, etc.)
|
|
355
|
+
- HTTPS or localhost (required for service workers)
|
|
54
356
|
|
|
55
357
|
## License
|
|
56
358
|
|
|
@@ -4,7 +4,6 @@ import { defaultConfig } from "../lib/shared/config-types.js";
|
|
|
4
4
|
describe("assembleSW", () => {
|
|
5
5
|
const config = {
|
|
6
6
|
...defaultConfig,
|
|
7
|
-
version: "1.0.0",
|
|
8
7
|
};
|
|
9
8
|
it("generates a service worker string", () => {
|
|
10
9
|
const sw = assembleSW(config, "1.0.0");
|
|
@@ -97,6 +96,21 @@ describe("assembleSW", () => {
|
|
|
97
96
|
const sw2 = assembleSW(configNoAutoActivate, "1.0.0");
|
|
98
97
|
expect(sw2).toContain("const AUTO_SKIP_WAITING = false");
|
|
99
98
|
});
|
|
99
|
+
it("uses hash-based cache name when version is disabled", () => {
|
|
100
|
+
const configNoVersion = {
|
|
101
|
+
...config,
|
|
102
|
+
features: {
|
|
103
|
+
...config.features,
|
|
104
|
+
serviceWorker: {
|
|
105
|
+
...config.features.serviceWorker,
|
|
106
|
+
version: { ...config.features.serviceWorker.version, enabled: false },
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
const sw = assembleSW(configNoVersion, "1.0.0");
|
|
111
|
+
expect(sw).toContain("CACHE_NAME = 'sw-cache-");
|
|
112
|
+
expect(sw).not.toContain("sw-v1.0.0");
|
|
113
|
+
});
|
|
100
114
|
it("includes PWA assets when pwa feature is enabled", () => {
|
|
101
115
|
const configWithPwa = {
|
|
102
116
|
...config,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assemble-sw.test.js","sourceRoot":"","sources":["../../src/__tests__/assemble-sw.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,8CAA8C,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAoB,MAAM,+BAA+B,CAAC;AAEhF,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,MAAM,MAAM,GAAgB;QAC1B,GAAG,aAAa;
|
|
1
|
+
{"version":3,"file":"assemble-sw.test.js","sourceRoot":"","sources":["../../src/__tests__/assemble-sw.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,13 +17,15 @@ describe("CLI commands integration", () => {
|
|
|
17
17
|
const config = {
|
|
18
18
|
$schema: "https://swoff.netlify.app/schema/v1.json",
|
|
19
19
|
enabled: true,
|
|
20
|
-
version: "from-package",
|
|
21
|
-
minSupportedVersion: "1.0.0",
|
|
22
20
|
features: {
|
|
23
21
|
pwa: { enabled: true, preventDefaultInstall: false },
|
|
24
22
|
serviceWorker: {
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
version: {
|
|
24
|
+
enabled: true,
|
|
25
|
+
source: "from-package",
|
|
26
|
+
minSupportedVersion: "1.0.0",
|
|
27
|
+
},
|
|
28
|
+
autoUpdate: true,
|
|
27
29
|
autoActivate: false,
|
|
28
30
|
defaultStrategy: "cache-first",
|
|
29
31
|
strategies: { "/api/*": "network-first", "/static/*": "cache-first" },
|
|
@@ -41,7 +43,7 @@ describe("CLI commands integration", () => {
|
|
|
41
43
|
const parsed = JSON.parse(readFileSync(join(testDir, "swoff.config.json"), "utf8"));
|
|
42
44
|
expect(parsed.$schema).toBe("https://swoff.netlify.app/schema/v1.json");
|
|
43
45
|
expect(parsed.enabled).toBe(true);
|
|
44
|
-
expect(parsed.version).toBe("from-package");
|
|
46
|
+
expect(parsed.features.serviceWorker.version.source).toBe("from-package");
|
|
45
47
|
expect(parsed.features.pwa.preventDefaultInstall).toBe(false);
|
|
46
48
|
});
|
|
47
49
|
it("creates swoff directory", () => {
|
|
@@ -95,9 +97,8 @@ describe("CLI commands integration", () => {
|
|
|
95
97
|
describe("config validation scenarios", () => {
|
|
96
98
|
it("detects missing required fields", () => {
|
|
97
99
|
const config = { enabled: true };
|
|
98
|
-
const required = ["enabled", "
|
|
100
|
+
const required = ["enabled", "features", "build"];
|
|
99
101
|
const missing = required.filter((f) => !(f in config));
|
|
100
|
-
expect(missing).toContain("version");
|
|
101
102
|
expect(missing).toContain("features");
|
|
102
103
|
expect(missing).toContain("build");
|
|
103
104
|
});
|
|
@@ -105,7 +106,7 @@ describe("CLI commands integration", () => {
|
|
|
105
106
|
const config = {
|
|
106
107
|
features: {
|
|
107
108
|
pwa: { enabled: true, preventDefaultInstall: false },
|
|
108
|
-
serviceWorker: {
|
|
109
|
+
serviceWorker: { version: { enabled: true, source: "from-package", minSupportedVersion: "0.0.0" }, autoUpdate: true, autoActivate: false, defaultStrategy: "cache-first" },
|
|
109
110
|
auth: 1,
|
|
110
111
|
},
|
|
111
112
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-integration.test.js","sourceRoot":"","sources":["../../src/__tests__/cli-integration.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AACzG,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,MAAM,OAAO,GAAG,qBAAqB,CAAC;IAEtC,UAAU,CAAC,GAAG,EAAE;QACd,IAAI,UAAU,CAAC,OAAO,CAAC;YAAE,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9D,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,UAAU,CAAC,OAAO,CAAC;YAAE,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;QAC7B,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;YAC1D,MAAM,MAAM,GAAG;gBACb,OAAO,EAAE,0CAA0C;gBACnD,OAAO,EAAE,IAAI;gBACb,
|
|
1
|
+
{"version":3,"file":"cli-integration.test.js","sourceRoot":"","sources":["../../src/__tests__/cli-integration.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,21 +4,20 @@ describe("config-types", () => {
|
|
|
4
4
|
describe("defaultConfig", () => {
|
|
5
5
|
it("has all required fields", () => {
|
|
6
6
|
expect(defaultConfig).toHaveProperty("enabled");
|
|
7
|
-
expect(defaultConfig).toHaveProperty("version");
|
|
8
|
-
expect(defaultConfig).toHaveProperty("minSupportedVersion");
|
|
9
7
|
expect(defaultConfig).toHaveProperty("features");
|
|
10
8
|
expect(defaultConfig).toHaveProperty("build");
|
|
11
9
|
});
|
|
12
10
|
it("has correct default values", () => {
|
|
13
11
|
expect(defaultConfig.enabled).toBe(true);
|
|
14
|
-
expect(defaultConfig.
|
|
15
|
-
expect(defaultConfig.minSupportedVersion).toBe("0.0.0");
|
|
16
|
-
expect(defaultConfig.features.serviceWorker.autoRegister).toBe(true);
|
|
12
|
+
expect(defaultConfig.features.serviceWorker.autoUpdate).toBe(true);
|
|
17
13
|
expect(defaultConfig.features.serviceWorker.autoActivate).toBe(false);
|
|
18
14
|
expect(defaultConfig.features.serviceWorker.defaultStrategy).toBe("cache-first");
|
|
19
15
|
expect(defaultConfig.features.serviceWorker.clearRuntimeOnUpdate).toBe(false);
|
|
20
16
|
expect(defaultConfig.features.serviceWorker.navigationMode).toBe("spa");
|
|
21
17
|
expect(defaultConfig.features.serviceWorker.spaEntry).toBe("/index.html");
|
|
18
|
+
expect(defaultConfig.features.serviceWorker.version.enabled).toBe(true);
|
|
19
|
+
expect(defaultConfig.features.serviceWorker.version.source).toBe("from-package");
|
|
20
|
+
expect(defaultConfig.features.serviceWorker.version.minSupportedVersion).toBe("0.0.0");
|
|
22
21
|
expect(defaultConfig.build.outputDir).toBe("dist");
|
|
23
22
|
expect(defaultConfig.build.swFilename).toBe("sw");
|
|
24
23
|
expect(defaultConfig.features.pwa.enabled).toBe(true);
|
|
@@ -55,7 +54,7 @@ describe("config-types", () => {
|
|
|
55
54
|
});
|
|
56
55
|
});
|
|
57
56
|
it("has minSupportedVersion of 1.0.0", () => {
|
|
58
|
-
expect(defaultInitConfig.minSupportedVersion).toBe("1.0.0");
|
|
57
|
+
expect(defaultInitConfig.features.serviceWorker.version.minSupportedVersion).toBe("1.0.0");
|
|
59
58
|
});
|
|
60
59
|
});
|
|
61
60
|
describe("constants", () => {
|
|
@@ -69,6 +68,7 @@ describe("config-types", () => {
|
|
|
69
68
|
expect(KNOWN_FEATURES).not.toContain("pwa");
|
|
70
69
|
expect(KNOWN_FEATURES).not.toContain("serviceWorker");
|
|
71
70
|
expect(KNOWN_FEATURES).not.toContain("versionedSw");
|
|
71
|
+
expect(KNOWN_FEATURES).not.toContain("autoUpdate");
|
|
72
72
|
});
|
|
73
73
|
it("OBJECT_FEATURES lists pwa, serviceWorker, and auth", () => {
|
|
74
74
|
expect(OBJECT_FEATURES).toContain("pwa");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-types.test.js","sourceRoot":"","sources":["../../src/__tests__/config-types.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,cAAc,EAAE,gBAAgB,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAElJ,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;QAC7B,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;YACjC,MAAM,CAAC,aAAa,CAAC,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;YAChD,MAAM,CAAC,aAAa,CAAC,CAAC,cAAc,CAAC,
|
|
1
|
+
{"version":3,"file":"config-types.test.js","sourceRoot":"","sources":["../../src/__tests__/config-types.test.ts"],"names":[],"mappings":"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"}
|