@serwist/next 9.0.0-preview.8 → 9.0.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 (51) hide show
  1. package/dist/chunks/schema.js +20 -0
  2. package/dist/index.d.ts +10 -3
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +51 -36
  5. package/dist/index.schema.d.ts +3 -0
  6. package/dist/index.schema.d.ts.map +1 -0
  7. package/dist/index.schema.js +4 -0
  8. package/dist/index.worker.js +28 -17
  9. package/dist/lib/find-first-truthy.d.ts.map +1 -0
  10. package/dist/lib/get-content-hash.d.ts.map +1 -0
  11. package/dist/lib/get-file-hash.d.ts.map +1 -0
  12. package/dist/lib/get-package-version.d.ts.map +1 -0
  13. package/dist/lib/index.d.ts.map +1 -0
  14. package/dist/lib/load-tsconfig.d.ts.map +1 -0
  15. package/dist/lib/logger.d.ts.map +1 -0
  16. package/dist/lib/schema.d.ts +240 -0
  17. package/dist/lib/schema.d.ts.map +1 -0
  18. package/dist/lib/types.d.ts +95 -0
  19. package/dist/lib/types.d.ts.map +1 -0
  20. package/dist/lib/validator.d.ts +3 -0
  21. package/dist/lib/validator.d.ts.map +1 -0
  22. package/dist/worker/defaultCache.d.ts +8 -14
  23. package/dist/worker/defaultCache.d.ts.map +1 -1
  24. package/package.json +24 -26
  25. package/src/index.schema.ts +3 -0
  26. package/src/index.ts +37 -41
  27. package/src/lib/schema.ts +21 -0
  28. package/src/lib/types.ts +104 -0
  29. package/src/lib/validator.ts +13 -0
  30. package/src/worker/defaultCache.ts +264 -241
  31. package/dist/utils/find-first-truthy.d.ts.map +0 -1
  32. package/dist/utils/get-content-hash.d.ts.map +0 -1
  33. package/dist/utils/get-file-hash.d.ts.map +0 -1
  34. package/dist/utils/get-package-version.d.ts.map +0 -1
  35. package/dist/utils/index.d.ts.map +0 -1
  36. package/dist/utils/load-tsconfig.d.ts.map +0 -1
  37. package/dist/utils/logger.d.ts.map +0 -1
  38. /package/dist/{utils → lib}/find-first-truthy.d.ts +0 -0
  39. /package/dist/{utils → lib}/get-content-hash.d.ts +0 -0
  40. /package/dist/{utils → lib}/get-file-hash.d.ts +0 -0
  41. /package/dist/{utils → lib}/get-package-version.d.ts +0 -0
  42. /package/dist/{utils → lib}/index.d.ts +0 -0
  43. /package/dist/{utils → lib}/load-tsconfig.d.ts +0 -0
  44. /package/dist/{utils → lib}/logger.d.ts +0 -0
  45. /package/src/{utils → lib}/find-first-truthy.ts +0 -0
  46. /package/src/{utils → lib}/get-content-hash.ts +0 -0
  47. /package/src/{utils → lib}/get-file-hash.ts +0 -0
  48. /package/src/{utils → lib}/get-package-version.ts +0 -0
  49. /package/src/{utils → lib}/index.ts +0 -0
  50. /package/src/{utils → lib}/load-tsconfig.ts +0 -0
  51. /package/src/{utils → lib}/logger.ts +0 -0
