@serwist/build
Version:
A module that integrates into your build process, helping you generate a manifest of local files that should be precached.
475 lines (474 loc) • 17.6 kB
text/typescript
import { n as manifestTransformResult, r as manifestEntry } from "./chunks/manifest-transform-BCUeQ0-V.js";
import { z } from "zod";
import { MaybePromise, Require } from "@serwist/utils";
import { RawSourceMap } from "source-map";
import { PackageJson } from "type-fest";
//#region src/types.d.ts
type ManifestEntry = z.input<typeof manifestEntry>;
type ManifestTransformResult = z.input<typeof manifestTransformResult>;
type ManifestTransform = (entries: (ManifestEntry & {
size: number;
})[], params?: unknown) => MaybePromise<ManifestTransformResult>;
type ResolvedManifestTransform = (entries: (ManifestEntry & {
size: number;
})[], params?: unknown) => Promise<ManifestTransformResult>;
interface BasePartial {
/**
* A list of entries to be precached, in addition to any entries that are
* generated as part of the build configuration.
*/
additionalPrecacheEntries?: (string | ManifestEntry)[];
/**
* Whether the precache manifest should be set to `undefined`. Essentially whether `@serwist/build` should
* be disabled. Mostly useful when you want it to only check if the provided options are valid.
* @default false
*/
disablePrecacheManifest?: boolean;
/**
* Assets that match this will be assumed to be uniquely versioned via their
* URL, and exempted from the normal HTTP cache-busting that's done when
* populating the precache. While not required, it's recommended that if your
* existing build process already inserts a `[hash]` value into each filename,
* you provide a RegExp that will detect that, as it will reduce the bandwidth
* consumed when precaching.
*/
dontCacheBustURLsMatching?: RegExp;
/**
* One or more functions which will be applied sequentially against the
* generated manifest. If `modifyURLPrefix` or `dontCacheBustURLsMatching` are
* also specified, their corresponding transformations will be applied first.
*/
manifestTransforms?: ManifestTransform[];
/**
* Determines the maximum size of files that will be precached. This prevents
* you from inadvertently precaching very large files that might have accidentally
* matched one of your patterns.
* @default 2097152
*/
maximumFileSizeToCacheInBytes?: number;
/**
* An object mapping string prefixes to replacement string values. This can be
* used to, e.g., remove or add a path prefix from a manifest entry if your
* web hosting setup doesn't match your local filesystem setup. As an
* alternative with more flexibility, you can use the `manifestTransforms`
* option and provide a function that modifies the entries in the manifest
* using whatever logic you provide.
*
* Example usage:
*
* ```
* // Replace a '/dist/' prefix with '/', and also prepend
* // '/static' to every URL.
* modifyURLPrefix: {
* '/dist/': '/',
* '': '/static',
* }
* ```
*/
modifyURLPrefix?: {
[key: string]: string;
};
}
interface BaseResolved extends Require<BasePartial, "disablePrecacheManifest" | "maximumFileSizeToCacheInBytes"> {
manifestTransforms?: ResolvedManifestTransform[];
}
interface RequiredGlobDirectoryPartial {
/**
* The local directory you wish to match `globPatterns` against. The path is
* relative to the current directory.
*/
globDirectory: string;
}
type RequiredGlobDirectoryResolved = RequiredGlobDirectoryPartial;
interface OptionalGlobDirectoryPartial {
/**
* The local directory you wish to match `globPatterns` against. The path is
* relative to the current directory.
*/
globDirectory?: string;
}
type OptionalGlobDirectoryResolved = OptionalGlobDirectoryPartial;
interface GlobPartial {
/**
* Determines whether or not symlinks are followed when generating the
* precache manifest. For more information, see the definition of `follow` in
* [`node-glob`'s documentation](https://github.com/isaacs/node-glob#options).
* @default true
*/
globFollow?: boolean;
/**
* A set of patterns matching files to always exclude when generating the
* precache manifest. For more information, see the definition of `ignore` in
* [`node-glob`'s documentation](https://github.com/isaacs/node-glob#options).
* @default
* ```
* ["**\/node_modules\/**\/*"]
* ```
*/
globIgnores?: string[];
/**
* Files matching any of these patterns will be included in the precache
* manifest. For more information, see
* [`node-glob`'s Glob Primer](https://github.com/isaacs/node-glob#glob-primer).
* @default
* ```
* ["**\/*.{js,css,html}"]
* ```
*/
globPatterns?: string[];
/**
* If true, an error reading a directory when generating a precache manifest
* will cause the build to fail. If false, the problematic directory will be
* skipped. For more information, see the definition of `strict` in
* [`node-glob`'s documentation](https://github.com/isaacs/node-glob#options).
* @default true
*/
globStrict?: boolean;
/**
* If a URL is rendered based on some server-side logic, its contents may
* depend on multiple files or on some other unique string value. The keys in
* this object are server-rendered URLs. If the values are an array of
* strings, they will be interpreted as glob patterns, and the contents of
* any files matching the patterns will be used to uniquely version the URL.
* If used with a single string, it will be interpreted as unique versioning
* information that you've generated for a given URL.
*/
templatedURLs?: {
[key: string]: string | string[];
};
}
type GlobResolved = Require<GlobPartial, "globFollow" | "globIgnores" | "globPatterns" | "globStrict">;
interface InjectPartial {
/**
* The string to find inside of the `swSrc` file. Once found, it will be
* replaced by the generated precache manifest.
* @default "self.__SW_MANIFEST"
*/
injectionPoint?: string;
/**
* The path to the service worker file that will be read during
* the build process, relative to the current working directory.
*/
swSrc: string;
}
type InjectResolved = Require<InjectPartial, "injectionPoint">;
interface RequiredSwDestPartial {
/**
* The path and filename of the service worker file that will be created by
* the build process. It must end in '.js'.
*/
swDest: string;
}
type RequiredSwDestResolved = RequiredSwDestPartial;
interface OptionalSwDestPartial {
/**
* The path and filename of the service worker file that will be created by
* the build process. It must end in '.js'. If omitted, the path will be
* based on `swSrc`.
*/
swDest?: string;
}
type OptionalSwDestResolved = OptionalSwDestPartial;
type GetManifestOptions = BasePartial & GlobPartial & RequiredGlobDirectoryPartial;
type GetManifestOptionsComplete = BaseResolved & GlobResolved & RequiredGlobDirectoryResolved;
type InjectManifestOptions = BasePartial & GlobPartial & InjectPartial & RequiredSwDestPartial & RequiredGlobDirectoryPartial;
type InjectManifestOptionsComplete = BaseResolved & GlobResolved & InjectResolved & RequiredSwDestResolved & RequiredGlobDirectoryResolved;
interface GetManifestResult {
count: number;
manifestEntries: ManifestEntry[] | undefined;
size: number;
warnings: string[];
}
type BuildResult = Omit<GetManifestResult, "manifestEntries"> & {
filePaths: string[];
};
/**
* @private
*/
interface FileDetails {
file: string;
hash: string | null;
size: number;
}
/**
* @private
*/
type BuildType = "dev" | "prod";
/**
* @private
*/
type SerwistPackageJSON = PackageJson;
/**
* @private
*/
type MethodNames = "GetManifest" | "InjectManifest" | "WebpackInjectManifest" | "ViteInjectManifest";
//#endregion
//#region src/get-manifest.d.ts
/**
* This method returns a list of URLs to precache, referred to as a "precache
* manifest", along with details about the number of entries and their size,
* based on the options you provide.
*
* ```
* // The following lists some common options; see the rest of the documentation
* // for the full set of options and defaults.
* const {count, manifestEntries, size, warnings} = await getManifest({
* dontCacheBustURLsMatching: [new RegExp('...')],
* globDirectory: '...',
* globPatterns: ['...', '...'],
* maximumFileSizeToCacheInBytes: ...,
* });
* ```
*/
declare const getManifest: (config: GetManifestOptions) => Promise<GetManifestResult>;
//#endregion
//#region src/inject-manifest.d.ts
/**
* This method creates a list of URLs to precache, referred to as a "precache
* manifest", based on the options you provide.
*
* The manifest is injected into the `swSrc` file, and the placeholder string
* `injectionPoint` determines where in the file the manifest should go.
*
* The final service worker file, with the manifest injected, is written to
* disk at `swDest`.
*
* This method will not compile or bundle your `swSrc` file; it just handles
* injecting the manifest.
*
* ```
* // The following lists some common options; see the rest of the documentation
* // for the full set of options and defaults.
* const {count, size, warnings} = await injectManifest({
* dontCacheBustURLsMatching: [new RegExp('...')],
* globDirectory: '...',
* globPatterns: ['...', '...'],
* maximumFileSizeToCacheInBytes: ...,
* swDest: '...',
* swSrc: '...',
* });
* ```
*/
declare const injectManifest: (config: InjectManifestOptions) => Promise<BuildResult>;
//#endregion
//#region src/lib/constants.d.ts
declare const DEFAULT_GLOB_PATTERNS: string[];
//#endregion
//#region src/lib/errors.d.ts
declare const errors: {
"unable-to-get-rootdir": string;
"no-extension": string;
"invalid-file-manifest-name": string;
"unable-to-get-file-manifest-name": string;
"invalid-sw-dest": string;
"unable-to-get-sw-name": string;
"unable-to-get-save-config": string;
"unable-to-get-file-hash": string;
"unable-to-get-file-size": string;
"unable-to-glob-files": string;
"unable-to-make-manifest-directory": string;
"read-manifest-template-failure": string;
"populating-manifest-tmpl-failed": string;
"manifest-file-write-failure": string;
"unable-to-make-sw-directory": string;
"sw-write-failure": string;
"sw-write-failure-directory": string;
"unable-to-copy-serwist-libraries": string;
"invalid-glob-directory": string;
"invalid-dont-cache-bust": string;
"invalid-exclude-files": string;
"invalid-get-manifest-entries-input": string;
"invalid-manifest-path": string;
"invalid-manifest-entries": string;
"invalid-manifest-format": string;
"invalid-static-file-globs": string;
"invalid-templated-urls": string;
"templated-url-matches-glob": string;
"invalid-glob-ignores": string;
"manifest-entry-bad-url": string;
"modify-url-prefix-bad-prefixes": string;
"invalid-inject-manifest-arg": string;
"injection-point-not-found": string;
"multiple-injection-points": string;
"bad-template-urls-asset": string;
"invalid-generate-file-manifest-arg": string;
"invalid-sw-src": string;
"same-src-and-dest": string;
"no-module-name": string;
"bad-manifest-transforms-return-value": string;
"string-entry-warning": string;
"cant-find-sourcemap": string;
"manifest-transforms": string;
};
//#endregion
//#region src/lib/escape-regexp.d.ts
declare const escapeRegExp: (str: string) => string;
//#endregion
//#region src/lib/get-file-manifest-entries.d.ts
declare const getFileManifestEntries: ({
additionalPrecacheEntries,
dontCacheBustURLsMatching,
globDirectory,
globFollow,
globIgnores,
globPatterns,
globStrict,
manifestTransforms,
maximumFileSizeToCacheInBytes,
modifyURLPrefix,
templatedURLs,
disablePrecacheManifest
}: GetManifestOptionsComplete) => Promise<GetManifestResult>;
//#endregion
//#region src/lib/get-source-map-url.d.ts
declare function getSourceMapURL(srcContents: string): string | null;
//#endregion
//#region src/lib/rebase-path.d.ts
declare function rebasePath({
baseDirectory,
file
}: {
baseDirectory: string;
file: string;
}): string;
//#endregion
//#region src/lib/replace-and-update-source-map.d.ts
interface ReplaceAndUpdateSourceMapOptions {
/**
* The name for the file whose contents
* correspond to originalSource.
*/
jsFilename: string;
/**
* The sourcemap for originalSource,
* prior to any replacements.
*/
originalMap: RawSourceMap;
/**
* The source code, prior to any
* replacements.
*/
originalSource: string;
/**
* A string to swap in for searchString.
*/
replaceString: string;
/**
* A string in originalSource to replace.
* Only the first occurrence will be replaced.
*/
searchString: string;
}
/**
* Adapted from https://github.com/nsams/sourcemap-aware-replace, with modern
* JavaScript updates, along with additional properties copied from originalMap.
*
* @param options
* @returns An object containing both
* originalSource with the replacement applied, and the modified originalMap.
* @private
*/
declare function replaceAndUpdateSourceMap({
jsFilename,
originalMap,
originalSource,
replaceString,
searchString
}: ReplaceAndUpdateSourceMapOptions): Promise<{
map: string;
source: string;
}>;
//#endregion
//#region src/lib/transform-manifest.d.ts
/**
* A `ManifestTransform` function can be used to modify the modify the `url` or
* `revision` properties of some or all of the {@linkcode ManifestEntry} in the manifest.
*
* Deleting the `revision` property of an entry will cause
* the corresponding `url` to be precached without cache-busting parameters
* applied, which is to say, it implies that the URL itself contains
* proper versioning info. If the `revision` property is present, it must be
* set to a string.
*
* @example A transformation that prepended the origin of a CDN for any
* URL starting with '/assets/' could be implemented as:
*
* const cdnTransform = async (manifestEntries) => {
* const manifest = manifestEntries.map(entry => {
* const cdnOrigin = 'https://example.com';
* if (entry.url.startsWith('/assets/')) {
* entry.url = cdnOrigin + entry.url;
* }
* return entry;
* });
* return {manifest, warnings: []};
* };
*
* @example A transformation that nulls the revision field when the
* URL contains an 8-character hash surrounded by '.', indicating that it
* already contains revision information:
*
* const removeRevisionTransform = async (manifestEntries) => {
* const manifest = manifestEntries.map(entry => {
* const hashRegExp = /\.\w{8}\./;
* if (entry.url.match(hashRegExp)) {
* entry.revision = null;
* }
* return entry;
* });
* return {manifest, warnings: []};
* };
*
* @callback ManifestTransform
* @param manifestEntries The full
* array of entries, prior to the current transformation.
* @param compilation When used in the webpack plugins, this param
* will be set to the current `compilation`.
* @returns The array of entries with the transformation applied,
* and optionally, any warnings that should be reported back to the build tool.
*/
interface ManifestTransformResultWithWarnings {
count: number;
size: number;
manifestEntries: ManifestEntry[] | undefined;
warnings: string[];
}
interface TransformManifestOptions extends Pick<BaseResolved, "additionalPrecacheEntries" | "dontCacheBustURLsMatching" | "manifestTransforms" | "maximumFileSizeToCacheInBytes" | "modifyURLPrefix" | "disablePrecacheManifest"> {
fileDetails: FileDetails[];
transformParam?: unknown;
}
declare function transformManifest({
additionalPrecacheEntries,
dontCacheBustURLsMatching,
fileDetails,
manifestTransforms,
maximumFileSizeToCacheInBytes,
modifyURLPrefix,
transformParam,
disablePrecacheManifest
}: TransformManifestOptions): Promise<ManifestTransformResultWithWarnings>;
//#endregion
//#region src/lib/translate-url-to-sourcemap-paths.d.ts
declare function translateURLToSourcemapPaths(url: string | null, swSrc: string, swDest: string): {
destPath: string | undefined;
srcPath: string | undefined;
warning: string | undefined;
};
//#endregion
//#region src/lib/validate-options.d.ts
declare const validateGetManifestOptions: (input: unknown) => Promise<GetManifestOptionsComplete>;
declare const validateInjectManifestOptions: (input: unknown) => Promise<InjectManifestOptionsComplete>;
//#endregion
//#region src/index.d.ts
/**
* Use `JSON.stringify` instead.
*
* @deprecated
*/
declare const stringify: {
(value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string;
(value: any, replacer?: (number | string)[] | null, space?: string | number): string;
};
//#endregion
export { BasePartial, BaseResolved, BuildResult, BuildType, DEFAULT_GLOB_PATTERNS, FileDetails, GetManifestOptions, GetManifestOptionsComplete, GetManifestResult, GlobPartial, GlobResolved, InjectManifestOptions, InjectManifestOptionsComplete, InjectPartial, InjectResolved, ManifestEntry, ManifestTransform, ManifestTransformResult, MethodNames, OptionalGlobDirectoryPartial, OptionalGlobDirectoryResolved, OptionalSwDestPartial, OptionalSwDestResolved, RequiredGlobDirectoryPartial, RequiredGlobDirectoryResolved, RequiredSwDestPartial, RequiredSwDestResolved, ResolvedManifestTransform, SerwistPackageJSON, errors, escapeRegExp, getFileManifestEntries, getManifest, getSourceMapURL, injectManifest, rebasePath, replaceAndUpdateSourceMap, stringify, transformManifest, translateURLToSourcemapPaths, validateGetManifestOptions, validateInjectManifestOptions };
//# sourceMappingURL=index.d.mts.map