@serwist/turbopack 9.3.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.
@@ -0,0 +1,261 @@
1
+ import { NetworkOnly, CacheFirst, StaleWhileRevalidate, NetworkFirst, ExpirationPlugin, RangeRequestsPlugin } from 'serwist';
2
+
3
+ const PAGES_CACHE_NAME = {
4
+ rscPrefetch: "pages-rsc-prefetch",
5
+ rsc: "pages-rsc",
6
+ html: "pages"
7
+ };
8
+ const defaultCache = process.env.NODE_ENV !== "production" ? [
9
+ {
10
+ matcher: /.*/i,
11
+ handler: new NetworkOnly()
12
+ }
13
+ ] : [
14
+ {
15
+ matcher: /^https:\/\/fonts\.(?:gstatic)\.com\/.*/i,
16
+ handler: new CacheFirst({
17
+ cacheName: "google-fonts-webfonts",
18
+ plugins: [
19
+ new ExpirationPlugin({
20
+ maxEntries: 4,
21
+ maxAgeSeconds: 365 * 24 * 60 * 60,
22
+ maxAgeFrom: "last-used"
23
+ })
24
+ ]
25
+ })
26
+ },
27
+ {
28
+ matcher: /^https:\/\/fonts\.(?:googleapis)\.com\/.*/i,
29
+ handler: new StaleWhileRevalidate({
30
+ cacheName: "google-fonts-stylesheets",
31
+ plugins: [
32
+ new ExpirationPlugin({
33
+ maxEntries: 4,
34
+ maxAgeSeconds: 7 * 24 * 60 * 60,
35
+ maxAgeFrom: "last-used"
36
+ })
37
+ ]
38
+ })
39
+ },
40
+ {
41
+ matcher: /\.(?:eot|otf|ttc|ttf|woff|woff2|font.css)$/i,
42
+ handler: new StaleWhileRevalidate({
43
+ cacheName: "static-font-assets",
44
+ plugins: [
45
+ new ExpirationPlugin({
46
+ maxEntries: 4,
47
+ maxAgeSeconds: 7 * 24 * 60 * 60,
48
+ maxAgeFrom: "last-used"
49
+ })
50
+ ]
51
+ })
52
+ },
53
+ {
54
+ matcher: /\.(?:jpg|jpeg|gif|png|svg|ico|webp)$/i,
55
+ handler: new StaleWhileRevalidate({
56
+ cacheName: "static-image-assets",
57
+ plugins: [
58
+ new ExpirationPlugin({
59
+ maxEntries: 64,
60
+ maxAgeSeconds: 30 * 24 * 60 * 60,
61
+ maxAgeFrom: "last-used"
62
+ })
63
+ ]
64
+ })
65
+ },
66
+ {
67
+ matcher: /\/_next\/static.+\.js$/i,
68
+ handler: new CacheFirst({
69
+ cacheName: "next-static-js-assets",
70
+ plugins: [
71
+ new ExpirationPlugin({
72
+ maxEntries: 64,
73
+ maxAgeSeconds: 24 * 60 * 60,
74
+ maxAgeFrom: "last-used"
75
+ })
76
+ ]
77
+ })
78
+ },
79
+ {
80
+ matcher: /\/_next\/image\?url=.+$/i,
81
+ handler: new StaleWhileRevalidate({
82
+ cacheName: "next-image",
83
+ plugins: [
84
+ new ExpirationPlugin({
85
+ maxEntries: 64,
86
+ maxAgeSeconds: 24 * 60 * 60,
87
+ maxAgeFrom: "last-used"
88
+ })
89
+ ]
90
+ })
91
+ },
92
+ {
93
+ matcher: /\.(?:mp3|wav|ogg)$/i,
94
+ handler: new CacheFirst({
95
+ cacheName: "static-audio-assets",
96
+ plugins: [
97
+ new ExpirationPlugin({
98
+ maxEntries: 32,
99
+ maxAgeSeconds: 24 * 60 * 60,
100
+ maxAgeFrom: "last-used"
101
+ }),
102
+ new RangeRequestsPlugin()
103
+ ]
104
+ })
105
+ },
106
+ {
107
+ matcher: /\.(?:mp4|webm)$/i,
108
+ handler: new CacheFirst({
109
+ cacheName: "static-video-assets",
110
+ plugins: [
111
+ new ExpirationPlugin({
112
+ maxEntries: 32,
113
+ maxAgeSeconds: 24 * 60 * 60,
114
+ maxAgeFrom: "last-used"
115
+ }),
116
+ new RangeRequestsPlugin()
117
+ ]
118
+ })
119
+ },
120
+ {
121
+ matcher: /\.(?:js)$/i,
122
+ handler: new StaleWhileRevalidate({
123
+ cacheName: "static-js-assets",
124
+ plugins: [
125
+ new ExpirationPlugin({
126
+ maxEntries: 48,
127
+ maxAgeSeconds: 24 * 60 * 60,
128
+ maxAgeFrom: "last-used"
129
+ })
130
+ ]
131
+ })
132
+ },
133
+ {
134
+ matcher: /\.(?:css|less)$/i,
135
+ handler: new StaleWhileRevalidate({
136
+ cacheName: "static-style-assets",
137
+ plugins: [
138
+ new ExpirationPlugin({
139
+ maxEntries: 32,
140
+ maxAgeSeconds: 24 * 60 * 60,
141
+ maxAgeFrom: "last-used"
142
+ })
143
+ ]
144
+ })
145
+ },
146
+ {
147
+ matcher: /\/_next\/data\/.+\/.+\.json$/i,
148
+ handler: new NetworkFirst({
149
+ cacheName: "next-data",
150
+ plugins: [
151
+ new ExpirationPlugin({
152
+ maxEntries: 32,
153
+ maxAgeSeconds: 24 * 60 * 60,
154
+ maxAgeFrom: "last-used"
155
+ })
156
+ ]
157
+ })
158
+ },
159
+ {
160
+ matcher: /\.(?:json|xml|csv)$/i,
161
+ handler: new NetworkFirst({
162
+ cacheName: "static-data-assets",
163
+ plugins: [
164
+ new ExpirationPlugin({
165
+ maxEntries: 32,
166
+ maxAgeSeconds: 24 * 60 * 60,
167
+ maxAgeFrom: "last-used"
168
+ })
169
+ ]
170
+ })
171
+ },
172
+ {
173
+ matcher: /\/api\/auth\/.*/,
174
+ handler: new NetworkOnly({
175
+ networkTimeoutSeconds: 10
176
+ })
177
+ },
178
+ {
179
+ matcher: ({ sameOrigin, url: { pathname } })=>sameOrigin && pathname.startsWith("/api/"),
180
+ method: "GET",
181
+ handler: new NetworkFirst({
182
+ cacheName: "apis",
183
+ plugins: [
184
+ new ExpirationPlugin({
185
+ maxEntries: 16,
186
+ maxAgeSeconds: 24 * 60 * 60,
187
+ maxAgeFrom: "last-used"
188
+ })
189
+ ],
190
+ networkTimeoutSeconds: 10
191
+ })
192
+ },
193
+ {
194
+ matcher: ({ request, url: { pathname }, sameOrigin })=>request.headers.get("RSC") === "1" && request.headers.get("Next-Router-Prefetch") === "1" && sameOrigin && !pathname.startsWith("/api/"),
195
+ handler: new NetworkFirst({
196
+ cacheName: PAGES_CACHE_NAME.rscPrefetch,
197
+ plugins: [
198
+ new ExpirationPlugin({
199
+ maxEntries: 32,
200
+ maxAgeSeconds: 24 * 60 * 60
201
+ })
202
+ ]
203
+ })
204
+ },
205
+ {
206
+ matcher: ({ request, url: { pathname }, sameOrigin })=>request.headers.get("RSC") === "1" && sameOrigin && !pathname.startsWith("/api/"),
207
+ handler: new NetworkFirst({
208
+ cacheName: PAGES_CACHE_NAME.rsc,
209
+ plugins: [
210
+ new ExpirationPlugin({
211
+ maxEntries: 32,
212
+ maxAgeSeconds: 24 * 60 * 60
213
+ })
214
+ ]
215
+ })
216
+ },
217
+ {
218
+ matcher: ({ request, url: { pathname }, sameOrigin })=>request.headers.get("Content-Type")?.includes("text/html") && sameOrigin && !pathname.startsWith("/api/"),
219
+ handler: new NetworkFirst({
220
+ cacheName: PAGES_CACHE_NAME.html,
221
+ plugins: [
222
+ new ExpirationPlugin({
223
+ maxEntries: 32,
224
+ maxAgeSeconds: 24 * 60 * 60
225
+ })
226
+ ]
227
+ })
228
+ },
229
+ {
230
+ matcher: ({ url: { pathname }, sameOrigin })=>sameOrigin && !pathname.startsWith("/api/"),
231
+ handler: new NetworkFirst({
232
+ cacheName: "others",
233
+ plugins: [
234
+ new ExpirationPlugin({
235
+ maxEntries: 32,
236
+ maxAgeSeconds: 24 * 60 * 60
237
+ })
238
+ ]
239
+ })
240
+ },
241
+ {
242
+ matcher: ({ sameOrigin })=>!sameOrigin,
243
+ handler: new NetworkFirst({
244
+ cacheName: "cross-origin",
245
+ plugins: [
246
+ new ExpirationPlugin({
247
+ maxEntries: 32,
248
+ maxAgeSeconds: 60 * 60
249
+ })
250
+ ],
251
+ networkTimeoutSeconds: 10
252
+ })
253
+ },
254
+ {
255
+ matcher: /.*/i,
256
+ method: "GET",
257
+ handler: new NetworkOnly()
258
+ }
259
+ ];
260
+
261
+ export { PAGES_CACHE_NAME, defaultCache };
@@ -0,0 +1,2 @@
1
+ export declare const SUPPORTED_ESBUILD_OPTIONS: readonly ["sourcemap", "legalComments", "sourceRoot", "sourcesContent", "format", "globalName", "target", "supported", "define", "treeShaking", "minify", "mangleProps", "reserveProps", "mangleQuoted", "mangleCache", "drop", "dropLabels", "minifyWhitespace", "minifyIdentifiers", "minifySyntax", "lineLimit", "charset", "ignoreAnnotations", "jsx", "jsxFactory", "jsxFragment", "jsxImportSource", "jsxDev", "jsxSideEffects", "pure", "keepNames", "absPaths", "color", "logLevel", "logLimit", "logOverride", "tsconfigRaw", "bundle", "splitting", "preserveSymlinks", "external", "packages", "alias", "loader", "resolveExtensions", "mainFields", "conditions", "allowOverwrite", "tsconfig", "outExtension", "publicPath", "inject", "banner", "footer", "plugins"];
2
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,yBAAyB,ovBA0Dc,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { Serwist } from "@serwist/window";
2
+ export interface SerwistContextValues {
3
+ serwist: Serwist | null;
4
+ }
5
+ export declare const SerwistContext: import("react").Context<SerwistContextValues>;
6
+ export declare const useSerwist: () => SerwistContextValues;
7
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/lib/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAG/C,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;CACzB;AAED,eAAO,MAAM,cAAc,+CAA6C,CAAC;AAEzE,eAAO,MAAM,UAAU,4BAMtB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import * as logger from "./logger.js";
2
+ export { logger };
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AAEtC,OAAO,EAAE,MAAM,EAAE,CAAC"}
@@ -0,0 +1,7 @@
1
+ export type LoggingMethods = "wait" | "error" | "warn" | "info" | "event";
2
+ export declare const wait: (...message: any[]) => void;
3
+ export declare const error: (...message: any[]) => void;
4
+ export declare const warn: (...message: any[]) => void;
5
+ export declare const info: (...message: any[]) => void;
6
+ export declare const event: (...message: any[]) => void;
7
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAyC1E,eAAO,MAAM,IAAI,GAAI,GAAG,SAAS,GAAG,EAAE,SAAoC,CAAC;AAE3E,eAAO,MAAM,KAAK,GAAI,GAAG,SAAS,GAAG,EAAE,SAAqC,CAAC;AAE7E,eAAO,MAAM,IAAI,GAAI,GAAG,SAAS,GAAG,EAAE,SAAoC,CAAC;AAE3E,eAAO,MAAM,IAAI,GAAI,GAAG,SAAS,GAAG,EAAE,SAAoC,CAAC;AAE3E,eAAO,MAAM,KAAK,GAAI,GAAG,SAAS,GAAG,EAAE,SAAqC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const generateGlobPatterns: (distDir: string) => string[];
2
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,GAAI,SAAS,MAAM,aAGnD,CAAC"}
@@ -0,0 +1,57 @@
1
+ import type { BasePartial, BaseResolved, GlobPartial, GlobResolved, InjectPartial, InjectResolved, OptionalGlobDirectoryPartial, RequiredGlobDirectoryResolved } from "@serwist/build";
2
+ import type { Prettify, Require } from "@serwist/utils";
3
+ import type { BuildOptions } from "esbuild-wasm";
4
+ import type { SUPPORTED_ESBUILD_OPTIONS } from "./lib/constants.js";
5
+ import type { NextConfig as CompleteNextConfig } from "next";
6
+ export type EsbuildSupportedOptions = (typeof SUPPORTED_ESBUILD_OPTIONS)[number];
7
+ export type EsbuildOptions = Pick<BuildOptions, EsbuildSupportedOptions>;
8
+ export interface NextConfig extends Pick<CompleteNextConfig, "basePath" | "distDir"> {
9
+ /**
10
+ * The Next.js `assetPrefix` config option.
11
+ *
12
+ * @see https://nextjs.org/docs/app/api-reference/config/next-config-js/assetPrefix
13
+ */
14
+ assetPrefix?: string;
15
+ /**
16
+ * The Next.js `basePath` config option.
17
+ *
18
+ * @default "/"
19
+ * @see https://nextjs.org/docs/app/api-reference/config/next-config-js/basePath
20
+ */
21
+ basePath?: string;
22
+ /**
23
+ * The Next.js `distDir` config option.
24
+ *
25
+ * @default ".next"
26
+ * @see https://nextjs.org/docs/app/api-reference/config/next-config-js/distDir
27
+ */
28
+ distDir?: string;
29
+ }
30
+ export interface TurboPartial {
31
+ /**
32
+ * The path to your working directory.
33
+ *
34
+ * @default process.cwd()
35
+ */
36
+ cwd?: string;
37
+ /**
38
+ * A copy of your Next.js configuration. You must check
39
+ * if any option you've configured is needed by Serwist
40
+ * to ensure expected behavior.
41
+ *
42
+ * The following options are currently needed: `assetPrefix`,
43
+ * `basePath`, `distDir`.
44
+ */
45
+ nextConfig: Prettify<NextConfig>;
46
+ /**
47
+ * Options to configure the esbuild instance used to bundle
48
+ * the service worker.
49
+ */
50
+ esbuildOptions?: EsbuildOptions;
51
+ }
52
+ export interface TurboResolved extends Require<TurboPartial, "cwd" | "esbuildOptions"> {
53
+ nextConfig: Require<NextConfig, "basePath" | "distDir">;
54
+ }
55
+ export type InjectManifestOptions = Prettify<Omit<BasePartial & GlobPartial & InjectPartial & OptionalGlobDirectoryPartial & TurboPartial, "disablePrecacheManifest">>;
56
+ export type InjectManifestOptionsComplete = Prettify<Omit<Require<BaseResolved, "dontCacheBustURLsMatching"> & GlobResolved & InjectResolved & RequiredGlobDirectoryResolved & TurboResolved, "disablePrecacheManifest">>;
57
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,aAAa,EACb,cAAc,EACd,4BAA4B,EAC5B,6BAA6B,EAC9B,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,KAAK,EAAE,UAAU,IAAI,kBAAkB,EAAE,MAAM,MAAM,CAAC;AAE7D,MAAM,MAAM,uBAAuB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjF,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,YAAY,EAAE,uBAAuB,CAAC,CAAC;AAEzE,MAAM,WAAW,UAAW,SAAQ,IAAI,CAAC,kBAAkB,EAAE,UAAU,GAAG,SAAS,CAAC;IAClF;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;;;OAOG;IACH,UAAU,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;IACjC;;;OAGG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED,MAAM,WAAW,aAAc,SAAQ,OAAO,CAAC,YAAY,EAAE,KAAK,GAAG,gBAAgB,CAAC;IACpF,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,UAAU,GAAG,SAAS,CAAC,CAAC;CACzD;AAED,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAC1C,IAAI,CAAC,WAAW,GAAG,WAAW,GAAG,aAAa,GAAG,4BAA4B,GAAG,YAAY,EAAE,yBAAyB,CAAC,CACzH,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG,QAAQ,CAClD,IAAI,CACF,OAAO,CAAC,YAAY,EAAE,2BAA2B,CAAC,GAAG,YAAY,GAAG,cAAc,GAAG,6BAA6B,GAAG,aAAa,EAClI,yBAAyB,CAC1B,CACF,CAAC"}
package/package.json ADDED
@@ -0,0 +1,106 @@
1
+ {
2
+ "name": "@serwist/turbopack",
3
+ "version": "9.3.0",
4
+ "type": "module",
5
+ "sideEffects": false,
6
+ "description": "A module that integrates Serwist into your Next.js / Turbopack application.",
7
+ "files": [
8
+ "src",
9
+ "dist"
10
+ ],
11
+ "keywords": [
12
+ "serwist",
13
+ "serwistjs",
14
+ "sw",
15
+ "service worker",
16
+ "progressive web apps",
17
+ "web",
18
+ "service-worker",
19
+ "progressive-web-apps",
20
+ "next",
21
+ "next.js",
22
+ "turbo",
23
+ "turbopack",
24
+ "pwa"
25
+ ],
26
+ "engines": {
27
+ "node": ">=18.0.0"
28
+ },
29
+ "author": "Serwist <ducanh2912.rusty@gmail.com> (https://serwist.pages.dev/)",
30
+ "license": "MIT",
31
+ "repository": "https://github.com/serwist/serwist",
32
+ "bugs": "https://github.com/serwist/serwist/issues",
33
+ "homepage": "https://serwist.pages.dev",
34
+ "main": "./dist/index.js",
35
+ "types": "./dist/index.d.ts",
36
+ "typesVersions": {
37
+ "*": {
38
+ "worker": [
39
+ "./dist/index.worker.d.ts"
40
+ ],
41
+ "schema": [
42
+ "./dist/index.schema.d.ts"
43
+ ]
44
+ }
45
+ },
46
+ "exports": {
47
+ ".": {
48
+ "types": "./dist/index.d.ts",
49
+ "default": "./dist/index.js"
50
+ },
51
+ "./react": {
52
+ "types": "./dist/index.react.d.ts",
53
+ "default": "./dist/index.react.js"
54
+ },
55
+ "./worker": {
56
+ "types": "./dist/index.worker.d.ts",
57
+ "default": "./dist/index.worker.js"
58
+ },
59
+ "./schema": {
60
+ "types": "./dist/index.schema.d.ts",
61
+ "default": "./dist/index.schema.js"
62
+ },
63
+ "./package.json": "./package.json"
64
+ },
65
+ "dependencies": {
66
+ "@swc/core": "1.15.7",
67
+ "kolorist": "1.8.0",
68
+ "semver": "7.7.3",
69
+ "zod": "4.2.1",
70
+ "@serwist/build": "9.3.0",
71
+ "@serwist/window": "9.3.0",
72
+ "serwist": "9.3.0"
73
+ },
74
+ "devDependencies": {
75
+ "@types/node": "25.0.3",
76
+ "@types/react": "19.2.7",
77
+ "@types/semver": "7.7.1",
78
+ "esbuild-wasm": "0.27.2",
79
+ "next": "16.1.0",
80
+ "react": "19.2.3",
81
+ "react-dom": "19.2.3",
82
+ "rollup": "4.54.0",
83
+ "type-fest": "5.3.1",
84
+ "typescript": "5.9.3",
85
+ "@serwist/configs": "9.3.0",
86
+ "@serwist/utils": "9.3.0"
87
+ },
88
+ "peerDependencies": {
89
+ "esbuild-wasm": ">=0.25.0 <1.0.0",
90
+ "next": ">=14.0.0",
91
+ "react": ">=18.0.0",
92
+ "typescript": ">=5.0.0"
93
+ },
94
+ "peerDependenciesMeta": {
95
+ "typescript": {
96
+ "optional": true
97
+ }
98
+ },
99
+ "scripts": {
100
+ "build": "rimraf dist && NODE_ENV=production rollup --config rollup.config.js",
101
+ "dev": "rollup --config rollup.config.js --watch",
102
+ "lint": "biome lint ./src",
103
+ "qcheck": "biome check ./src",
104
+ "typecheck": "tsc"
105
+ }
106
+ }
@@ -0,0 +1,44 @@
1
+ import { Serwist } from "@serwist/window";
2
+ import { isCurrentPageOutOfScope } from "@serwist/window/internal";
3
+ import { type ReactNode, useEffect, useState } from "react";
4
+ import { SerwistContext } from "./lib/context.js";
5
+
6
+ export interface SerwistProviderProps {
7
+ swUrl: string;
8
+ register?: boolean;
9
+ reloadOnOnline?: boolean;
10
+ options?: RegistrationOptions;
11
+ children?: ReactNode;
12
+ }
13
+
14
+ declare global {
15
+ interface Window {
16
+ serwist: Serwist;
17
+ }
18
+ }
19
+
20
+ export function SerwistProvider({ swUrl, register = true, reloadOnOnline = true, options, children }: SerwistProviderProps) {
21
+ const [serwist] = useState(() => {
22
+ if (typeof window === "undefined") return null;
23
+ if (!(window.serwist && window.serwist instanceof Serwist) && "serviceWorker" in navigator) {
24
+ window.serwist = new Serwist(swUrl, { ...options, type: options?.type || "module", scope: options?.scope || "/" });
25
+ }
26
+ return window.serwist ?? null;
27
+ });
28
+ useEffect(() => {
29
+ const scope = options?.scope || "/";
30
+ if (register && !isCurrentPageOutOfScope(scope)) {
31
+ void serwist?.register();
32
+ }
33
+ }, [register, options?.scope, serwist?.register]);
34
+ useEffect(() => {
35
+ const reload = () => location.reload();
36
+ if (reloadOnOnline) {
37
+ window.addEventListener("online", reload);
38
+ }
39
+ return () => {
40
+ window.removeEventListener("online", reload);
41
+ };
42
+ }, [reloadOnOnline]);
43
+ return <SerwistContext.Provider value={{ serwist }}>{children}</SerwistContext.Provider>;
44
+ }
@@ -0,0 +1,48 @@
1
+ import path from "node:path";
2
+ import { assertType, type Equals, basePartial, globPartial, injectPartial } from "@serwist/build/schema";
3
+ import z from "zod";
4
+ import { SUPPORTED_ESBUILD_OPTIONS } from "./lib/constants.js";
5
+ import { generateGlobPatterns } from "./lib/utils.js";
6
+ import type { InjectManifestOptions, InjectManifestOptionsComplete, TurboPartial, TurboResolved } from "./types.js";
7
+
8
+ export const turboPartial = z.strictObject({
9
+ cwd: z.string().prefault(process.cwd()),
10
+ nextConfig: z.strictObject({
11
+ assetPrefix: z.string().optional(),
12
+ basePath: z.string().prefault("/"),
13
+ distDir: z.string().prefault(".next"),
14
+ }),
15
+ esbuildOptions: z.partialRecord(z.literal(SUPPORTED_ESBUILD_OPTIONS), z.any()).prefault({}),
16
+ });
17
+
18
+ export const injectManifestOptions = z
19
+ .strictObject({
20
+ ...basePartial.shape,
21
+ ...globPartial.shape,
22
+ ...injectPartial.shape,
23
+ ...turboPartial.shape,
24
+ globPatterns: z.array(z.string()).optional(),
25
+ globDirectory: z.string().optional(),
26
+ })
27
+ .omit({ disablePrecacheManifest: true })
28
+ .transform((input) => {
29
+ let distDir = input.nextConfig.distDir;
30
+ if (distDir[0] === "/") distDir = distDir.slice(1);
31
+ if (distDir[distDir.length - 1] !== "/") distDir += "/";
32
+ return {
33
+ ...input,
34
+ swSrc: path.isAbsolute(input.swSrc) ? input.swSrc : path.join(input.cwd, input.swSrc),
35
+ globPatterns: input.globPatterns ?? generateGlobPatterns(distDir),
36
+ globDirectory: input.globDirectory ?? input.cwd,
37
+ dontCacheBustURLsMatching: input.dontCacheBustURLsMatching ?? new RegExp(`^${distDir}static/`),
38
+ nextConfig: {
39
+ ...input.nextConfig,
40
+ distDir,
41
+ },
42
+ };
43
+ });
44
+
45
+ assertType<Equals<TurboPartial, z.input<typeof turboPartial>>>();
46
+ assertType<Equals<TurboResolved, z.output<typeof turboPartial>>>();
47
+ assertType<Equals<InjectManifestOptions, z.input<typeof injectManifestOptions>>>();
48
+ assertType<Equals<InjectManifestOptionsComplete, z.output<typeof injectManifestOptions>>>();