@@ -0,0 +1,95 @@
1
+ import type { RequiredSwDestPartial, RequiredSwDestResolved } from "@serwist/build";
2
+ import type { Require } from "@serwist/utils";
3
+ import type { InjectManifestOptions as WebpackInjectManifestOptions, InjectManifestOptionsComplete as WebpackInjectManifestOptionsComplete } from "@serwist/webpack-plugin";
4
+ export interface InjectPartial {
5
+ /**
6
+ * Enables additional route caching when users navigate through pages with
7
+ * `next/link`. This improves the user experience in some cases but it
8
+ * also adds a bit of overhead due to additional network calls.
9
+ * @default false
10
+ */
11
+ cacheOnNavigation?: boolean;
12
+ /**
13
+ * Whether Serwist should be disabled.
14
+ * @default false
15
+ */
16
+ disable?: boolean;
17
+ /**
18
+ * Whether `@serwist/next` should automatically register the service worker for you. If
19
+ * you want to register the service worker yourself, set this to `false` and run
20
+ * `window.serwist.register()` in `componentDidMount` or `useEffect`.
21
+ * @example
22
+ * ```tsx
23
+ * // app/register-pwa.tsx
24
+ * "use client";
25
+ * import { useEffect } from "react";
26
+ * import type { Serwist } from "@serwist/window";
27
+ *
28
+ * declare global {
29
+ * interface Window {
30
+ * serwist: Serwist;
31
+ * }
32
+ * }
33
+ *
34
+ * export default function RegisterPWA() {
35
+ * useEffect(() => {
36
+ * if ("serviceWorker" in navigator && window.serwist !== undefined) {
37
+ * window.serwist.register();
38
+ * }
39
+ * }, []);
40
+ * return <></>;
41
+ * }
42
+ *
43
+ * // app/layout.tsx
44
+ * import RegisterPWA from "./register-pwa";
45
+ *
46
+ * export default function RootLayout({
47
+ * children,
48
+ * }: {
49
+ * children: React.ReactNode;
50
+ * }) {
51
+ * return (
52
+ * <html lang="en">
53
+ * <head />
54
+ * <body>
55
+ * <RegisterPWA />
56
+ * {children}
57
+ * </body>
58
+ * </html>
59
+ * );
60
+ * }
61
+ * ```
62
+ * @default true
63
+ */
64
+ register?: boolean;
65
+ /**
66
+ * Whether Serwist should reload the app when it goes online.
67
+ * @default true
68
+ */
69
+ reloadOnOnline?: boolean;
70
+ /**
71
+ * The service worker's URL scope. Set to `/foo/` so that paths under `/foo/` are under the service
72
+ * worker's control while others are not.
73
+ * @default nextConfig.basePath
74
+ */
75
+ scope?: string;
76
+ /**
77
+ * The URL to the service worker.
78
+ * @default "/sw.js"
79
+ */
80
+ swUrl?: string;
81
+ /**
82
+ * Files in the public directory matching any of these patterns
83
+ * will be included in the precache manifest. For more information,
84
+ * see [`node-glob`'s Glob Primer](https://github.com/isaacs/node-glob#glob-primer).
85
+ * @default
86
+ * ```
87
+ * ["**\/*"]
88
+ * ```
89
+ */
90
+ globPublicPatterns?: string[];
91
+ }
92
+ export type InjectResolved = Require<InjectPartial, "cacheOnNavigation" | "disable" | "register" | "reloadOnOnline" | "swUrl" | "globPublicPatterns">;
93
+ export type InjectManifestOptions = Omit<WebpackInjectManifestOptions & RequiredSwDestPartial & InjectPartial, "disablePrecacheManifest">;
94
+ export type InjectManifestOptionsComplete = Omit<WebpackInjectManifestOptionsComplete & RequiredSwDestResolved & InjectResolved, "disablePrecacheManifest">;
95
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AACpF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,KAAK,EACV,qBAAqB,IAAI,4BAA4B,EACrD,6BAA6B,IAAI,oCAAoC,EACtE,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8CG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;OAQG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC,aAAa,EAAE,mBAAmB,GAAG,SAAS,GAAG,UAAU,GAAG,gBAAgB,GAAG,OAAO,GAAG,oBAAoB,CAAC,CAAC;AAEtJ,MAAM,MAAM,qBAAqB,GAAG,IAAI,CAAC,4BAA4B,GAAG,qBAAqB,GAAG,aAAa,EAAE,yBAAyB,CAAC,CAAC;AAE1I,MAAM,MAAM,6BAA6B,GAAG,IAAI,CAC9C,oCAAoC,GAAG,sBAAsB,GAAG,cAAc,EAC9E,yBAAyB,CAC1B,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { InjectManifestOptionsComplete } from "./types.js";
2
+ export declare const validateInjectManifestOptions: (input: unknown) => InjectManifestOptionsComplete;
3
+ //# sourceMappingURL=validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/lib/validator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,YAAY,CAAC;AAEhE,eAAO,MAAM,6BAA6B,UAAW,OAAO,KAAG,6BAQ9D,CAAC"}
@@ -1,15 +1,9 @@
1
- import { CacheFirst, NetworkFirst } from "@serwist/strategies";
2
- export declare const defaultCache: ({
3
- matcher: RegExp;
4
- handler: CacheFirst;
5
- method?: undefined;
6
- } | {
7
- matcher: ({ sameOrigin, url: { pathname } }: import("@serwist/core").RouteMatchCallbackOptions) => boolean;
8
- method: "GET";
9
- handler: NetworkFirst;
10
- } | {
11
- matcher: ({ request, url: { pathname }, sameOrigin }: import("@serwist/core").RouteMatchCallbackOptions) => boolean | undefined;
12
- handler: NetworkFirst;
13
- method?: undefined;
14
- })[];
1
+ import type { RuntimeCaching } from "serwist";
2
+ /**
3
+ * The default, recommended list of caching strategies for applications
4
+ * built with Next.js.
5
+ *
6
+ * @see https://serwist.pages.dev/docs/next/worker-exports#default-cache
7
+ */
8
+ export declare const defaultCache: RuntimeCaching[];
15
9
  //# sourceMappingURL=defaultCache.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"defaultCache.d.ts","sourceRoot":"","sources":["../../src/worker/defaultCache.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAwB,MAAM,qBAAqB,CAAC;AAMrF,eAAO,MAAM,YAAY;;;;;;;;;;;;IA6OG,CAAC"}
