diff --git a/packages/rspack/src/builtin-plugin/IgnorePlugin.ts b/packages/rspack/src/builtin-plugin/IgnorePlugin.ts index 10fe6f6ec694..8f13e4ab05ef 100644 --- a/packages/rspack/src/builtin-plugin/IgnorePlugin.ts +++ b/packages/rspack/src/builtin-plugin/IgnorePlugin.ts @@ -38,7 +38,7 @@ const getIgnorePluginOptionsSchema = memoize( export const IgnorePlugin = create( BuiltinPluginName.IgnorePlugin, (options: IgnorePluginOptions): RawIgnorePluginOptions => { - validate(options, getIgnorePluginOptionsSchema()); + validate(options, getIgnorePluginOptionsSchema); return options; } diff --git a/packages/rspack/src/builtin-plugin/RsdoctorPlugin.ts b/packages/rspack/src/builtin-plugin/RsdoctorPlugin.ts index 4c0a67e95726..858f271408cb 100644 --- a/packages/rspack/src/builtin-plugin/RsdoctorPlugin.ts +++ b/packages/rspack/src/builtin-plugin/RsdoctorPlugin.ts @@ -85,7 +85,7 @@ const RsdoctorPluginImpl = create( chunkGraphFeatures: true } ): RawRsdoctorPluginOptions { - validate(c, getRsdoctorPluginSchema()); + validate(c, getRsdoctorPluginSchema); return { moduleGraphFeatures: c.moduleGraphFeatures ?? true, chunkGraphFeatures: c.chunkGraphFeatures ?? true diff --git a/packages/rspack/src/builtin-plugin/SubresourceIntegrityPlugin.ts b/packages/rspack/src/builtin-plugin/SubresourceIntegrityPlugin.ts index 324b7e2e1997..3328139c79bf 100644 --- a/packages/rspack/src/builtin-plugin/SubresourceIntegrityPlugin.ts +++ b/packages/rspack/src/builtin-plugin/SubresourceIntegrityPlugin.ts @@ -326,7 +326,7 @@ export class SubresourceIntegrityPlugin extends NativeSubresourceIntegrityPlugin function validateSubresourceIntegrityPluginOptions( options: SubresourceIntegrityPluginOptions ) { - validate(options, getPluginOptionsSchema()); + validate(options, getPluginOptionsSchema); } function isErrorWithCode(obj: T): boolean { diff --git a/packages/rspack/src/builtin-plugin/html-plugin/options.ts b/packages/rspack/src/builtin-plugin/html-plugin/options.ts index db60b2218b40..2b3ae84bf15f 100644 --- a/packages/rspack/src/builtin-plugin/html-plugin/options.ts +++ b/packages/rspack/src/builtin-plugin/html-plugin/options.ts @@ -160,7 +160,7 @@ const getPluginOptionsSchema = memoize( ); export function validateHtmlPluginOptions(options: HtmlRspackPluginOptions) { - return validate(options, getPluginOptionsSchema()); + return validate(options, getPluginOptionsSchema); } export const getPluginOptions = (compilation: Compilation, uid: number) => { diff --git a/packages/rspack/src/config/zod.ts b/packages/rspack/src/config/zod.ts index 1694b396c610..2d815313b6e0 100644 --- a/packages/rspack/src/config/zod.ts +++ b/packages/rspack/src/config/zod.ts @@ -2,6 +2,7 @@ import nodePath from "node:path"; import { createErrorMap, fromZodError } from "zod-validation-error/v4"; import * as z from "zod/v4"; import { getZodSwcLoaderOptionsSchema } from "../builtin-loader/swc/types"; +import { memoize } from "../util/memoize"; import type * as t from "./types"; import { anyFunction, numberOrInfinity } from "./utils"; @@ -9,1430 +10,1456 @@ z.config({ jitless: true }); -const filenameTemplate = z.string() satisfies z.ZodType; - -const filename = filenameTemplate.or( - anyFunction -) satisfies z.ZodType; - -//#region Name -const name = z.string() satisfies z.ZodType; -//#endregion - -//#region Dependencies -const dependencies = z.array(name) satisfies z.ZodType; -//#endregion - -//#region Context -const context = z.string().refine(val => nodePath.isAbsolute(val), { - error: issue => - `The provided value ${JSON.stringify(issue.input)} must be an absolute path` -}) satisfies z.ZodType; -//#endregion - -//#region Mode -const mode = z.enum([ - "development", - "production", - "none" -]) satisfies z.ZodType; -//#endregion - -//#region Falsy -const falsy = z.union([ - z.literal(false), - z.literal(0), - z.literal(""), - z.null(), - z.undefined() -]) satisfies z.ZodType; - -//#endregion - -//#region Entry -const publicPath = z - .literal("auto") - .or(filename) satisfies z.ZodType; - -const baseUri = z.string() satisfies z.ZodType; - -const chunkLoadingType = z - .enum(["jsonp", "import-scripts", "require", "async-node", "import"]) - .or(z.string()) satisfies z.ZodType; - -const chunkLoading = z - .literal(false) - .or(chunkLoadingType) satisfies z.ZodType; - -const asyncChunks = z.boolean() satisfies z.ZodType; - -const wasmLoadingType = z - .enum(["fetch-streaming", "fetch", "async-node"]) - .or(z.string()) satisfies z.ZodType; - -const wasmLoading = z - .literal(false) - .or(wasmLoadingType) satisfies z.ZodType; - -const scriptType = z - .enum(["text/javascript", "module"]) - .or(z.literal(false)) satisfies z.ZodType; - -const libraryCustomUmdObject = z.strictObject({ - amd: z.string().optional(), - commonjs: z.string().optional(), - root: z.string().or(z.array(z.string())).optional() -}) satisfies z.ZodType; - -const libraryName = z - .string() - .or(z.array(z.string())) - .or(libraryCustomUmdObject) satisfies z.ZodType; - -const libraryCustomUmdCommentObject = z.strictObject({ - amd: z.string().optional(), - commonjs: z.string().optional(), - commonjs2: z.string().optional(), - root: z.string().optional() -}) satisfies z.ZodType; - -const amdContainer = z.string() satisfies z.ZodType; - -const auxiliaryComment = z - .string() - .or(libraryCustomUmdCommentObject) satisfies z.ZodType; - -const libraryExport = z - .string() - .or(z.array(z.string())) satisfies z.ZodType; - -const libraryType = z - .enum([ - "var", - "module", - "assign", - "assign-properties", - "this", - "window", - "self", - "global", - "commonjs", - "commonjs2", - "commonjs-module", - "commonjs-static", - "amd", - "amd-require", - "umd", - "umd2", - "jsonp", - "system" - ]) - .or(z.string()) satisfies z.ZodType; - -const umdNamedDefine = z.boolean() satisfies z.ZodType; - -const libraryOptions = z.strictObject({ - amdContainer: amdContainer.optional(), - auxiliaryComment: auxiliaryComment.optional(), - export: libraryExport.optional(), - name: libraryName.optional(), - type: libraryType, - umdNamedDefine: umdNamedDefine.optional() -}) satisfies z.ZodType; - -const library = libraryName - .or(libraryOptions) - .optional() satisfies z.ZodType; - -const layer = z.string().or(z.null()) satisfies z.ZodType; - -const entryFilename = filename satisfies z.ZodType; - -const entryRuntime = z - .literal(false) - .or(z.string()) satisfies z.ZodType; - -const entryItem = z - .string() - .or(z.array(z.string())) satisfies z.ZodType; +export const getExternalsTypeSchema = memoize( + () => + z.enum([ + "var", + "module", + "assign", + "this", + "window", + "self", + "global", + "commonjs", + "commonjs2", + "commonjs-module", + "commonjs-static", + "amd", + "amd-require", + "umd", + "umd2", + "jsonp", + "system", + "promise", + "import", + "module-import", + "script", + "node-commonjs", + "commonjs-import" + ]) satisfies z.ZodType +); + +export const getRspackOptionsSchema = memoize(() => { + const filenameTemplate = z.string() satisfies z.ZodType; + + const filename = filenameTemplate.or( + anyFunction + ) satisfies z.ZodType; + + //#region Name + const name = z.string() satisfies z.ZodType; + //#endregion + + //#region Dependencies + const dependencies = z.array(name) satisfies z.ZodType; + //#endregion + + //#region Context + const context = z.string().refine(val => nodePath.isAbsolute(val), { + error: issue => + `The provided value ${JSON.stringify(issue.input)} must be an absolute path` + }) satisfies z.ZodType; + //#endregion + + //#region Mode + const mode = z.enum([ + "development", + "production", + "none" + ]) satisfies z.ZodType; + //#endregion + + //#region Falsy + const falsy = z.union([ + z.literal(false), + z.literal(0), + z.literal(""), + z.null(), + z.undefined() + ]) satisfies z.ZodType; + + //#endregion + + //#region Entry + const publicPath = z + .literal("auto") + .or(filename) satisfies z.ZodType; + + const baseUri = z.string() satisfies z.ZodType; + + const chunkLoadingType = z + .enum(["jsonp", "import-scripts", "require", "async-node", "import"]) + .or(z.string()) satisfies z.ZodType; + + const chunkLoading = z + .literal(false) + .or(chunkLoadingType) satisfies z.ZodType; + + const asyncChunks = z.boolean() satisfies z.ZodType; + + const wasmLoadingType = z + .enum(["fetch-streaming", "fetch", "async-node"]) + .or(z.string()) satisfies z.ZodType; + + const wasmLoading = z + .literal(false) + .or(wasmLoadingType) satisfies z.ZodType; + + const scriptType = z + .enum(["text/javascript", "module"]) + .or(z.literal(false)) satisfies z.ZodType; + + const libraryCustomUmdObject = z.strictObject({ + amd: z.string().optional(), + commonjs: z.string().optional(), + root: z.string().or(z.array(z.string())).optional() + }) satisfies z.ZodType; + + const libraryName = z + .string() + .or(z.array(z.string())) + .or(libraryCustomUmdObject) satisfies z.ZodType; + + const libraryCustomUmdCommentObject = z.strictObject({ + amd: z.string().optional(), + commonjs: z.string().optional(), + commonjs2: z.string().optional(), + root: z.string().optional() + }) satisfies z.ZodType; + + const amdContainer = z.string() satisfies z.ZodType; + + const auxiliaryComment = z + .string() + .or(libraryCustomUmdCommentObject) satisfies z.ZodType; + + const libraryExport = z + .string() + .or(z.array(z.string())) satisfies z.ZodType; + + const libraryType = z + .enum([ + "var", + "module", + "assign", + "assign-properties", + "this", + "window", + "self", + "global", + "commonjs", + "commonjs2", + "commonjs-module", + "commonjs-static", + "amd", + "amd-require", + "umd", + "umd2", + "jsonp", + "system" + ]) + .or(z.string()) satisfies z.ZodType; + + const umdNamedDefine = z.boolean() satisfies z.ZodType; + + const libraryOptions = z.strictObject({ + amdContainer: amdContainer.optional(), + auxiliaryComment: auxiliaryComment.optional(), + export: libraryExport.optional(), + name: libraryName.optional(), + type: libraryType, + umdNamedDefine: umdNamedDefine.optional() + }) satisfies z.ZodType; + + const library = libraryName + .or(libraryOptions) + .optional() satisfies z.ZodType; + + const layer = z.string().or(z.null()) satisfies z.ZodType; + + const entryFilename = filename satisfies z.ZodType; + + const entryRuntime = z + .literal(false) + .or(z.string()) satisfies z.ZodType; + + const entryItem = z + .string() + .or(z.array(z.string())) satisfies z.ZodType; + + const entryDependOn = z + .string() + .or(z.array(z.string())) satisfies z.ZodType; + + const entryDescription = z.strictObject({ + import: entryItem, + runtime: entryRuntime.optional(), + publicPath: publicPath.optional(), + baseUri: baseUri.optional(), + chunkLoading: chunkLoading.optional(), + asyncChunks: asyncChunks.optional(), + wasmLoading: wasmLoading.optional(), + filename: entryFilename.optional(), + library: libraryOptions.optional(), + dependOn: entryDependOn.optional(), + layer: layer.optional() + }) satisfies z.ZodType; + + const entryUnnamed = entryItem satisfies z.ZodType; + + const entryObject = z.record( + z.string(), + entryItem.or(entryDescription) + ) satisfies z.ZodType; + + const entryStatic = entryObject.or( + entryUnnamed + ) satisfies z.ZodType; -const entryDependOn = z - .string() - .or(z.array(z.string())) satisfies z.ZodType; + const entryDynamic = anyFunction satisfies z.ZodType; -const entryDescription = z.strictObject({ - import: entryItem, - runtime: entryRuntime.optional(), - publicPath: publicPath.optional(), - baseUri: baseUri.optional(), - chunkLoading: chunkLoading.optional(), - asyncChunks: asyncChunks.optional(), - wasmLoading: wasmLoading.optional(), - filename: entryFilename.optional(), - library: libraryOptions.optional(), - dependOn: entryDependOn.optional(), - layer: layer.optional() -}) satisfies z.ZodType; + const entry = entryStatic.or(entryDynamic) satisfies z.ZodType; + //#endregion -const entryUnnamed = entryItem satisfies z.ZodType; + //#region Output + const path = z.string() satisfies z.ZodType; + + const pathinfo = z + .boolean() + .or(z.literal("verbose")) satisfies z.ZodType; + + const assetModuleFilename = + filename satisfies z.ZodType; + + const webassemblyModuleFilename = + z.string() satisfies z.ZodType; + + const chunkFilename = filename satisfies z.ZodType; + + const crossOriginLoading = z + .literal(false) + .or( + z.enum(["anonymous", "use-credentials"]) + ) satisfies z.ZodType; + + const cssFilename = filename satisfies z.ZodType; + + const cssChunkFilename = filename satisfies z.ZodType; + + const hotUpdateChunkFilename = + filenameTemplate satisfies z.ZodType; + + const hotUpdateMainFilename = + filenameTemplate satisfies z.ZodType; + + const hotUpdateGlobal = z.string() satisfies z.ZodType; + + const uniqueName = z.string() satisfies z.ZodType; + + const chunkLoadingGlobal = + z.string() satisfies z.ZodType; + + const enabledLibraryTypes = z.array( + libraryType + ) satisfies z.ZodType; + + const clean = z.union([ + z.boolean(), + z.strictObject({ + keep: z.instanceof(RegExp).or(z.string()).or(anyFunction).optional() + }) + ]) satisfies z.ZodType; -const entryObject = z.record( - z.string(), - entryItem.or(entryDescription) -) satisfies z.ZodType; + const outputModule = z.boolean() satisfies z.ZodType; -const entryStatic = entryObject.or( - entryUnnamed -) satisfies z.ZodType; + const strictModuleExceptionHandling = + z.boolean() satisfies z.ZodType; -const entryDynamic = anyFunction satisfies z.ZodType; + const strictModuleErrorHandling = + z.boolean() satisfies z.ZodType; -const entry = entryStatic.or(entryDynamic) satisfies z.ZodType; -//#endregion + const globalObject = z.string() satisfies z.ZodType; -//#region Output -const path = z.string() satisfies z.ZodType; + const enabledWasmLoadingTypes = z.array( + wasmLoadingType + ) satisfies z.ZodType; -const pathinfo = z - .boolean() - .or(z.literal("verbose")) satisfies z.ZodType; + const importFunctionName = + z.string() satisfies z.ZodType; -const assetModuleFilename = filename satisfies z.ZodType; + const importMetaName = z.string() satisfies z.ZodType; -const webassemblyModuleFilename = - z.string() satisfies z.ZodType; + const iife = z.boolean() satisfies z.ZodType; -const chunkFilename = filename satisfies z.ZodType; + const enabledChunkLoadingTypes = z.array( + chunkLoadingType + ) satisfies z.ZodType; -const crossOriginLoading = z - .literal(false) - .or( - z.enum(["anonymous", "use-credentials"]) - ) satisfies z.ZodType; + const chunkFormat = z + .literal(false) + .or(z.string()) satisfies z.ZodType; -const cssFilename = filename satisfies z.ZodType; + const workerPublicPath = z.string() satisfies z.ZodType; -const cssChunkFilename = filename satisfies z.ZodType; + const trustedTypes = z.strictObject({ + policyName: z.string().optional(), + onPolicyCreationFailure: z.enum(["continue", "stop"]).optional() + }) satisfies z.ZodType; -const hotUpdateChunkFilename = - filenameTemplate satisfies z.ZodType; + const hashDigest = z.string() satisfies z.ZodType; -const hotUpdateMainFilename = - filenameTemplate satisfies z.ZodType; + const hashDigestLength = z.int() satisfies z.ZodType; -const hotUpdateGlobal = z.string() satisfies z.ZodType; + const hashFunction = z.enum([ + "md4", + "xxhash64", + "sha256" + ]) satisfies z.ZodType; -const uniqueName = z.string() satisfies z.ZodType; + const hashSalt = z.string() satisfies z.ZodType; -const chunkLoadingGlobal = z.string() satisfies z.ZodType; + const sourceMapFilename = z.string() satisfies z.ZodType; -const enabledLibraryTypes = z.array( - libraryType -) satisfies z.ZodType; + const devtoolNamespace = z.string() satisfies z.ZodType; -const clean = z.union([ - z.boolean(), - z.strictObject({ - keep: z.instanceof(RegExp).or(z.string()).or(anyFunction).optional() - }) -]) satisfies z.ZodType; - -const outputModule = z.boolean() satisfies z.ZodType; - -const strictModuleExceptionHandling = - z.boolean() satisfies z.ZodType; - -const strictModuleErrorHandling = - z.boolean() satisfies z.ZodType; - -const globalObject = z.string() satisfies z.ZodType; - -const enabledWasmLoadingTypes = z.array( - wasmLoadingType -) satisfies z.ZodType; - -const importFunctionName = z.string() satisfies z.ZodType; - -const importMetaName = z.string() satisfies z.ZodType; - -const iife = z.boolean() satisfies z.ZodType; - -const enabledChunkLoadingTypes = z.array( - chunkLoadingType -) satisfies z.ZodType; - -const chunkFormat = z - .literal(false) - .or(z.string()) satisfies z.ZodType; - -const workerPublicPath = z.string() satisfies z.ZodType; - -const trustedTypes = z.strictObject({ - policyName: z.string().optional(), - onPolicyCreationFailure: z.enum(["continue", "stop"]).optional() -}) satisfies z.ZodType; - -const hashDigest = z.string() satisfies z.ZodType; - -const hashDigestLength = z.int() satisfies z.ZodType; - -const hashFunction = z.enum([ - "md4", - "xxhash64", - "sha256" -]) satisfies z.ZodType; - -const hashSalt = z.string() satisfies z.ZodType; - -const sourceMapFilename = z.string() satisfies z.ZodType; - -const devtoolNamespace = z.string() satisfies z.ZodType; - -const devtoolModuleFilenameTemplate = z.union([ - z.string(), - anyFunction -]) satisfies z.ZodType; - -const devtoolFallbackModuleFilenameTemplate = - devtoolModuleFilenameTemplate satisfies z.ZodType; - -const environment = z.strictObject({ - arrowFunction: z.boolean().optional(), - asyncFunction: z.boolean().optional(), - bigIntLiteral: z.boolean().optional(), - const: z.boolean().optional(), - destructuring: z.boolean().optional(), - document: z.boolean().optional(), - dynamicImport: z.boolean().optional(), - dynamicImportInWorker: z.boolean().optional(), - forOf: z.boolean().optional(), - globalThis: z.boolean().optional(), - module: z.boolean().optional(), - nodePrefixForCoreModules: z.boolean().optional(), - optionalChaining: z.boolean().optional(), - templateLiteral: z.boolean().optional() -}) satisfies z.ZodType; - -const output = z.strictObject({ - path: path.optional(), - pathinfo: pathinfo.optional(), - clean: clean.optional(), - publicPath: publicPath.optional(), - filename: filename.optional(), - chunkFilename: chunkFilename.optional(), - crossOriginLoading: crossOriginLoading.optional(), - cssFilename: cssFilename.optional(), - cssHeadDataCompression: z.boolean().optional(), - cssChunkFilename: cssChunkFilename.optional(), - hotUpdateMainFilename: hotUpdateMainFilename.optional(), - hotUpdateChunkFilename: hotUpdateChunkFilename.optional(), - hotUpdateGlobal: hotUpdateGlobal.optional(), - assetModuleFilename: assetModuleFilename.optional(), - uniqueName: uniqueName.optional(), - chunkLoadingGlobal: chunkLoadingGlobal.optional(), - enabledLibraryTypes: enabledLibraryTypes.optional(), - library: library.optional(), - libraryExport: libraryExport.optional(), - libraryTarget: libraryType.optional(), - umdNamedDefine: umdNamedDefine.optional(), - auxiliaryComment: auxiliaryComment.optional(), - module: outputModule.optional(), - strictModuleExceptionHandling: strictModuleExceptionHandling.optional(), - strictModuleErrorHandling: strictModuleErrorHandling.optional(), - globalObject: globalObject.optional(), - importFunctionName: importFunctionName.optional(), - importMetaName: importMetaName.optional(), - iife: iife.optional(), - wasmLoading: wasmLoading.optional(), - enabledWasmLoadingTypes: enabledWasmLoadingTypes.optional(), - webassemblyModuleFilename: webassemblyModuleFilename.optional(), - chunkFormat: chunkFormat.optional(), - chunkLoading: chunkLoading.optional(), - enabledChunkLoadingTypes: enabledChunkLoadingTypes.optional(), - trustedTypes: z.literal(true).or(z.string()).or(trustedTypes).optional(), - sourceMapFilename: sourceMapFilename.optional(), - hashDigest: hashDigest.optional(), - hashDigestLength: hashDigestLength.optional(), - hashFunction: hashFunction.optional(), - hashSalt: hashSalt.optional(), - asyncChunks: asyncChunks.optional(), - workerChunkLoading: chunkLoading.optional(), - workerWasmLoading: wasmLoading.optional(), - workerPublicPath: workerPublicPath.optional(), - scriptType: scriptType.optional(), - devtoolNamespace: devtoolNamespace.optional(), - devtoolModuleFilenameTemplate: devtoolModuleFilenameTemplate.optional(), - devtoolFallbackModuleFilenameTemplate: - devtoolFallbackModuleFilenameTemplate.optional(), - chunkLoadTimeout: numberOrInfinity.optional(), - charset: z.boolean().optional(), - environment: environment.optional(), - compareBeforeEmit: z.boolean().optional() -}) satisfies z.ZodType; -//#endregion - -//#region Resolve -const resolveAlias = z - .record( + const devtoolModuleFilenameTemplate = z.union([ z.string(), - z - .literal(false) - .or(z.string()) - .or(z.array(z.string().or(z.literal(false)))) - ) - .or(z.literal(false)) satisfies z.ZodType; - -const resolveTsConfigFile = z.string(); -const resolveTsConfig = resolveTsConfigFile.or( - z.strictObject({ - configFile: resolveTsConfigFile, - references: z.array(z.string()).or(z.literal("auto")).optional() - }) -) satisfies z.ZodType; - -const baseResolveOptions = z.strictObject({ - alias: resolveAlias.optional(), - conditionNames: z.array(z.string()).optional(), - extensions: z.array(z.string()).optional(), - fallback: resolveAlias.optional(), - mainFields: z.array(z.string()).optional(), - mainFiles: z.array(z.string()).optional(), - modules: z.array(z.string()).optional(), - preferRelative: z.boolean().optional(), - preferAbsolute: z.boolean().optional(), - symlinks: z.boolean().optional(), - enforceExtension: z.boolean().optional(), - importsFields: z.array(z.string()).optional(), - descriptionFiles: z.array(z.string()).optional(), - tsConfig: resolveTsConfig.optional(), - fullySpecified: z.boolean().optional(), - exportsFields: z.array(z.string()).optional(), - extensionAlias: z - .record(z.string(), z.string().or(z.array(z.string()))) - .optional(), - aliasFields: z.array(z.string()).optional(), - restrictions: z.array(z.string()).optional(), - roots: z.array(z.string()).optional(), - pnp: z.boolean().optional() -}) satisfies z.ZodType; - -const resolveOptions: z.ZodType = baseResolveOptions.extend({ - byDependency: z.lazy(() => z.record(z.string(), resolveOptions)).optional() -}); + anyFunction + ]) satisfies z.ZodType; + + const devtoolFallbackModuleFilenameTemplate = + devtoolModuleFilenameTemplate satisfies z.ZodType; + + const environment = z.strictObject({ + arrowFunction: z.boolean().optional(), + asyncFunction: z.boolean().optional(), + bigIntLiteral: z.boolean().optional(), + const: z.boolean().optional(), + destructuring: z.boolean().optional(), + document: z.boolean().optional(), + dynamicImport: z.boolean().optional(), + dynamicImportInWorker: z.boolean().optional(), + forOf: z.boolean().optional(), + globalThis: z.boolean().optional(), + module: z.boolean().optional(), + nodePrefixForCoreModules: z.boolean().optional(), + optionalChaining: z.boolean().optional(), + templateLiteral: z.boolean().optional() + }) satisfies z.ZodType; + + const output = z.strictObject({ + path: path.optional(), + pathinfo: pathinfo.optional(), + clean: clean.optional(), + publicPath: publicPath.optional(), + filename: filename.optional(), + chunkFilename: chunkFilename.optional(), + crossOriginLoading: crossOriginLoading.optional(), + cssFilename: cssFilename.optional(), + cssHeadDataCompression: z.boolean().optional(), + cssChunkFilename: cssChunkFilename.optional(), + hotUpdateMainFilename: hotUpdateMainFilename.optional(), + hotUpdateChunkFilename: hotUpdateChunkFilename.optional(), + hotUpdateGlobal: hotUpdateGlobal.optional(), + assetModuleFilename: assetModuleFilename.optional(), + uniqueName: uniqueName.optional(), + chunkLoadingGlobal: chunkLoadingGlobal.optional(), + enabledLibraryTypes: enabledLibraryTypes.optional(), + library: library.optional(), + libraryExport: libraryExport.optional(), + libraryTarget: libraryType.optional(), + umdNamedDefine: umdNamedDefine.optional(), + auxiliaryComment: auxiliaryComment.optional(), + module: outputModule.optional(), + strictModuleExceptionHandling: strictModuleExceptionHandling.optional(), + strictModuleErrorHandling: strictModuleErrorHandling.optional(), + globalObject: globalObject.optional(), + importFunctionName: importFunctionName.optional(), + importMetaName: importMetaName.optional(), + iife: iife.optional(), + wasmLoading: wasmLoading.optional(), + enabledWasmLoadingTypes: enabledWasmLoadingTypes.optional(), + webassemblyModuleFilename: webassemblyModuleFilename.optional(), + chunkFormat: chunkFormat.optional(), + chunkLoading: chunkLoading.optional(), + enabledChunkLoadingTypes: enabledChunkLoadingTypes.optional(), + trustedTypes: z.literal(true).or(z.string()).or(trustedTypes).optional(), + sourceMapFilename: sourceMapFilename.optional(), + hashDigest: hashDigest.optional(), + hashDigestLength: hashDigestLength.optional(), + hashFunction: hashFunction.optional(), + hashSalt: hashSalt.optional(), + asyncChunks: asyncChunks.optional(), + workerChunkLoading: chunkLoading.optional(), + workerWasmLoading: wasmLoading.optional(), + workerPublicPath: workerPublicPath.optional(), + scriptType: scriptType.optional(), + devtoolNamespace: devtoolNamespace.optional(), + devtoolModuleFilenameTemplate: devtoolModuleFilenameTemplate.optional(), + devtoolFallbackModuleFilenameTemplate: + devtoolFallbackModuleFilenameTemplate.optional(), + chunkLoadTimeout: numberOrInfinity.optional(), + charset: z.boolean().optional(), + environment: environment.optional(), + compareBeforeEmit: z.boolean().optional() + }) satisfies z.ZodType; + //#endregion + + //#region Resolve + const resolveAlias = z + .record( + z.string(), + z + .literal(false) + .or(z.string()) + .or(z.array(z.string().or(z.literal(false)))) + ) + .or(z.literal(false)) satisfies z.ZodType; + + const resolveTsConfigFile = z.string(); + const resolveTsConfig = resolveTsConfigFile.or( + z.strictObject({ + configFile: resolveTsConfigFile, + references: z.array(z.string()).or(z.literal("auto")).optional() + }) + ) satisfies z.ZodType; + + const baseResolveOptions = z.strictObject({ + alias: resolveAlias.optional(), + conditionNames: z.array(z.string()).optional(), + extensions: z.array(z.string()).optional(), + fallback: resolveAlias.optional(), + mainFields: z.array(z.string()).optional(), + mainFiles: z.array(z.string()).optional(), + modules: z.array(z.string()).optional(), + preferRelative: z.boolean().optional(), + preferAbsolute: z.boolean().optional(), + symlinks: z.boolean().optional(), + enforceExtension: z.boolean().optional(), + importsFields: z.array(z.string()).optional(), + descriptionFiles: z.array(z.string()).optional(), + tsConfig: resolveTsConfig.optional(), + fullySpecified: z.boolean().optional(), + exportsFields: z.array(z.string()).optional(), + extensionAlias: z + .record(z.string(), z.string().or(z.array(z.string()))) + .optional(), + aliasFields: z.array(z.string()).optional(), + restrictions: z.array(z.string()).optional(), + roots: z.array(z.string()).optional(), + pnp: z.boolean().optional() + }) satisfies z.ZodType; + + const resolveOptions: z.ZodType = baseResolveOptions.extend( + { + byDependency: z + .lazy(() => z.record(z.string(), resolveOptions)) + .optional() + } + ); -//#endregion + //#endregion -//#region Module -const baseRuleSetCondition = z - .instanceof(RegExp) - .or(z.string()) - .or(anyFunction); + //#region Module + const baseRuleSetCondition = z + .instanceof(RegExp) + .or(z.string()) + .or(anyFunction); -const ruleSetCondition: z.ZodType = baseRuleSetCondition - .or(z.lazy(() => ruleSetConditions)) - .or(z.lazy(() => ruleSetLogicalConditions)); + const ruleSetCondition: z.ZodType = baseRuleSetCondition + .or(z.lazy(() => ruleSetConditions)) + .or(z.lazy(() => ruleSetLogicalConditions)); -const ruleSetConditions: z.ZodType = z.lazy(() => - z.array(ruleSetCondition) -); + const ruleSetConditions: z.ZodType = z.lazy(() => + z.array(ruleSetCondition) + ); -const ruleSetLogicalConditions: z.ZodType = - z.strictObject({ - and: ruleSetConditions.optional(), - or: ruleSetConditions.optional(), - not: ruleSetCondition.optional() - }); - -const ruleSetLoader = z.string() satisfies z.ZodType; - -const ruleSetLoaderOptions = z - .string() - .or( - z.record(z.string(), z.any()) - ) satisfies z.ZodType; - -const ruleSetLoaderWithOptions = z.strictObject({ - ident: z.string().optional(), - loader: ruleSetLoader, - options: ruleSetLoaderOptions.optional(), - parallel: z.boolean().optional() -}) satisfies z.ZodType; - -const builtinSWCLoaderChecker: z.core.CheckFn< - t.RuleSetLoaderWithOptions | t.RuleSetRule | undefined -> = ctx => { - const data = ctx.value; - if ( - data?.loader !== "builtin:swc-loader" || - typeof data?.options !== "object" - ) { - return; - } - - const res = getZodSwcLoaderOptionsSchema().safeParse(data.options); - - if (!res.success) { - const validationErr = fromZodError(res.error, { - prefix: "Invalid options for 'builtin:swc-loader'", - error: createErrorMap({ - issuesInTitleCase: false - }) - }); - ctx.issues.push({ - code: "custom", - message: validationErr.message, - input: data.options + const ruleSetLogicalConditions: z.ZodType = + z.strictObject({ + and: ruleSetConditions.optional(), + or: ruleSetConditions.optional(), + not: ruleSetCondition.optional() }); - } -}; - -const ruleSetUseItem = ruleSetLoader.or( - ruleSetLoaderWithOptions.check(builtinSWCLoaderChecker) -) satisfies z.ZodType; - -const ruleSetUse = ruleSetUseItem - .or(ruleSetUseItem.array()) - .or(anyFunction) satisfies z.ZodType; - -const baseRuleSetRule = z.strictObject({ - test: ruleSetCondition.optional(), - exclude: ruleSetCondition.optional(), - include: ruleSetCondition.optional(), - issuer: ruleSetCondition.optional(), - issuerLayer: ruleSetCondition.optional(), - dependency: ruleSetCondition.optional(), - resource: ruleSetCondition.optional(), - resourceFragment: ruleSetCondition.optional(), - resourceQuery: ruleSetCondition.optional(), - scheme: ruleSetCondition.optional(), - mimetype: ruleSetCondition.optional(), - descriptionData: z.record(z.string(), ruleSetCondition).optional(), - with: z.record(z.string(), ruleSetCondition).optional(), - type: z.string().optional(), - layer: z.string().optional(), - loader: ruleSetLoader.optional(), - options: ruleSetLoaderOptions.optional(), - use: ruleSetUse.optional(), - parser: z.record(z.string(), z.any()).optional(), - generator: z.record(z.string(), z.any()).optional(), - resolve: resolveOptions.optional(), - sideEffects: z.boolean().optional(), - enforce: z.literal("pre").or(z.literal("post")).optional() -}) satisfies z.ZodType; - -const extendedBaseRuleSetRule: z.ZodType = - baseRuleSetRule.extend({ - oneOf: z.lazy(() => ruleSetRule.or(falsy).array()).optional(), - rules: z.lazy(() => ruleSetRule.or(falsy).array()).optional() + + const ruleSetLoader = z.string() satisfies z.ZodType; + + const ruleSetLoaderOptions = z + .string() + .or( + z.record(z.string(), z.any()) + ) satisfies z.ZodType; + + const ruleSetLoaderWithOptions = z.strictObject({ + ident: z.string().optional(), + loader: ruleSetLoader, + options: ruleSetLoaderOptions.optional(), + parallel: z.boolean().optional() + }) satisfies z.ZodType; + + const builtinSWCLoaderChecker: z.core.CheckFn< + t.RuleSetLoaderWithOptions | t.RuleSetRule | undefined + > = ctx => { + const data = ctx.value; + if ( + data?.loader !== "builtin:swc-loader" || + typeof data?.options !== "object" + ) { + return; + } + + const res = getZodSwcLoaderOptionsSchema().safeParse(data.options); + + if (!res.success) { + const validationErr = fromZodError(res.error, { + prefix: "Invalid options for 'builtin:swc-loader'", + error: createErrorMap({ + issuesInTitleCase: false + }) + }); + ctx.issues.push({ + code: "custom", + message: validationErr.message, + input: data.options + }); + } + }; + + const ruleSetUseItem = ruleSetLoader.or( + ruleSetLoaderWithOptions.check(builtinSWCLoaderChecker) + ) satisfies z.ZodType; + + const ruleSetUse = ruleSetUseItem + .or(ruleSetUseItem.array()) + .or(anyFunction) satisfies z.ZodType; + + const baseRuleSetRule = z.strictObject({ + test: ruleSetCondition.optional(), + exclude: ruleSetCondition.optional(), + include: ruleSetCondition.optional(), + issuer: ruleSetCondition.optional(), + issuerLayer: ruleSetCondition.optional(), + dependency: ruleSetCondition.optional(), + resource: ruleSetCondition.optional(), + resourceFragment: ruleSetCondition.optional(), + resourceQuery: ruleSetCondition.optional(), + scheme: ruleSetCondition.optional(), + mimetype: ruleSetCondition.optional(), + descriptionData: z.record(z.string(), ruleSetCondition).optional(), + with: z.record(z.string(), ruleSetCondition).optional(), + type: z.string().optional(), + layer: z.string().optional(), + loader: ruleSetLoader.optional(), + options: ruleSetLoaderOptions.optional(), + use: ruleSetUse.optional(), + parser: z.record(z.string(), z.any()).optional(), + generator: z.record(z.string(), z.any()).optional(), + resolve: resolveOptions.optional(), + sideEffects: z.boolean().optional(), + enforce: z.literal("pre").or(z.literal("post")).optional() }) satisfies z.ZodType; -const ruleSetRule = extendedBaseRuleSetRule.check(builtinSWCLoaderChecker); - -const ruleSetRules = z.array( - z.literal("...").or(ruleSetRule).or(falsy) -) satisfies z.ZodType; - -const assetParserDataUrlOptions = z.strictObject({ - maxSize: numberOrInfinity.optional() -}) satisfies z.ZodType; - -const assetParserDataUrl = - assetParserDataUrlOptions satisfies z.ZodType; - -const assetParserOptions = z.strictObject({ - dataUrlCondition: assetParserDataUrl.optional() -}) satisfies z.ZodType; - -const cssParserNamedExports = - z.boolean() satisfies z.ZodType; - -const cssParserUrl = z.boolean() satisfies z.ZodType; - -const cssParserOptions = z.strictObject({ - namedExports: cssParserNamedExports.optional(), - url: cssParserUrl.optional() -}) satisfies z.ZodType; - -const cssAutoParserOptions = z.strictObject({ - namedExports: cssParserNamedExports.optional(), - url: cssParserUrl.optional() -}) satisfies z.ZodType; - -const cssModuleParserOptions = z.strictObject({ - namedExports: cssParserNamedExports.optional(), - url: cssParserUrl.optional() -}) satisfies z.ZodType; - -const dynamicImportMode = z.enum(["eager", "lazy", "weak", "lazy-once"]); -const dynamicImportPreload = z.union([z.boolean(), numberOrInfinity]); -const dynamicImportPrefetch = z.union([z.boolean(), numberOrInfinity]); -const dynamicImportFetchPriority = z.enum(["low", "high", "auto"]); -const javascriptParserUrl = z.union([z.literal("relative"), z.boolean()]); -const exprContextCritical = z.boolean(); -const wrappedContextCritical = z.boolean(); -const wrappedContextRegExp = z.instanceof(RegExp); -const exportsPresence = z.enum(["error", "warn", "auto"]).or(z.literal(false)); -const importExportsPresence = z - .enum(["error", "warn", "auto"]) - .or(z.literal(false)); -const reexportExportsPresence = z - .enum(["error", "warn", "auto"]) - .or(z.literal(false)); -const strictExportPresence = z.boolean(); -const worker = z.array(z.string()).or(z.boolean()); -const overrideStrict = z.enum(["strict", "non-strict"]); -const requireAsExpression = z.boolean(); -const requireDynamic = z.boolean(); -const requireResolve = z.boolean(); -const importDynamic = z.boolean(); -const inlineConst = z.boolean(); -const typeReexportsPresence = z.enum([ - "no-tolerant", - "tolerant", - "tolerant-no-check" -]); - -const javascriptParserOptions = z.strictObject({ - dynamicImportMode: dynamicImportMode.optional(), - dynamicImportPreload: dynamicImportPreload.optional(), - dynamicImportPrefetch: dynamicImportPrefetch.optional(), - dynamicImportFetchPriority: dynamicImportFetchPriority.optional(), - importMeta: z.boolean().optional(), - url: javascriptParserUrl.optional(), - exprContextCritical: exprContextCritical.optional(), - wrappedContextCritical: wrappedContextCritical.optional(), - wrappedContextRegExp: wrappedContextRegExp.optional(), - exportsPresence: exportsPresence.optional(), - importExportsPresence: importExportsPresence.optional(), - reexportExportsPresence: reexportExportsPresence.optional(), - strictExportPresence: strictExportPresence.optional(), - worker: worker.optional(), - overrideStrict: overrideStrict.optional(), - // #region Not available in webpack yet. - requireAsExpression: requireAsExpression.optional(), - requireDynamic: requireDynamic.optional(), - requireResolve: requireResolve.optional(), - importDynamic: importDynamic.optional(), - inlineConst: inlineConst.optional(), - typeReexportsPresence: typeReexportsPresence.optional() - // #endregion -}) satisfies z.ZodType; - -const parserOptionsByModuleTypeKnown = z.strictObject({ - asset: assetParserOptions.optional(), - css: cssParserOptions.optional(), - "css/auto": cssAutoParserOptions.optional(), - "css/module": cssModuleParserOptions.optional(), - javascript: javascriptParserOptions.optional(), - "javascript/auto": javascriptParserOptions.optional(), - "javascript/dynamic": javascriptParserOptions.optional(), - "javascript/esm": javascriptParserOptions.optional() -}) satisfies z.ZodType; - -const parserOptionsByModuleType = parserOptionsByModuleTypeKnown; - -const assetGeneratorDataUrlOptions = z.strictObject({ - encoding: z.literal(false).or(z.literal("base64")).optional(), - mimetype: z.string().optional() -}) satisfies z.ZodType; - -const assetGeneratorDataUrlFunction = - anyFunction satisfies z.ZodType; - -const assetGeneratorDataUrl = assetGeneratorDataUrlOptions.or( - assetGeneratorDataUrlFunction -) satisfies z.ZodType; - -const assetInlineGeneratorOptions = z.strictObject({ - dataUrl: assetGeneratorDataUrl.optional() -}) satisfies z.ZodType; - -const assetResourceGeneratorOptions = z.strictObject({ - emit: z.boolean().optional(), - filename: filename.optional(), - publicPath: publicPath.optional(), - outputPath: filename.optional() -}) satisfies z.ZodType; - -const assetGeneratorOptions = assetInlineGeneratorOptions.merge( - assetResourceGeneratorOptions -) satisfies z.ZodType; - -const cssGeneratorExportsConvention = z.enum([ - "as-is", - "camel-case", - "camel-case-only", - "dashes", - "dashes-only" -]) satisfies z.ZodType; - -const cssGeneratorExportsOnly = - z.boolean() satisfies z.ZodType; - -const cssGeneratorLocalIdentName = - z.string() satisfies z.ZodType; - -const cssGeneratorEsModule = - z.boolean() satisfies z.ZodType; - -const cssGeneratorOptions = z.strictObject({ - exportsOnly: cssGeneratorExportsOnly.optional(), - esModule: cssGeneratorEsModule.optional() -}) satisfies z.ZodType; - -const cssAutoGeneratorOptions = z.strictObject({ - exportsConvention: cssGeneratorExportsConvention.optional(), - exportsOnly: cssGeneratorExportsOnly.optional(), - localIdentName: cssGeneratorLocalIdentName.optional(), - esModule: cssGeneratorEsModule.optional() -}) satisfies z.ZodType; - -const cssModuleGeneratorOptions = z.strictObject({ - exportsConvention: cssGeneratorExportsConvention.optional(), - exportsOnly: cssGeneratorExportsOnly.optional(), - localIdentName: cssGeneratorLocalIdentName.optional(), - esModule: cssGeneratorEsModule.optional() -}) satisfies z.ZodType; - -const jsonGeneratorOptions = z.strictObject({ - JSONParse: z.boolean().optional() -}) satisfies z.ZodType; - -const generatorOptionsByModuleTypeKnown = z.strictObject({ - asset: assetGeneratorOptions.optional(), - "asset/inline": assetInlineGeneratorOptions.optional(), - "asset/resource": assetResourceGeneratorOptions.optional(), - css: cssGeneratorOptions.optional(), - "css/auto": cssAutoGeneratorOptions.optional(), - "css/module": cssModuleGeneratorOptions.optional(), - json: jsonGeneratorOptions.optional() -}) satisfies z.ZodType; - -const generatorOptionsByModuleType = generatorOptionsByModuleTypeKnown; - -const noParseOptionSingle = z.string().or(z.instanceof(RegExp)).or(anyFunction); -const noParseOption = noParseOptionSingle.or( - z.array(noParseOptionSingle) -) satisfies z.ZodType; - -const moduleOptions = z.strictObject({ - defaultRules: ruleSetRules.optional(), - rules: ruleSetRules.optional(), - parser: parserOptionsByModuleType.optional(), - generator: generatorOptionsByModuleType.optional(), - noParse: noParseOption.optional() -}) satisfies z.ZodType; -//#endregion - -//#region Target -const allowTarget = z.union([ - z.enum([ - "web", - "webworker", - "es3", - "es5", - "es2015", - "es2016", - "es2017", - "es2018", - "es2019", - "es2020", - "es2021", - "es2022", - "es2023", - "es2024", - "es2025" - ]), - z.literal("node"), - z.literal("async-node"), - z.custom<`node${number}`>( - value => typeof value === "string" && /^node\d+$/.test(value) - ), - z.custom<`async-node${number}`>( - value => typeof value === "string" && /^async-node\d+$/.test(value) - ), - z.custom<`node${number}.${number}`>( - value => typeof value === "string" && /^node\d+\.\d+$/.test(value) - ), - z.custom<`async-node${number}.${number}`>( - value => typeof value === "string" && /^async-node\d+\.\d+$/.test(value) - ), - z.literal("electron-main"), - z.custom<`electron${number}-main`>( - value => typeof value === "string" && /^electron\d+-main$/.test(value) - ), - z.custom<`electron${number}.${number}-main`>( - value => typeof value === "string" && /^electron\d+\.\d+-main$/.test(value) - ), - z.literal("electron-renderer"), - z.custom<`electron${number}-renderer`>( - value => typeof value === "string" && /^electron\d+-renderer$/.test(value) - ), - z.custom<`electron${number}.${number}-renderer`>( - value => - typeof value === "string" && /^electron\d+\.\d+-renderer$/.test(value) - ), - z.literal("electron-preload"), - z.custom<`electron${number}-preload`>( - value => typeof value === "string" && /^electron\d+-preload$/.test(value) - ), - z.custom<`electron${number}.${number}-preload`>( - value => - typeof value === "string" && /^electron\d+\.\d+-preload$/.test(value) - ), - z.literal("nwjs"), - z.custom<`nwjs${number}`>( - value => typeof value === "string" && /^nwjs\d+$/.test(value) - ), - z.custom<`nwjs${number}.${number}`>( - value => typeof value === "string" && /^nwjs\d+\.\d+$/.test(value) - ), - z.literal("node-webkit"), - z.custom<`node-webkit${number}`>( - value => typeof value === "string" && /^node-webkit\d+$/.test(value) - ), - z.custom<`node-webkit${number}.${number}`>( - value => typeof value === "string" && /^node-webkit\d+\.\d+$/.test(value) - ), - z.literal("browserslist"), - z.custom<`browserslist:${string}`>( - value => typeof value === "string" && /^browserslist:(.+)$/.test(value) - ) -]); - -const target = z.union([ - z.literal(false), - allowTarget, - allowTarget.array() -]) satisfies z.ZodType; -//#endregion - -//#region ExternalsType -export const externalsType = z.enum([ - "var", - "module", - "assign", - "this", - "window", - "self", - "global", - "commonjs", - "commonjs2", - "commonjs-module", - "commonjs-static", - "amd", - "amd-require", - "umd", - "umd2", - "jsonp", - "system", - "promise", - "import", - "module-import", - "script", - "node-commonjs", - "commonjs-import" -]) satisfies z.ZodType; -//#endregion - -const externalItemObjectValue = z.record( - z.string(), - z.string().or(z.string().array()) -) satisfies z.ZodType; - -const externalItemUmdValue = z.strictObject({ - root: z.string().or(z.string().array()), - commonjs: z.string().or(z.string().array()), - commonjs2: z.string().or(z.string().array()), - amd: z.string().or(z.string().array()) -}) satisfies z.ZodType; - -const externalUmdChecker: z.core.CheckFn = ctx => { - let isLibraryUmd = false; - const config = ctx.value; - const library = config?.output?.library; - if (typeof library === "object" && "type" in library) { - isLibraryUmd = library.type === "umd"; - } else { - isLibraryUmd = config?.output?.libraryTarget === "umd"; - } - - if (!isLibraryUmd) { - return; - } - - if (config?.externalsType !== undefined && config?.externalsType !== "umd") { - return; - } - - if (!Array.isArray(config?.externals)) { - checkExternalItem(config?.externals, ["externals"]); - } else { - config.externals.forEach((external, index) => - checkExternalItem(external, ["externals", index]) - ); - } - - function checkExternalItem( - externalItem: t.ExternalItem | undefined, - path: (string | number)[] - ) { - if (typeof externalItem === "object" && externalItem !== null) { - for (const [key, value] of Object.entries(externalItem)) { - checkExternalItemValue(value, [...path, key]); - } + const extendedBaseRuleSetRule: z.ZodType = + baseRuleSetRule.extend({ + oneOf: z.lazy(() => ruleSetRule.or(falsy).array()).optional(), + rules: z.lazy(() => ruleSetRule.or(falsy).array()).optional() + }) satisfies z.ZodType; + + const ruleSetRule = extendedBaseRuleSetRule.check(builtinSWCLoaderChecker); + + const ruleSetRules = z.array( + z.literal("...").or(ruleSetRule).or(falsy) + ) satisfies z.ZodType; + + const assetParserDataUrlOptions = z.strictObject({ + maxSize: numberOrInfinity.optional() + }) satisfies z.ZodType; + + const assetParserDataUrl = + assetParserDataUrlOptions satisfies z.ZodType; + + const assetParserOptions = z.strictObject({ + dataUrlCondition: assetParserDataUrl.optional() + }) satisfies z.ZodType; + + const cssParserNamedExports = + z.boolean() satisfies z.ZodType; + + const cssParserUrl = z.boolean() satisfies z.ZodType; + + const cssParserOptions = z.strictObject({ + namedExports: cssParserNamedExports.optional(), + url: cssParserUrl.optional() + }) satisfies z.ZodType; + + const cssAutoParserOptions = z.strictObject({ + namedExports: cssParserNamedExports.optional(), + url: cssParserUrl.optional() + }) satisfies z.ZodType; + + const cssModuleParserOptions = z.strictObject({ + namedExports: cssParserNamedExports.optional(), + url: cssParserUrl.optional() + }) satisfies z.ZodType; + + const dynamicImportMode = z.enum(["eager", "lazy", "weak", "lazy-once"]); + const dynamicImportPreload = z.union([z.boolean(), numberOrInfinity]); + const dynamicImportPrefetch = z.union([z.boolean(), numberOrInfinity]); + const dynamicImportFetchPriority = z.enum(["low", "high", "auto"]); + const javascriptParserUrl = z.union([z.literal("relative"), z.boolean()]); + const exprContextCritical = z.boolean(); + const wrappedContextCritical = z.boolean(); + const wrappedContextRegExp = z.instanceof(RegExp); + const exportsPresence = z + .enum(["error", "warn", "auto"]) + .or(z.literal(false)); + const importExportsPresence = z + .enum(["error", "warn", "auto"]) + .or(z.literal(false)); + const reexportExportsPresence = z + .enum(["error", "warn", "auto"]) + .or(z.literal(false)); + const strictExportPresence = z.boolean(); + const worker = z.array(z.string()).or(z.boolean()); + const overrideStrict = z.enum(["strict", "non-strict"]); + const requireAsExpression = z.boolean(); + const requireDynamic = z.boolean(); + const requireResolve = z.boolean(); + const importDynamic = z.boolean(); + const inlineConst = z.boolean(); + const typeReexportsPresence = z.enum([ + "no-tolerant", + "tolerant", + "tolerant-no-check" + ]); + + const javascriptParserOptions = z.strictObject({ + dynamicImportMode: dynamicImportMode.optional(), + dynamicImportPreload: dynamicImportPreload.optional(), + dynamicImportPrefetch: dynamicImportPrefetch.optional(), + dynamicImportFetchPriority: dynamicImportFetchPriority.optional(), + importMeta: z.boolean().optional(), + url: javascriptParserUrl.optional(), + exprContextCritical: exprContextCritical.optional(), + wrappedContextCritical: wrappedContextCritical.optional(), + wrappedContextRegExp: wrappedContextRegExp.optional(), + exportsPresence: exportsPresence.optional(), + importExportsPresence: importExportsPresence.optional(), + reexportExportsPresence: reexportExportsPresence.optional(), + strictExportPresence: strictExportPresence.optional(), + worker: worker.optional(), + overrideStrict: overrideStrict.optional(), + // #region Not available in webpack yet. + requireAsExpression: requireAsExpression.optional(), + requireDynamic: requireDynamic.optional(), + requireResolve: requireResolve.optional(), + importDynamic: importDynamic.optional(), + inlineConst: inlineConst.optional(), + typeReexportsPresence: typeReexportsPresence.optional() + // #endregion + }) satisfies z.ZodType; + + const parserOptionsByModuleTypeKnown = z.strictObject({ + asset: assetParserOptions.optional(), + css: cssParserOptions.optional(), + "css/auto": cssAutoParserOptions.optional(), + "css/module": cssModuleParserOptions.optional(), + javascript: javascriptParserOptions.optional(), + "javascript/auto": javascriptParserOptions.optional(), + "javascript/dynamic": javascriptParserOptions.optional(), + "javascript/esm": javascriptParserOptions.optional() + }) satisfies z.ZodType; + + const parserOptionsByModuleType = parserOptionsByModuleTypeKnown; + + const assetGeneratorDataUrlOptions = z.strictObject({ + encoding: z.literal(false).or(z.literal("base64")).optional(), + mimetype: z.string().optional() + }) satisfies z.ZodType; + + const assetGeneratorDataUrlFunction = + anyFunction satisfies z.ZodType; + + const assetGeneratorDataUrl = assetGeneratorDataUrlOptions.or( + assetGeneratorDataUrlFunction + ) satisfies z.ZodType; + + const assetInlineGeneratorOptions = z.strictObject({ + dataUrl: assetGeneratorDataUrl.optional() + }) satisfies z.ZodType; + + const assetResourceGeneratorOptions = z.strictObject({ + emit: z.boolean().optional(), + filename: filename.optional(), + publicPath: publicPath.optional(), + outputPath: filename.optional() + }) satisfies z.ZodType; + + const assetGeneratorOptions = assetInlineGeneratorOptions.merge( + assetResourceGeneratorOptions + ) satisfies z.ZodType; + + const cssGeneratorExportsConvention = z.enum([ + "as-is", + "camel-case", + "camel-case-only", + "dashes", + "dashes-only" + ]) satisfies z.ZodType; + + const cssGeneratorExportsOnly = + z.boolean() satisfies z.ZodType; + + const cssGeneratorLocalIdentName = + z.string() satisfies z.ZodType; + + const cssGeneratorEsModule = + z.boolean() satisfies z.ZodType; + + const cssGeneratorOptions = z.strictObject({ + exportsOnly: cssGeneratorExportsOnly.optional(), + esModule: cssGeneratorEsModule.optional() + }) satisfies z.ZodType; + + const cssAutoGeneratorOptions = z.strictObject({ + exportsConvention: cssGeneratorExportsConvention.optional(), + exportsOnly: cssGeneratorExportsOnly.optional(), + localIdentName: cssGeneratorLocalIdentName.optional(), + esModule: cssGeneratorEsModule.optional() + }) satisfies z.ZodType; + + const cssModuleGeneratorOptions = z.strictObject({ + exportsConvention: cssGeneratorExportsConvention.optional(), + exportsOnly: cssGeneratorExportsOnly.optional(), + localIdentName: cssGeneratorLocalIdentName.optional(), + esModule: cssGeneratorEsModule.optional() + }) satisfies z.ZodType; + + const jsonGeneratorOptions = z.strictObject({ + JSONParse: z.boolean().optional() + }) satisfies z.ZodType; + + const generatorOptionsByModuleTypeKnown = z.strictObject({ + asset: assetGeneratorOptions.optional(), + "asset/inline": assetInlineGeneratorOptions.optional(), + "asset/resource": assetResourceGeneratorOptions.optional(), + css: cssGeneratorOptions.optional(), + "css/auto": cssAutoGeneratorOptions.optional(), + "css/module": cssModuleGeneratorOptions.optional(), + json: jsonGeneratorOptions.optional() + }) satisfies z.ZodType; + + const generatorOptionsByModuleType = generatorOptionsByModuleTypeKnown; + + const noParseOptionSingle = z + .string() + .or(z.instanceof(RegExp)) + .or(anyFunction); + const noParseOption = noParseOptionSingle.or( + z.array(noParseOptionSingle) + ) satisfies z.ZodType; + + const moduleOptions = z.strictObject({ + defaultRules: ruleSetRules.optional(), + rules: ruleSetRules.optional(), + parser: parserOptionsByModuleType.optional(), + generator: generatorOptionsByModuleType.optional(), + noParse: noParseOption.optional() + }) satisfies z.ZodType; + //#endregion + + //#region Target + const allowTarget = z.union([ + z.enum([ + "web", + "webworker", + "es3", + "es5", + "es2015", + "es2016", + "es2017", + "es2018", + "es2019", + "es2020", + "es2021", + "es2022", + "es2023", + "es2024", + "es2025" + ]), + z.literal("node"), + z.literal("async-node"), + z.custom<`node${number}`>( + value => typeof value === "string" && /^node\d+$/.test(value) + ), + z.custom<`async-node${number}`>( + value => typeof value === "string" && /^async-node\d+$/.test(value) + ), + z.custom<`node${number}.${number}`>( + value => typeof value === "string" && /^node\d+\.\d+$/.test(value) + ), + z.custom<`async-node${number}.${number}`>( + value => typeof value === "string" && /^async-node\d+\.\d+$/.test(value) + ), + z.literal("electron-main"), + z.custom<`electron${number}-main`>( + value => typeof value === "string" && /^electron\d+-main$/.test(value) + ), + z.custom<`electron${number}.${number}-main`>( + value => + typeof value === "string" && /^electron\d+\.\d+-main$/.test(value) + ), + z.literal("electron-renderer"), + z.custom<`electron${number}-renderer`>( + value => typeof value === "string" && /^electron\d+-renderer$/.test(value) + ), + z.custom<`electron${number}.${number}-renderer`>( + value => + typeof value === "string" && /^electron\d+\.\d+-renderer$/.test(value) + ), + z.literal("electron-preload"), + z.custom<`electron${number}-preload`>( + value => typeof value === "string" && /^electron\d+-preload$/.test(value) + ), + z.custom<`electron${number}.${number}-preload`>( + value => + typeof value === "string" && /^electron\d+\.\d+-preload$/.test(value) + ), + z.literal("nwjs"), + z.custom<`nwjs${number}`>( + value => typeof value === "string" && /^nwjs\d+$/.test(value) + ), + z.custom<`nwjs${number}.${number}`>( + value => typeof value === "string" && /^nwjs\d+\.\d+$/.test(value) + ), + z.literal("node-webkit"), + z.custom<`node-webkit${number}`>( + value => typeof value === "string" && /^node-webkit\d+$/.test(value) + ), + z.custom<`node-webkit${number}.${number}`>( + value => typeof value === "string" && /^node-webkit\d+\.\d+$/.test(value) + ), + z.literal("browserslist"), + z.custom<`browserslist:${string}`>( + value => typeof value === "string" && /^browserslist:(.+)$/.test(value) + ) + ]); + + const target = z.union([ + z.literal(false), + allowTarget, + allowTarget.array() + ]) satisfies z.ZodType; + //#endregion + + const externalItemObjectValue = z.record( + z.string(), + z.string().or(z.string().array()) + ) satisfies z.ZodType; + + const externalItemUmdValue = z.strictObject({ + root: z.string().or(z.string().array()), + commonjs: z.string().or(z.string().array()), + commonjs2: z.string().or(z.string().array()), + amd: z.string().or(z.string().array()) + }) satisfies z.ZodType; + + const externalUmdChecker: z.core.CheckFn = ctx => { + let isLibraryUmd = false; + const config = ctx.value; + const library = config?.output?.library; + if (typeof library === "object" && "type" in library) { + isLibraryUmd = library.type === "umd"; + } else { + isLibraryUmd = config?.output?.libraryTarget === "umd"; } - } - - function checkExternalItemValue( - externalItemValue: t.ExternalItemValue | undefined, - path: (string | number)[] - ) { - if (typeof externalItemValue === "object" && externalItemValue !== null) { - const result = externalItemUmdValue.safeParse(externalItemValue); - if (!result.success) { - ctx.issues.push({ - code: "custom", - message: `External object must have "root", "commonjs", "commonjs2", "amd" properties when "libraryType" or "externalsType" is "umd"`, - input: externalItemValue, - path - }); - } + + if (!isLibraryUmd) { return; } - } -}; - -// #region Externals -const externalItemValue = z - .string() - .or(z.boolean()) - .or(z.string().array().min(1)) - .or(externalItemObjectValue) satisfies z.ZodType; - -const externalItemObjectUnknown = z.record( - z.string(), - externalItemValue -) satisfies z.ZodType; - -const externalItem = z - .string() - .or(z.instanceof(RegExp)) - .or(externalItemObjectUnknown) - .or(anyFunction) satisfies z.ZodType; - -const externals = externalItem - .array() - .or(externalItem) satisfies z.ZodType; - -//#region ExternalsPresets -const externalsPresets = z.strictObject({ - node: z.boolean().optional(), - web: z.boolean().optional(), - webAsync: z.boolean().optional(), - electron: z.boolean().optional(), - electronMain: z.boolean().optional(), - electronPreload: z.boolean().optional(), - electronRenderer: z.boolean().optional(), - nwjs: z.boolean().optional() -}) satisfies z.ZodType; -//#endregion - -//#region InfrastructureLogging -const filterItemTypes = z - .instanceof(RegExp) - .or(z.string()) - .or(anyFunction) satisfies z.ZodType; - -const filterTypes = filterItemTypes - .array() - .or(filterItemTypes) satisfies z.ZodType; - -const infrastructureLogging = z.strictObject({ - appendOnly: z.boolean().optional(), - colors: z.boolean().optional(), - console: z.custom().optional(), - debug: z.boolean().or(filterTypes).optional(), - level: z.enum(["none", "error", "warn", "info", "log", "verbose"]).optional(), - stream: z.custom().optional() -}) satisfies z.ZodType; -//#endregion - -//#region DevTool -const devTool = z - .literal(false) - .or(z.literal("eval")) - .or( - z.string().refine( - val => { - // Pattern: [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map[-debugids] - const pattern = - /^(inline-|hidden-|eval-)?(nosources-)?(cheap-(module-)?)?source-map(-debugids)?$/; - return pattern.test(val); - }, - { - error: - "Expect value to match the pattern: [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map[-debugids]" + + if ( + config?.externalsType !== undefined && + config?.externalsType !== "umd" + ) { + return; + } + + if (!Array.isArray(config?.externals)) { + checkExternalItem(config?.externals, ["externals"]); + } else { + config.externals.forEach((external, index) => + checkExternalItem(external, ["externals", index]) + ); + } + + function checkExternalItem( + externalItem: t.ExternalItem | undefined, + path: (string | number)[] + ) { + if (typeof externalItem === "object" && externalItem !== null) { + for (const [key, value] of Object.entries(externalItem)) { + checkExternalItemValue(value, [...path, key]); + } } - ) as z.ZodType - ) satisfies z.ZodType; -//#endregion + } -//#region Node -const nodeOptions = z.strictObject({ - __dirname: z - .boolean() - .or(z.enum(["warn-mock", "mock", "eval-only", "node-module"])) - .optional(), - __filename: z - .boolean() - .or(z.enum(["warn-mock", "mock", "eval-only", "node-module"])) - .optional(), - global: z.boolean().or(z.literal("warn")).optional() -}) satisfies z.ZodType; - -const node = z.literal(false).or(nodeOptions) satisfies z.ZodType; - -const loader = z.record(z.string(), z.any()) satisfies z.ZodType; -//#endregion - -//#region Snapshot -const snapshotOptions = z.strictObject( - {} -) satisfies z.ZodType; -//#endregion - -//#region Cache -const cacheOptions = z.boolean() satisfies z.ZodType; -//#endregion - -//#region Stats -const statsPresets = z.enum([ - "normal", - "none", - "verbose", - "errors-only", - "errors-warnings", - "minimal", - "detailed", - "summary" -]); -const statsOptions = z.strictObject({ - all: z.boolean().optional(), - preset: z.boolean().or(statsPresets).optional(), - assets: z.boolean().optional(), - chunks: z.boolean().optional(), - modules: z.boolean().optional(), - entrypoints: z.boolean().or(z.literal("auto")).optional(), - chunkGroups: z.boolean().optional(), - warnings: z.boolean().optional(), - warningsCount: z.boolean().optional(), - errors: z.boolean().optional(), - errorsCount: z.boolean().optional(), - colors: z.boolean().optional(), - hash: z.boolean().optional(), - version: z.boolean().optional(), - reasons: z.boolean().optional(), - publicPath: z.boolean().optional(), - outputPath: z.boolean().optional(), - chunkModules: z.boolean().optional(), - chunkRelations: z.boolean().optional(), - ids: z.boolean().optional(), - timings: z.boolean().optional(), - builtAt: z.boolean().optional(), - moduleAssets: z.boolean().optional(), - nestedModules: z.boolean().optional(), - source: z.boolean().optional(), - logging: z - .enum(["none", "error", "warn", "info", "log", "verbose"]) + function checkExternalItemValue( + externalItemValue: t.ExternalItemValue | undefined, + path: (string | number)[] + ) { + if (typeof externalItemValue === "object" && externalItemValue !== null) { + const result = externalItemUmdValue.safeParse(externalItemValue); + if (!result.success) { + ctx.issues.push({ + code: "custom", + message: `External object must have "root", "commonjs", "commonjs2", "amd" properties when "libraryType" or "externalsType" is "umd"`, + input: externalItemValue, + path + }); + } + return; + } + } + }; + + // #region Externals + const externalItemValue = z + .string() .or(z.boolean()) - .optional(), - loggingDebug: z.boolean().or(filterTypes).optional(), - loggingTrace: z.boolean().optional(), - runtimeModules: z.boolean().optional(), - children: z.boolean().optional(), - usedExports: z.boolean().optional(), - providedExports: z.boolean().optional(), - optimizationBailout: z.boolean().optional(), - groupModulesByType: z.boolean().optional(), - groupModulesByCacheStatus: z.boolean().optional(), - groupModulesByLayer: z.boolean().optional(), - groupModulesByAttributes: z.boolean().optional(), - groupModulesByPath: z.boolean().optional(), - groupModulesByExtension: z.boolean().optional(), - modulesSpace: z.int().optional(), - chunkModulesSpace: z.int().optional(), - nestedModulesSpace: z.int().optional(), - relatedAssets: z.boolean().optional(), - groupAssetsByEmitStatus: z.boolean().optional(), - groupAssetsByInfo: z.boolean().optional(), - groupAssetsByPath: z.boolean().optional(), - groupAssetsByExtension: z.boolean().optional(), - groupAssetsByChunk: z.boolean().optional(), - assetsSpace: z.int().optional(), - orphanModules: z.boolean().optional(), - excludeModules: z - .array(z.string().or(z.instanceof(RegExp)).or(anyFunction)) - .or(z.string()) + .or(z.string().array().min(1)) + .or(externalItemObjectValue) satisfies z.ZodType; + + const externalItemObjectUnknown = z.record( + z.string(), + externalItemValue + ) satisfies z.ZodType; + + const externalItem = z + .string() .or(z.instanceof(RegExp)) - .or(anyFunction) - .or(z.boolean()) - .optional(), - excludeAssets: z - .array(z.string().or(z.instanceof(RegExp)).or(anyFunction)) + .or(externalItemObjectUnknown) + .or(anyFunction) satisfies z.ZodType; + + const externals = externalItem + .array() + .or(externalItem) satisfies z.ZodType; + + //#region ExternalsPresets + const externalsPresets = z.strictObject({ + node: z.boolean().optional(), + web: z.boolean().optional(), + webAsync: z.boolean().optional(), + electron: z.boolean().optional(), + electronMain: z.boolean().optional(), + electronPreload: z.boolean().optional(), + electronRenderer: z.boolean().optional(), + nwjs: z.boolean().optional() + }) satisfies z.ZodType; + //#endregion + + //#region InfrastructureLogging + const filterItemTypes = z + .instanceof(RegExp) .or(z.string()) + .or(anyFunction) satisfies z.ZodType; + + const filterTypes = filterItemTypes + .array() + .or(filterItemTypes) satisfies z.ZodType; + + const infrastructureLogging = z.strictObject({ + appendOnly: z.boolean().optional(), + colors: z.boolean().optional(), + console: z.custom().optional(), + debug: z.boolean().or(filterTypes).optional(), + level: z + .enum(["none", "error", "warn", "info", "log", "verbose"]) + .optional(), + stream: z.custom().optional() + }) satisfies z.ZodType; + //#endregion + + //#region DevTool + const devTool = z + .literal(false) + .or(z.literal("eval")) + .or( + z.string().refine( + val => { + // Pattern: [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map[-debugids] + const pattern = + /^(inline-|hidden-|eval-)?(nosources-)?(cheap-(module-)?)?source-map(-debugids)?$/; + return pattern.test(val); + }, + { + error: + "Expect value to match the pattern: [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map[-debugids]" + } + ) as z.ZodType + ) satisfies z.ZodType; + //#endregion + + //#region Node + const nodeOptions = z.strictObject({ + __dirname: z + .boolean() + .or(z.enum(["warn-mock", "mock", "eval-only", "node-module"])) + .optional(), + __filename: z + .boolean() + .or(z.enum(["warn-mock", "mock", "eval-only", "node-module"])) + .optional(), + global: z.boolean().or(z.literal("warn")).optional() + }) satisfies z.ZodType; + + const node = z.literal(false).or(nodeOptions) satisfies z.ZodType; + + const loader = z.record(z.string(), z.any()) satisfies z.ZodType; + //#endregion + + //#region Snapshot + const snapshotOptions = z.strictObject( + {} + ) satisfies z.ZodType; + //#endregion + + //#region Cache + const cacheOptions = z.boolean() satisfies z.ZodType; + //#endregion + + //#region Stats + const statsPresets = z.enum([ + "normal", + "none", + "verbose", + "errors-only", + "errors-warnings", + "minimal", + "detailed", + "summary" + ]); + const statsOptions = z.strictObject({ + all: z.boolean().optional(), + preset: z.boolean().or(statsPresets).optional(), + assets: z.boolean().optional(), + chunks: z.boolean().optional(), + modules: z.boolean().optional(), + entrypoints: z.boolean().or(z.literal("auto")).optional(), + chunkGroups: z.boolean().optional(), + warnings: z.boolean().optional(), + warningsCount: z.boolean().optional(), + errors: z.boolean().optional(), + errorsCount: z.boolean().optional(), + colors: z.boolean().optional(), + hash: z.boolean().optional(), + version: z.boolean().optional(), + reasons: z.boolean().optional(), + publicPath: z.boolean().optional(), + outputPath: z.boolean().optional(), + chunkModules: z.boolean().optional(), + chunkRelations: z.boolean().optional(), + ids: z.boolean().optional(), + timings: z.boolean().optional(), + builtAt: z.boolean().optional(), + moduleAssets: z.boolean().optional(), + nestedModules: z.boolean().optional(), + source: z.boolean().optional(), + logging: z + .enum(["none", "error", "warn", "info", "log", "verbose"]) + .or(z.boolean()) + .optional(), + loggingDebug: z.boolean().or(filterTypes).optional(), + loggingTrace: z.boolean().optional(), + runtimeModules: z.boolean().optional(), + children: z.boolean().optional(), + usedExports: z.boolean().optional(), + providedExports: z.boolean().optional(), + optimizationBailout: z.boolean().optional(), + groupModulesByType: z.boolean().optional(), + groupModulesByCacheStatus: z.boolean().optional(), + groupModulesByLayer: z.boolean().optional(), + groupModulesByAttributes: z.boolean().optional(), + groupModulesByPath: z.boolean().optional(), + groupModulesByExtension: z.boolean().optional(), + modulesSpace: z.int().optional(), + chunkModulesSpace: z.int().optional(), + nestedModulesSpace: z.int().optional(), + relatedAssets: z.boolean().optional(), + groupAssetsByEmitStatus: z.boolean().optional(), + groupAssetsByInfo: z.boolean().optional(), + groupAssetsByPath: z.boolean().optional(), + groupAssetsByExtension: z.boolean().optional(), + groupAssetsByChunk: z.boolean().optional(), + assetsSpace: z.int().optional(), + orphanModules: z.boolean().optional(), + excludeModules: z + .array(z.string().or(z.instanceof(RegExp)).or(anyFunction)) + .or(z.string()) + .or(z.instanceof(RegExp)) + .or(anyFunction) + .or(z.boolean()) + .optional(), + excludeAssets: z + .array(z.string().or(z.instanceof(RegExp)).or(anyFunction)) + .or(z.string()) + .or(z.instanceof(RegExp)) + .or(anyFunction) + .optional(), + modulesSort: z.string().optional(), + chunkModulesSort: z.string().optional(), + nestedModulesSort: z.string().optional(), + chunksSort: z.string().optional(), + assetsSort: z.string().optional(), + performance: z.boolean().optional(), + env: z.boolean().optional(), + chunkGroupAuxiliary: z.boolean().optional(), + chunkGroupChildren: z.boolean().optional(), + chunkGroupMaxAssets: numberOrInfinity.optional(), + dependentModules: z.boolean().optional(), + chunkOrigins: z.boolean().optional(), + runtime: z.boolean().optional(), + depth: z.boolean().optional(), + reasonsSpace: z.int().optional(), + groupReasonsByOrigin: z.boolean().optional(), + errorDetails: z.boolean().optional(), + errorStack: z.boolean().optional(), + moduleTrace: z.boolean().optional(), + cachedModules: z.boolean().optional(), + cachedAssets: z.boolean().optional(), + cached: z.boolean().optional(), + errorsSpace: z.int().optional(), + warningsSpace: z.int().optional() + }) satisfies z.ZodType; + + const statsValue = z + .boolean() + .or(statsPresets) + .or(statsOptions) satisfies z.ZodType; + //#endregion + + //#region Plugins + const plugin = z.union([ + z.custom< + | t.RspackPluginInstance + | t.RspackPluginFunction + | t.WebpackPluginInstance + | t.WebpackPluginFunction + >(), + falsy + ]) satisfies z.ZodType; + + const plugins = plugin.array() satisfies z.ZodType; + //#endregion + + //#region Optimization + const optimizationRuntimeChunk = z + .enum(["single", "multiple"]) + .or(z.boolean()) + .or( + z.strictObject({ + name: z.string().or(anyFunction).optional() + }) + ) satisfies z.ZodType; + + const optimizationSplitChunksNameFunction = + anyFunction satisfies z.ZodType; + + const optimizationSplitChunksName = z + .string() + .or(z.literal(false)) + .or(optimizationSplitChunksNameFunction); + const optimizationSplitChunksChunks = z + .enum(["initial", "async", "all"]) .or(z.instanceof(RegExp)) - .or(anyFunction) - .optional(), - modulesSort: z.string().optional(), - chunkModulesSort: z.string().optional(), - nestedModulesSort: z.string().optional(), - chunksSort: z.string().optional(), - assetsSort: z.string().optional(), - performance: z.boolean().optional(), - env: z.boolean().optional(), - chunkGroupAuxiliary: z.boolean().optional(), - chunkGroupChildren: z.boolean().optional(), - chunkGroupMaxAssets: numberOrInfinity.optional(), - dependentModules: z.boolean().optional(), - chunkOrigins: z.boolean().optional(), - runtime: z.boolean().optional(), - depth: z.boolean().optional(), - reasonsSpace: z.int().optional(), - groupReasonsByOrigin: z.boolean().optional(), - errorDetails: z.boolean().optional(), - errorStack: z.boolean().optional(), - moduleTrace: z.boolean().optional(), - cachedModules: z.boolean().optional(), - cachedAssets: z.boolean().optional(), - cached: z.boolean().optional(), - errorsSpace: z.int().optional(), - warningsSpace: z.int().optional() -}) satisfies z.ZodType; - -const statsValue = z - .boolean() - .or(statsPresets) - .or(statsOptions) satisfies z.ZodType; -//#endregion - -//#region Plugins -const plugin = z.union([ - z.custom< - | t.RspackPluginInstance - | t.RspackPluginFunction - | t.WebpackPluginInstance - | t.WebpackPluginFunction - >(), - falsy -]) satisfies z.ZodType; - -const plugins = plugin.array() satisfies z.ZodType; -//#endregion - -//#region Optimization -const optimizationRuntimeChunk = z - .enum(["single", "multiple"]) - .or(z.boolean()) - .or( - z.strictObject({ - name: z.string().or(anyFunction).optional() + .or(anyFunction); + const optimizationSplitChunksSizes = numberOrInfinity.or( + z.record(z.string(), numberOrInfinity) + ); + const optimizationSplitChunksDefaultSizeTypes = z.array(z.string()); + const sharedOptimizationSplitChunksCacheGroup = { + chunks: optimizationSplitChunksChunks.optional(), + defaultSizeTypes: optimizationSplitChunksDefaultSizeTypes.optional(), + minChunks: z + .number() + .min(1) + .or(z.literal(Number.POSITIVE_INFINITY)) + .optional(), + usedExports: z.boolean().optional(), + name: optimizationSplitChunksName.optional(), + filename: filename.optional(), + minSize: optimizationSplitChunksSizes.optional(), + minSizeReduction: optimizationSplitChunksSizes.optional(), + maxSize: optimizationSplitChunksSizes.optional(), + maxAsyncSize: optimizationSplitChunksSizes.optional(), + maxInitialSize: optimizationSplitChunksSizes.optional(), + maxAsyncRequests: numberOrInfinity.optional(), + maxInitialRequests: numberOrInfinity.optional(), + automaticNameDelimiter: z.string().optional() + }; + const optimizationSplitChunksCacheGroup = z.strictObject({ + test: z.string().or(z.instanceof(RegExp)).or(anyFunction).optional(), + priority: numberOrInfinity.optional(), + enforce: z.boolean().optional(), + reuseExistingChunk: z.boolean().optional(), + type: z.string().or(z.instanceof(RegExp)).optional(), + idHint: z.string().optional(), + layer: z.string().or(z.instanceof(RegExp)).or(anyFunction).optional(), + ...sharedOptimizationSplitChunksCacheGroup + }) satisfies z.ZodType; + + const optimizationSplitChunksOptions = z.strictObject({ + cacheGroups: z + .record( + z.string(), + z.literal(false).or(optimizationSplitChunksCacheGroup) + ) + .optional(), + fallbackCacheGroup: z + .strictObject({ + chunks: optimizationSplitChunksChunks.optional(), + minSize: numberOrInfinity.optional(), + maxSize: numberOrInfinity.optional(), + maxAsyncSize: numberOrInfinity.optional(), + maxInitialSize: numberOrInfinity.optional(), + automaticNameDelimiter: z.string().optional() + }) + .optional(), + hidePathInfo: z.boolean().optional(), + ...sharedOptimizationSplitChunksCacheGroup + }) satisfies z.ZodType; + + const optimization = z.strictObject({ + moduleIds: z.enum(["named", "natural", "deterministic"]).optional(), + chunkIds: z + .enum(["natural", "named", "deterministic", "size", "total-size"]) + .optional(), + minimize: z.boolean().optional(), + minimizer: z.literal("...").or(plugin).array().optional(), + mergeDuplicateChunks: z.boolean().optional(), + splitChunks: z.literal(false).or(optimizationSplitChunksOptions).optional(), + runtimeChunk: optimizationRuntimeChunk.optional(), + removeAvailableModules: z.boolean().optional(), + removeEmptyChunks: z.boolean().optional(), + realContentHash: z.boolean().optional(), + sideEffects: z.enum(["flag"]).or(z.boolean()).optional(), + providedExports: z.boolean().optional(), + concatenateModules: z.boolean().optional(), + innerGraph: z.boolean().optional(), + usedExports: z.enum(["global"]).or(z.boolean()).optional(), + mangleExports: z.enum(["size", "deterministic"]).or(z.boolean()).optional(), + nodeEnv: z.union([z.string(), z.literal(false)]).optional(), + emitOnErrors: z.boolean().optional(), + avoidEntryIife: z.boolean().optional() + }) satisfies z.ZodType; + //#endregion + + //#region Experiments + const rspackFutureOptions = z.strictObject({ + bundlerInfo: z + .strictObject({ + version: z.string().optional(), + bundler: z.string().optional(), + force: z + .boolean() + .or(z.array(z.enum(["version", "uniqueId"]))) + .optional() + }) + .optional() + }) satisfies z.ZodType; + + const experimentCacheOptions = z + .object({ + type: z.enum(["memory"]) }) - ) satisfies z.ZodType; - -const optimizationSplitChunksNameFunction = - anyFunction satisfies z.ZodType; - -const optimizationSplitChunksName = z - .string() - .or(z.literal(false)) - .or(optimizationSplitChunksNameFunction); -const optimizationSplitChunksChunks = z - .enum(["initial", "async", "all"]) - .or(z.instanceof(RegExp)) - .or(anyFunction); -const optimizationSplitChunksSizes = numberOrInfinity.or( - z.record(z.string(), numberOrInfinity) -); -const optimizationSplitChunksDefaultSizeTypes = z.array(z.string()); -const sharedOptimizationSplitChunksCacheGroup = { - chunks: optimizationSplitChunksChunks.optional(), - defaultSizeTypes: optimizationSplitChunksDefaultSizeTypes.optional(), - minChunks: z - .number() - .min(1) - .or(z.literal(Number.POSITIVE_INFINITY)) - .optional(), - usedExports: z.boolean().optional(), - name: optimizationSplitChunksName.optional(), - filename: filename.optional(), - minSize: optimizationSplitChunksSizes.optional(), - minSizeReduction: optimizationSplitChunksSizes.optional(), - maxSize: optimizationSplitChunksSizes.optional(), - maxAsyncSize: optimizationSplitChunksSizes.optional(), - maxInitialSize: optimizationSplitChunksSizes.optional(), - maxAsyncRequests: numberOrInfinity.optional(), - maxInitialRequests: numberOrInfinity.optional(), - automaticNameDelimiter: z.string().optional() -}; -const optimizationSplitChunksCacheGroup = z.strictObject({ - test: z.string().or(z.instanceof(RegExp)).or(anyFunction).optional(), - priority: numberOrInfinity.optional(), - enforce: z.boolean().optional(), - reuseExistingChunk: z.boolean().optional(), - type: z.string().or(z.instanceof(RegExp)).optional(), - idHint: z.string().optional(), - layer: z.string().or(z.instanceof(RegExp)).or(anyFunction).optional(), - ...sharedOptimizationSplitChunksCacheGroup -}) satisfies z.ZodType; - -const optimizationSplitChunksOptions = z.strictObject({ - cacheGroups: z - .record(z.string(), z.literal(false).or(optimizationSplitChunksCacheGroup)) - .optional(), - fallbackCacheGroup: z + .or( + z.object({ + type: z.enum(["persistent"]), + buildDependencies: z.string().array().optional(), + version: z.string().optional(), + snapshot: z + .object({ + immutablePaths: z + .string() + .or(z.instanceof(RegExp)) + .array() + .optional(), + unmanagedPaths: z + .string() + .or(z.instanceof(RegExp)) + .array() + .optional(), + managedPaths: z.string().or(z.instanceof(RegExp)).array().optional() + }) + .optional(), + storage: z + .object({ + type: z.enum(["filesystem"]), + directory: z.string().optional() + }) + .optional() + }) + ); + + const lazyCompilationOptions = z.object({ + imports: z.boolean().optional(), + entries: z.boolean().optional(), + test: z.instanceof(RegExp).or(anyFunction).optional(), + client: z.string().optional(), + serverUrl: z.string().optional(), + prefix: z.string().optional() + }) satisfies z.ZodType; + + const incremental = z.strictObject({ + make: z.boolean().optional(), + inferAsyncModules: z.boolean().optional(), + providedExports: z.boolean().optional(), + dependenciesDiagnostics: z.boolean().optional(), + sideEffects: z.boolean().optional(), + buildChunkGraph: z.boolean().optional(), + moduleIds: z.boolean().optional(), + chunkIds: z.boolean().optional(), + modulesHashes: z.boolean().optional(), + modulesCodegen: z.boolean().optional(), + modulesRuntimeRequirements: z.boolean().optional(), + chunksRuntimeRequirements: z.boolean().optional(), + chunksHashes: z.boolean().optional(), + chunksRender: z.boolean().optional(), + emitAssets: z.boolean().optional() + }) satisfies z.ZodType; + + // Define buildHttp options schema + const buildHttpOptions = z.object({ + allowedUris: z.array(z.union([z.string(), z.instanceof(RegExp)])), + lockfileLocation: z.string().optional(), + cacheLocation: z.union([z.string(), z.literal(false)]).optional(), + upgrade: z.boolean().optional(), + // proxy: z.string().optional(), + // frozen: z.boolean().optional(), + httpClient: anyFunction.optional() + }) satisfies z.ZodType; + + const useInputFileSystem = z.union([ + z.literal(false), + z.array(z.instanceof(RegExp)) + ]) satisfies z.ZodType; + + const experiments = z.strictObject({ + cache: z.boolean().optional().or(experimentCacheOptions), + lazyCompilation: z.boolean().optional().or(lazyCompilationOptions), + asyncWebAssembly: z.boolean().optional(), + outputModule: z.boolean().optional(), + topLevelAwait: z.boolean().optional(), + css: z.boolean().optional(), + layers: z.boolean().optional(), + incremental: z + .boolean() + .or(z.literal("safe")) + .or(z.literal("advance")) + .or(z.literal("advance-silent")) + .or(incremental) + .optional(), + parallelCodeSplitting: z.boolean().optional(), + futureDefaults: z.boolean().optional(), + rspackFuture: rspackFutureOptions.optional(), + buildHttp: buildHttpOptions.optional(), + parallelLoader: z.boolean().optional(), + useInputFileSystem: useInputFileSystem.optional(), + inlineConst: z.boolean().optional(), + typeReexportsPresence: typeReexportsPresence.optional() + }) satisfies z.ZodType; + //#endregion + + //#region Watch + const watch = z.boolean() satisfies z.ZodType; + //#endregion + + //#region WatchOptions + const watchOptions = z.strictObject({ + aggregateTimeout: numberOrInfinity.optional(), + followSymlinks: z.boolean().optional(), + ignored: z + .string() + .array() + .or(z.instanceof(RegExp)) + .or(z.string()) + .optional(), + poll: numberOrInfinity.or(z.boolean()).optional(), + stdin: z.boolean().optional() + }) satisfies z.ZodType; + //#endregion + + //#region DevServer + const devServer = z.custom(); + //#endregion + + //#region IgnoreWarnings + const ignoreWarnings = z + .instanceof(RegExp) + .or(anyFunction) + .array() satisfies z.ZodType; + //#endregion + + //#region Profile + const profile = z.boolean() satisfies z.ZodType; + //#endregion + + //#region Amd + const amd = z + .literal(false) + .or(z.record(z.string(), z.any())) satisfies z.ZodType; + //#endregion + + //#region Bail + const bail = z.boolean() satisfies z.ZodType; + //#endregion + + //#region Performance + const performance = z .strictObject({ - chunks: optimizationSplitChunksChunks.optional(), - minSize: numberOrInfinity.optional(), - maxSize: numberOrInfinity.optional(), - maxAsyncSize: numberOrInfinity.optional(), - maxInitialSize: numberOrInfinity.optional(), - automaticNameDelimiter: z.string().optional() + assetFilter: anyFunction.optional(), + hints: z.enum(["error", "warning"]).or(z.literal(false)).optional(), + maxAssetSize: numberOrInfinity.optional(), + maxEntrypointSize: numberOrInfinity.optional() }) - .optional(), - hidePathInfo: z.boolean().optional(), - ...sharedOptimizationSplitChunksCacheGroup -}) satisfies z.ZodType; - -const optimization = z.strictObject({ - moduleIds: z.enum(["named", "natural", "deterministic"]).optional(), - chunkIds: z - .enum(["natural", "named", "deterministic", "size", "total-size"]) - .optional(), - minimize: z.boolean().optional(), - minimizer: z.literal("...").or(plugin).array().optional(), - mergeDuplicateChunks: z.boolean().optional(), - splitChunks: z.literal(false).or(optimizationSplitChunksOptions).optional(), - runtimeChunk: optimizationRuntimeChunk.optional(), - removeAvailableModules: z.boolean().optional(), - removeEmptyChunks: z.boolean().optional(), - realContentHash: z.boolean().optional(), - sideEffects: z.enum(["flag"]).or(z.boolean()).optional(), - providedExports: z.boolean().optional(), - concatenateModules: z.boolean().optional(), - innerGraph: z.boolean().optional(), - usedExports: z.enum(["global"]).or(z.boolean()).optional(), - mangleExports: z.enum(["size", "deterministic"]).or(z.boolean()).optional(), - nodeEnv: z.union([z.string(), z.literal(false)]).optional(), - emitOnErrors: z.boolean().optional(), - avoidEntryIife: z.boolean().optional() -}) satisfies z.ZodType; -//#endregion - -//#region Experiments -const rspackFutureOptions = z.strictObject({ - bundlerInfo: z + .or(z.literal(false)) satisfies z.ZodType; + //#endregion + + const rspackOptions = z .strictObject({ - version: z.string().optional(), - bundler: z.string().optional(), - force: z - .boolean() - .or(z.array(z.enum(["version", "uniqueId"]))) - .optional() - }) - .optional() -}) satisfies z.ZodType; - -const experimentCacheOptions = z - .object({ - type: z.enum(["memory"]) - }) - .or( - z.object({ - type: z.enum(["persistent"]), - buildDependencies: z.string().array().optional(), - version: z.string().optional(), - snapshot: z - .object({ - immutablePaths: z - .string() - .or(z.instanceof(RegExp)) - .array() - .optional(), - unmanagedPaths: z - .string() - .or(z.instanceof(RegExp)) - .array() - .optional(), - managedPaths: z.string().or(z.instanceof(RegExp)).array().optional() - }) - .optional(), - storage: z - .object({ - type: z.enum(["filesystem"]), - directory: z.string().optional() - }) - .optional() + name: name.optional(), + dependencies: dependencies.optional(), + extends: z.union([z.string(), z.array(z.string())]).optional(), + entry: entry.optional(), + output: output.optional(), + target: target.optional(), + mode: mode.optional(), + experiments: experiments.optional(), + externals: externals.optional(), + externalsType: getExternalsTypeSchema().optional(), + externalsPresets: externalsPresets.optional(), + infrastructureLogging: infrastructureLogging.optional(), + cache: cacheOptions.optional(), + context: context.optional(), + devtool: devTool.optional(), + node: node.optional(), + loader: loader.optional(), + ignoreWarnings: ignoreWarnings.optional(), + watchOptions: watchOptions.optional(), + watch: watch.optional(), + stats: statsValue.optional(), + snapshot: snapshotOptions.optional(), + optimization: optimization.optional(), + resolve: resolveOptions.optional(), + resolveLoader: resolveOptions.optional(), + plugins: plugins.optional(), + devServer: devServer.optional(), + module: moduleOptions.optional(), + profile: profile.optional(), + amd: amd.optional(), + bail: bail.optional(), + performance: performance.optional() }) - ); + .check(externalUmdChecker) satisfies z.ZodType; -const lazyCompilationOptions = z.object({ - imports: z.boolean().optional(), - entries: z.boolean().optional(), - test: z.instanceof(RegExp).or(anyFunction).optional(), - client: z.string().optional(), - serverUrl: z.string().optional(), - prefix: z.string().optional() -}) satisfies z.ZodType; - -const incremental = z.strictObject({ - make: z.boolean().optional(), - inferAsyncModules: z.boolean().optional(), - providedExports: z.boolean().optional(), - dependenciesDiagnostics: z.boolean().optional(), - sideEffects: z.boolean().optional(), - buildChunkGraph: z.boolean().optional(), - moduleIds: z.boolean().optional(), - chunkIds: z.boolean().optional(), - modulesHashes: z.boolean().optional(), - modulesCodegen: z.boolean().optional(), - modulesRuntimeRequirements: z.boolean().optional(), - chunksRuntimeRequirements: z.boolean().optional(), - chunksHashes: z.boolean().optional(), - chunksRender: z.boolean().optional(), - emitAssets: z.boolean().optional() -}) satisfies z.ZodType; - -// Define buildHttp options schema -const buildHttpOptions = z.object({ - allowedUris: z.array(z.union([z.string(), z.instanceof(RegExp)])), - lockfileLocation: z.string().optional(), - cacheLocation: z.union([z.string(), z.literal(false)]).optional(), - upgrade: z.boolean().optional(), - // proxy: z.string().optional(), - // frozen: z.boolean().optional(), - httpClient: anyFunction.optional() -}) satisfies z.ZodType; - -const useInputFileSystem = z.union([ - z.literal(false), - z.array(z.instanceof(RegExp)) -]) satisfies z.ZodType; - -const experiments = z.strictObject({ - cache: z.boolean().optional().or(experimentCacheOptions), - lazyCompilation: z.boolean().optional().or(lazyCompilationOptions), - asyncWebAssembly: z.boolean().optional(), - outputModule: z.boolean().optional(), - topLevelAwait: z.boolean().optional(), - css: z.boolean().optional(), - layers: z.boolean().optional(), - incremental: z - .boolean() - .or(z.literal("safe")) - .or(z.literal("advance")) - .or(z.literal("advance-silent")) - .or(incremental) - .optional(), - parallelCodeSplitting: z.boolean().optional(), - futureDefaults: z.boolean().optional(), - rspackFuture: rspackFutureOptions.optional(), - buildHttp: buildHttpOptions.optional(), - parallelLoader: z.boolean().optional(), - useInputFileSystem: useInputFileSystem.optional(), - inlineConst: z.boolean().optional(), - typeReexportsPresence: typeReexportsPresence.optional() -}) satisfies z.ZodType; -//#endregion - -//#region Watch -const watch = z.boolean() satisfies z.ZodType; -//#endregion - -//#region WatchOptions -const watchOptions = z.strictObject({ - aggregateTimeout: numberOrInfinity.optional(), - followSymlinks: z.boolean().optional(), - ignored: z - .string() - .array() - .or(z.instanceof(RegExp)) - .or(z.string()) - .optional(), - poll: numberOrInfinity.or(z.boolean()).optional(), - stdin: z.boolean().optional() -}) satisfies z.ZodType; -//#endregion - -//#region DevServer -const devServer = z.custom(); -//#endregion - -//#region IgnoreWarnings -const ignoreWarnings = z - .instanceof(RegExp) - .or(anyFunction) - .array() satisfies z.ZodType; -//#endregion - -//#region Profile -const profile = z.boolean() satisfies z.ZodType; -//#endregion - -//#region Amd -const amd = z - .literal(false) - .or(z.record(z.string(), z.any())) satisfies z.ZodType; -//#endregion - -//#region Bail -const bail = z.boolean() satisfies z.ZodType; -//#endregion - -//#region Performance -const performance = z - .strictObject({ - assetFilter: anyFunction.optional(), - hints: z.enum(["error", "warning"]).or(z.literal(false)).optional(), - maxAssetSize: numberOrInfinity.optional(), - maxEntrypointSize: numberOrInfinity.optional() - }) - .or(z.literal(false)) satisfies z.ZodType; -//#endregion - -export const rspackOptions = z - .strictObject({ - name: name.optional(), - dependencies: dependencies.optional(), - extends: z.union([z.string(), z.array(z.string())]).optional(), - entry: entry.optional(), - output: output.optional(), - target: target.optional(), - mode: mode.optional(), - experiments: experiments.optional(), - externals: externals.optional(), - externalsType: externalsType.optional(), - externalsPresets: externalsPresets.optional(), - infrastructureLogging: infrastructureLogging.optional(), - cache: cacheOptions.optional(), - context: context.optional(), - devtool: devTool.optional(), - node: node.optional(), - loader: loader.optional(), - ignoreWarnings: ignoreWarnings.optional(), - watchOptions: watchOptions.optional(), - watch: watch.optional(), - stats: statsValue.optional(), - snapshot: snapshotOptions.optional(), - optimization: optimization.optional(), - resolve: resolveOptions.optional(), - resolveLoader: resolveOptions.optional(), - plugins: plugins.optional(), - devServer: devServer.optional(), - module: moduleOptions.optional(), - profile: profile.optional(), - amd: amd.optional(), - bail: bail.optional(), - performance: performance.optional() - }) - .check(externalUmdChecker) satisfies z.ZodType; + return rspackOptions; +}); diff --git a/packages/rspack/src/container/ModuleFederationPlugin.ts b/packages/rspack/src/container/ModuleFederationPlugin.ts index 3d5e3d5113e7..ea14d7924c5b 100644 --- a/packages/rspack/src/container/ModuleFederationPlugin.ts +++ b/packages/rspack/src/container/ModuleFederationPlugin.ts @@ -1,6 +1,6 @@ import type { Compiler } from "../Compiler"; import type { ExternalsType } from "../config"; -import { externalsType } from "../config/zod"; +import { getExternalsTypeSchema } from "../config/zod"; import { isValidate } from "../util/validate"; import type { ModuleFederationPluginV1Options } from "./ModuleFederationPluginV1"; import { ModuleFederationRuntimePlugin } from "./ModuleFederationRuntimePlugin"; @@ -93,7 +93,7 @@ function getRemoteInfos(options: ModuleFederationPluginOptions): RemoteInfos { const remoteType = options.remoteType || - (options.library && isValidate(options.library.type, externalsType) + (options.library && isValidate(options.library.type, getExternalsTypeSchema) ? (options.library.type as ExternalsType) : "script"); const remotes = parseOptions( diff --git a/packages/rspack/src/container/ModuleFederationPluginV1.ts b/packages/rspack/src/container/ModuleFederationPluginV1.ts index ad79e86119bd..1c418253d50f 100644 --- a/packages/rspack/src/container/ModuleFederationPluginV1.ts +++ b/packages/rspack/src/container/ModuleFederationPluginV1.ts @@ -1,6 +1,6 @@ import type { Compiler } from "../Compiler"; import type { EntryRuntime, ExternalsType, LibraryOptions } from "../config"; -import { externalsType } from "../config/zod"; +import { getExternalsTypeSchema } from "../config/zod"; import { SharePlugin, type Shared } from "../sharing/SharePlugin"; import { ShareRuntimePlugin } from "../sharing/ShareRuntimePlugin"; import { isValidate } from "../util/validate"; @@ -33,7 +33,8 @@ export class ModuleFederationPluginV1 { const library = options.library || { type: "var", name: options.name }; const remoteType = options.remoteType || - (options.library && isValidate(options.library.type, externalsType) + (options.library && + isValidate(options.library.type, getExternalsTypeSchema) ? (options.library.type as ExternalsType) : "script"); if ( diff --git a/packages/rspack/src/lib/DllPlugin.ts b/packages/rspack/src/lib/DllPlugin.ts index 43d9c8b39c12..f3d474f912e2 100644 --- a/packages/rspack/src/lib/DllPlugin.ts +++ b/packages/rspack/src/lib/DllPlugin.ts @@ -65,7 +65,7 @@ export class DllPlugin { private options: DllPluginOptions; constructor(options: DllPluginOptions) { - validate(options, getDllPluginOptionsSchema()); + validate(options, getDllPluginOptionsSchema); this.options = { ...options, entryOnly: options.entryOnly !== false diff --git a/packages/rspack/src/lib/DllReferencePlugin.ts b/packages/rspack/src/lib/DllReferencePlugin.ts index 45bd88cb740c..d2ccb5944f8d 100644 --- a/packages/rspack/src/lib/DllReferencePlugin.ts +++ b/packages/rspack/src/lib/DllReferencePlugin.ts @@ -204,7 +204,7 @@ export class DllReferencePlugin { private errors: WeakMap; constructor(options: DllReferencePluginOptions) { - validate(options, getDllReferencePluginOptionsSchema()); + validate(options, getDllReferencePluginOptionsSchema); this.options = options; this.errors = new WeakMap(); diff --git a/packages/rspack/src/rspack.ts b/packages/rspack/src/rspack.ts index ca9d64085248..f491656f9cb8 100644 --- a/packages/rspack/src/rspack.ts +++ b/packages/rspack/src/rspack.ts @@ -26,7 +26,7 @@ import { applyRspackOptionsDefaults, getNormalizedRspackOptions } from "./config"; -import { rspackOptions } from "./config/zod"; +import { getRspackOptionsSchema } from "./config/zod"; import NodeEnvironmentPlugin from "./node/NodeEnvironmentPlugin"; import { RspackOptionsApply } from "./rspackOptionsApply"; import { asArray, isNil } from "./util"; @@ -105,7 +105,7 @@ function rspack( ) { try { for (const o of asArray(options)) { - validate(o, rspackOptions); + validate(o, getRspackOptionsSchema); } } catch (e) { if (e instanceof Error && callback) { diff --git a/packages/rspack/src/util/validate.ts b/packages/rspack/src/util/validate.ts index 6c73e63a87cf..20052f32502a 100644 --- a/packages/rspack/src/util/validate.ts +++ b/packages/rspack/src/util/validate.ts @@ -10,18 +10,26 @@ export class ValidationError extends Error { export function validate( opts: any, - schema: T, + createSchema: () => T, options: { output?: boolean; strategy?: "strict" | "loose-unrecognized-keys" | "loose-silent" | "loose"; } = {} ): string | null { + const strategy = + options.strategy ?? process.env.RSPACK_CONFIG_VALIDATE ?? "strict"; + + // Skip schema validation if the strategy is `loose-silent` + if (strategy === "loose-silent") { + return null; + } + + const schema = + typeof createSchema === "function" ? createSchema() : createSchema; const res = schema.safeParse(opts); + if (!res.success) { - const strategy = - options.strategy ?? process.env.RSPACK_CONFIG_VALIDATE ?? "strict"; const output = options.output ?? true; - if (strategy === "loose-silent") return null; let friendlyErr: ValidationError; const originalIssues = res.error.issues; @@ -89,9 +97,12 @@ function toValidationError(error: z.ZodError): ValidationError { return new ValidationError(validationErr.message); } -export function isValidate(opts: any, schema: T) { +export function isValidate( + opts: any, + createSchema: () => T +) { try { - validate(opts, schema); + validate(opts, createSchema); return true; } catch { return false;