@serwist/build 9.5.6 → 9.5.8
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/dist/chunks/constants-BLOVm9H2.js +6 -0
- package/dist/chunks/constants-BLOVm9H2.js.map +1 -0
- package/dist/chunks/error-Cl4d1Wf-.js +31 -0
- package/dist/chunks/error-Cl4d1Wf-.js.map +1 -0
- package/dist/chunks/get-manifest-De0D0LAJ.js +14 -0
- package/dist/chunks/get-manifest-De0D0LAJ.js.map +1 -0
- package/dist/chunks/glob-B4_meZ_o.js +67 -0
- package/dist/chunks/glob-B4_meZ_o.js.map +1 -0
- package/dist/chunks/inject-manifest-DNqDY-04.js +27 -0
- package/dist/chunks/inject-manifest-DNqDY-04.js.map +1 -0
- package/dist/chunks/manifest-transform-BCUeQ0-V.d.ts +75 -0
- package/dist/chunks/manifest-transform-BCUeQ0-V.d.ts.map +1 -0
- package/dist/chunks/rolldown-runtime-CzwdidQP.js +13 -0
- package/dist/index.d.mts +475 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +594 -0
- package/dist/index.mjs.map +1 -0
- package/dist/index.schema.d.mts +278 -0
- package/dist/index.schema.d.mts.map +1 -0
- package/dist/index.schema.mjs +5 -0
- package/package.json +15 -16
- package/src/lib/replace-and-update-source-map.ts +0 -1
- package/dist/chunks/constants.js +0 -59
- package/dist/chunks/get-manifest.js +0 -11
- package/dist/chunks/glob.js +0 -75
- package/dist/chunks/inject-manifest.js +0 -29
- package/dist/get-manifest.d.ts +0 -19
- package/dist/get-manifest.d.ts.map +0 -1
- package/dist/index.d.ts +0 -24
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -614
- package/dist/index.schema.d.ts +0 -13
- package/dist/index.schema.d.ts.map +0 -1
- package/dist/index.schema.js +0 -9
- package/dist/inject-manifest.d.ts +0 -29
- package/dist/inject-manifest.d.ts.map +0 -1
- package/dist/lib/additional-precache-entries-transform.d.ts +0 -12
- package/dist/lib/additional-precache-entries-transform.d.ts.map +0 -1
- package/dist/lib/constants.d.ts +0 -2
- package/dist/lib/constants.d.ts.map +0 -1
- package/dist/lib/errors.d.ts +0 -46
- package/dist/lib/errors.d.ts.map +0 -1
- package/dist/lib/escape-regexp.d.ts +0 -2
- package/dist/lib/escape-regexp.d.ts.map +0 -1
- package/dist/lib/get-composite-details.d.ts +0 -3
- package/dist/lib/get-composite-details.d.ts.map +0 -1
- package/dist/lib/get-file-details.d.ts +0 -9
- package/dist/lib/get-file-details.d.ts.map +0 -1
- package/dist/lib/get-file-hash.d.ts +0 -2
- package/dist/lib/get-file-hash.d.ts.map +0 -1
- package/dist/lib/get-file-manifest-entries.d.ts +0 -3
- package/dist/lib/get-file-manifest-entries.d.ts.map +0 -1
- package/dist/lib/get-file-size.d.ts +0 -2
- package/dist/lib/get-file-size.d.ts.map +0 -1
- package/dist/lib/get-source-map-url.d.ts +0 -2
- package/dist/lib/get-source-map-url.d.ts.map +0 -1
- package/dist/lib/get-string-details.d.ts +0 -3
- package/dist/lib/get-string-details.d.ts.map +0 -1
- package/dist/lib/get-string-hash.d.ts +0 -3
- package/dist/lib/get-string-hash.d.ts.map +0 -1
- package/dist/lib/maximum-size-transform.d.ts +0 -3
- package/dist/lib/maximum-size-transform.d.ts.map +0 -1
- package/dist/lib/modify-url-prefix-transform.d.ts +0 -5
- package/dist/lib/modify-url-prefix-transform.d.ts.map +0 -1
- package/dist/lib/no-revision-for-urls-matching-transform.d.ts +0 -3
- package/dist/lib/no-revision-for-urls-matching-transform.d.ts.map +0 -1
- package/dist/lib/rebase-path.d.ts +0 -5
- package/dist/lib/rebase-path.d.ts.map +0 -1
- package/dist/lib/replace-and-update-source-map.d.ts +0 -42
- package/dist/lib/replace-and-update-source-map.d.ts.map +0 -1
- package/dist/lib/transform-manifest.d.ts +0 -61
- package/dist/lib/transform-manifest.d.ts.map +0 -1
- package/dist/lib/translate-url-to-sourcemap-paths.d.ts +0 -6
- package/dist/lib/translate-url-to-sourcemap-paths.d.ts.map +0 -1
- package/dist/lib/validate-options.d.ts +0 -4
- package/dist/lib/validate-options.d.ts.map +0 -1
- package/dist/schema/assert-type.d.ts +0 -4
- package/dist/schema/assert-type.d.ts.map +0 -1
- package/dist/schema/base.d.ts +0 -66
- package/dist/schema/base.d.ts.map +0 -1
- package/dist/schema/error.d.ts +0 -9
- package/dist/schema/error.d.ts.map +0 -1
- package/dist/schema/get-manifest.d.ts +0 -72
- package/dist/schema/get-manifest.d.ts.map +0 -1
- package/dist/schema/glob.d.ts +0 -15
- package/dist/schema/glob.d.ts.map +0 -1
- package/dist/schema/inject-manifest.d.ts +0 -79
- package/dist/schema/inject-manifest.d.ts.map +0 -1
- package/dist/schema/manifest-entry.d.ts +0 -7
- package/dist/schema/manifest-entry.d.ts.map +0 -1
- package/dist/schema/manifest-transform.d.ts +0 -64
- package/dist/schema/manifest-transform.d.ts.map +0 -1
- package/dist/schema/sw-dest.d.ts +0 -8
- package/dist/schema/sw-dest.d.ts.map +0 -1
- package/dist/schema/utils.d.ts +0 -10
- package/dist/schema/utils.d.ts.map +0 -1
- package/dist/types.d.ts +0 -204
- package/dist/types.d.ts.map +0 -1
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,594 @@
|
|
|
1
|
+
import { n as validationErrorMap, t as SerwistConfigError } from "./chunks/error-Cl4d1Wf-.js";
|
|
2
|
+
import { t as DEFAULT_GLOB_PATTERNS } from "./chunks/constants-BLOVm9H2.js";
|
|
3
|
+
import assert from "node:assert";
|
|
4
|
+
import { oneLine } from "common-tags";
|
|
5
|
+
import crypto from "node:crypto";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { globSync } from "glob";
|
|
8
|
+
import fs, { readFileSync } from "node:fs";
|
|
9
|
+
import prettyBytes from "pretty-bytes";
|
|
10
|
+
import { z } from "zod";
|
|
11
|
+
import fsp from "node:fs/promises";
|
|
12
|
+
import { toUnix } from "@serwist/utils";
|
|
13
|
+
import { SourceMapConsumer, SourceMapGenerator } from "source-map";
|
|
14
|
+
//#region src/lib/errors.ts
|
|
15
|
+
const errors = {
|
|
16
|
+
"unable-to-get-rootdir": "Unable to get the root directory of your web app.",
|
|
17
|
+
"no-extension": oneLine`Unable to detect a usable extension for a file in your web
|
|
18
|
+
app directory.`,
|
|
19
|
+
"invalid-file-manifest-name": oneLine`The File Manifest Name must have at least one
|
|
20
|
+
character.`,
|
|
21
|
+
"unable-to-get-file-manifest-name": "Unable to get a file manifest name.",
|
|
22
|
+
"invalid-sw-dest": `The 'swDest' value must be a valid path.`,
|
|
23
|
+
"unable-to-get-sw-name": "Unable to get a service worker file name.",
|
|
24
|
+
"unable-to-get-save-config": oneLine`An error occurred when asking to save details
|
|
25
|
+
in a config file.`,
|
|
26
|
+
"unable-to-get-file-hash": oneLine`An error occurred when attempting to create a
|
|
27
|
+
file hash.`,
|
|
28
|
+
"unable-to-get-file-size": oneLine`An error occurred when attempting to get a file
|
|
29
|
+
size.`,
|
|
30
|
+
"unable-to-glob-files": "An error occurred when globbing for files.",
|
|
31
|
+
"unable-to-make-manifest-directory": oneLine`Unable to make output directory for
|
|
32
|
+
file manifest.`,
|
|
33
|
+
"read-manifest-template-failure": "Unable to read template for file manifest",
|
|
34
|
+
"populating-manifest-tmpl-failed": oneLine`An error occurred when populating the
|
|
35
|
+
file manifest template.`,
|
|
36
|
+
"manifest-file-write-failure": "Unable to write the file manifest.",
|
|
37
|
+
"unable-to-make-sw-directory": oneLine`Unable to make the directories to output
|
|
38
|
+
the service worker path.`,
|
|
39
|
+
"sw-write-failure": "Unable to write the service worker file.",
|
|
40
|
+
"sw-write-failure-directory": oneLine`Unable to write the service worker file;
|
|
41
|
+
'swDest' should be a full path to the file, not a path to a directory.`,
|
|
42
|
+
"unable-to-copy-serwist-libraries": oneLine`One or more of the Serwist libraries
|
|
43
|
+
could not be copied over to the destination directory: `,
|
|
44
|
+
"invalid-glob-directory": oneLine`The supplied globDirectory must be a path as a
|
|
45
|
+
string.`,
|
|
46
|
+
"invalid-dont-cache-bust": oneLine`The supplied 'dontCacheBustURLsMatching'
|
|
47
|
+
parameter must be a RegExp.`,
|
|
48
|
+
"invalid-exclude-files": "The excluded files should be an array of strings.",
|
|
49
|
+
"invalid-get-manifest-entries-input": oneLine`The input to
|
|
50
|
+
'getFileManifestEntries()' must be an object.`,
|
|
51
|
+
"invalid-manifest-path": oneLine`The supplied manifest path is not a string with
|
|
52
|
+
at least one character.`,
|
|
53
|
+
"invalid-manifest-entries": oneLine`The manifest entries must be an array of
|
|
54
|
+
strings or JavaScript objects containing a url parameter.`,
|
|
55
|
+
"invalid-manifest-format": oneLine`The value of the 'format' option passed to
|
|
56
|
+
generateFileManifest() must be either 'iife' (the default) or 'es'.`,
|
|
57
|
+
"invalid-static-file-globs": oneLine`The 'globPatterns' value must be an array
|
|
58
|
+
of strings.`,
|
|
59
|
+
"invalid-templated-urls": oneLine`The 'templatedURLs' value should be an object
|
|
60
|
+
that maps URLs to either a string, or to an array of glob patterns.`,
|
|
61
|
+
"templated-url-matches-glob": oneLine`One of the 'templatedURLs' URLs is already
|
|
62
|
+
being tracked via 'globPatterns': `,
|
|
63
|
+
"invalid-glob-ignores": oneLine`The 'globIgnores' parameter must be an array of
|
|
64
|
+
glob pattern strings.`,
|
|
65
|
+
"manifest-entry-bad-url": oneLine`The generated manifest contains an entry without
|
|
66
|
+
a URL string. This is likely an error with @serwist/build.`,
|
|
67
|
+
"modify-url-prefix-bad-prefixes": oneLine`The 'modifyURLPrefix' parameter must be
|
|
68
|
+
an object with string key value pairs.`,
|
|
69
|
+
"invalid-inject-manifest-arg": oneLine`The input to 'injectManifest()' must be an
|
|
70
|
+
object.`,
|
|
71
|
+
"injection-point-not-found": oneLine`Unable to find a place to inject the manifest.
|
|
72
|
+
Please ensure that your service worker file contains the following: `,
|
|
73
|
+
"multiple-injection-points": oneLine`Please ensure that your 'swSrc' file contains
|
|
74
|
+
only one match for the following: `,
|
|
75
|
+
"bad-template-urls-asset": oneLine`There was an issue using one of the provided
|
|
76
|
+
'templatedURLs'.`,
|
|
77
|
+
"invalid-generate-file-manifest-arg": oneLine`The input to generateFileManifest()
|
|
78
|
+
must be an Object.`,
|
|
79
|
+
"invalid-sw-src": `The 'swSrc' file can't be read.`,
|
|
80
|
+
"same-src-and-dest": oneLine`Unable to find a place to inject the manifest. This is
|
|
81
|
+
likely because swSrc and swDest are configured to the same file.
|
|
82
|
+
Please ensure that your swSrc file contains the following:`,
|
|
83
|
+
"no-module-name": oneLine`You must provide a moduleName parameter when calling
|
|
84
|
+
getModuleURL().`,
|
|
85
|
+
"bad-manifest-transforms-return-value": oneLine`The return value from a
|
|
86
|
+
manifestTransform should be an object with 'manifest' and optionally
|
|
87
|
+
'warnings' properties.`,
|
|
88
|
+
"string-entry-warning": oneLine`Some items were passed to additionalPrecacheEntries
|
|
89
|
+
without revisioning info. This is generally NOT safe. Learn more at
|
|
90
|
+
https://bit.ly/wb-precache.`,
|
|
91
|
+
"cant-find-sourcemap": oneLine`The swSrc file refers to a sourcemap that can't be
|
|
92
|
+
opened:`,
|
|
93
|
+
"manifest-transforms": oneLine`When using manifestTransforms, you must provide
|
|
94
|
+
an array of functions.`
|
|
95
|
+
};
|
|
96
|
+
//#endregion
|
|
97
|
+
//#region src/lib/get-composite-details.ts
|
|
98
|
+
const getCompositeDetails = (compositeURL, dependencyDetails) => {
|
|
99
|
+
let totalSize = 0;
|
|
100
|
+
let compositeHash = "";
|
|
101
|
+
for (const fileDetails of dependencyDetails) {
|
|
102
|
+
totalSize += fileDetails.size;
|
|
103
|
+
compositeHash += fileDetails.hash === null ? "" : fileDetails.hash;
|
|
104
|
+
}
|
|
105
|
+
const md5 = crypto.createHash("md5");
|
|
106
|
+
md5.update(compositeHash);
|
|
107
|
+
return {
|
|
108
|
+
file: compositeURL,
|
|
109
|
+
hash: md5.digest("hex"),
|
|
110
|
+
size: totalSize
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
//#endregion
|
|
114
|
+
//#region src/lib/get-string-hash.ts
|
|
115
|
+
function getStringHash(input) {
|
|
116
|
+
const md5 = crypto.createHash("md5");
|
|
117
|
+
md5.update(input);
|
|
118
|
+
return md5.digest("hex");
|
|
119
|
+
}
|
|
120
|
+
//#endregion
|
|
121
|
+
//#region src/lib/get-file-hash.ts
|
|
122
|
+
const getFileHash = (file) => {
|
|
123
|
+
try {
|
|
124
|
+
return getStringHash(readFileSync(file));
|
|
125
|
+
} catch (err) {
|
|
126
|
+
throw new Error(`${errors["unable-to-get-file-hash"]} '${err instanceof Error && err.message ? err.message : ""}'`);
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
//#endregion
|
|
130
|
+
//#region src/lib/get-file-size.ts
|
|
131
|
+
const getFileSize = (file) => {
|
|
132
|
+
try {
|
|
133
|
+
const stat = fs.statSync(file);
|
|
134
|
+
if (!stat.isFile()) return null;
|
|
135
|
+
return stat.size;
|
|
136
|
+
} catch (err) {
|
|
137
|
+
throw new Error(`${errors["unable-to-get-file-size"]} '${err instanceof Error && err.message ? err.message : ""}'`);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
//#endregion
|
|
141
|
+
//#region src/lib/get-file-details.ts
|
|
142
|
+
const getFileDetails = ({ globDirectory, globFollow, globIgnores, globPattern }) => {
|
|
143
|
+
let globbedFiles;
|
|
144
|
+
let warning = "";
|
|
145
|
+
try {
|
|
146
|
+
globbedFiles = globSync(globPattern, {
|
|
147
|
+
cwd: globDirectory,
|
|
148
|
+
follow: globFollow,
|
|
149
|
+
ignore: globIgnores
|
|
150
|
+
});
|
|
151
|
+
} catch (err) {
|
|
152
|
+
throw new Error(`${errors["unable-to-glob-files"]} '${err instanceof Error && err.message ? err.message : ""}'`);
|
|
153
|
+
}
|
|
154
|
+
const globbedFileDetails = [];
|
|
155
|
+
for (const file of globbedFiles) {
|
|
156
|
+
const fullPath = path.join(globDirectory, file);
|
|
157
|
+
const fileSize = getFileSize(fullPath);
|
|
158
|
+
if (fileSize !== null) {
|
|
159
|
+
const fileHash = getFileHash(fullPath);
|
|
160
|
+
globbedFileDetails.push({
|
|
161
|
+
file: path.relative(globDirectory, fullPath),
|
|
162
|
+
hash: fileHash,
|
|
163
|
+
size: fileSize
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
globbedFileDetails,
|
|
169
|
+
warning
|
|
170
|
+
};
|
|
171
|
+
};
|
|
172
|
+
//#endregion
|
|
173
|
+
//#region src/lib/get-string-details.ts
|
|
174
|
+
const getStringDetails = (url, str) => ({
|
|
175
|
+
file: url,
|
|
176
|
+
hash: getStringHash(str),
|
|
177
|
+
size: str.length
|
|
178
|
+
});
|
|
179
|
+
//#endregion
|
|
180
|
+
//#region src/lib/additional-precache-entries-transform.ts
|
|
181
|
+
const additionalPrecacheEntriesTransform = (additionalPrecacheEntries) => {
|
|
182
|
+
return (manifest) => {
|
|
183
|
+
const warnings = [];
|
|
184
|
+
const stringEntries = /* @__PURE__ */ new Set();
|
|
185
|
+
for (const additionalEntry of additionalPrecacheEntries) if (typeof additionalEntry === "string") {
|
|
186
|
+
stringEntries.add(additionalEntry);
|
|
187
|
+
manifest.push({
|
|
188
|
+
revision: null,
|
|
189
|
+
size: 0,
|
|
190
|
+
url: additionalEntry
|
|
191
|
+
});
|
|
192
|
+
} else {
|
|
193
|
+
if (additionalEntry && !additionalEntry.integrity && additionalEntry.revision === void 0) stringEntries.add(additionalEntry.url);
|
|
194
|
+
manifest.push(Object.assign({ size: 0 }, additionalEntry));
|
|
195
|
+
}
|
|
196
|
+
if (stringEntries.size > 0) {
|
|
197
|
+
let urls = "\n";
|
|
198
|
+
for (const stringEntry of stringEntries) urls += ` - ${stringEntry}\n`;
|
|
199
|
+
warnings.push(errors["string-entry-warning"] + urls);
|
|
200
|
+
}
|
|
201
|
+
return {
|
|
202
|
+
manifest,
|
|
203
|
+
warnings
|
|
204
|
+
};
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
//#endregion
|
|
208
|
+
//#region src/lib/maximum-size-transform.ts
|
|
209
|
+
function maximumSizeTransform(maximumFileSizeToCacheInBytes) {
|
|
210
|
+
return (originalManifest) => {
|
|
211
|
+
const warnings = [];
|
|
212
|
+
return {
|
|
213
|
+
manifest: originalManifest.filter((entry) => {
|
|
214
|
+
if (entry.size <= maximumFileSizeToCacheInBytes) return true;
|
|
215
|
+
warnings.push(`${entry.url} is ${prettyBytes(entry.size)}, and won't be precached. Configure maximumFileSizeToCacheInBytes to change this limit.`);
|
|
216
|
+
return false;
|
|
217
|
+
}),
|
|
218
|
+
warnings
|
|
219
|
+
};
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
//#endregion
|
|
223
|
+
//#region src/lib/escape-regexp.ts
|
|
224
|
+
const escapeRegExp = (str) => {
|
|
225
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
226
|
+
};
|
|
227
|
+
//#endregion
|
|
228
|
+
//#region src/lib/modify-url-prefix-transform.ts
|
|
229
|
+
function modifyURLPrefixTransform(modifyURLPrefix) {
|
|
230
|
+
if (!modifyURLPrefix || typeof modifyURLPrefix !== "object" || Array.isArray(modifyURLPrefix)) throw new Error(errors["modify-url-prefix-bad-prefixes"]);
|
|
231
|
+
if (Object.keys(modifyURLPrefix).length === 0) return (manifest) => {
|
|
232
|
+
return { manifest };
|
|
233
|
+
};
|
|
234
|
+
for (const key of Object.keys(modifyURLPrefix)) if (typeof modifyURLPrefix[key] !== "string") throw new Error(errors["modify-url-prefix-bad-prefixes"]);
|
|
235
|
+
const prefixMatchesStrings = Object.keys(modifyURLPrefix).map(escapeRegExp).join("|");
|
|
236
|
+
const modifyRegex = new RegExp(`^(${prefixMatchesStrings})`);
|
|
237
|
+
return (originalManifest) => {
|
|
238
|
+
return { manifest: originalManifest.map((entry) => {
|
|
239
|
+
if (typeof entry.url !== "string") throw new Error(errors["manifest-entry-bad-url"]);
|
|
240
|
+
entry.url = entry.url.replace(modifyRegex, (match) => {
|
|
241
|
+
return modifyURLPrefix[match];
|
|
242
|
+
});
|
|
243
|
+
return entry;
|
|
244
|
+
}) };
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
//#endregion
|
|
248
|
+
//#region src/lib/no-revision-for-urls-matching-transform.ts
|
|
249
|
+
function noRevisionForURLsMatchingTransform(regexp) {
|
|
250
|
+
if (!(regexp instanceof RegExp)) throw new Error(errors["invalid-dont-cache-bust"]);
|
|
251
|
+
return (originalManifest) => {
|
|
252
|
+
return { manifest: originalManifest.map((entry) => {
|
|
253
|
+
if (typeof entry.url !== "string") throw new Error(errors["manifest-entry-bad-url"]);
|
|
254
|
+
if (entry.url.match(regexp)) entry.revision = null;
|
|
255
|
+
return entry;
|
|
256
|
+
}) };
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
//#endregion
|
|
260
|
+
//#region src/lib/transform-manifest.ts
|
|
261
|
+
async function transformManifest({ additionalPrecacheEntries, dontCacheBustURLsMatching, fileDetails, manifestTransforms, maximumFileSizeToCacheInBytes, modifyURLPrefix, transformParam, disablePrecacheManifest }) {
|
|
262
|
+
if (disablePrecacheManifest) return {
|
|
263
|
+
count: 0,
|
|
264
|
+
size: 0,
|
|
265
|
+
manifestEntries: void 0,
|
|
266
|
+
warnings: []
|
|
267
|
+
};
|
|
268
|
+
const allWarnings = [];
|
|
269
|
+
const normalizedManifest = fileDetails.map((fileDetails) => ({
|
|
270
|
+
url: fileDetails.file.replace(/\\/g, "/"),
|
|
271
|
+
revision: fileDetails.hash,
|
|
272
|
+
size: fileDetails.size
|
|
273
|
+
}));
|
|
274
|
+
const transformsToApply = [];
|
|
275
|
+
if (maximumFileSizeToCacheInBytes) transformsToApply.push(maximumSizeTransform(maximumFileSizeToCacheInBytes));
|
|
276
|
+
if (modifyURLPrefix) transformsToApply.push(modifyURLPrefixTransform(modifyURLPrefix));
|
|
277
|
+
if (dontCacheBustURLsMatching) transformsToApply.push(noRevisionForURLsMatchingTransform(dontCacheBustURLsMatching));
|
|
278
|
+
if (manifestTransforms) transformsToApply.push(...manifestTransforms);
|
|
279
|
+
if (additionalPrecacheEntries) transformsToApply.push(additionalPrecacheEntriesTransform(additionalPrecacheEntries));
|
|
280
|
+
let transformedManifest = normalizedManifest;
|
|
281
|
+
for (const transform of transformsToApply) {
|
|
282
|
+
const result = await transform(transformedManifest, transformParam);
|
|
283
|
+
if (!("manifest" in result)) throw new Error(errors["bad-manifest-transforms-return-value"]);
|
|
284
|
+
transformedManifest = result.manifest;
|
|
285
|
+
allWarnings.push(...result.warnings || []);
|
|
286
|
+
}
|
|
287
|
+
const count = transformedManifest.length;
|
|
288
|
+
let size = 0;
|
|
289
|
+
for (const manifestEntry of transformedManifest) {
|
|
290
|
+
size += manifestEntry.size || 0;
|
|
291
|
+
delete manifestEntry.size;
|
|
292
|
+
}
|
|
293
|
+
return {
|
|
294
|
+
count,
|
|
295
|
+
size,
|
|
296
|
+
manifestEntries: transformedManifest,
|
|
297
|
+
warnings: allWarnings
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
//#endregion
|
|
301
|
+
//#region src/lib/get-file-manifest-entries.ts
|
|
302
|
+
const getFileManifestEntries = async ({ additionalPrecacheEntries, dontCacheBustURLsMatching, globDirectory, globFollow, globIgnores, globPatterns = [], globStrict, manifestTransforms, maximumFileSizeToCacheInBytes, modifyURLPrefix, templatedURLs, disablePrecacheManifest }) => {
|
|
303
|
+
if (disablePrecacheManifest) return {
|
|
304
|
+
count: 0,
|
|
305
|
+
size: 0,
|
|
306
|
+
manifestEntries: void 0,
|
|
307
|
+
warnings: []
|
|
308
|
+
};
|
|
309
|
+
const warnings = [];
|
|
310
|
+
const allFileDetails = /* @__PURE__ */ new Map();
|
|
311
|
+
try {
|
|
312
|
+
for (const globPattern of globPatterns) {
|
|
313
|
+
const { globbedFileDetails, warning } = getFileDetails({
|
|
314
|
+
globDirectory,
|
|
315
|
+
globFollow,
|
|
316
|
+
globIgnores,
|
|
317
|
+
globPattern,
|
|
318
|
+
globStrict
|
|
319
|
+
});
|
|
320
|
+
if (warning) warnings.push(warning);
|
|
321
|
+
for (const details of globbedFileDetails) if (details && !allFileDetails.has(details.file)) allFileDetails.set(details.file, details);
|
|
322
|
+
}
|
|
323
|
+
} catch (error) {
|
|
324
|
+
if (error instanceof Error && error.message) warnings.push(error.message);
|
|
325
|
+
}
|
|
326
|
+
if (templatedURLs) for (const url of Object.keys(templatedURLs)) {
|
|
327
|
+
assert(!allFileDetails.has(url), errors["templated-url-matches-glob"]);
|
|
328
|
+
const dependencies = templatedURLs[url];
|
|
329
|
+
if (Array.isArray(dependencies)) {
|
|
330
|
+
const details = dependencies.reduce((previous, globPattern) => {
|
|
331
|
+
try {
|
|
332
|
+
const { globbedFileDetails, warning } = getFileDetails({
|
|
333
|
+
globDirectory,
|
|
334
|
+
globFollow,
|
|
335
|
+
globIgnores,
|
|
336
|
+
globPattern,
|
|
337
|
+
globStrict
|
|
338
|
+
});
|
|
339
|
+
if (warning) warnings.push(warning);
|
|
340
|
+
return previous.concat(globbedFileDetails);
|
|
341
|
+
} catch (error) {
|
|
342
|
+
const debugObj = {};
|
|
343
|
+
debugObj[url] = dependencies;
|
|
344
|
+
throw new Error(`${errors["bad-template-urls-asset"]} '${globPattern}' from '${JSON.stringify(debugObj)}':\n${error instanceof Error ? error.toString() : ""}`);
|
|
345
|
+
}
|
|
346
|
+
}, []);
|
|
347
|
+
if (details.length === 0) throw new Error(`${errors["bad-template-urls-asset"]} The glob pattern '${dependencies.toString()}' did not match anything.`);
|
|
348
|
+
allFileDetails.set(url, getCompositeDetails(url, details));
|
|
349
|
+
} else if (typeof dependencies === "string") allFileDetails.set(url, getStringDetails(url, dependencies));
|
|
350
|
+
}
|
|
351
|
+
const transformedManifest = await transformManifest({
|
|
352
|
+
additionalPrecacheEntries,
|
|
353
|
+
dontCacheBustURLsMatching,
|
|
354
|
+
manifestTransforms,
|
|
355
|
+
maximumFileSizeToCacheInBytes,
|
|
356
|
+
modifyURLPrefix,
|
|
357
|
+
fileDetails: Array.from(allFileDetails.values()),
|
|
358
|
+
disablePrecacheManifest
|
|
359
|
+
});
|
|
360
|
+
transformedManifest.warnings.push(...warnings);
|
|
361
|
+
return transformedManifest;
|
|
362
|
+
};
|
|
363
|
+
//#endregion
|
|
364
|
+
//#region src/lib/validate-options.ts
|
|
365
|
+
const validateGetManifestOptions = async (input) => {
|
|
366
|
+
const result = await (await import("./chunks/get-manifest-De0D0LAJ.js").then((n) => n.n)).getManifestOptions.spa(input, { error: validationErrorMap });
|
|
367
|
+
if (!result.success) throw new SerwistConfigError({
|
|
368
|
+
moduleName: "@serwist/build",
|
|
369
|
+
message: z.prettifyError(result.error)
|
|
370
|
+
});
|
|
371
|
+
return result.data;
|
|
372
|
+
};
|
|
373
|
+
const validateInjectManifestOptions = async (input) => {
|
|
374
|
+
const result = await (await import("./chunks/inject-manifest-DNqDY-04.js").then((n) => n.r)).injectManifestOptions.spa(input, { error: validationErrorMap });
|
|
375
|
+
if (!result.success) throw new SerwistConfigError({
|
|
376
|
+
moduleName: "@serwist/build",
|
|
377
|
+
message: z.prettifyError(result.error)
|
|
378
|
+
});
|
|
379
|
+
return result.data;
|
|
380
|
+
};
|
|
381
|
+
//#endregion
|
|
382
|
+
//#region src/get-manifest.ts
|
|
383
|
+
/**
|
|
384
|
+
* This method returns a list of URLs to precache, referred to as a "precache
|
|
385
|
+
* manifest", along with details about the number of entries and their size,
|
|
386
|
+
* based on the options you provide.
|
|
387
|
+
*
|
|
388
|
+
* ```
|
|
389
|
+
* // The following lists some common options; see the rest of the documentation
|
|
390
|
+
* // for the full set of options and defaults.
|
|
391
|
+
* const {count, manifestEntries, size, warnings} = await getManifest({
|
|
392
|
+
* dontCacheBustURLsMatching: [new RegExp('...')],
|
|
393
|
+
* globDirectory: '...',
|
|
394
|
+
* globPatterns: ['...', '...'],
|
|
395
|
+
* maximumFileSizeToCacheInBytes: ...,
|
|
396
|
+
* });
|
|
397
|
+
* ```
|
|
398
|
+
*/
|
|
399
|
+
const getManifest = async (config) => {
|
|
400
|
+
return await getFileManifestEntries(await validateGetManifestOptions(config));
|
|
401
|
+
};
|
|
402
|
+
//#endregion
|
|
403
|
+
//#region src/lib/get-source-map-url.ts
|
|
404
|
+
const innerRegex = /[#@] sourceMappingURL=([^\s'"]*)/;
|
|
405
|
+
const regex = RegExp(`(?:/\\*(?:\\s*\r?\n(?://)?)?(?:${innerRegex.source})\\s*\\*/|//(?:${innerRegex.source}))\\s*`);
|
|
406
|
+
function getSourceMapURL(srcContents) {
|
|
407
|
+
const match = srcContents.match(regex);
|
|
408
|
+
return match ? match[1] || match[2] || "" : null;
|
|
409
|
+
}
|
|
410
|
+
//#endregion
|
|
411
|
+
//#region src/lib/rebase-path.ts
|
|
412
|
+
function rebasePath({ baseDirectory, file }) {
|
|
413
|
+
const absolutePath = path.resolve(file);
|
|
414
|
+
const relativePath = path.relative(baseDirectory, absolutePath);
|
|
415
|
+
return toUnix(path.normalize(relativePath));
|
|
416
|
+
}
|
|
417
|
+
//#endregion
|
|
418
|
+
//#region src/lib/replace-and-update-source-map.ts
|
|
419
|
+
/**
|
|
420
|
+
* Adapted from https://github.com/nsams/sourcemap-aware-replace, with modern
|
|
421
|
+
* JavaScript updates, along with additional properties copied from originalMap.
|
|
422
|
+
*
|
|
423
|
+
* @param options
|
|
424
|
+
* @returns An object containing both
|
|
425
|
+
* originalSource with the replacement applied, and the modified originalMap.
|
|
426
|
+
* @private
|
|
427
|
+
*/
|
|
428
|
+
async function replaceAndUpdateSourceMap({ jsFilename, originalMap, originalSource, replaceString, searchString }) {
|
|
429
|
+
const generator = new SourceMapGenerator({ file: jsFilename });
|
|
430
|
+
const consumer = await new SourceMapConsumer(originalMap);
|
|
431
|
+
let pos;
|
|
432
|
+
let src = originalSource;
|
|
433
|
+
const replacements = [];
|
|
434
|
+
let lineNum = 0;
|
|
435
|
+
let filePos = 0;
|
|
436
|
+
const lines = src.split("\n");
|
|
437
|
+
for (let line of lines) {
|
|
438
|
+
lineNum++;
|
|
439
|
+
let searchPos = 0;
|
|
440
|
+
while ((pos = line.indexOf(searchString, searchPos)) !== -1) {
|
|
441
|
+
src = src.substring(0, filePos + pos) + replaceString + src.substring(filePos + pos + searchString.length);
|
|
442
|
+
line = line.substring(0, pos) + replaceString + line.substring(pos + searchString.length);
|
|
443
|
+
replacements.push({
|
|
444
|
+
line: lineNum,
|
|
445
|
+
column: pos
|
|
446
|
+
});
|
|
447
|
+
searchPos = pos + replaceString.length;
|
|
448
|
+
}
|
|
449
|
+
filePos += line.length + 1;
|
|
450
|
+
}
|
|
451
|
+
replacements.reverse();
|
|
452
|
+
consumer.eachMapping((mapping) => {
|
|
453
|
+
for (const replacement of replacements) if (replacement.line === mapping.generatedLine && mapping.generatedColumn > replacement.column) {
|
|
454
|
+
const offset = searchString.length - replaceString.length;
|
|
455
|
+
mapping.generatedColumn -= offset;
|
|
456
|
+
}
|
|
457
|
+
if (mapping.source) {
|
|
458
|
+
const newMapping = {
|
|
459
|
+
generated: {
|
|
460
|
+
line: mapping.generatedLine,
|
|
461
|
+
column: mapping.generatedColumn
|
|
462
|
+
},
|
|
463
|
+
original: {
|
|
464
|
+
line: mapping.originalLine,
|
|
465
|
+
column: mapping.originalColumn
|
|
466
|
+
},
|
|
467
|
+
source: mapping.source
|
|
468
|
+
};
|
|
469
|
+
return generator.addMapping(newMapping);
|
|
470
|
+
}
|
|
471
|
+
return mapping;
|
|
472
|
+
});
|
|
473
|
+
consumer.destroy();
|
|
474
|
+
const updatedSourceMap = Object.assign(JSON.parse(generator.toString()), {
|
|
475
|
+
names: originalMap.names,
|
|
476
|
+
sourceRoot: originalMap.sourceRoot,
|
|
477
|
+
sources: originalMap.sources,
|
|
478
|
+
sourcesContent: originalMap.sourcesContent
|
|
479
|
+
});
|
|
480
|
+
return {
|
|
481
|
+
map: JSON.stringify(updatedSourceMap),
|
|
482
|
+
source: src
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
//#endregion
|
|
486
|
+
//#region src/lib/translate-url-to-sourcemap-paths.ts
|
|
487
|
+
function translateURLToSourcemapPaths(url, swSrc, swDest) {
|
|
488
|
+
let destPath;
|
|
489
|
+
let srcPath;
|
|
490
|
+
let warning;
|
|
491
|
+
if (url && !url.startsWith("data:")) {
|
|
492
|
+
const possibleSrcPath = path.resolve(path.dirname(swSrc), url);
|
|
493
|
+
if (fs.existsSync(possibleSrcPath)) {
|
|
494
|
+
srcPath = toUnix(possibleSrcPath);
|
|
495
|
+
destPath = toUnix(path.resolve(path.dirname(swDest), url));
|
|
496
|
+
} else warning = `${errors["cant-find-sourcemap"]} ${possibleSrcPath}`;
|
|
497
|
+
}
|
|
498
|
+
return {
|
|
499
|
+
destPath,
|
|
500
|
+
srcPath,
|
|
501
|
+
warning
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
//#endregion
|
|
505
|
+
//#region src/inject-manifest.ts
|
|
506
|
+
/**
|
|
507
|
+
* This method creates a list of URLs to precache, referred to as a "precache
|
|
508
|
+
* manifest", based on the options you provide.
|
|
509
|
+
*
|
|
510
|
+
* The manifest is injected into the `swSrc` file, and the placeholder string
|
|
511
|
+
* `injectionPoint` determines where in the file the manifest should go.
|
|
512
|
+
*
|
|
513
|
+
* The final service worker file, with the manifest injected, is written to
|
|
514
|
+
* disk at `swDest`.
|
|
515
|
+
*
|
|
516
|
+
* This method will not compile or bundle your `swSrc` file; it just handles
|
|
517
|
+
* injecting the manifest.
|
|
518
|
+
*
|
|
519
|
+
* ```
|
|
520
|
+
* // The following lists some common options; see the rest of the documentation
|
|
521
|
+
* // for the full set of options and defaults.
|
|
522
|
+
* const {count, size, warnings} = await injectManifest({
|
|
523
|
+
* dontCacheBustURLsMatching: [new RegExp('...')],
|
|
524
|
+
* globDirectory: '...',
|
|
525
|
+
* globPatterns: ['...', '...'],
|
|
526
|
+
* maximumFileSizeToCacheInBytes: ...,
|
|
527
|
+
* swDest: '...',
|
|
528
|
+
* swSrc: '...',
|
|
529
|
+
* });
|
|
530
|
+
* ```
|
|
531
|
+
*/
|
|
532
|
+
const injectManifest = async (config) => {
|
|
533
|
+
const options = await validateInjectManifestOptions(config);
|
|
534
|
+
for (const file of [options.swSrc, options.swDest]) options.globIgnores.push(rebasePath({
|
|
535
|
+
file,
|
|
536
|
+
baseDirectory: options.globDirectory
|
|
537
|
+
}));
|
|
538
|
+
const globalRegexp = new RegExp(escapeRegExp(options.injectionPoint), "g");
|
|
539
|
+
const { count, size, manifestEntries, warnings } = await getFileManifestEntries(options);
|
|
540
|
+
let swFileContents;
|
|
541
|
+
try {
|
|
542
|
+
swFileContents = await fsp.readFile(options.swSrc, "utf8");
|
|
543
|
+
} catch (error) {
|
|
544
|
+
throw new Error(`${errors["invalid-sw-src"]} ${error instanceof Error && error.message ? error.message : ""}`);
|
|
545
|
+
}
|
|
546
|
+
const injectionResults = swFileContents.match(globalRegexp);
|
|
547
|
+
const injectionPoint = options.injectionPoint ? options.injectionPoint : "";
|
|
548
|
+
if (!injectionResults) {
|
|
549
|
+
if (path.resolve(options.swSrc) === path.resolve(options.swDest)) throw new Error(`${errors["same-src-and-dest"]} ${injectionPoint}`);
|
|
550
|
+
throw new Error(`${errors["injection-point-not-found"]} ${injectionPoint}`);
|
|
551
|
+
}
|
|
552
|
+
assert(injectionResults.length === 1, `${errors["multiple-injection-points"]} ${injectionPoint}`);
|
|
553
|
+
const manifestString = manifestEntries === void 0 ? "undefined" : JSON.stringify(manifestEntries);
|
|
554
|
+
const filesToWrite = {};
|
|
555
|
+
const { destPath, srcPath, warning } = translateURLToSourcemapPaths(getSourceMapURL(swFileContents), options.swSrc, options.swDest);
|
|
556
|
+
if (warning) warnings.push(warning);
|
|
557
|
+
if (srcPath && destPath) {
|
|
558
|
+
const { map, source } = await replaceAndUpdateSourceMap({
|
|
559
|
+
originalMap: JSON.parse(await fsp.readFile(srcPath, "utf-8")),
|
|
560
|
+
jsFilename: toUnix(path.basename(options.swDest)),
|
|
561
|
+
originalSource: swFileContents,
|
|
562
|
+
replaceString: manifestString,
|
|
563
|
+
searchString: options.injectionPoint
|
|
564
|
+
});
|
|
565
|
+
filesToWrite[options.swDest] = source;
|
|
566
|
+
filesToWrite[destPath] = map;
|
|
567
|
+
} else filesToWrite[options.swDest] = swFileContents.replace(globalRegexp, manifestString);
|
|
568
|
+
for (const [file, contents] of Object.entries(filesToWrite)) {
|
|
569
|
+
try {
|
|
570
|
+
await fsp.mkdir(path.dirname(file), { recursive: true });
|
|
571
|
+
} catch (error) {
|
|
572
|
+
throw new Error(`${errors["unable-to-make-sw-directory"]} '${error instanceof Error && error.message ? error.message : ""}'`);
|
|
573
|
+
}
|
|
574
|
+
await fsp.writeFile(file, contents);
|
|
575
|
+
}
|
|
576
|
+
return {
|
|
577
|
+
count,
|
|
578
|
+
size,
|
|
579
|
+
warnings,
|
|
580
|
+
filePaths: Object.keys(filesToWrite).map((f) => toUnix(path.resolve(f)))
|
|
581
|
+
};
|
|
582
|
+
};
|
|
583
|
+
//#endregion
|
|
584
|
+
//#region src/index.ts
|
|
585
|
+
/**
|
|
586
|
+
* Use `JSON.stringify` instead.
|
|
587
|
+
*
|
|
588
|
+
* @deprecated
|
|
589
|
+
*/
|
|
590
|
+
const stringify = JSON.stringify;
|
|
591
|
+
//#endregion
|
|
592
|
+
export { DEFAULT_GLOB_PATTERNS, errors, escapeRegExp, getFileManifestEntries, getManifest, getSourceMapURL, injectManifest, rebasePath, replaceAndUpdateSourceMap, stringify, transformManifest, translateURLToSourcemapPaths, validateGetManifestOptions, validateInjectManifestOptions };
|
|
593
|
+
|
|
594
|
+
//# sourceMappingURL=index.mjs.map
|