1
+ {"version":3,"file":"defaultCache.d.ts","sourceRoot":"","sources":["../../src/worker/defaultCache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAK9C;;;;;GAKG;AACH,eAAO,MAAM,YAAY,EAAE,cAAc,EAiQlC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serwist/next",
3
- "version": "9.0.0-preview.8",
3
+ "version": "9.0.0",
4
4
  "type": "module",
5
5
  "description": "A module that integrates Serwist into your Next.js application.",
6
6
  "files": [
@@ -25,7 +25,7 @@
25
25
  },
26
26
  "author": "Serwist's Team",
27
27
  "license": "MIT",
28
- "repository": "serwist/serwist",
28
+ "repository": "https://github.com/serwist/serwist",
29
29
  "bugs": "https://github.com/serwist/serwist/issues",
30
30
  "homepage": "https://serwist.pages.dev",
31
31
  "main": "./dist/index.js",
@@ -37,6 +37,9 @@
37
37
  ],
38
38
  "typings": [
39
39
  "./dist/sw-entry.d.ts"
40
+ ],
41
+ "schema": [
42
+ "./dist/index.schema.d.ts"
40
43
  ]
41
44
  }
42
45
  },
@@ -52,43 +55,38 @@
52
55
  "./typings": {
53
56
  "types": "./dist/sw-entry.d.ts"
54
57
  },
58
+ "./schema": {
59
+ "types": "./dist/index.schema.d.ts",
60
+ "default": "./dist/index.schema.js"
61
+ },
55
62
  "./package.json": "./package.json"
56
63
  },
57
64
  "dependencies": {
58
65
  "chalk": "5.3.0",
59
- "clean-webpack-plugin": "4.0.0",
60
- "fast-glob": "3.3.2",
61
- "@serwist/build": "9.0.0-preview.8",
62
- "@serwist/core": "9.0.0-preview.8",
63
- "@serwist/expiration": "9.0.0-preview.8",
64
- "@serwist/range-requests": "9.0.0-preview.8",
65
- "@serwist/strategies": "9.0.0-preview.8",
66
- "@serwist/webpack-plugin": "9.0.0-preview.8",
67
- "@serwist/window": "9.0.0-preview.8"
66
+ "glob": "10.3.12",
67
+ "zod": "3.22.4",
68
+ "@serwist/build": "9.0.0",
69
+ "@serwist/webpack-plugin": "9.0.0",
70
+ "@serwist/window": "9.0.0",
71
+ "serwist": "9.0.0"
68
72
  },
69
73
  "devDependencies": {
70
- "@types/node": "20.11.16",
71
- "next": "14.1.0",
74
+ "@types/node": "20.12.7",
75
+ "next": "14.2.1",
72
76
  "react": "18.2.0",
73
77
  "react-dom": "18.2.0",
74
- "rollup": "4.9.6",
75
- "type-fest": "4.10.2",
76
- "typescript": "5.4.0-dev.20240206",
77
- "webpack": "5.90.1",
78
- "@serwist/constants": "9.0.0-preview.8",
79
- "@serwist/sw": "9.0.0-preview.8",
80
- "@serwist/utils": "9.0.0-preview.8"
78
+ "rollup": "4.14.3",
79
+ "type-fest": "4.15.0",
80
+ "typescript": "5.5.0-dev.20240415",
81
+ "webpack": "5.91.0",
82
+ "@serwist/configs": "9.0.0",
83
+ "@serwist/utils": "9.0.0"
81
84
  },
82
85
  "peerDependencies": {
83
86
  "next": ">=14.0.0",
84
- "typescript": ">=5.0.0",
85
- "webpack": ">=5.9.0",
86
- "@serwist/sw": "9.0.0-preview.8"
87
+ "typescript": ">=5.0.0"
87
88
  },
88
89
  "peerDependenciesMeta": {
89
- "@serwist/sw": {
90
- "optional": true
91
- },
92
90
  "typescript": {
93
91
  "optional": true
94
92
  }
@@ -0,0 +1,3 @@
1
+ import { injectManifestOptions, injectPartial } from "./lib/schema.js";
2
+
3
+ export { injectPartial, injectManifestOptions };
package/src/index.ts CHANGED
@@ -1,21 +1,24 @@
1
+ import fs from "node:fs";
1
2
  import path from "node:path";
2
3
  import { fileURLToPath } from "node:url";
3
-
4
- import type { NextInjectManifestOptions } from "@serwist/build";
5
- import { validateNextInjectManifestOptions } from "@serwist/build/next";
6
4
  import { InjectManifest } from "@serwist/webpack-plugin";
7
5
  import { ChildCompilationPlugin, relativeToOutputPath } from "@serwist/webpack-plugin/internal";
8
- import { CleanWebpackPlugin } from "clean-webpack-plugin";
9
- import fg from "fast-glob";
6
+ import { globSync } from "glob";
10
7
  import type { NextConfig } from "next";
11
8
  import type { Compilation, Configuration, default as Webpack } from "webpack";
12
-
13
9
  import type { ExcludeParams, SerwistNextOptions, SerwistNextOptionsKey } from "./internal-types.js";
14
- import { getContentHash, getFileHash, loadTSConfig, logger } from "./utils/index.js";
10
+ import { getContentHash, getFileHash, loadTSConfig, logger } from "./lib/index.js";
11
+ import type { InjectManifestOptions, InjectManifestOptionsComplete } from "./lib/types.js";
12
+ import { validateInjectManifestOptions } from "./lib/validator.js";
15
13
 
16
14
  const __dirname = fileURLToPath(new URL(".", import.meta.url));
17
15
 
18
- const withSerwistInit = (pluginOptions: NextInjectManifestOptions): ((nextConfig?: NextConfig) => NextConfig) => {
16
+ /**
17
+ * Integrates Serwist into your Next.js app.
18
+ * @param userOptions
19
+ * @returns
20
+ */
21
+ const withSerwistInit = (userOptions: InjectManifestOptions): ((nextConfig?: NextConfig) => NextConfig) => {
19
22
  return (nextConfig = {}) => ({
20
23
  ...nextConfig,
21
24
  webpack(config: Configuration, options) {
@@ -35,7 +38,7 @@ const withSerwistInit = (pluginOptions: NextInjectManifestOptions): ((nextConfig
35
38
  reloadOnOnline,
36
39
  globPublicPatterns,
37
40
  ...buildOptions
38
- } = validateNextInjectManifestOptions(pluginOptions);
41
+ } = validateInjectManifestOptions(userOptions);
39
42
 
40
43
  if (typeof nextConfig.webpack === "function") {
41
44
  config = nextConfig.webpack(config, options);
@@ -50,8 +53,6 @@ const withSerwistInit = (pluginOptions: NextInjectManifestOptions): ((nextConfig
50
53
  config.plugins = [];
51
54
  }
52
55
 
53
- logger.event(`Compiling for ${options.isServer ? "server" : "client (static)"}...`);
54
-
55
56
  const _sw = path.posix.join(basePath, swUrl);
56
57
  const _scope = path.posix.join(scope, "/");
57
58
 
@@ -89,13 +90,13 @@ const withSerwistInit = (pluginOptions: NextInjectManifestOptions): ((nextConfig
89
90
  if (!options.isServer) {
90
91
  if (!register) {
91
92
  logger.info(
92
- "Service worker won't be automatically registered as per the config, please call the following code in componentDidMount or useEffect:",
93
+ "The service worker will not be automatically registered, please call 'window.serwist.register()' in 'componentDidMount' or 'useEffect'.",
93
94
  );
94
95
 
95
- logger.info(" window.serwist.register()");
96
-
97
96
  if (!tsConfigJson?.compilerOptions?.types?.includes("@serwist/next/typings")) {
98
- logger.info("You may also want to add @serwist/next/typings to compilerOptions.types in your tsconfig.json/jsconfig.json.");
97
+ logger.info(
98
+ "You may also want to add '@serwist/next/typings' to your TypeScript/JavaScript configuration file at 'compilerOptions.types'.",
99
+ );
99
100
  }
100
101
  }
101
102
 
@@ -122,7 +123,19 @@ const withSerwistInit = (pluginOptions: NextInjectManifestOptions): ((nextConfig
122
123
  }
123
124
 
124
125
  const publicDir = path.resolve(options.dir, "public");
125
- const destDir = path.dirname(swDest);
126
+ const { dir: destDir, base: destBase } = path.parse(swDest);
127
+
128
+ const cleanUpList = globSync(["swe-worker-*.js", "swe-worker-*.js.map", destBase, `${destBase}.map`], {
129
+ absolute: true,
130
+ nodir: true,
131
+ cwd: destDir,
132
+ });
133
+
134
+ for (const file of cleanUpList) {
135
+ fs.rm(file, { force: true }, (err) => {
136
+ if (err) throw err;
137
+ });
138
+ }
126
139
 
127
140
  const shouldBuildSWEntryWorker = cacheOnNavigation;
128
141
  let swEntryPublicPath: string | undefined = undefined;
@@ -146,35 +159,17 @@ const withSerwistInit = (pluginOptions: NextInjectManifestOptions): ((nextConfig
146
159
  } satisfies Record<`${SerwistNextOptionsKey}.${Extract<keyof SerwistNextOptions, "swEntryWorker">}`, string | undefined>),
147
160
  );
148
161
 
149
- logger.info(`Service worker: ${swDest}`);
150
- logger.info(` URL: ${_sw}`);
151
- logger.info(` Scope: ${_scope}`);
152
-
153
- config.plugins.push(
154
- new CleanWebpackPlugin({
155
- cleanOnceBeforeBuildPatterns: [path.join(destDir, "swe-worker-*.js"), path.join(destDir, "swe-worker-*.js.map"), swDest],
156
- }),
157
- );
162
+ logger.event(`Bundling the service worker script with the URL '${_sw}' and the scope '${_scope}'...`);
158
163
 
159
164
  // Precache files in public folder
160
165
  let resolvedManifestEntries = additionalPrecacheEntries;
161
166
 
162
167
  if (!resolvedManifestEntries) {
163
- const swDestFileName = path.basename(swDest);
164
- const userPublicGlob = typeof globPublicPatterns === "string" ? [globPublicPatterns] : globPublicPatterns ?? ["**/*"];
165
- const publicScan = fg.sync(
166
- [
167
- ...userPublicGlob,
168
- // Forcibly include these in case the user outputs these files to `public`.
169
- "!swe-worker-*.js",
170
- "!swe-worker-*.js.map",
171
- `!${swDestFileName.replace(/^\/+/, "")}`,
172
- `!${swDestFileName.replace(/^\/+/, "")}.map`,
173
- ],
174
- {
175
- cwd: publicDir,
176
- },
177
- );
168
+ const publicScan = globSync(globPublicPatterns, {
169
+ nodir: true,
170
+ cwd: publicDir,
171
+ ignore: ["swe-worker-*.js", destBase, `${destBase}.map`],
172
+ });
178
173
  resolvedManifestEntries = publicScan.map((f) => ({
179
174
  url: path.posix.join(basePath, f),
180
175
  revision: getFileHash(path.join(publicDir, f)),
@@ -238,4 +233,5 @@ const withSerwistInit = (pluginOptions: NextInjectManifestOptions): ((nextConfig
238
233
  };
239
234
 
240
235
  export default withSerwistInit;
241
- export type { NextInjectManifestOptions as PluginOptions };
236
+ export { validateInjectManifestOptions };
237
+ export type { InjectManifestOptions as PluginOptions, InjectManifestOptionsComplete as PluginOptionsComplete };
@@ -0,0 +1,21 @@
1
+ import { requiredSwDestPartial } from "@serwist/build/schema";
2
+ import { injectManifestOptions as webpackInjectManifestOptions } from "@serwist/webpack-plugin/schema";
3
+ import { z } from "zod";
4
+
5
+ export const injectPartial = z
6
+ .object({
7
+ cacheOnNavigation: z.boolean().default(false),
8
+ disable: z.boolean().default(false),
9
+ register: z.boolean().default(true),
10
+ reloadOnOnline: z.boolean().default(true),
11
+ scope: z.string().optional(),
12
+ swUrl: z.string().default("/sw.js"),
13
+ globPublicPatterns: z.array(z.string()).default(["**/*"]),
14
+ })
15
+ .strict("Do not pass invalid properties to NextInjectManifestPartial!");
16
+
17
+ export const injectManifestOptions = webpackInjectManifestOptions
18
+ .merge(requiredSwDestPartial)
19
+ .merge(injectPartial)
20
+ .omit({ disablePrecacheManifest: true })
21
+ .strict("Do not pass invalid properties to NextInjectManifestOptions!");
@@ -0,0 +1,104 @@
1
+ import type { RequiredSwDestPartial, RequiredSwDestResolved } from "@serwist/build";
2
+ import type { Require } from "@serwist/utils";
3
+ import type {
4
+ InjectManifestOptions as WebpackInjectManifestOptions,
5
+ InjectManifestOptionsComplete as WebpackInjectManifestOptionsComplete,
6
+ } from "@serwist/webpack-plugin";
7
+
8
+ export interface InjectPartial {
9
+ /**
10
+ * Enables additional route caching when users navigate through pages with
11
+ * `next/link`. This improves the user experience in some cases but it
12
+ * also adds a bit of overhead due to additional network calls.
13
+ * @default false
14
+ */
15
+ cacheOnNavigation?: boolean;
16
+ /**
17
+ * Whether Serwist should be disabled.
18
+ * @default false
19
+ */
20
+ disable?: boolean;
21
+ /**
22
+ * Whether `@serwist/next` should automatically register the service worker for you. If
23
+ * you want to register the service worker yourself, set this to `false` and run
24
+ * `window.serwist.register()` in `componentDidMount` or `useEffect`.
25
+ * @example
26
+ * ```tsx
27
+ * // app/register-pwa.tsx
28
+ * "use client";
29
+ * import { useEffect } from "react";
30
+ * import type { Serwist } from "@serwist/window";
31
+ *
32
+ * declare global {
33
+ * interface Window {
34
+ * serwist: Serwist;
35
+ * }
36
+ * }
37
+ *
38
+ * export default function RegisterPWA() {
39
+ * useEffect(() => {
40
+ * if ("serviceWorker" in navigator && window.serwist !== undefined) {
41
+ * window.serwist.register();
42
+ * }
43
+ * }, []);
44
+ * return <></>;
45
+ * }
46
+ *
47
+ * // app/layout.tsx
48
+ * import RegisterPWA from "./register-pwa";
49
+ *
50
+ * export default function RootLayout({
51
+ * children,
52
+ * }: {
53
+ * children: React.ReactNode;
54
+ * }) {
55
+ * return (
56
+ * <html lang="en">
57
+ * <head />
58
+ * <body>
59
+ * <RegisterPWA />
60
+ * {children}
61
+ * </body>
62
+ * </html>
63
+ * );
64
+ * }
65
+ * ```
66
+ * @default true
67
+ */
68
+ register?: boolean;
69
+ /**
70
+ * Whether Serwist should reload the app when it goes online.
71
+ * @default true
72
+ */
73
+ reloadOnOnline?: boolean;
74
+ /**
75
+ * The service worker's URL scope. Set to `/foo/` so that paths under `/foo/` are under the service
76
+ * worker's control while others are not.
77
+ * @default nextConfig.basePath
78
+ */
79
+ scope?: string;
80
+ /**
81
+ * The URL to the service worker.
82
+ * @default "/sw.js"
83
+ */
84
+ swUrl?: string;
85
+ /**
86
+ * Files in the public directory matching any of these patterns
87
+ * will be included in the precache manifest. For more information,
88
+ * see [`node-glob`'s Glob Primer](https://github.com/isaacs/node-glob#glob-primer).
89
+ * @default
90
+ * ```
91
+ * ["**\/*"]
92
+ * ```
93
+ */
94
+ globPublicPatterns?: string[];
95
+ }
96
+
97
+ export type InjectResolved = Require<InjectPartial, "cacheOnNavigation" | "disable" | "register" | "reloadOnOnline" | "swUrl" | "globPublicPatterns">;
98
+
99
+ export type InjectManifestOptions = Omit<WebpackInjectManifestOptions & RequiredSwDestPartial & InjectPartial, "disablePrecacheManifest">;
100
+
101
+ export type InjectManifestOptionsComplete = Omit<
102
+ WebpackInjectManifestOptionsComplete & RequiredSwDestResolved & InjectResolved,
103
+ "disablePrecacheManifest"
104
+ >;
@@ -0,0 +1,13 @@
1
+ import { SerwistConfigError, validationErrorMap } from "@serwist/build/schema";
2
+ import { injectManifestOptions } from "./schema.js";
3
+ import type { InjectManifestOptionsComplete } from "./types.js";
4
+
5
+ export const validateInjectManifestOptions = (input: unknown): InjectManifestOptionsComplete => {
6
+ const result = injectManifestOptions.safeParse(input, {
7
+ errorMap: validationErrorMap,
8
+ });
9
+ if (!result.success) {
10
+ throw new SerwistConfigError({ moduleName: "@serwist/next", message: JSON.stringify(result.error.format(), null, 2) });
11
+ }
12
+ return result.data;
13
+ };