@rspack/cli
Advanced tools
+35
-3
@@ -6,2 +6,31 @@ import node_process from "node:process"; | ||
| let isRegistered = false; | ||
| async function flushStdio() { | ||
| const flush = (stream)=>new Promise((resolve)=>{ | ||
| if (!stream || !stream.writable || stream.writableEnded || stream.destroyed) return void resolve(); | ||
| const onError = ()=>{ | ||
| stream.off('error', onError); | ||
| resolve(); | ||
| }; | ||
| stream.once('error', onError); | ||
| try { | ||
| stream.write('', ()=>{ | ||
| stream.off('error', onError); | ||
| resolve(); | ||
| }); | ||
| } catch { | ||
| stream.off('error', onError); | ||
| resolve(); | ||
| } | ||
| }); | ||
| const timeout = new Promise((resolve)=>{ | ||
| setTimeout(resolve, 1000); | ||
| }); | ||
| await Promise.race([ | ||
| Promise.all([ | ||
| flush(node_process.stdout), | ||
| flush(node_process.stderr) | ||
| ]), | ||
| timeout | ||
| ]); | ||
| } | ||
| async function exit(shouldManuallyExit, isSynchronous, signal) { | ||
@@ -11,3 +40,5 @@ if (isCalled) return; | ||
| if (asyncCallbacks.size > 0 && isSynchronous) console.error("SYNCHRONOUS TERMINATION NOTICE: When explicitly exiting the process via process.exit or via a parent process, asynchronous tasks in your exitHooks will not run. Either remove these tasks, use gracefulExit() instead of process.exit(), or ensure your parent process sends a SIGINT to the process running this code."); | ||
| const exitCode = 128 + signal; | ||
| let exitCode = 0; | ||
| if (signal > 0) exitCode = 128 + signal; | ||
| else if ('number' == typeof node_process.exitCode || 'string' == typeof node_process.exitCode) exitCode = node_process.exitCode; | ||
| const done = (force = false)=>{ | ||
@@ -24,7 +55,8 @@ if (true === force || true === shouldManuallyExit) node_process.exit(exitCode); | ||
| } | ||
| const asyncTimer = setTimeout(()=>{ | ||
| const asyncTimer = forceAfter > 0 ? setTimeout(()=>{ | ||
| done(true); | ||
| }, forceAfter); | ||
| }, forceAfter) : void 0; | ||
| await Promise.all(promises); | ||
| clearTimeout(asyncTimer); | ||
| await flushStdio(); | ||
| done(); | ||
@@ -31,0 +63,0 @@ } |
+1209
-1
@@ -1,1 +0,1209 @@ | ||
| export { RspackCLI, defineConfig, definePlugin } from "./162.js"; | ||
| import node_path from "node:path"; | ||
| import node_util from "node:util"; | ||
| import { rspack } from "@rspack/core"; | ||
| import node_fs from "node:fs"; | ||
| import { Readable } from "node:stream"; | ||
| import { createRequire } from "node:module"; | ||
| import { pathToFileURL } from "node:url"; | ||
| function toArr(any) { | ||
| return null == any ? [] : Array.isArray(any) ? any : [ | ||
| any | ||
| ]; | ||
| } | ||
| function toVal(out, key, val, opts) { | ||
| var x, old = out[key], nxt = ~opts.string.indexOf(key) ? null == val || true === val ? "" : String(val) : "boolean" == typeof val ? val : ~opts.boolean.indexOf(key) ? "false" === val ? false : "true" === val || (out._.push((x = +val, 0 * x === 0) ? x : val), !!val) : (x = +val, 0 * x === 0) ? x : val; | ||
| out[key] = null == old ? nxt : Array.isArray(old) ? old.concat(nxt) : [ | ||
| old, | ||
| nxt | ||
| ]; | ||
| } | ||
| function lib_default(args, opts) { | ||
| args = args || []; | ||
| opts = opts || {}; | ||
| var k, arr, arg, name, val, out = { | ||
| _: [] | ||
| }; | ||
| var i = 0, j = 0, idx = 0, len = args.length; | ||
| const alibi = void 0 !== opts.alias; | ||
| const strict = void 0 !== opts.unknown; | ||
| const defaults = void 0 !== opts.default; | ||
| opts.alias = opts.alias || {}; | ||
| opts.string = toArr(opts.string); | ||
| opts.boolean = toArr(opts.boolean); | ||
| if (alibi) for(k in opts.alias){ | ||
| arr = opts.alias[k] = toArr(opts.alias[k]); | ||
| for(i = 0; i < arr.length; i++)(opts.alias[arr[i]] = arr.concat(k)).splice(i, 1); | ||
| } | ||
| for(i = opts.boolean.length; i-- > 0;){ | ||
| arr = opts.alias[opts.boolean[i]] || []; | ||
| for(j = arr.length; j-- > 0;)opts.boolean.push(arr[j]); | ||
| } | ||
| for(i = opts.string.length; i-- > 0;){ | ||
| arr = opts.alias[opts.string[i]] || []; | ||
| for(j = arr.length; j-- > 0;)opts.string.push(arr[j]); | ||
| } | ||
| if (defaults) for(k in opts.default){ | ||
| name = typeof opts.default[k]; | ||
| arr = opts.alias[k] = opts.alias[k] || []; | ||
| if (void 0 !== opts[name]) { | ||
| opts[name].push(k); | ||
| for(i = 0; i < arr.length; i++)opts[name].push(arr[i]); | ||
| } | ||
| } | ||
| const keys = strict ? Object.keys(opts.alias) : []; | ||
| for(i = 0; i < len; i++){ | ||
| arg = args[i]; | ||
| if ("--" === arg) { | ||
| out._ = out._.concat(args.slice(++i)); | ||
| break; | ||
| } | ||
| for(j = 0; j < arg.length && 45 === arg.charCodeAt(j); j++); | ||
| if (0 === j) out._.push(arg); | ||
| else if ("no-" === arg.substring(j, j + 3)) { | ||
| name = arg.substring(j + 3); | ||
| if (strict && !~keys.indexOf(name)) return opts.unknown(arg); | ||
| out[name] = false; | ||
| } else { | ||
| for(idx = j + 1; idx < arg.length && 61 !== arg.charCodeAt(idx); idx++); | ||
| name = arg.substring(j, idx); | ||
| val = arg.substring(++idx) || i + 1 === len || 45 === ("" + args[i + 1]).charCodeAt(0) || args[++i]; | ||
| arr = 2 === j ? [ | ||
| name | ||
| ] : name; | ||
| for(idx = 0; idx < arr.length; idx++){ | ||
| name = arr[idx]; | ||
| if (strict && !~keys.indexOf(name)) return opts.unknown("-".repeat(j) + name); | ||
| toVal(out, name, idx + 1 < arr.length || val, opts); | ||
| } | ||
| } | ||
| } | ||
| if (defaults) { | ||
| for(k in opts.default)if (void 0 === out[k]) out[k] = opts.default[k]; | ||
| } | ||
| if (alibi) for(k in out){ | ||
| arr = opts.alias[k] || []; | ||
| while(arr.length > 0)out[arr.shift()] = out[k]; | ||
| } | ||
| return out; | ||
| } | ||
| function removeBrackets(v) { | ||
| return v.replace(/[<[].+/, "").trim(); | ||
| } | ||
| function findAllBrackets(v) { | ||
| const ANGLED_BRACKET_RE_GLOBAL = /<([^>]+)>/g; | ||
| const SQUARE_BRACKET_RE_GLOBAL = /\[([^\]]+)\]/g; | ||
| const res = []; | ||
| const parse = (match)=>{ | ||
| let variadic = false; | ||
| let value = match[1]; | ||
| if (value.startsWith("...")) { | ||
| value = value.slice(3); | ||
| variadic = true; | ||
| } | ||
| return { | ||
| required: match[0].startsWith("<"), | ||
| value, | ||
| variadic | ||
| }; | ||
| }; | ||
| let angledMatch; | ||
| while(angledMatch = ANGLED_BRACKET_RE_GLOBAL.exec(v))res.push(parse(angledMatch)); | ||
| let squareMatch; | ||
| while(squareMatch = SQUARE_BRACKET_RE_GLOBAL.exec(v))res.push(parse(squareMatch)); | ||
| return res; | ||
| } | ||
| function getMriOptions(options) { | ||
| const result = { | ||
| alias: {}, | ||
| boolean: [] | ||
| }; | ||
| for (const [index, option] of options.entries()){ | ||
| if (option.names.length > 1) result.alias[option.names[0]] = option.names.slice(1); | ||
| if (option.isBoolean) if (option.negated) { | ||
| if (!options.some((o, i)=>i !== index && o.names.some((name)=>option.names.includes(name)) && "boolean" == typeof o.required)) result.boolean.push(option.names[0]); | ||
| } else result.boolean.push(option.names[0]); | ||
| } | ||
| return result; | ||
| } | ||
| function findLongest(arr) { | ||
| return arr.sort((a, b)=>a.length > b.length ? -1 : 1)[0]; | ||
| } | ||
| function padRight(str, length) { | ||
| return str.length >= length ? str : `${str}${" ".repeat(length - str.length)}`; | ||
| } | ||
| function camelcase(input) { | ||
| return input.replaceAll(/([a-z])-([a-z])/g, (_, p1, p2)=>p1 + p2.toUpperCase()); | ||
| } | ||
| function setDotProp(obj, keys, val) { | ||
| let current = obj; | ||
| for(let i = 0; i < keys.length; i++){ | ||
| const key = keys[i]; | ||
| if (i === keys.length - 1) { | ||
| current[key] = val; | ||
| return; | ||
| } | ||
| if (null == current[key]) { | ||
| const nextKeyIsArrayIndex = +keys[i + 1] > -1; | ||
| current[key] = nextKeyIsArrayIndex ? [] : {}; | ||
| } | ||
| current = current[key]; | ||
| } | ||
| } | ||
| function setByType(obj, transforms) { | ||
| for (const key of Object.keys(transforms)){ | ||
| const transform = transforms[key]; | ||
| if (transform.shouldTransform) { | ||
| obj[key] = [ | ||
| obj[key] | ||
| ].flat(); | ||
| if ("function" == typeof transform.transformFunction) obj[key] = obj[key].map(transform.transformFunction); | ||
| } | ||
| } | ||
| } | ||
| function getFileName(input) { | ||
| const m = /([^\\/]+)$/.exec(input); | ||
| return m ? m[1] : ""; | ||
| } | ||
| function camelcaseOptionName(name) { | ||
| return name.split(".").map((v, i)=>0 === i ? camelcase(v) : v).join("."); | ||
| } | ||
| var CACError = class extends Error { | ||
| constructor(message){ | ||
| super(message); | ||
| this.name = "CACError"; | ||
| if ("function" != typeof Error.captureStackTrace) this.stack = new Error(message).stack; | ||
| } | ||
| }; | ||
| var Option = class { | ||
| rawName; | ||
| description; | ||
| name; | ||
| names; | ||
| isBoolean; | ||
| required; | ||
| config; | ||
| negated; | ||
| constructor(rawName, description, config){ | ||
| this.rawName = rawName; | ||
| this.description = description; | ||
| this.config = Object.assign({}, config); | ||
| rawName = rawName.replaceAll(".*", ""); | ||
| this.negated = false; | ||
| this.names = removeBrackets(rawName).split(",").map((v)=>{ | ||
| let name = v.trim().replace(/^-{1,2}/, ""); | ||
| if (name.startsWith("no-")) { | ||
| this.negated = true; | ||
| name = name.replace(/^no-/, ""); | ||
| } | ||
| return camelcaseOptionName(name); | ||
| }).sort((a, b)=>a.length > b.length ? 1 : -1); | ||
| this.name = this.names.at(-1); | ||
| if (this.negated && null == this.config.default) this.config.default = true; | ||
| if (rawName.includes("<")) this.required = true; | ||
| else if (rawName.includes("[")) this.required = false; | ||
| else this.isBoolean = true; | ||
| } | ||
| }; | ||
| let runtimeProcessArgs; | ||
| let runtimeInfo; | ||
| if ("u" > typeof process) { | ||
| let runtimeName; | ||
| runtimeName = "u" > typeof Deno && "string" == typeof Deno.version?.deno ? "deno" : "u" > typeof Bun && "string" == typeof Bun.version ? "bun" : "node"; | ||
| runtimeInfo = `${process.platform}-${process.arch} ${runtimeName}-${process.version}`; | ||
| runtimeProcessArgs = process.argv; | ||
| } else runtimeInfo = "u" < typeof navigator ? "unknown" : `${navigator.platform} ${navigator.userAgent}`; | ||
| var Command = class { | ||
| rawName; | ||
| description; | ||
| config; | ||
| cli; | ||
| options; | ||
| aliasNames; | ||
| name; | ||
| args; | ||
| commandAction; | ||
| usageText; | ||
| versionNumber; | ||
| examples; | ||
| helpCallback; | ||
| globalCommand; | ||
| constructor(rawName, description, config = {}, cli){ | ||
| this.rawName = rawName; | ||
| this.description = description; | ||
| this.config = config; | ||
| this.cli = cli; | ||
| this.options = []; | ||
| this.aliasNames = []; | ||
| this.name = removeBrackets(rawName); | ||
| this.args = findAllBrackets(rawName); | ||
| this.examples = []; | ||
| } | ||
| usage(text) { | ||
| this.usageText = text; | ||
| return this; | ||
| } | ||
| allowUnknownOptions() { | ||
| this.config.allowUnknownOptions = true; | ||
| return this; | ||
| } | ||
| ignoreOptionDefaultValue() { | ||
| this.config.ignoreOptionDefaultValue = true; | ||
| return this; | ||
| } | ||
| version(version, customFlags = "-v, --version") { | ||
| this.versionNumber = version; | ||
| this.option(customFlags, "Display version number"); | ||
| return this; | ||
| } | ||
| example(example) { | ||
| this.examples.push(example); | ||
| return this; | ||
| } | ||
| option(rawName, description, config) { | ||
| const option = new Option(rawName, description, config); | ||
| this.options.push(option); | ||
| return this; | ||
| } | ||
| alias(name) { | ||
| this.aliasNames.push(name); | ||
| return this; | ||
| } | ||
| action(callback) { | ||
| this.commandAction = callback; | ||
| return this; | ||
| } | ||
| isMatched(name) { | ||
| return this.name === name || this.aliasNames.includes(name); | ||
| } | ||
| get isDefaultCommand() { | ||
| return "" === this.name || this.aliasNames.includes("!"); | ||
| } | ||
| get isGlobalCommand() { | ||
| return this instanceof GlobalCommand; | ||
| } | ||
| hasOption(name) { | ||
| name = name.split(".")[0]; | ||
| return this.options.find((option)=>option.names.includes(name)); | ||
| } | ||
| outputHelp() { | ||
| const { name, commands } = this.cli; | ||
| const { versionNumber, options: globalOptions, helpCallback } = this.cli.globalCommand; | ||
| let sections = [ | ||
| { | ||
| body: `${name}${versionNumber ? `/${versionNumber}` : ""}` | ||
| } | ||
| ]; | ||
| sections.push({ | ||
| title: "Usage", | ||
| body: ` $ ${name} ${this.usageText || this.rawName}` | ||
| }); | ||
| if ((this.isGlobalCommand || this.isDefaultCommand) && commands.length > 0) { | ||
| const longestCommandName = findLongest(commands.map((command)=>command.rawName)); | ||
| sections.push({ | ||
| title: "Commands", | ||
| body: commands.map((command)=>` ${padRight(command.rawName, longestCommandName.length)} ${command.description}`).join("\n") | ||
| }, { | ||
| title: "For more info, run any command with the `--help` flag", | ||
| body: commands.map((command)=>` $ ${name}${"" === command.name ? "" : ` ${command.name}`} --help`).join("\n") | ||
| }); | ||
| } | ||
| let options = this.isGlobalCommand ? globalOptions : [ | ||
| ...this.options, | ||
| ...globalOptions || [] | ||
| ]; | ||
| if (!this.isGlobalCommand && !this.isDefaultCommand) options = options.filter((option)=>"version" !== option.name); | ||
| if (options.length > 0) { | ||
| const longestOptionName = findLongest(options.map((option)=>option.rawName)); | ||
| sections.push({ | ||
| title: "Options", | ||
| body: options.map((option)=>` ${padRight(option.rawName, longestOptionName.length)} ${option.description} ${void 0 === option.config.default ? "" : `(default: ${option.config.default})`}`).join("\n") | ||
| }); | ||
| } | ||
| if (this.examples.length > 0) sections.push({ | ||
| title: "Examples", | ||
| body: this.examples.map((example)=>{ | ||
| if ("function" == typeof example) return example(name); | ||
| return example; | ||
| }).join("\n") | ||
| }); | ||
| if (helpCallback) sections = helpCallback(sections) || sections; | ||
| console.info(sections.map((section)=>section.title ? `${section.title}:\n${section.body}` : section.body).join("\n\n")); | ||
| } | ||
| outputVersion() { | ||
| const { name } = this.cli; | ||
| const { versionNumber } = this.cli.globalCommand; | ||
| if (versionNumber) console.info(`${name}/${versionNumber} ${runtimeInfo}`); | ||
| } | ||
| checkRequiredArgs() { | ||
| const minimalArgsCount = this.args.filter((arg)=>arg.required).length; | ||
| if (this.cli.args.length < minimalArgsCount) throw new CACError(`missing required args for command \`${this.rawName}\``); | ||
| } | ||
| checkUnknownOptions() { | ||
| const { options, globalCommand } = this.cli; | ||
| if (!this.config.allowUnknownOptions) { | ||
| for (const name of Object.keys(options))if ("--" !== name && !this.hasOption(name) && !globalCommand.hasOption(name)) throw new CACError(`Unknown option \`${name.length > 1 ? `--${name}` : `-${name}`}\``); | ||
| } | ||
| } | ||
| checkOptionValue() { | ||
| const { options: parsedOptions, globalCommand } = this.cli; | ||
| const options = [ | ||
| ...globalCommand.options, | ||
| ...this.options | ||
| ]; | ||
| for (const option of options){ | ||
| const value = parsedOptions[option.name.split(".")[0]]; | ||
| if (option.required) { | ||
| const hasNegated = options.some((o)=>o.negated && o.names.includes(option.name)); | ||
| if (true === value || false === value && !hasNegated) throw new CACError(`option \`${option.rawName}\` value is missing`); | ||
| } | ||
| } | ||
| } | ||
| checkUnusedArgs() { | ||
| const maximumArgsCount = this.args.some((arg)=>arg.variadic) ? 1 / 0 : this.args.length; | ||
| if (maximumArgsCount < this.cli.args.length) throw new CACError(`Unused args: ${this.cli.args.slice(maximumArgsCount).map((arg)=>`\`${arg}\``).join(", ")}`); | ||
| } | ||
| }; | ||
| var GlobalCommand = class extends Command { | ||
| constructor(cli){ | ||
| super("@@global@@", "", {}, cli); | ||
| } | ||
| }; | ||
| var CAC = class extends EventTarget { | ||
| name; | ||
| commands; | ||
| globalCommand; | ||
| matchedCommand; | ||
| matchedCommandName; | ||
| rawArgs; | ||
| args; | ||
| options; | ||
| showHelpOnExit; | ||
| showVersionOnExit; | ||
| constructor(name = ""){ | ||
| super(); | ||
| this.name = name; | ||
| this.commands = []; | ||
| this.rawArgs = []; | ||
| this.args = []; | ||
| this.options = {}; | ||
| this.globalCommand = new GlobalCommand(this); | ||
| this.globalCommand.usage("<command> [options]"); | ||
| } | ||
| usage(text) { | ||
| this.globalCommand.usage(text); | ||
| return this; | ||
| } | ||
| command(rawName, description, config) { | ||
| const command = new Command(rawName, description || "", config, this); | ||
| command.globalCommand = this.globalCommand; | ||
| this.commands.push(command); | ||
| return command; | ||
| } | ||
| option(rawName, description, config) { | ||
| this.globalCommand.option(rawName, description, config); | ||
| return this; | ||
| } | ||
| help(callback) { | ||
| this.globalCommand.option("-h, --help", "Display this message"); | ||
| this.globalCommand.helpCallback = callback; | ||
| this.showHelpOnExit = true; | ||
| return this; | ||
| } | ||
| version(version, customFlags = "-v, --version") { | ||
| this.globalCommand.version(version, customFlags); | ||
| this.showVersionOnExit = true; | ||
| return this; | ||
| } | ||
| example(example) { | ||
| this.globalCommand.example(example); | ||
| return this; | ||
| } | ||
| outputHelp() { | ||
| if (this.matchedCommand) this.matchedCommand.outputHelp(); | ||
| else this.globalCommand.outputHelp(); | ||
| } | ||
| outputVersion() { | ||
| this.globalCommand.outputVersion(); | ||
| } | ||
| setParsedInfo({ args, options }, matchedCommand, matchedCommandName) { | ||
| this.args = args; | ||
| this.options = options; | ||
| if (matchedCommand) this.matchedCommand = matchedCommand; | ||
| if (matchedCommandName) this.matchedCommandName = matchedCommandName; | ||
| return this; | ||
| } | ||
| unsetMatchedCommand() { | ||
| this.matchedCommand = void 0; | ||
| this.matchedCommandName = void 0; | ||
| } | ||
| parse(argv, { run = true } = {}) { | ||
| if (!argv) { | ||
| if (!runtimeProcessArgs) throw new Error("No argv provided and runtime process argv is not available."); | ||
| argv = runtimeProcessArgs; | ||
| } | ||
| this.rawArgs = argv; | ||
| if (!this.name) this.name = argv[1] ? getFileName(argv[1]) : "cli"; | ||
| let shouldParse = true; | ||
| for (const command of this.commands){ | ||
| const parsed = this.mri(argv.slice(2), command); | ||
| const commandName = parsed.args[0]; | ||
| if (command.isMatched(commandName)) { | ||
| shouldParse = false; | ||
| const parsedInfo = { | ||
| ...parsed, | ||
| args: parsed.args.slice(1) | ||
| }; | ||
| this.setParsedInfo(parsedInfo, command, commandName); | ||
| this.dispatchEvent(new CustomEvent(`command:${commandName}`, { | ||
| detail: command | ||
| })); | ||
| } | ||
| } | ||
| if (shouldParse) { | ||
| for (const command of this.commands)if (command.isDefaultCommand) { | ||
| shouldParse = false; | ||
| const parsed = this.mri(argv.slice(2), command); | ||
| this.setParsedInfo(parsed, command); | ||
| this.dispatchEvent(new CustomEvent("command:!", { | ||
| detail: command | ||
| })); | ||
| } | ||
| } | ||
| if (shouldParse) { | ||
| const parsed = this.mri(argv.slice(2)); | ||
| this.setParsedInfo(parsed); | ||
| } | ||
| if (this.options.help && this.showHelpOnExit) { | ||
| this.outputHelp(); | ||
| run = false; | ||
| this.unsetMatchedCommand(); | ||
| } | ||
| if (this.options.version && this.showVersionOnExit && null == this.matchedCommandName) { | ||
| this.outputVersion(); | ||
| run = false; | ||
| this.unsetMatchedCommand(); | ||
| } | ||
| const parsedArgv = { | ||
| args: this.args, | ||
| options: this.options | ||
| }; | ||
| if (run) this.runMatchedCommand(); | ||
| if (!this.matchedCommand && this.args[0]) this.dispatchEvent(new CustomEvent("command:*", { | ||
| detail: this.args[0] | ||
| })); | ||
| return parsedArgv; | ||
| } | ||
| mri(argv, command) { | ||
| const cliOptions = [ | ||
| ...this.globalCommand.options, | ||
| ...command ? command.options : [] | ||
| ]; | ||
| const mriOptions = getMriOptions(cliOptions); | ||
| let argsAfterDoubleDashes = []; | ||
| const doubleDashesIndex = argv.indexOf("--"); | ||
| if (-1 !== doubleDashesIndex) { | ||
| argsAfterDoubleDashes = argv.slice(doubleDashesIndex + 1); | ||
| argv = argv.slice(0, doubleDashesIndex); | ||
| } | ||
| let parsed = lib_default(argv, mriOptions); | ||
| parsed = Object.keys(parsed).reduce((res, name)=>({ | ||
| ...res, | ||
| [camelcaseOptionName(name)]: parsed[name] | ||
| }), { | ||
| _: [] | ||
| }); | ||
| const args = parsed._; | ||
| const options = { | ||
| "--": argsAfterDoubleDashes | ||
| }; | ||
| const ignoreDefault = command && command.config.ignoreOptionDefaultValue ? command.config.ignoreOptionDefaultValue : this.globalCommand.config.ignoreOptionDefaultValue; | ||
| const transforms = Object.create(null); | ||
| for (const cliOption of cliOptions){ | ||
| if (!ignoreDefault && void 0 !== cliOption.config.default) for (const name of cliOption.names)options[name] = cliOption.config.default; | ||
| if (Array.isArray(cliOption.config.type) && void 0 === transforms[cliOption.name]) { | ||
| transforms[cliOption.name] = Object.create(null); | ||
| transforms[cliOption.name].shouldTransform = true; | ||
| transforms[cliOption.name].transformFunction = cliOption.config.type[0]; | ||
| } | ||
| } | ||
| for (const key of Object.keys(parsed))if ("_" !== key) { | ||
| setDotProp(options, key.split("."), parsed[key]); | ||
| setByType(options, transforms); | ||
| } | ||
| return { | ||
| args, | ||
| options | ||
| }; | ||
| } | ||
| runMatchedCommand() { | ||
| const { args, options, matchedCommand: command } = this; | ||
| if (!command || !command.commandAction) return; | ||
| command.checkUnknownOptions(); | ||
| command.checkOptionValue(); | ||
| command.checkRequiredArgs(); | ||
| command.checkUnusedArgs(); | ||
| const actionArgs = []; | ||
| command.args.forEach((arg, index)=>{ | ||
| if (arg.variadic) actionArgs.push(args.slice(index)); | ||
| else actionArgs.push(args[index]); | ||
| }); | ||
| actionArgs.push(options); | ||
| return command.commandAction.apply(this, actionArgs); | ||
| } | ||
| }; | ||
| const cac = (name = "")=>new CAC(name); | ||
| const commonOptions = (command)=>command.option('-c, --config <path>', 'config file').option('--config-name <name>', 'Name(s) of the configuration to use.', { | ||
| type: [ | ||
| String | ||
| ], | ||
| default: [] | ||
| }).option('--config-loader <loader>', 'Specify the loader to load the config file, can be `auto`, `jiti` or `native`.', { | ||
| default: 'auto' | ||
| }).option('--env <env>', 'env passed to config function', { | ||
| type: [ | ||
| String | ||
| ], | ||
| default: [] | ||
| }).option('--node-env <value>', 'sets `process.env.NODE_ENV` to be specified value'); | ||
| function normalizeDevtoolOption(value) { | ||
| if ('string' == typeof value) { | ||
| const trimmed = value.trim(); | ||
| if ('' === trimmed || 'false' === trimmed) return false; | ||
| if ('true' === trimmed) return 'source-map'; | ||
| return trimmed; | ||
| } | ||
| if ('boolean' == typeof value) return value ? 'source-map' : false; | ||
| } | ||
| const normalizeCommonOptions = (options, action)=>{ | ||
| const isEmptyArray = (arr)=>Array.isArray(arr) && 0 === arr.length; | ||
| for (const key of [ | ||
| 'entry', | ||
| 'configName' | ||
| ]){ | ||
| const val = options[key]; | ||
| if (isEmptyArray(val)) options[key] = void 0; | ||
| } | ||
| const env = Array.isArray(options.env) ? normalizeEnvToObject(options) : {}; | ||
| options.env = env; | ||
| if ('serve' === action) setBuiltinEnvArg(env, 'SERVE', true); | ||
| else if ('build' === action) if (options.watch) setBuiltinEnvArg(env, 'WATCH', true); | ||
| else { | ||
| setBuiltinEnvArg(env, 'BUNDLE', true); | ||
| setBuiltinEnvArg(env, 'BUILD', true); | ||
| } | ||
| if ('devtool' in options) options.devtool = normalizeDevtoolOption(options.devtool); | ||
| }; | ||
| const commonOptionsForBuildAndServe = (command)=>command.option('-d, --devtool <value>', 'specify a developer tool for debugging. Defaults to `cheap-module-source-map` in development and `source-map` in production.').option('--entry <entry>', 'entry file', { | ||
| type: [ | ||
| String | ||
| ], | ||
| default: [] | ||
| }).option('-m, --mode <mode>', 'mode').option('-o, --output-path <dir>', 'output path dir').option('-w, --watch', 'watch'); | ||
| function setBuiltinEnvArg(env, envNameSuffix, value) { | ||
| const envName = `RSPACK_${envNameSuffix}`; | ||
| if (!(envName in env)) env[envName] = value; | ||
| } | ||
| function normalizeEnvToObject(options) { | ||
| function parseValue(previous, value) { | ||
| const [allKeys, val] = value.split(/=(.+)/, 2); | ||
| const splitKeys = allKeys.split(/\.(?!$)/); | ||
| let prevRef = previous; | ||
| splitKeys.forEach((key, index)=>{ | ||
| let someKey = key; | ||
| if (someKey.endsWith('=')) { | ||
| someKey = someKey.slice(0, -1); | ||
| prevRef[someKey] = void 0; | ||
| return; | ||
| } | ||
| if (!prevRef[someKey] || 'string' == typeof prevRef[someKey]) prevRef[someKey] = {}; | ||
| if (index === splitKeys.length - 1) if ('string' == typeof val) prevRef[someKey] = val; | ||
| else prevRef[someKey] = true; | ||
| prevRef = prevRef[someKey]; | ||
| }); | ||
| return previous; | ||
| } | ||
| return (options.env ?? []).reduce(parseValue, {}); | ||
| } | ||
| function setDefaultNodeEnv(options, defaultEnv) { | ||
| if (void 0 === process.env.NODE_ENV) process.env.NODE_ENV = 'string' == typeof options.nodeEnv ? options.nodeEnv : defaultEnv; | ||
| } | ||
| async function runBuild(cli, options) { | ||
| setDefaultNodeEnv(options, 'production'); | ||
| normalizeCommonOptions(options, 'build'); | ||
| const logger = cli.getLogger(); | ||
| let createJsonStringifyStream; | ||
| if (options.json) { | ||
| const jsonExt = await import("./json-ext.js"); | ||
| createJsonStringifyStream = (value)=>Readable.from(jsonExt.stringifyChunked(value)); | ||
| } | ||
| const errorHandler = (error, stats)=>{ | ||
| if (error) { | ||
| logger.error(error); | ||
| process.exit(2); | ||
| } | ||
| if (stats?.hasErrors()) process.exitCode = 1; | ||
| if (!compiler || !stats) return; | ||
| const getStatsOptions = ()=>{ | ||
| if (cli.isMultipleCompiler(compiler)) return { | ||
| children: compiler.compilers.map((item)=>item.options ? item.options.stats : void 0) | ||
| }; | ||
| return compiler.options?.stats; | ||
| }; | ||
| const statsOptions = getStatsOptions(); | ||
| if (options.json && createJsonStringifyStream) { | ||
| const handleWriteError = (error)=>{ | ||
| logger.error(error); | ||
| process.exit(2); | ||
| }; | ||
| if (true === options.json) createJsonStringifyStream(stats.toJson(statsOptions)).on('error', handleWriteError).pipe(process.stdout).on('error', handleWriteError).on('close', ()=>process.stdout.write('\n')); | ||
| else if ('string' == typeof options.json) createJsonStringifyStream(stats.toJson(statsOptions)).on('error', handleWriteError).pipe(node_fs.createWriteStream(options.json)).on('error', handleWriteError).on('close', ()=>{ | ||
| process.stderr.write(`[rspack-cli] ${cli.colors.green(`stats are successfully stored as json to ${options.json}`)}\n`); | ||
| }); | ||
| } else { | ||
| const printedStats = stats.toString(statsOptions); | ||
| if (printedStats) logger.raw(printedStats); | ||
| } | ||
| }; | ||
| const userOption = await cli.buildCompilerConfig(options, 'build'); | ||
| const compiler = await cli.createCompiler(userOption, errorHandler); | ||
| if (!compiler || cli.isWatch(compiler)) return; | ||
| compiler.run((error, stats)=>{ | ||
| compiler.close((closeErr)=>{ | ||
| if (closeErr) logger.error(closeErr); | ||
| errorHandler(error, stats); | ||
| }); | ||
| }); | ||
| } | ||
| class BuildCommand { | ||
| async apply(cli) { | ||
| const command = cli.program.command('', 'run the Rspack build').alias('build').alias('bundle').alias('b'); | ||
| commonOptionsForBuildAndServe(commonOptions(command)).option('--json [path]', 'emit stats json'); | ||
| command.action(cli.wrapAction(async (options)=>{ | ||
| await runBuild(cli, options); | ||
| })); | ||
| } | ||
| } | ||
| class PreviewCommand { | ||
| async apply(cli) { | ||
| const command = cli.program.command('preview [dir]', 'run the Rspack server for build output').alias('p'); | ||
| commonOptions(command).option('--public-path <path>', 'static resource server path').option('--port <port>', 'preview server port').option('--host <host>', 'preview server host').option('--open', 'open browser').option('--server <config>', 'Configuration items for the server.'); | ||
| command.action(cli.wrapAction(async (dir, options)=>{ | ||
| setDefaultNodeEnv(options, 'production'); | ||
| normalizeCommonOptions(options, 'preview'); | ||
| let RspackDevServer; | ||
| try { | ||
| const devServerModule = await import("@rspack/dev-server"); | ||
| RspackDevServer = devServerModule.RspackDevServer; | ||
| } catch (error) { | ||
| const logger = cli.getLogger(); | ||
| if (error?.code === 'MODULE_NOT_FOUND' || error?.code === 'ERR_MODULE_NOT_FOUND') logger.error('The "@rspack/dev-server" package is required to use the preview command.\nPlease install it by running:\n pnpm add -D @rspack/dev-server\n or\n npm install -D @rspack/dev-server'); | ||
| else logger.error('Failed to load "@rspack/dev-server":\n' + (error?.message || String(error))); | ||
| process.exit(1); | ||
| } | ||
| let { config } = await cli.loadConfig(options); | ||
| config = await getPreviewConfig(config, options, dir); | ||
| if (!Array.isArray(config)) config = [ | ||
| config | ||
| ]; | ||
| const singleConfig = config.find((item)=>item.devServer) || config[0]; | ||
| const devServerOptions = singleConfig.devServer; | ||
| try { | ||
| const compiler = rspack({ | ||
| entry: {} | ||
| }); | ||
| if (!compiler) return; | ||
| const server = new RspackDevServer(devServerOptions, compiler); | ||
| await server.start(); | ||
| } catch (error) { | ||
| const logger = cli.getLogger(); | ||
| logger.error(error); | ||
| process.exit(2); | ||
| } | ||
| })); | ||
| } | ||
| } | ||
| async function getPreviewConfig(item, options, dir) { | ||
| const DEFAULT_ROOT = 'dist'; | ||
| const internalPreviewConfig = async (item)=>{ | ||
| const devServer = false === item.devServer ? void 0 : item.devServer; | ||
| item.devServer = { | ||
| static: { | ||
| directory: dir ? node_path.join(item.context ?? process.cwd(), dir) : item.output?.path ?? node_path.join(item.context ?? process.cwd(), DEFAULT_ROOT), | ||
| publicPath: options.publicPath ?? '/' | ||
| }, | ||
| hot: false, | ||
| port: options.port ?? devServer?.port ?? 8080, | ||
| proxy: devServer?.proxy, | ||
| host: options.host ?? devServer?.host, | ||
| open: options.open ?? devServer?.open, | ||
| server: options.server ?? devServer?.server, | ||
| historyApiFallback: devServer?.historyApiFallback | ||
| }; | ||
| return item; | ||
| }; | ||
| if (Array.isArray(item)) return Promise.all(item.map(internalPreviewConfig)); | ||
| return internalPreviewConfig(item); | ||
| } | ||
| function normalizeHotOption(value) { | ||
| if ('false' === value) return false; | ||
| if ('true' === value) return true; | ||
| return value; | ||
| } | ||
| class ServeCommand { | ||
| async apply(cli) { | ||
| const command = cli.program.command('serve', 'run the rspack dev server.').alias('server').alias('s').alias('dev'); | ||
| commonOptionsForBuildAndServe(commonOptions(command)).option('--hot [mode]', 'enables hot module replacement').option('--port <port>', 'allows to specify a port to use').option('--host <host>', 'allows to specify a hostname to use').option('--open [value]', 'open browser on server start; pass --no-open to disable, or --open <url> to open a specific URL'); | ||
| command.action(cli.wrapAction(async (cliOptions)=>{ | ||
| setDefaultNodeEnv(cliOptions, 'development'); | ||
| normalizeCommonOptions(cliOptions, 'serve'); | ||
| cliOptions.hot = normalizeHotOption(cliOptions.hot); | ||
| let RspackDevServer; | ||
| try { | ||
| const devServerModule = await import("@rspack/dev-server"); | ||
| RspackDevServer = devServerModule.RspackDevServer; | ||
| } catch (error) { | ||
| const logger = cli.getLogger(); | ||
| if (error?.code === 'MODULE_NOT_FOUND' || error?.code === 'ERR_MODULE_NOT_FOUND') logger.error('The "@rspack/dev-server" package is required to use the serve command.\nPlease install it by running:\n pnpm add -D @rspack/dev-server\n or\n npm install -D @rspack/dev-server'); | ||
| else logger.error('Failed to load "@rspack/dev-server":\n' + (error?.message || String(error))); | ||
| process.exit(1); | ||
| } | ||
| const userConfig = await cli.buildCompilerConfig(cliOptions, 'serve'); | ||
| const compiler = await cli.createCompiler(userConfig); | ||
| if (!compiler) return; | ||
| const isMultiCompiler = cli.isMultipleCompiler(compiler); | ||
| const compilers = isMultiCompiler ? compiler.compilers : [ | ||
| compiler | ||
| ]; | ||
| const userConfigs = isMultiCompiler ? userConfig : [ | ||
| userConfig | ||
| ]; | ||
| const possibleCompilers = compilers.filter((compiler)=>compiler.options.devServer); | ||
| const usedPorts = []; | ||
| const servers = []; | ||
| const compilerForDevServer = possibleCompilers.length > 0 ? possibleCompilers[0] : compilers[0]; | ||
| for (const [index, compiler] of compilers.entries()){ | ||
| const userConfig = userConfigs[index]; | ||
| const existingDevServer = compiler.options.devServer; | ||
| if (false === existingDevServer) continue; | ||
| const devServer = existingDevServer ?? (compiler.options.devServer = {}); | ||
| const isWebAppOnly = compiler.platform.web && !compiler.platform.node && !compiler.platform.nwjs && !compiler.platform.electron && !compiler.platform.webworker; | ||
| if (isWebAppOnly && void 0 === userConfig.lazyCompilation) compiler.options.lazyCompilation = { | ||
| imports: true, | ||
| entries: false | ||
| }; | ||
| devServer.hot = cliOptions.hot ?? devServer.hot ?? true; | ||
| if (false !== devServer.client) { | ||
| if (true === devServer.client || null == devServer.client) devServer.client = {}; | ||
| devServer.client = { | ||
| overlay: { | ||
| errors: true, | ||
| warnings: false | ||
| }, | ||
| ...devServer.client | ||
| }; | ||
| } | ||
| } | ||
| const compilerForDevServerOptions = compilerForDevServer.options.devServer; | ||
| const devServerOptions = false === compilerForDevServerOptions ? {} : compilerForDevServerOptions ?? (compilerForDevServer.options.devServer = {}); | ||
| const { setupMiddlewares } = devServerOptions; | ||
| const lazyCompileMiddleware = rspack.lazyCompilationMiddleware(compiler); | ||
| devServerOptions.setupMiddlewares = (middlewares, server)=>{ | ||
| let finalMiddlewares = middlewares; | ||
| if (setupMiddlewares) finalMiddlewares = setupMiddlewares(finalMiddlewares, server); | ||
| return [ | ||
| ...finalMiddlewares, | ||
| lazyCompileMiddleware | ||
| ]; | ||
| }; | ||
| devServerOptions.hot = cliOptions.hot ?? devServerOptions.hot ?? true; | ||
| devServerOptions.host = cliOptions.host || devServerOptions.host; | ||
| devServerOptions.port = cliOptions.port ?? devServerOptions.port; | ||
| if (void 0 !== cliOptions.open) devServerOptions.open = cliOptions.open; | ||
| if (false !== devServerOptions.client) { | ||
| if (true === devServerOptions.client || null == devServerOptions.client) devServerOptions.client = {}; | ||
| devServerOptions.client = { | ||
| overlay: { | ||
| errors: true, | ||
| warnings: false | ||
| }, | ||
| ...devServerOptions.client | ||
| }; | ||
| } | ||
| if (devServerOptions.port) { | ||
| const portNumber = Number(devServerOptions.port); | ||
| if (!Number.isNaN(portNumber)) { | ||
| if (usedPorts.find((port)=>portNumber === port)) throw new Error('Unique ports must be specified for each devServer option in your rspack configuration. Alternatively, run only 1 devServer config using the --config-name flag to specify your desired config.'); | ||
| usedPorts.push(portNumber); | ||
| } | ||
| } | ||
| try { | ||
| const server = new RspackDevServer(devServerOptions, compiler); | ||
| await server.start(); | ||
| servers.push(server); | ||
| } catch (error) { | ||
| const logger = cli.getLogger(); | ||
| logger.error(error); | ||
| process.exit(2); | ||
| } | ||
| })); | ||
| } | ||
| } | ||
| const DEFAULT_EXTENSIONS = [ | ||
| '.ts', | ||
| '.js', | ||
| '.mts', | ||
| '.mjs', | ||
| '.cts', | ||
| '.cjs' | ||
| ]; | ||
| const findConfig = (basePath)=>DEFAULT_EXTENSIONS.map((ext)=>basePath + ext).find(node_fs.existsSync); | ||
| const utils_findConfig = findConfig; | ||
| const loadConfig_require = createRequire(import.meta.url); | ||
| const loadConfig_DEFAULT_CONFIG_NAME = 'rspack.config'; | ||
| const JS_CONFIG_EXTENSION_REGEXP = /\.(?:js|mjs|cjs)$/; | ||
| const CONFIG_LOADER_VALUES = [ | ||
| 'auto', | ||
| 'jiti', | ||
| 'native' | ||
| ]; | ||
| const PREBUNDLED_JITI_PATH = new URL('../compiled/jiti/index.js', import.meta.url).href; | ||
| const supportsNativeTypeScript = ()=>{ | ||
| const features = process.features; | ||
| return Boolean(features.typescript || process.versions.bun || process.versions.deno); | ||
| }; | ||
| const normalizeConfigLoader = (configLoader)=>{ | ||
| const normalizedLoader = configLoader ?? 'auto'; | ||
| if (CONFIG_LOADER_VALUES.includes(normalizedLoader)) return normalizedLoader; | ||
| throw new Error(`config loader "${normalizedLoader}" is not supported. Expected one of: ${CONFIG_LOADER_VALUES.join(', ')}.`); | ||
| }; | ||
| const resolveDefaultExport = (result)=>result && 'object' == typeof result && 'default' in result ? result.default : result; | ||
| const loadConfigWithNativeLoader = async (configPath)=>{ | ||
| const configFileURL = pathToFileURL(configPath).href; | ||
| const loadedModule = await import(`${configFileURL}?t=${Date.now()}`); | ||
| return resolveDefaultExport(loadedModule); | ||
| }; | ||
| let jitiInstancePromise; | ||
| const getJiti = async ()=>{ | ||
| if (!jitiInstancePromise) jitiInstancePromise = import(PREBUNDLED_JITI_PATH).then((module)=>{ | ||
| const createJiti = 'createJiti' in module ? module.createJiti : module.default; | ||
| return createJiti(import.meta.filename, { | ||
| moduleCache: false, | ||
| interopDefault: true, | ||
| nativeModules: [ | ||
| "typescript" | ||
| ] | ||
| }); | ||
| }); | ||
| return jitiInstancePromise; | ||
| }; | ||
| const loadConfigWithJiti = async (configPath)=>{ | ||
| const jiti = await getJiti(); | ||
| return jiti.import(configPath, { | ||
| default: true | ||
| }); | ||
| }; | ||
| const loadConfigByPath = async (configPath, options)=>{ | ||
| const configLoader = normalizeConfigLoader(options.configLoader); | ||
| const useNative = Boolean('native' === configLoader || 'auto' === configLoader && supportsNativeTypeScript()); | ||
| if (useNative || JS_CONFIG_EXTENSION_REGEXP.test(configPath)) try { | ||
| return await loadConfigWithNativeLoader(configPath); | ||
| } catch (error) { | ||
| if ('native' === configLoader) throw error; | ||
| } | ||
| return loadConfigWithJiti(configPath); | ||
| }; | ||
| const isConfigObject = (value)=>Boolean(value) && 'object' == typeof value && !Array.isArray(value); | ||
| const isRspackConfig = (value)=>Array.isArray(value) || isConfigObject(value); | ||
| const resolveRspackConfigExport = async (configExport, options)=>{ | ||
| let loadedConfig = configExport; | ||
| if ('function' == typeof loadedConfig) { | ||
| let functionResult = loadedConfig(options.env, options); | ||
| if ('function' == typeof functionResult.then) functionResult = await functionResult; | ||
| if (void 0 === functionResult) throw new Error('[rspack-cli:loadConfig] The config function must return a config object.'); | ||
| loadedConfig = functionResult; | ||
| } | ||
| if (!isRspackConfig(loadedConfig)) throw new Error(`[rspack-cli:loadConfig] The config must be an object, an array, or a function that returns one, get ${String(loadedConfig)}`); | ||
| return loadedConfig; | ||
| }; | ||
| const checkIsMultiRspackOptions = (config)=>Array.isArray(config); | ||
| async function loadExtendedConfig(config, configPath, cwd, options) { | ||
| if (checkIsMultiRspackOptions(config)) { | ||
| const resultPathMap = new WeakMap(); | ||
| const extendedConfigs = await Promise.all(config.map(async (item)=>{ | ||
| const { config, pathMap } = await loadExtendedConfig(item, configPath, cwd, options); | ||
| resultPathMap.set(config, pathMap.get(config)); | ||
| return config; | ||
| })); | ||
| extendedConfigs.parallelism = config.parallelism; | ||
| return { | ||
| config: extendedConfigs, | ||
| pathMap: resultPathMap | ||
| }; | ||
| } | ||
| const pathMap = new WeakMap(); | ||
| pathMap.set(config, [ | ||
| configPath | ||
| ]); | ||
| if (!('extends' in config) || !config.extends) return { | ||
| config, | ||
| pathMap | ||
| }; | ||
| const extendsList = Array.isArray(config.extends) ? config.extends : [ | ||
| config.extends | ||
| ]; | ||
| const { extends: _, ...configWithoutExtends } = config; | ||
| const baseDir = node_path.dirname(configPath); | ||
| let resultConfig = configWithoutExtends; | ||
| pathMap.set(resultConfig, [ | ||
| configPath | ||
| ]); | ||
| for (const extendPath of extendsList){ | ||
| let resolvedPath; | ||
| if (extendPath.startsWith('.') || extendPath.startsWith('/') || extendPath.includes(':\\')) { | ||
| resolvedPath = node_path.resolve(baseDir, extendPath); | ||
| if (!node_path.extname(resolvedPath)) { | ||
| const foundConfig = utils_findConfig(resolvedPath); | ||
| if (foundConfig) resolvedPath = foundConfig; | ||
| else throw new Error(`Extended configuration file "${resolvedPath}" not found.`); | ||
| } | ||
| } else try { | ||
| resolvedPath = loadConfig_require.resolve(extendPath, { | ||
| paths: [ | ||
| baseDir, | ||
| cwd | ||
| ] | ||
| }); | ||
| } catch { | ||
| throw new Error(`Cannot find module '${extendPath}' to extend from.`); | ||
| } | ||
| if (!node_fs.existsSync(resolvedPath)) throw new Error(`Extended configuration file "${resolvedPath}" not found.`); | ||
| const loadedConfig = await loadConfigByPath(resolvedPath, options); | ||
| const resolvedConfig = await resolveRspackConfigExport(loadedConfig, options); | ||
| const { config: extendedConfig, pathMap: extendedPathMap } = await loadExtendedConfig(resolvedConfig, resolvedPath, cwd, options); | ||
| const configPaths = [ | ||
| ...pathMap.get(resultConfig) || [], | ||
| ...extendedPathMap.get(extendedConfig) || [] | ||
| ]; | ||
| resultConfig = rspack.util.cleverMerge(extendedConfig, resultConfig); | ||
| pathMap.set(resultConfig, configPaths); | ||
| } | ||
| return { | ||
| config: resultConfig, | ||
| pathMap | ||
| }; | ||
| } | ||
| async function loadRspackConfig(options, cwd = process.cwd()) { | ||
| let configPath = ''; | ||
| if (options.config) { | ||
| configPath = node_path.resolve(cwd, options.config); | ||
| if (!node_fs.existsSync(configPath)) throw new Error(`config file "${configPath}" not found.`); | ||
| } else { | ||
| const defaultConfig = utils_findConfig(node_path.resolve(cwd, loadConfig_DEFAULT_CONFIG_NAME)); | ||
| if (!defaultConfig) return null; | ||
| configPath = defaultConfig; | ||
| } | ||
| const loadedConfig = await loadConfigByPath(configPath, options); | ||
| return { | ||
| loadedConfig, | ||
| configPath | ||
| }; | ||
| } | ||
| function isEnvColorSupported() { | ||
| if ("u" < typeof process) return false; | ||
| const p = process; | ||
| const argv = p.argv ?? []; | ||
| const env = p.env ?? {}; | ||
| return !('NO_COLOR' in env || argv.includes('--no-color')) && ('FORCE_COLOR' in env || argv.includes('--color') || 'win32' === p.platform || p.stdout?.isTTY && 'dumb' !== env.TERM || 'CI' in env); | ||
| } | ||
| function createAnsiFormatter(open, close, replace = open) { | ||
| const closeLength = close.length; | ||
| return (input)=>{ | ||
| const string = String(input); | ||
| let index = string.indexOf(close, open.length); | ||
| if (-1 === index) return open + string + close; | ||
| let result = ''; | ||
| let cursor = 0; | ||
| do { | ||
| result += string.substring(cursor, index) + replace; | ||
| cursor = index + closeLength; | ||
| index = string.indexOf(close, cursor); | ||
| }while (-1 !== index); | ||
| return open + result + string.substring(cursor) + close; | ||
| }; | ||
| } | ||
| class RspackCLI { | ||
| colors; | ||
| program; | ||
| _actionPromise; | ||
| constructor(){ | ||
| const program = cac('rspack'); | ||
| this.colors = this.createColors(); | ||
| this.program = program; | ||
| program.help(); | ||
| program.version("2.0.2"); | ||
| } | ||
| wrapAction(fn) { | ||
| return (...args)=>{ | ||
| this._actionPromise = fn(...args); | ||
| return this._actionPromise; | ||
| }; | ||
| } | ||
| async buildCompilerConfig(options, rspackCommand) { | ||
| let { config, pathMap } = await this.loadConfig(options); | ||
| config = await this.buildConfig(config, pathMap, options, rspackCommand); | ||
| return config; | ||
| } | ||
| async createCompiler(config, callback) { | ||
| const isWatch = Array.isArray(config) ? config.some((i)=>i.watch) : config.watch; | ||
| let compiler; | ||
| try { | ||
| compiler = rspack(config, isWatch ? callback : void 0); | ||
| if (!isWatch && compiler) compiler.unsafeFastDrop = true; | ||
| } catch (e) { | ||
| if (e instanceof rspack.ValidationError) { | ||
| this.getLogger().error(e.message); | ||
| process.exit(2); | ||
| } else if (e instanceof Error) { | ||
| if ('function' == typeof callback) callback(e); | ||
| else this.getLogger().error(e); | ||
| return null; | ||
| } | ||
| throw e; | ||
| } | ||
| return compiler; | ||
| } | ||
| createColors(useColor) { | ||
| const envSupported = isEnvColorSupported(); | ||
| const enabled = useColor ?? envSupported; | ||
| if (!enabled) { | ||
| const passthrough = (text)=>String(text); | ||
| return { | ||
| isColorSupported: false, | ||
| red: passthrough, | ||
| yellow: passthrough, | ||
| cyan: passthrough, | ||
| green: passthrough | ||
| }; | ||
| } | ||
| return { | ||
| isColorSupported: true, | ||
| red: createAnsiFormatter('\x1b[31m', '\x1b[39m'), | ||
| green: createAnsiFormatter('\x1b[32m', '\x1b[39m'), | ||
| yellow: createAnsiFormatter('\x1b[33m', '\x1b[39m'), | ||
| cyan: createAnsiFormatter('\x1b[36m', '\x1b[39m') | ||
| }; | ||
| } | ||
| getLogger() { | ||
| return { | ||
| error: (val)=>console.error(`[rspack-cli] ${this.colors.red(node_util.format(val))}`), | ||
| warn: (val)=>console.warn(`[rspack-cli] ${this.colors.yellow(val)}`), | ||
| info: (val)=>console.info(`[rspack-cli] ${this.colors.cyan(val)}`), | ||
| success: (val)=>console.log(`[rspack-cli] ${this.colors.green(val)}`), | ||
| log: (val)=>console.log(`[rspack-cli] ${val}`), | ||
| raw: (val)=>console.log(val) | ||
| }; | ||
| } | ||
| async run(argv) { | ||
| await this.registerCommands(); | ||
| this.program.parse(argv); | ||
| if (this._actionPromise) await this._actionPromise; | ||
| } | ||
| async registerCommands() { | ||
| const builtinCommands = [ | ||
| new BuildCommand(), | ||
| new ServeCommand(), | ||
| new PreviewCommand() | ||
| ]; | ||
| for (const command of builtinCommands)await command.apply(this); | ||
| } | ||
| async buildConfig(item, pathMap, options, command) { | ||
| const isBuild = 'build' === command; | ||
| const isServe = 'serve' === command; | ||
| const internalBuildConfig = async (item)=>{ | ||
| if (options.entry) item.entry = { | ||
| main: options.entry.map((x)=>node_path.resolve(process.cwd(), x))[0] | ||
| }; | ||
| item.output = item.output || {}; | ||
| if (options.outputPath) item.output.path = node_path.resolve(process.cwd(), options.outputPath); | ||
| if (process.env.RSPACK_PROFILE) { | ||
| const { applyProfile } = await import("./profile.js"); | ||
| await applyProfile(process.env.RSPACK_PROFILE, process.env.RSPACK_TRACE_LAYER, process.env.RSPACK_TRACE_OUTPUT); | ||
| } | ||
| if (options.watch) item.watch = options.watch; | ||
| if (!item.mode) item.mode = isBuild ? 'production' : 'development'; | ||
| if (options.mode) item.mode = options.mode; | ||
| if (void 0 === item.devtool) item.devtool = isBuild ? false : 'cheap-module-source-map'; | ||
| if (void 0 !== options.devtool) item.devtool = options.devtool; | ||
| if (isServe) { | ||
| const installed = (item.plugins ||= []).find((item)=>item instanceof rspack.ProgressPlugin); | ||
| if (!installed) (item.plugins ??= []).push(new rspack.ProgressPlugin()); | ||
| } | ||
| const cacheOptions = item.cache; | ||
| if ('object' == typeof cacheOptions && 'persistent' === cacheOptions.type) { | ||
| const configPaths = pathMap.get(item); | ||
| if (configPaths) cacheOptions.buildDependencies = [ | ||
| ...configPaths, | ||
| ...cacheOptions.buildDependencies || [] | ||
| ]; | ||
| } | ||
| if (void 0 === item.stats) item.stats = { | ||
| preset: 'errors-warnings', | ||
| timings: true | ||
| }; | ||
| else if ('boolean' == typeof item.stats) item.stats = item.stats ? { | ||
| preset: 'normal' | ||
| } : { | ||
| preset: 'none' | ||
| }; | ||
| else if ('string' == typeof item.stats) item.stats = { | ||
| preset: item.stats | ||
| }; | ||
| return item; | ||
| }; | ||
| if (Array.isArray(item)) return Promise.all(item.map(internalBuildConfig)); | ||
| return internalBuildConfig(item); | ||
| } | ||
| async loadConfig(options) { | ||
| const config = await loadRspackConfig(options); | ||
| if (!config) return { | ||
| config: this.filterConfig(options, {}), | ||
| pathMap: new WeakMap() | ||
| }; | ||
| const { loadedConfig, configPath } = config; | ||
| const resolvedConfig = await resolveRspackConfigExport(loadedConfig, options); | ||
| const { config: extendedConfig, pathMap } = await loadExtendedConfig(resolvedConfig, configPath, process.cwd(), options); | ||
| return { | ||
| config: this.filterConfig(options, extendedConfig), | ||
| pathMap | ||
| }; | ||
| } | ||
| filterConfig(options, config) { | ||
| if (options.configName) { | ||
| const notFoundConfigNames = []; | ||
| config = options.configName.map((configName)=>{ | ||
| let found; | ||
| found = Array.isArray(config) ? config.find((options)=>options.name === configName) : config.name === configName ? config : void 0; | ||
| if (!found) notFoundConfigNames.push(configName); | ||
| return found; | ||
| }); | ||
| if (notFoundConfigNames.length > 0) { | ||
| this.getLogger().error(notFoundConfigNames.map((configName)=>`Configuration with the name "${configName}" was not found.`).join(' ')); | ||
| process.exit(2); | ||
| } | ||
| } | ||
| return config; | ||
| } | ||
| isMultipleCompiler(compiler) { | ||
| return Boolean(compiler.compilers); | ||
| } | ||
| isWatch(compiler) { | ||
| return Boolean(this.isMultipleCompiler(compiler) ? compiler.compilers.some((compiler)=>compiler.options.watch) : compiler.options.watch); | ||
| } | ||
| } | ||
| function defineConfig(config) { | ||
| return config; | ||
| } | ||
| function definePlugin(plugin) { | ||
| return plugin; | ||
| } | ||
| export { RspackCLI, defineConfig, definePlugin }; |
+197
-763
@@ -1,776 +0,210 @@ | ||
| import { __webpack_require__ } from "./162.js"; | ||
| import "./162.js"; | ||
| import * as __rspack_external_util from "util"; | ||
| __webpack_require__.add({ | ||
| "../../node_modules/.pnpm/@discoveryjs+json-ext@0.5.7/node_modules/@discoveryjs/json-ext/src/index.js" (module, __unused_rspack_exports, __webpack_require__) { | ||
| module.exports = { | ||
| version: __webpack_require__("../../node_modules/.pnpm/@discoveryjs+json-ext@0.5.7/node_modules/@discoveryjs/json-ext/src/version.js"), | ||
| stringifyInfo: __webpack_require__("../../node_modules/.pnpm/@discoveryjs+json-ext@0.5.7/node_modules/@discoveryjs/json-ext/src/stringify-info.js"), | ||
| stringifyStream: __webpack_require__("../../node_modules/.pnpm/@discoveryjs+json-ext@0.5.7/node_modules/@discoveryjs/json-ext/src/stringify-stream.js"), | ||
| parseChunked: __webpack_require__("../../node_modules/.pnpm/@discoveryjs+json-ext@0.5.7/node_modules/@discoveryjs/json-ext/src/parse-chunked.js") | ||
| }; | ||
| }, | ||
| "../../node_modules/.pnpm/@discoveryjs+json-ext@0.5.7/node_modules/@discoveryjs/json-ext/src/parse-chunked.js" (module, __unused_rspack_exports, __webpack_require__) { | ||
| const { isReadableStream } = __webpack_require__("../../node_modules/.pnpm/@discoveryjs+json-ext@0.5.7/node_modules/@discoveryjs/json-ext/src/utils.js"); | ||
| const TextDecoder = __webpack_require__("../../node_modules/.pnpm/@discoveryjs+json-ext@0.5.7/node_modules/@discoveryjs/json-ext/src/text-decoder.js"); | ||
| const STACK_OBJECT = 1; | ||
| const STACK_ARRAY = 2; | ||
| const decoder = new TextDecoder(); | ||
| function isObject(value) { | ||
| return null !== value && 'object' == typeof value; | ||
| } | ||
| function adjustPosition(error, parser) { | ||
| if ('SyntaxError' === error.name && parser.jsonParseOffset) error.message = error.message.replace(/at position (\d+)/, (_, pos)=>'at position ' + (Number(pos) + parser.jsonParseOffset)); | ||
| return error; | ||
| } | ||
| function append(array, elements) { | ||
| const initialLength = array.length; | ||
| array.length += elements.length; | ||
| for(let i = 0; i < elements.length; i++)array[initialLength + i] = elements[i]; | ||
| } | ||
| module.exports = function(chunkEmitter) { | ||
| let parser = new ChunkParser(); | ||
| if (isObject(chunkEmitter) && isReadableStream(chunkEmitter)) return new Promise((resolve, reject)=>{ | ||
| chunkEmitter.on('data', (chunk)=>{ | ||
| try { | ||
| parser.push(chunk); | ||
| } catch (e) { | ||
| reject(adjustPosition(e, parser)); | ||
| parser = null; | ||
| } | ||
| }).on('error', (e)=>{ | ||
| parser = null; | ||
| reject(e); | ||
| }).on('end', ()=>{ | ||
| try { | ||
| resolve(parser.finish()); | ||
| } catch (e) { | ||
| reject(adjustPosition(e, parser)); | ||
| } finally{ | ||
| parser = null; | ||
| } | ||
| }); | ||
| }); | ||
| if ('function' == typeof chunkEmitter) { | ||
| const iterator = chunkEmitter(); | ||
| if (isObject(iterator) && (Symbol.iterator in iterator || Symbol.asyncIterator in iterator)) return new Promise(async (resolve, reject)=>{ | ||
| try { | ||
| for await (const chunk of iterator)parser.push(chunk); | ||
| resolve(parser.finish()); | ||
| } catch (e) { | ||
| reject(adjustPosition(e, parser)); | ||
| } finally{ | ||
| parser = null; | ||
| } | ||
| }); | ||
| Symbol('empty'); | ||
| new TextDecoder(); | ||
| function utils_replaceValue(holder, key, value, replacer) { | ||
| if (value && 'function' == typeof value.toJSON) value = value.toJSON(); | ||
| if (null !== replacer) value = replacer.call(holder, String(key), value); | ||
| switch(typeof value){ | ||
| case 'function': | ||
| case 'symbol': | ||
| value = void 0; | ||
| break; | ||
| case 'object': | ||
| if (null !== value) { | ||
| const cls = value.constructor; | ||
| if (cls === String || cls === Number || cls === Boolean) value = value.valueOf(); | ||
| } | ||
| throw new Error("Chunk emitter should be readable stream, generator, async generator or function returning an iterable object"); | ||
| break; | ||
| } | ||
| return value; | ||
| } | ||
| function normalizeReplacer(replacer) { | ||
| if ('function' == typeof replacer) return replacer; | ||
| if (Array.isArray(replacer)) { | ||
| const allowlist = new Set(replacer.map((item)=>{ | ||
| const cls = item && item.constructor; | ||
| return cls === String || cls === Number ? String(item) : null; | ||
| }).filter((item)=>'string' == typeof item)); | ||
| return [ | ||
| ...allowlist | ||
| ]; | ||
| } | ||
| return null; | ||
| } | ||
| function normalizeSpace(space) { | ||
| if ('number' == typeof space) { | ||
| if (!Number.isFinite(space) || space < 1) return false; | ||
| return ' '.repeat(Math.min(space, 10)); | ||
| } | ||
| if ('string' == typeof space) return space.slice(0, 10) || false; | ||
| return false; | ||
| } | ||
| function utils_normalizeStringifyOptions(optionsOrReplacer, space) { | ||
| if (null === optionsOrReplacer || Array.isArray(optionsOrReplacer) || 'object' != typeof optionsOrReplacer) optionsOrReplacer = { | ||
| replacer: optionsOrReplacer, | ||
| space | ||
| }; | ||
| let replacer = normalizeReplacer(optionsOrReplacer.replacer); | ||
| let getKeys = Object.keys; | ||
| if (Array.isArray(replacer)) { | ||
| const allowlist = replacer; | ||
| getKeys = ()=>allowlist; | ||
| replacer = null; | ||
| } | ||
| return { | ||
| ...optionsOrReplacer, | ||
| replacer, | ||
| getKeys, | ||
| space: normalizeSpace(optionsOrReplacer.space) | ||
| }; | ||
| } | ||
| function utils_resolveStringifyMode(mode = 'json') { | ||
| if ('json' === mode || 'jsonl' === mode) return mode; | ||
| throw new TypeError('Invalid options: `mode` should be "json" or "jsonl"'); | ||
| } | ||
| function encodeString(value) { | ||
| if (/[^\x20\x21\x23-\x5B\x5D-\uD799]/.test(value)) return JSON.stringify(value); | ||
| return '"' + value + '"'; | ||
| } | ||
| function* stringify_chunked_stringifyChunked(value, ...args) { | ||
| const { replacer, getKeys, space, ...options } = utils_normalizeStringifyOptions(...args); | ||
| const highWaterMark = Number(options.highWaterMark) || 0x4000; | ||
| const roots = 'jsonl' === utils_resolveStringifyMode(options.mode) && Array.isArray(value) ? value : [ | ||
| value | ||
| ]; | ||
| const rootCount = roots.length; | ||
| const keyStrings = new Map(); | ||
| const stack = []; | ||
| let rootValue = null; | ||
| let prevState = null; | ||
| let state = null; | ||
| let stateValue = null; | ||
| let stateEmpty = true; | ||
| let stateKeys = []; | ||
| let stateIndex = 0; | ||
| let buffer = ''; | ||
| for(let i = 0; i < rootCount; i++){ | ||
| if (null !== rootValue) buffer += '\n'; | ||
| rootValue = { | ||
| '': roots[i] | ||
| }; | ||
| class ChunkParser { | ||
| constructor(){ | ||
| this.value = void 0; | ||
| this.valueStack = null; | ||
| this.stack = new Array(100); | ||
| this.lastFlushDepth = 0; | ||
| this.flushDepth = 0; | ||
| this.stateString = false; | ||
| this.stateStringEscape = false; | ||
| this.pendingByteSeq = null; | ||
| this.pendingChunk = null; | ||
| this.chunkOffset = 0; | ||
| this.jsonParseOffset = 0; | ||
| prevState = null; | ||
| state = ()=>printEntry('', roots[i]); | ||
| stateValue = rootValue; | ||
| stateEmpty = true; | ||
| stateKeys = [ | ||
| '' | ||
| ]; | ||
| stateIndex = 0; | ||
| do { | ||
| state(); | ||
| if (buffer.length >= highWaterMark || null === prevState && i === rootCount - 1) { | ||
| yield buffer; | ||
| buffer = ''; | ||
| } | ||
| parseAndAppend(fragment, wrap) { | ||
| if (this.stack[this.lastFlushDepth - 1] === STACK_OBJECT) { | ||
| if (wrap) { | ||
| this.jsonParseOffset--; | ||
| fragment = '{' + fragment + '}'; | ||
| } | ||
| Object.assign(this.valueStack.value, JSON.parse(fragment)); | ||
| } else { | ||
| if (wrap) { | ||
| this.jsonParseOffset--; | ||
| fragment = '[' + fragment + ']'; | ||
| } | ||
| append(this.valueStack.value, JSON.parse(fragment)); | ||
| } | ||
| } | ||
| prepareAddition(fragment) { | ||
| const { value } = this.valueStack; | ||
| const expectComma = Array.isArray(value) ? 0 !== value.length : 0 !== Object.keys(value).length; | ||
| if (expectComma) { | ||
| if (',' === fragment[0]) { | ||
| this.jsonParseOffset++; | ||
| return fragment.slice(1); | ||
| } | ||
| if ('}' !== fragment[0] && ']' !== fragment[0]) { | ||
| this.jsonParseOffset -= 3; | ||
| return '[[]' + fragment; | ||
| } | ||
| } | ||
| return fragment; | ||
| } | ||
| flush(chunk, start, end) { | ||
| let fragment = chunk.slice(start, end); | ||
| this.jsonParseOffset = this.chunkOffset + start; | ||
| if (null !== this.pendingChunk) { | ||
| fragment = this.pendingChunk + fragment; | ||
| this.jsonParseOffset -= this.pendingChunk.length; | ||
| this.pendingChunk = null; | ||
| } | ||
| if (this.flushDepth === this.lastFlushDepth) if (this.flushDepth > 0) this.parseAndAppend(this.prepareAddition(fragment), true); | ||
| else { | ||
| this.value = JSON.parse(fragment); | ||
| this.valueStack = { | ||
| value: this.value, | ||
| prev: null | ||
| }; | ||
| } | ||
| else if (this.flushDepth > this.lastFlushDepth) { | ||
| for(let i = this.flushDepth - 1; i >= this.lastFlushDepth; i--)fragment += this.stack[i] === STACK_OBJECT ? '}' : ']'; | ||
| if (0 === this.lastFlushDepth) { | ||
| this.value = JSON.parse(fragment); | ||
| this.valueStack = { | ||
| value: this.value, | ||
| prev: null | ||
| }; | ||
| } else this.parseAndAppend(this.prepareAddition(fragment), true); | ||
| for(let i = this.lastFlushDepth || 1; i < this.flushDepth; i++){ | ||
| let value = this.valueStack.value; | ||
| if (this.stack[i - 1] === STACK_OBJECT) { | ||
| let key; | ||
| for(key in value); | ||
| value = value[key]; | ||
| } else value = value[value.length - 1]; | ||
| this.valueStack = { | ||
| value, | ||
| prev: this.valueStack | ||
| }; | ||
| } | ||
| } else { | ||
| fragment = this.prepareAddition(fragment); | ||
| for(let i = this.lastFlushDepth - 1; i >= this.flushDepth; i--){ | ||
| this.jsonParseOffset--; | ||
| fragment = (this.stack[i] === STACK_OBJECT ? '{' : '[') + fragment; | ||
| } | ||
| this.parseAndAppend(fragment, false); | ||
| for(let i = this.lastFlushDepth - 1; i >= this.flushDepth; i--)this.valueStack = this.valueStack.prev; | ||
| } | ||
| this.lastFlushDepth = this.flushDepth; | ||
| } | ||
| push(chunk) { | ||
| if ('string' != typeof chunk) { | ||
| if (null !== this.pendingByteSeq) { | ||
| const origRawChunk = chunk; | ||
| chunk = new Uint8Array(this.pendingByteSeq.length + origRawChunk.length); | ||
| chunk.set(this.pendingByteSeq); | ||
| chunk.set(origRawChunk, this.pendingByteSeq.length); | ||
| this.pendingByteSeq = null; | ||
| } | ||
| if (chunk[chunk.length - 1] > 127) for(let seqLength = 0; seqLength < chunk.length; seqLength++){ | ||
| const byte = chunk[chunk.length - 1 - seqLength]; | ||
| if (byte >> 6 === 3) { | ||
| seqLength++; | ||
| if (4 !== seqLength && byte >> 3 === 30 || 3 !== seqLength && byte >> 4 === 14 || 2 !== seqLength && byte >> 5 === 6) { | ||
| this.pendingByteSeq = chunk.slice(chunk.length - seqLength); | ||
| chunk = chunk.slice(0, -seqLength); | ||
| } | ||
| break; | ||
| } | ||
| } | ||
| chunk = decoder.decode(chunk); | ||
| } | ||
| const chunkLength = chunk.length; | ||
| let lastFlushPoint = 0; | ||
| let flushPoint = 0; | ||
| scan: for(let i = 0; i < chunkLength; i++){ | ||
| if (this.stateString) { | ||
| for(; i < chunkLength; i++)if (this.stateStringEscape) this.stateStringEscape = false; | ||
| else switch(chunk.charCodeAt(i)){ | ||
| case 0x22: | ||
| this.stateString = false; | ||
| continue scan; | ||
| case 0x5C: | ||
| this.stateStringEscape = true; | ||
| } | ||
| break; | ||
| } | ||
| switch(chunk.charCodeAt(i)){ | ||
| case 0x22: | ||
| this.stateString = true; | ||
| this.stateStringEscape = false; | ||
| break; | ||
| case 0x2C: | ||
| flushPoint = i; | ||
| break; | ||
| case 0x7B: | ||
| flushPoint = i + 1; | ||
| this.stack[this.flushDepth++] = STACK_OBJECT; | ||
| break; | ||
| case 0x5B: | ||
| flushPoint = i + 1; | ||
| this.stack[this.flushDepth++] = STACK_ARRAY; | ||
| break; | ||
| case 0x5D: | ||
| case 0x7D: | ||
| flushPoint = i + 1; | ||
| this.flushDepth--; | ||
| if (this.flushDepth < this.lastFlushDepth) { | ||
| this.flush(chunk, lastFlushPoint, flushPoint); | ||
| lastFlushPoint = flushPoint; | ||
| } | ||
| break; | ||
| case 0x09: | ||
| case 0x0A: | ||
| case 0x0D: | ||
| case 0x20: | ||
| if (lastFlushPoint === i) lastFlushPoint++; | ||
| if (flushPoint === i) flushPoint++; | ||
| break; | ||
| } | ||
| } | ||
| if (flushPoint > lastFlushPoint) this.flush(chunk, lastFlushPoint, flushPoint); | ||
| if (flushPoint < chunkLength) if (null !== this.pendingChunk) this.pendingChunk += chunk; | ||
| else this.pendingChunk = chunk.slice(flushPoint, chunkLength); | ||
| this.chunkOffset += chunkLength; | ||
| } | ||
| finish() { | ||
| if (null !== this.pendingChunk) { | ||
| this.flush('', 0, 0); | ||
| this.pendingChunk = null; | ||
| } | ||
| return this.value; | ||
| } | ||
| }while (null !== prevState); | ||
| } | ||
| function printObject() { | ||
| if (0 === stateIndex) { | ||
| stateKeys = getKeys(stateValue); | ||
| buffer += '{'; | ||
| } | ||
| }, | ||
| "../../node_modules/.pnpm/@discoveryjs+json-ext@0.5.7/node_modules/@discoveryjs/json-ext/src/stringify-info.js" (module, __unused_rspack_exports, __webpack_require__) { | ||
| const { normalizeReplacer, normalizeSpace, replaceValue, getTypeNative, getTypeAsync, isLeadingSurrogate, isTrailingSurrogate, escapableCharCodeSubstitution, type: { PRIMITIVE, OBJECT, ARRAY, PROMISE, STRING_STREAM, OBJECT_STREAM } } = __webpack_require__("../../node_modules/.pnpm/@discoveryjs+json-ext@0.5.7/node_modules/@discoveryjs/json-ext/src/utils.js"); | ||
| const charLength2048 = Array.from({ | ||
| length: 2048 | ||
| }).map((_, code)=>{ | ||
| if (escapableCharCodeSubstitution.hasOwnProperty(code)) return 2; | ||
| if (code < 0x20) return 6; | ||
| return code < 128 ? 1 : 2; | ||
| }); | ||
| function stringLength(str) { | ||
| let len = 0; | ||
| let prevLeadingSurrogate = false; | ||
| for(let i = 0; i < str.length; i++){ | ||
| const code = str.charCodeAt(i); | ||
| if (code < 2048) len += charLength2048[code]; | ||
| else if (isLeadingSurrogate(code)) { | ||
| len += 6; | ||
| prevLeadingSurrogate = true; | ||
| continue; | ||
| } else if (isTrailingSurrogate(code)) len = prevLeadingSurrogate ? len - 2 : len + 6; | ||
| else len += 3; | ||
| prevLeadingSurrogate = false; | ||
| } | ||
| return len + 2; | ||
| if (stateIndex === stateKeys.length) { | ||
| buffer += space && !stateEmpty ? `\n${space.repeat(stack.length - 1)}}` : '}'; | ||
| popState(); | ||
| return; | ||
| } | ||
| function primitiveLength(value) { | ||
| switch(typeof value){ | ||
| case 'string': | ||
| return stringLength(value); | ||
| case 'number': | ||
| return Number.isFinite(value) ? String(value).length : 4; | ||
| case 'boolean': | ||
| return value ? 4 : 5; | ||
| case 'undefined': | ||
| case 'object': | ||
| return 4; | ||
| default: | ||
| return 0; | ||
| } | ||
| const key = stateKeys[stateIndex++]; | ||
| printEntry(key, stateValue[key]); | ||
| } | ||
| function printArray() { | ||
| if (0 === stateIndex) buffer += '['; | ||
| if (stateIndex === stateValue.length) { | ||
| buffer += space && !stateEmpty ? `\n${space.repeat(stack.length - 1)}]` : ']'; | ||
| popState(); | ||
| return; | ||
| } | ||
| function spaceLength(space) { | ||
| space = normalizeSpace(space); | ||
| return 'string' == typeof space ? space.length : 0; | ||
| printEntry(stateIndex, stateValue[stateIndex++]); | ||
| } | ||
| function printEntryPrelude(key) { | ||
| if (stateEmpty) stateEmpty = false; | ||
| else buffer += ','; | ||
| if (space && null !== prevState) buffer += `\n${space.repeat(stack.length)}`; | ||
| if (state === printObject) { | ||
| let keyString = keyStrings.get(key); | ||
| if (void 0 === keyString) keyStrings.set(key, keyString = encodeString(key) + (space ? ': ' : ':')); | ||
| buffer += keyString; | ||
| } | ||
| module.exports = function(value, replacer, space, options) { | ||
| function walk(holder, key, value) { | ||
| if (stop) return; | ||
| value = replaceValue(holder, key, value, replacer); | ||
| let type = getType(value); | ||
| if (type !== PRIMITIVE && stack.has(value)) { | ||
| circular.add(value); | ||
| length += 4; | ||
| if (!options.continueOnCircular) stop = true; | ||
| return; | ||
| } | ||
| switch(type){ | ||
| case PRIMITIVE: | ||
| if (void 0 !== value || Array.isArray(holder)) length += primitiveLength(value); | ||
| else if (holder === root) length += 9; | ||
| break; | ||
| case OBJECT: | ||
| { | ||
| if (visited.has(value)) { | ||
| duplicate.add(value); | ||
| length += visited.get(value); | ||
| break; | ||
| } | ||
| const valueLength = length; | ||
| let entries = 0; | ||
| length += 2; | ||
| stack.add(value); | ||
| for(const key in value)if (hasOwnProperty.call(value, key) && (null === allowlist || allowlist.has(key))) { | ||
| const prevLength = length; | ||
| walk(value, key, value[key]); | ||
| if (prevLength !== length) { | ||
| length += stringLength(key) + 1; | ||
| entries++; | ||
| } | ||
| } | ||
| if (entries > 1) length += entries - 1; | ||
| stack.delete(value); | ||
| if (space > 0 && entries > 0) { | ||
| length += (1 + (stack.size + 1) * space + 1) * entries; | ||
| length += 1 + stack.size * space; | ||
| } | ||
| visited.set(value, length - valueLength); | ||
| break; | ||
| } | ||
| case ARRAY: | ||
| { | ||
| if (visited.has(value)) { | ||
| duplicate.add(value); | ||
| length += visited.get(value); | ||
| break; | ||
| } | ||
| const valueLength = length; | ||
| length += 2; | ||
| stack.add(value); | ||
| for(let i = 0; i < value.length; i++)walk(value, i, value[i]); | ||
| if (value.length > 1) length += value.length - 1; | ||
| stack.delete(value); | ||
| if (space > 0 && value.length > 0) { | ||
| length += (1 + (stack.size + 1) * space) * value.length; | ||
| length += 1 + stack.size * space; | ||
| } | ||
| visited.set(value, length - valueLength); | ||
| break; | ||
| } | ||
| case PROMISE: | ||
| case STRING_STREAM: | ||
| async.add(value); | ||
| break; | ||
| case OBJECT_STREAM: | ||
| length += 2; | ||
| async.add(value); | ||
| break; | ||
| } | ||
| } | ||
| function printEntry(key, value) { | ||
| value = utils_replaceValue(stateValue, key, value, replacer); | ||
| if (null === value || 'object' != typeof value) { | ||
| if (state !== printObject || void 0 !== value) { | ||
| printEntryPrelude(key); | ||
| pushPrimitive(value); | ||
| } | ||
| let allowlist = null; | ||
| replacer = normalizeReplacer(replacer); | ||
| if (Array.isArray(replacer)) { | ||
| allowlist = new Set(replacer); | ||
| replacer = null; | ||
| } | ||
| space = spaceLength(space); | ||
| options = options || {}; | ||
| const visited = new Map(); | ||
| const stack = new Set(); | ||
| const duplicate = new Set(); | ||
| const circular = new Set(); | ||
| const async = new Set(); | ||
| const getType = options.async ? getTypeAsync : getTypeNative; | ||
| const root = { | ||
| '': value | ||
| }; | ||
| let stop = false; | ||
| let length = 0; | ||
| walk(root, '', value); | ||
| return { | ||
| minLength: isNaN(length) ? 1 / 0 : length, | ||
| circular: [ | ||
| ...circular | ||
| ], | ||
| duplicate: [ | ||
| ...duplicate | ||
| ], | ||
| async: [ | ||
| ...async | ||
| ] | ||
| }; | ||
| }; | ||
| }, | ||
| "../../node_modules/.pnpm/@discoveryjs+json-ext@0.5.7/node_modules/@discoveryjs/json-ext/src/stringify-stream.js" (module, __unused_rspack_exports, __webpack_require__) { | ||
| const { Readable } = __webpack_require__("stream"); | ||
| const { normalizeReplacer, normalizeSpace, replaceValue, getTypeAsync, type: { PRIMITIVE, OBJECT, ARRAY, PROMISE, STRING_STREAM, OBJECT_STREAM } } = __webpack_require__("../../node_modules/.pnpm/@discoveryjs+json-ext@0.5.7/node_modules/@discoveryjs/json-ext/src/utils.js"); | ||
| const noop = ()=>{}; | ||
| const hasOwnProperty1 = Object.prototype.hasOwnProperty; | ||
| const wellformedStringStringify = '"\\ud800"' === JSON.stringify('\ud800') ? JSON.stringify : (s)=>JSON.stringify(s).replace(/\p{Surrogate}/gu, (m)=>`\\u${m.charCodeAt(0).toString(16)}`); | ||
| function push() { | ||
| this.push(this._stack.value); | ||
| this.popStack(); | ||
| } else { | ||
| if (stack.includes(value)) throw new TypeError('Converting circular structure to JSON'); | ||
| printEntryPrelude(key); | ||
| stack.push(value); | ||
| pushState(); | ||
| state = Array.isArray(value) ? printArray : printObject; | ||
| stateValue = value; | ||
| stateEmpty = true; | ||
| stateIndex = 0; | ||
| } | ||
| function pushPrimitive(value) { | ||
| switch(typeof value){ | ||
| case 'string': | ||
| this.push(this.encodeString(value)); | ||
| break; | ||
| case 'number': | ||
| this.push(Number.isFinite(value) ? this.encodeNumber(value) : 'null'); | ||
| break; | ||
| case 'boolean': | ||
| this.push(value ? 'true' : 'false'); | ||
| break; | ||
| case 'undefined': | ||
| case 'object': | ||
| this.push('null'); | ||
| break; | ||
| default: | ||
| this.destroy(new TypeError(`Do not know how to serialize a ${value.constructor && value.constructor.name || typeof value}`)); | ||
| } | ||
| } | ||
| function pushPrimitive(value) { | ||
| switch(typeof value){ | ||
| case 'string': | ||
| buffer += encodeString(value); | ||
| break; | ||
| case 'number': | ||
| buffer += Number.isFinite(value) ? String(value) : 'null'; | ||
| break; | ||
| case 'boolean': | ||
| buffer += value ? 'true' : 'false'; | ||
| break; | ||
| case 'undefined': | ||
| case 'object': | ||
| buffer += 'null'; | ||
| break; | ||
| default: | ||
| throw new TypeError(`Do not know how to serialize a ${value.constructor?.name || typeof value}`); | ||
| } | ||
| function processObjectEntry(key) { | ||
| const current = this._stack; | ||
| if (current.first) this.push(','); | ||
| else current.first = true; | ||
| if (this.space) this.push(`\n${this.space.repeat(this._depth)}${this.encodeString(key)}: `); | ||
| else this.push(this.encodeString(key) + ':'); | ||
| } | ||
| function processObject() { | ||
| const current = this._stack; | ||
| if (current.index === current.keys.length) { | ||
| if (this.space && current.first) this.push(`\n${this.space.repeat(this._depth - 1)}}`); | ||
| else this.push('}'); | ||
| this.popStack(); | ||
| return; | ||
| } | ||
| const key = current.keys[current.index]; | ||
| this.processValue(current.value, key, current.value[key], processObjectEntry); | ||
| current.index++; | ||
| } | ||
| function processArrayItem(index) { | ||
| if (0 !== index) this.push(','); | ||
| if (this.space) this.push(`\n${this.space.repeat(this._depth)}`); | ||
| } | ||
| function processArray() { | ||
| const current = this._stack; | ||
| if (current.index === current.value.length) { | ||
| if (this.space && current.index > 0) this.push(`\n${this.space.repeat(this._depth - 1)}]`); | ||
| else this.push(']'); | ||
| this.popStack(); | ||
| return; | ||
| } | ||
| this.processValue(current.value, current.index, current.value[current.index], processArrayItem); | ||
| current.index++; | ||
| } | ||
| function createStreamReader(fn) { | ||
| return function() { | ||
| const current = this._stack; | ||
| const data = current.value.read(this._readSize); | ||
| if (null !== data) { | ||
| current.first = false; | ||
| fn.call(this, data, current); | ||
| } else if (current.first && !current.value._readableState.reading || current.ended) this.popStack(); | ||
| else { | ||
| current.first = true; | ||
| current.awaiting = true; | ||
| } | ||
| }; | ||
| } | ||
| const processReadableObject = createStreamReader(function(data, current) { | ||
| this.processValue(current.value, current.index, data, processArrayItem); | ||
| current.index++; | ||
| }); | ||
| const processReadableString = createStreamReader(function(data) { | ||
| this.push(data); | ||
| }); | ||
| class JsonStringifyStream extends Readable { | ||
| constructor(value, replacer, space){ | ||
| super({ | ||
| autoDestroy: true | ||
| }); | ||
| this.getKeys = Object.keys; | ||
| this.replacer = normalizeReplacer(replacer); | ||
| if (Array.isArray(this.replacer)) { | ||
| const allowlist = this.replacer; | ||
| this.getKeys = (value)=>allowlist.filter((key)=>hasOwnProperty1.call(value, key)); | ||
| this.replacer = null; | ||
| } | ||
| this.space = normalizeSpace(space); | ||
| this._depth = 0; | ||
| this.error = null; | ||
| this._processing = false; | ||
| this._ended = false; | ||
| this._readSize = 0; | ||
| this._buffer = ''; | ||
| this._stack = null; | ||
| this._visited = new WeakSet(); | ||
| this.pushStack({ | ||
| handler: ()=>{ | ||
| this.popStack(); | ||
| this.processValue({ | ||
| '': value | ||
| }, '', value, noop); | ||
| } | ||
| }); | ||
| } | ||
| encodeString(value) { | ||
| if (/[^\x20-\uD799]|[\x22\x5c]/.test(value)) return wellformedStringStringify(value); | ||
| return '"' + value + '"'; | ||
| } | ||
| encodeNumber(value) { | ||
| return value; | ||
| } | ||
| processValue(holder, key, value, callback) { | ||
| value = replaceValue(holder, key, value, this.replacer); | ||
| let type = getTypeAsync(value); | ||
| switch(type){ | ||
| case PRIMITIVE: | ||
| if (callback !== processObjectEntry || void 0 !== value) { | ||
| callback.call(this, key); | ||
| pushPrimitive.call(this, value); | ||
| } | ||
| break; | ||
| case OBJECT: | ||
| callback.call(this, key); | ||
| if (this._visited.has(value)) return this.destroy(new TypeError('Converting circular structure to JSON')); | ||
| this._visited.add(value); | ||
| this._depth++; | ||
| this.push('{'); | ||
| this.pushStack({ | ||
| handler: processObject, | ||
| value, | ||
| index: 0, | ||
| first: false, | ||
| keys: this.getKeys(value) | ||
| }); | ||
| break; | ||
| case ARRAY: | ||
| callback.call(this, key); | ||
| if (this._visited.has(value)) return this.destroy(new TypeError('Converting circular structure to JSON')); | ||
| this._visited.add(value); | ||
| this.push('['); | ||
| this.pushStack({ | ||
| handler: processArray, | ||
| value, | ||
| index: 0 | ||
| }); | ||
| this._depth++; | ||
| break; | ||
| case PROMISE: | ||
| this.pushStack({ | ||
| handler: noop, | ||
| awaiting: true | ||
| }); | ||
| Promise.resolve(value).then((resolved)=>{ | ||
| this.popStack(); | ||
| this.processValue(holder, key, resolved, callback); | ||
| this.processStack(); | ||
| }).catch((error)=>{ | ||
| this.destroy(error); | ||
| }); | ||
| break; | ||
| case STRING_STREAM: | ||
| case OBJECT_STREAM: | ||
| callback.call(this, key); | ||
| if (value.readableEnded || value._readableState.endEmitted) return this.destroy(new Error('Readable Stream has ended before it was serialized. All stream data have been lost')); | ||
| if (value.readableFlowing) return this.destroy(new Error('Readable Stream is in flowing mode, data may have been lost. Trying to pause stream.')); | ||
| if (type === OBJECT_STREAM) { | ||
| this.push('['); | ||
| this.pushStack({ | ||
| handler: push, | ||
| value: this.space ? '\n' + this.space.repeat(this._depth) + ']' : ']' | ||
| }); | ||
| this._depth++; | ||
| } | ||
| const self = this.pushStack({ | ||
| handler: type === OBJECT_STREAM ? processReadableObject : processReadableString, | ||
| value, | ||
| index: 0, | ||
| first: false, | ||
| ended: false, | ||
| awaiting: !value.readable || 0 === value.readableLength | ||
| }); | ||
| const continueProcessing = ()=>{ | ||
| if (self.awaiting) { | ||
| self.awaiting = false; | ||
| this.processStack(); | ||
| } | ||
| }; | ||
| value.once('error', (error)=>this.destroy(error)); | ||
| value.once('end', ()=>{ | ||
| self.ended = true; | ||
| continueProcessing(); | ||
| }); | ||
| value.on('readable', continueProcessing); | ||
| break; | ||
| } | ||
| } | ||
| pushStack(node) { | ||
| node.prev = this._stack; | ||
| return this._stack = node; | ||
| } | ||
| popStack() { | ||
| const { handler, value } = this._stack; | ||
| if (handler === processObject || handler === processArray || handler === processReadableObject) { | ||
| this._visited.delete(value); | ||
| this._depth--; | ||
| } | ||
| this._stack = this._stack.prev; | ||
| } | ||
| processStack() { | ||
| if (this._processing || this._ended) return; | ||
| try { | ||
| this._processing = true; | ||
| while(null !== this._stack && !this._stack.awaiting){ | ||
| this._stack.handler.call(this); | ||
| if (!this._processing) return; | ||
| } | ||
| this._processing = false; | ||
| } catch (error) { | ||
| this.destroy(error); | ||
| return; | ||
| } | ||
| if (null === this._stack && !this._ended) { | ||
| this._finish(); | ||
| this.push(null); | ||
| } | ||
| } | ||
| push(data) { | ||
| if (null !== data) { | ||
| this._buffer += data; | ||
| if (this._buffer.length < this._readSize) return; | ||
| data = this._buffer; | ||
| this._buffer = ''; | ||
| this._processing = false; | ||
| } | ||
| super.push(data); | ||
| } | ||
| _read(size) { | ||
| this._readSize = size || this.readableHighWaterMark; | ||
| this.processStack(); | ||
| } | ||
| _finish() { | ||
| this._ended = true; | ||
| this._processing = false; | ||
| this._stack = null; | ||
| this._visited = null; | ||
| if (this._buffer && this._buffer.length) super.push(this._buffer); | ||
| this._buffer = ''; | ||
| } | ||
| _destroy(error, cb) { | ||
| this.error = this.error || error; | ||
| this._finish(); | ||
| cb(error); | ||
| } | ||
| } | ||
| module.exports = function(value, replacer, space) { | ||
| return new JsonStringifyStream(value, replacer, space); | ||
| } | ||
| function pushState() { | ||
| prevState = { | ||
| keys: stateKeys, | ||
| index: stateIndex, | ||
| prev: prevState | ||
| }; | ||
| }, | ||
| "../../node_modules/.pnpm/@discoveryjs+json-ext@0.5.7/node_modules/@discoveryjs/json-ext/src/text-decoder.js" (module, __unused_rspack_exports, __webpack_require__) { | ||
| module.exports = __webpack_require__("util").TextDecoder; | ||
| }, | ||
| "../../node_modules/.pnpm/@discoveryjs+json-ext@0.5.7/node_modules/@discoveryjs/json-ext/src/utils.js" (module) { | ||
| const PrimitiveType = 1; | ||
| const ObjectType = 2; | ||
| const ArrayType = 3; | ||
| const PromiseType = 4; | ||
| const ReadableStringType = 5; | ||
| const ReadableObjectType = 6; | ||
| const escapableCharCodeSubstitution = { | ||
| 0x08: '\\b', | ||
| 0x09: '\\t', | ||
| 0x0a: '\\n', | ||
| 0x0c: '\\f', | ||
| 0x0d: '\\r', | ||
| 0x22: '\\\"', | ||
| 0x5c: '\\\\' | ||
| }; | ||
| function isLeadingSurrogate(code) { | ||
| return code >= 0xD800 && code <= 0xDBFF; | ||
| } | ||
| function isTrailingSurrogate(code) { | ||
| return code >= 0xDC00 && code <= 0xDFFF; | ||
| } | ||
| function isReadableStream(value) { | ||
| return 'function' == typeof value.pipe && 'function' == typeof value._read && 'object' == typeof value._readableState && null !== value._readableState; | ||
| } | ||
| function replaceValue(holder, key, value, replacer) { | ||
| if (value && 'function' == typeof value.toJSON) value = value.toJSON(); | ||
| if (null !== replacer) value = replacer.call(holder, String(key), value); | ||
| switch(typeof value){ | ||
| case 'function': | ||
| case 'symbol': | ||
| value = void 0; | ||
| break; | ||
| case 'object': | ||
| if (null !== value) { | ||
| const cls = value.constructor; | ||
| if (cls === String || cls === Number || cls === Boolean) value = value.valueOf(); | ||
| } | ||
| break; | ||
| } | ||
| return value; | ||
| } | ||
| function getTypeNative(value) { | ||
| if (null === value || 'object' != typeof value) return PrimitiveType; | ||
| if (Array.isArray(value)) return ArrayType; | ||
| return ObjectType; | ||
| } | ||
| function getTypeAsync(value) { | ||
| if (null === value || 'object' != typeof value) return PrimitiveType; | ||
| if ('function' == typeof value.then) return PromiseType; | ||
| if (isReadableStream(value)) return value._readableState.objectMode ? ReadableObjectType : ReadableStringType; | ||
| if (Array.isArray(value)) return ArrayType; | ||
| return ObjectType; | ||
| } | ||
| function normalizeReplacer(replacer) { | ||
| if ('function' == typeof replacer) return replacer; | ||
| if (Array.isArray(replacer)) { | ||
| const allowlist = new Set(replacer.map((item)=>{ | ||
| const cls = item && item.constructor; | ||
| return cls === String || cls === Number ? String(item) : null; | ||
| }).filter((item)=>'string' == typeof item)); | ||
| return [ | ||
| ...allowlist | ||
| ]; | ||
| } | ||
| return null; | ||
| } | ||
| function normalizeSpace(space) { | ||
| if ('number' == typeof space) { | ||
| if (!Number.isFinite(space) || space < 1) return false; | ||
| return ' '.repeat(Math.min(space, 10)); | ||
| } | ||
| if ('string' == typeof space) return space.slice(0, 10) || false; | ||
| return false; | ||
| } | ||
| module.exports = { | ||
| escapableCharCodeSubstitution, | ||
| isLeadingSurrogate, | ||
| isTrailingSurrogate, | ||
| type: { | ||
| PRIMITIVE: PrimitiveType, | ||
| PROMISE: PromiseType, | ||
| ARRAY: ArrayType, | ||
| OBJECT: ObjectType, | ||
| STRING_STREAM: ReadableStringType, | ||
| OBJECT_STREAM: ReadableObjectType | ||
| }, | ||
| isReadableStream, | ||
| replaceValue, | ||
| getTypeNative, | ||
| getTypeAsync, | ||
| normalizeReplacer, | ||
| normalizeSpace | ||
| }; | ||
| }, | ||
| "../../node_modules/.pnpm/@discoveryjs+json-ext@0.5.7/node_modules/@discoveryjs/json-ext/src/version.js" (module, __unused_rspack_exports, __webpack_require__) { | ||
| module.exports = __webpack_require__("../../node_modules/.pnpm/@discoveryjs+json-ext@0.5.7/node_modules/@discoveryjs/json-ext/package.json").version; | ||
| }, | ||
| util (module) { | ||
| module.exports = __rspack_external_util; | ||
| }, | ||
| "../../node_modules/.pnpm/@discoveryjs+json-ext@0.5.7/node_modules/@discoveryjs/json-ext/package.json" (module) { | ||
| module.exports = { | ||
| version: "0.5.7" | ||
| }; | ||
| } | ||
| function popState() { | ||
| stack.pop(); | ||
| const value = stack.length > 0 ? stack[stack.length - 1] : rootValue; | ||
| state = Array.isArray(value) ? printArray : printObject; | ||
| stateValue = value; | ||
| stateEmpty = false; | ||
| stateKeys = prevState.keys; | ||
| stateIndex = prevState.index; | ||
| prevState = prevState.prev; | ||
| } | ||
| } | ||
| const hasOwn = 'function' == typeof Object.hasOwn ? Object.hasOwn : (object, key)=>Object.hasOwnProperty.call(object, key); | ||
| const escapableCharCodeSubstitution = { | ||
| 0x08: '\\b', | ||
| 0x09: '\\t', | ||
| 0x0a: '\\n', | ||
| 0x0c: '\\f', | ||
| 0x0d: '\\r', | ||
| 0x22: '\\\"', | ||
| 0x5c: '\\\\' | ||
| }; | ||
| Uint8Array.from({ | ||
| length: 2048 | ||
| }, (_, code)=>{ | ||
| if (hasOwn(escapableCharCodeSubstitution, code)) return 2; | ||
| if (code < 0x20) return 6; | ||
| return code < 128 ? 1 : 2; | ||
| }); | ||
| __webpack_require__("../../node_modules/.pnpm/@discoveryjs+json-ext@0.5.7/node_modules/@discoveryjs/json-ext/src/index.js"); | ||
| export { stringify_chunked_stringifyChunked as stringifyChunked }; |
+5
-5
| { | ||
| "name": "@rspack/cli", | ||
| "version": "2.0.1", | ||
| "version": "2.0.2", | ||
| "description": "CLI for rspack", | ||
@@ -31,3 +31,3 @@ "homepage": "https://rspack.rs", | ||
| "devDependencies": { | ||
| "@discoveryjs/json-ext": "^0.5.7", | ||
| "@discoveryjs/json-ext": "^1.1.0", | ||
| "@microsoft/api-extractor": "^7.58.7", | ||
@@ -40,8 +40,8 @@ "@rslib/core": "0.21.3", | ||
| "execa": "^5.1.1", | ||
| "exit-hook": "^4.0.0", | ||
| "exit-hook": "^5.1.0", | ||
| "jiti": "^2.6.1", | ||
| "prebundle": "^1.6.4", | ||
| "typescript": "^6.0.3", | ||
| "@rspack/core": "2.0.1", | ||
| "@rspack/test-tools": "2.0.1" | ||
| "@rspack/core": "2.0.2", | ||
| "@rspack/test-tools": "2.0.2" | ||
| }, | ||
@@ -48,0 +48,0 @@ "peerDependencies": { |
-1301
| import node_path from "node:path"; | ||
| import node_util from "node:util"; | ||
| import { rspack } from "@rspack/core"; | ||
| import node_fs from "node:fs"; | ||
| import { createRequire } from "node:module"; | ||
| import { pathToFileURL } from "node:url"; | ||
| import { createRequire as __rspack_createRequire } from "node:module"; | ||
| const __rspack_createRequire_require = __rspack_createRequire(import.meta.url); | ||
| var __webpack_modules__ = {}; | ||
| var __webpack_module_cache__ = {}; | ||
| function __webpack_require__(moduleId) { | ||
| var cachedModule = __webpack_module_cache__[moduleId]; | ||
| if (void 0 !== cachedModule) return cachedModule.exports; | ||
| var module = __webpack_module_cache__[moduleId] = { | ||
| exports: {} | ||
| }; | ||
| __webpack_modules__[moduleId](module, module.exports, __webpack_require__); | ||
| return module.exports; | ||
| } | ||
| __webpack_require__.m = __webpack_modules__; | ||
| (()=>{ | ||
| var getProto = Object.getPrototypeOf ? (obj)=>Object.getPrototypeOf(obj) : (obj)=>obj.__proto__; | ||
| var leafPrototypes; | ||
| __webpack_require__.t = function(value, mode) { | ||
| if (1 & mode) value = this(value); | ||
| if (8 & mode) return value; | ||
| if ('object' == typeof value && value) { | ||
| if (4 & mode && value.__esModule) return value; | ||
| if (16 & mode && 'function' == typeof value.then) return value; | ||
| } | ||
| var ns = Object.create(null); | ||
| __webpack_require__.r(ns); | ||
| var def = {}; | ||
| leafPrototypes = leafPrototypes || [ | ||
| null, | ||
| getProto({}), | ||
| getProto([]), | ||
| getProto(getProto) | ||
| ]; | ||
| for(var current = 2 & mode && value; ('object' == typeof current || 'function' == typeof current) && !~leafPrototypes.indexOf(current); current = getProto(current))Object.getOwnPropertyNames(current).forEach((key)=>{ | ||
| def[key] = ()=>value[key]; | ||
| }); | ||
| def['default'] = ()=>value; | ||
| __webpack_require__.d(ns, def); | ||
| return ns; | ||
| }; | ||
| })(); | ||
| (()=>{ | ||
| __webpack_require__.d = (exports, definition)=>{ | ||
| for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) Object.defineProperty(exports, key, { | ||
| enumerable: true, | ||
| get: definition[key] | ||
| }); | ||
| }; | ||
| })(); | ||
| (()=>{ | ||
| __webpack_require__.add = function(modules) { | ||
| Object.assign(__webpack_require__.m, modules); | ||
| }; | ||
| })(); | ||
| var __webpack_require__temp = __webpack_require__; | ||
| (()=>{ | ||
| __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop); | ||
| })(); | ||
| (()=>{ | ||
| __webpack_require__.r = (exports)=>{ | ||
| if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports, Symbol.toStringTag, { | ||
| value: 'Module' | ||
| }); | ||
| Object.defineProperty(exports, '__esModule', { | ||
| value: true | ||
| }); | ||
| }; | ||
| })(); | ||
| (()=>{ | ||
| var installedChunks = { | ||
| 162: 0, | ||
| 410: 0 | ||
| }; | ||
| var installChunk = (data)=>{ | ||
| var __rspack_esm_ids = data.__rspack_esm_ids; | ||
| var __webpack_modules__ = data.__webpack_modules__; | ||
| var __rspack_esm_runtime = data.__rspack_esm_runtime; | ||
| var moduleId, chunkId, i = 0; | ||
| for(moduleId in __webpack_modules__)if (__webpack_require__.o(__webpack_modules__, moduleId)) __webpack_require__.m[moduleId] = __webpack_modules__[moduleId]; | ||
| if (__rspack_esm_runtime) __rspack_esm_runtime(__webpack_require__); | ||
| for(; i < __rspack_esm_ids.length; i++){ | ||
| chunkId = __rspack_esm_ids[i]; | ||
| if (__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) installedChunks[chunkId][0](); | ||
| installedChunks[__rspack_esm_ids[i]] = 0; | ||
| } | ||
| }; | ||
| __webpack_require__.C = installChunk; | ||
| })(); | ||
| __webpack_require__.add({ | ||
| stream (module) { | ||
| module.exports = __rspack_createRequire_require("stream"); | ||
| } | ||
| }); | ||
| function toArr(any) { | ||
| return null == any ? [] : Array.isArray(any) ? any : [ | ||
| any | ||
| ]; | ||
| } | ||
| function toVal(out, key, val, opts) { | ||
| var x, old = out[key], nxt = ~opts.string.indexOf(key) ? null == val || true === val ? "" : String(val) : "boolean" == typeof val ? val : ~opts.boolean.indexOf(key) ? "false" === val ? false : "true" === val || (out._.push((x = +val, 0 * x === 0) ? x : val), !!val) : (x = +val, 0 * x === 0) ? x : val; | ||
| out[key] = null == old ? nxt : Array.isArray(old) ? old.concat(nxt) : [ | ||
| old, | ||
| nxt | ||
| ]; | ||
| } | ||
| function lib_default(args, opts) { | ||
| args = args || []; | ||
| opts = opts || {}; | ||
| var k, arr, arg, name, val, out = { | ||
| _: [] | ||
| }; | ||
| var i = 0, j = 0, idx = 0, len = args.length; | ||
| const alibi = void 0 !== opts.alias; | ||
| const strict = void 0 !== opts.unknown; | ||
| const defaults = void 0 !== opts.default; | ||
| opts.alias = opts.alias || {}; | ||
| opts.string = toArr(opts.string); | ||
| opts.boolean = toArr(opts.boolean); | ||
| if (alibi) for(k in opts.alias){ | ||
| arr = opts.alias[k] = toArr(opts.alias[k]); | ||
| for(i = 0; i < arr.length; i++)(opts.alias[arr[i]] = arr.concat(k)).splice(i, 1); | ||
| } | ||
| for(i = opts.boolean.length; i-- > 0;){ | ||
| arr = opts.alias[opts.boolean[i]] || []; | ||
| for(j = arr.length; j-- > 0;)opts.boolean.push(arr[j]); | ||
| } | ||
| for(i = opts.string.length; i-- > 0;){ | ||
| arr = opts.alias[opts.string[i]] || []; | ||
| for(j = arr.length; j-- > 0;)opts.string.push(arr[j]); | ||
| } | ||
| if (defaults) for(k in opts.default){ | ||
| name = typeof opts.default[k]; | ||
| arr = opts.alias[k] = opts.alias[k] || []; | ||
| if (void 0 !== opts[name]) { | ||
| opts[name].push(k); | ||
| for(i = 0; i < arr.length; i++)opts[name].push(arr[i]); | ||
| } | ||
| } | ||
| const keys = strict ? Object.keys(opts.alias) : []; | ||
| for(i = 0; i < len; i++){ | ||
| arg = args[i]; | ||
| if ("--" === arg) { | ||
| out._ = out._.concat(args.slice(++i)); | ||
| break; | ||
| } | ||
| for(j = 0; j < arg.length && 45 === arg.charCodeAt(j); j++); | ||
| if (0 === j) out._.push(arg); | ||
| else if ("no-" === arg.substring(j, j + 3)) { | ||
| name = arg.substring(j + 3); | ||
| if (strict && !~keys.indexOf(name)) return opts.unknown(arg); | ||
| out[name] = false; | ||
| } else { | ||
| for(idx = j + 1; idx < arg.length && 61 !== arg.charCodeAt(idx); idx++); | ||
| name = arg.substring(j, idx); | ||
| val = arg.substring(++idx) || i + 1 === len || 45 === ("" + args[i + 1]).charCodeAt(0) || args[++i]; | ||
| arr = 2 === j ? [ | ||
| name | ||
| ] : name; | ||
| for(idx = 0; idx < arr.length; idx++){ | ||
| name = arr[idx]; | ||
| if (strict && !~keys.indexOf(name)) return opts.unknown("-".repeat(j) + name); | ||
| toVal(out, name, idx + 1 < arr.length || val, opts); | ||
| } | ||
| } | ||
| } | ||
| if (defaults) { | ||
| for(k in opts.default)if (void 0 === out[k]) out[k] = opts.default[k]; | ||
| } | ||
| if (alibi) for(k in out){ | ||
| arr = opts.alias[k] || []; | ||
| while(arr.length > 0)out[arr.shift()] = out[k]; | ||
| } | ||
| return out; | ||
| } | ||
| function removeBrackets(v) { | ||
| return v.replace(/[<[].+/, "").trim(); | ||
| } | ||
| function findAllBrackets(v) { | ||
| const ANGLED_BRACKET_RE_GLOBAL = /<([^>]+)>/g; | ||
| const SQUARE_BRACKET_RE_GLOBAL = /\[([^\]]+)\]/g; | ||
| const res = []; | ||
| const parse = (match)=>{ | ||
| let variadic = false; | ||
| let value = match[1]; | ||
| if (value.startsWith("...")) { | ||
| value = value.slice(3); | ||
| variadic = true; | ||
| } | ||
| return { | ||
| required: match[0].startsWith("<"), | ||
| value, | ||
| variadic | ||
| }; | ||
| }; | ||
| let angledMatch; | ||
| while(angledMatch = ANGLED_BRACKET_RE_GLOBAL.exec(v))res.push(parse(angledMatch)); | ||
| let squareMatch; | ||
| while(squareMatch = SQUARE_BRACKET_RE_GLOBAL.exec(v))res.push(parse(squareMatch)); | ||
| return res; | ||
| } | ||
| function getMriOptions(options) { | ||
| const result = { | ||
| alias: {}, | ||
| boolean: [] | ||
| }; | ||
| for (const [index, option] of options.entries()){ | ||
| if (option.names.length > 1) result.alias[option.names[0]] = option.names.slice(1); | ||
| if (option.isBoolean) if (option.negated) { | ||
| if (!options.some((o, i)=>i !== index && o.names.some((name)=>option.names.includes(name)) && "boolean" == typeof o.required)) result.boolean.push(option.names[0]); | ||
| } else result.boolean.push(option.names[0]); | ||
| } | ||
| return result; | ||
| } | ||
| function findLongest(arr) { | ||
| return arr.sort((a, b)=>a.length > b.length ? -1 : 1)[0]; | ||
| } | ||
| function padRight(str, length) { | ||
| return str.length >= length ? str : `${str}${" ".repeat(length - str.length)}`; | ||
| } | ||
| function camelcase(input) { | ||
| return input.replaceAll(/([a-z])-([a-z])/g, (_, p1, p2)=>p1 + p2.toUpperCase()); | ||
| } | ||
| function setDotProp(obj, keys, val) { | ||
| let current = obj; | ||
| for(let i = 0; i < keys.length; i++){ | ||
| const key = keys[i]; | ||
| if (i === keys.length - 1) { | ||
| current[key] = val; | ||
| return; | ||
| } | ||
| if (null == current[key]) { | ||
| const nextKeyIsArrayIndex = +keys[i + 1] > -1; | ||
| current[key] = nextKeyIsArrayIndex ? [] : {}; | ||
| } | ||
| current = current[key]; | ||
| } | ||
| } | ||
| function setByType(obj, transforms) { | ||
| for (const key of Object.keys(transforms)){ | ||
| const transform = transforms[key]; | ||
| if (transform.shouldTransform) { | ||
| obj[key] = [ | ||
| obj[key] | ||
| ].flat(); | ||
| if ("function" == typeof transform.transformFunction) obj[key] = obj[key].map(transform.transformFunction); | ||
| } | ||
| } | ||
| } | ||
| function getFileName(input) { | ||
| const m = /([^\\/]+)$/.exec(input); | ||
| return m ? m[1] : ""; | ||
| } | ||
| function camelcaseOptionName(name) { | ||
| return name.split(".").map((v, i)=>0 === i ? camelcase(v) : v).join("."); | ||
| } | ||
| var CACError = class extends Error { | ||
| constructor(message){ | ||
| super(message); | ||
| this.name = "CACError"; | ||
| if ("function" != typeof Error.captureStackTrace) this.stack = new Error(message).stack; | ||
| } | ||
| }; | ||
| var Option = class { | ||
| rawName; | ||
| description; | ||
| name; | ||
| names; | ||
| isBoolean; | ||
| required; | ||
| config; | ||
| negated; | ||
| constructor(rawName, description, config){ | ||
| this.rawName = rawName; | ||
| this.description = description; | ||
| this.config = Object.assign({}, config); | ||
| rawName = rawName.replaceAll(".*", ""); | ||
| this.negated = false; | ||
| this.names = removeBrackets(rawName).split(",").map((v)=>{ | ||
| let name = v.trim().replace(/^-{1,2}/, ""); | ||
| if (name.startsWith("no-")) { | ||
| this.negated = true; | ||
| name = name.replace(/^no-/, ""); | ||
| } | ||
| return camelcaseOptionName(name); | ||
| }).sort((a, b)=>a.length > b.length ? 1 : -1); | ||
| this.name = this.names.at(-1); | ||
| if (this.negated && null == this.config.default) this.config.default = true; | ||
| if (rawName.includes("<")) this.required = true; | ||
| else if (rawName.includes("[")) this.required = false; | ||
| else this.isBoolean = true; | ||
| } | ||
| }; | ||
| let runtimeProcessArgs; | ||
| let runtimeInfo; | ||
| if ("u" > typeof process) { | ||
| let runtimeName; | ||
| runtimeName = "u" > typeof Deno && "string" == typeof Deno.version?.deno ? "deno" : "u" > typeof Bun && "string" == typeof Bun.version ? "bun" : "node"; | ||
| runtimeInfo = `${process.platform}-${process.arch} ${runtimeName}-${process.version}`; | ||
| runtimeProcessArgs = process.argv; | ||
| } else runtimeInfo = "u" < typeof navigator ? "unknown" : `${navigator.platform} ${navigator.userAgent}`; | ||
| var Command = class { | ||
| rawName; | ||
| description; | ||
| config; | ||
| cli; | ||
| options; | ||
| aliasNames; | ||
| name; | ||
| args; | ||
| commandAction; | ||
| usageText; | ||
| versionNumber; | ||
| examples; | ||
| helpCallback; | ||
| globalCommand; | ||
| constructor(rawName, description, config = {}, cli){ | ||
| this.rawName = rawName; | ||
| this.description = description; | ||
| this.config = config; | ||
| this.cli = cli; | ||
| this.options = []; | ||
| this.aliasNames = []; | ||
| this.name = removeBrackets(rawName); | ||
| this.args = findAllBrackets(rawName); | ||
| this.examples = []; | ||
| } | ||
| usage(text) { | ||
| this.usageText = text; | ||
| return this; | ||
| } | ||
| allowUnknownOptions() { | ||
| this.config.allowUnknownOptions = true; | ||
| return this; | ||
| } | ||
| ignoreOptionDefaultValue() { | ||
| this.config.ignoreOptionDefaultValue = true; | ||
| return this; | ||
| } | ||
| version(version, customFlags = "-v, --version") { | ||
| this.versionNumber = version; | ||
| this.option(customFlags, "Display version number"); | ||
| return this; | ||
| } | ||
| example(example) { | ||
| this.examples.push(example); | ||
| return this; | ||
| } | ||
| option(rawName, description, config) { | ||
| const option = new Option(rawName, description, config); | ||
| this.options.push(option); | ||
| return this; | ||
| } | ||
| alias(name) { | ||
| this.aliasNames.push(name); | ||
| return this; | ||
| } | ||
| action(callback) { | ||
| this.commandAction = callback; | ||
| return this; | ||
| } | ||
| isMatched(name) { | ||
| return this.name === name || this.aliasNames.includes(name); | ||
| } | ||
| get isDefaultCommand() { | ||
| return "" === this.name || this.aliasNames.includes("!"); | ||
| } | ||
| get isGlobalCommand() { | ||
| return this instanceof GlobalCommand; | ||
| } | ||
| hasOption(name) { | ||
| name = name.split(".")[0]; | ||
| return this.options.find((option)=>option.names.includes(name)); | ||
| } | ||
| outputHelp() { | ||
| const { name, commands } = this.cli; | ||
| const { versionNumber, options: globalOptions, helpCallback } = this.cli.globalCommand; | ||
| let sections = [ | ||
| { | ||
| body: `${name}${versionNumber ? `/${versionNumber}` : ""}` | ||
| } | ||
| ]; | ||
| sections.push({ | ||
| title: "Usage", | ||
| body: ` $ ${name} ${this.usageText || this.rawName}` | ||
| }); | ||
| if ((this.isGlobalCommand || this.isDefaultCommand) && commands.length > 0) { | ||
| const longestCommandName = findLongest(commands.map((command)=>command.rawName)); | ||
| sections.push({ | ||
| title: "Commands", | ||
| body: commands.map((command)=>` ${padRight(command.rawName, longestCommandName.length)} ${command.description}`).join("\n") | ||
| }, { | ||
| title: "For more info, run any command with the `--help` flag", | ||
| body: commands.map((command)=>` $ ${name}${"" === command.name ? "" : ` ${command.name}`} --help`).join("\n") | ||
| }); | ||
| } | ||
| let options = this.isGlobalCommand ? globalOptions : [ | ||
| ...this.options, | ||
| ...globalOptions || [] | ||
| ]; | ||
| if (!this.isGlobalCommand && !this.isDefaultCommand) options = options.filter((option)=>"version" !== option.name); | ||
| if (options.length > 0) { | ||
| const longestOptionName = findLongest(options.map((option)=>option.rawName)); | ||
| sections.push({ | ||
| title: "Options", | ||
| body: options.map((option)=>` ${padRight(option.rawName, longestOptionName.length)} ${option.description} ${void 0 === option.config.default ? "" : `(default: ${option.config.default})`}`).join("\n") | ||
| }); | ||
| } | ||
| if (this.examples.length > 0) sections.push({ | ||
| title: "Examples", | ||
| body: this.examples.map((example)=>{ | ||
| if ("function" == typeof example) return example(name); | ||
| return example; | ||
| }).join("\n") | ||
| }); | ||
| if (helpCallback) sections = helpCallback(sections) || sections; | ||
| console.info(sections.map((section)=>section.title ? `${section.title}:\n${section.body}` : section.body).join("\n\n")); | ||
| } | ||
| outputVersion() { | ||
| const { name } = this.cli; | ||
| const { versionNumber } = this.cli.globalCommand; | ||
| if (versionNumber) console.info(`${name}/${versionNumber} ${runtimeInfo}`); | ||
| } | ||
| checkRequiredArgs() { | ||
| const minimalArgsCount = this.args.filter((arg)=>arg.required).length; | ||
| if (this.cli.args.length < minimalArgsCount) throw new CACError(`missing required args for command \`${this.rawName}\``); | ||
| } | ||
| checkUnknownOptions() { | ||
| const { options, globalCommand } = this.cli; | ||
| if (!this.config.allowUnknownOptions) { | ||
| for (const name of Object.keys(options))if ("--" !== name && !this.hasOption(name) && !globalCommand.hasOption(name)) throw new CACError(`Unknown option \`${name.length > 1 ? `--${name}` : `-${name}`}\``); | ||
| } | ||
| } | ||
| checkOptionValue() { | ||
| const { options: parsedOptions, globalCommand } = this.cli; | ||
| const options = [ | ||
| ...globalCommand.options, | ||
| ...this.options | ||
| ]; | ||
| for (const option of options){ | ||
| const value = parsedOptions[option.name.split(".")[0]]; | ||
| if (option.required) { | ||
| const hasNegated = options.some((o)=>o.negated && o.names.includes(option.name)); | ||
| if (true === value || false === value && !hasNegated) throw new CACError(`option \`${option.rawName}\` value is missing`); | ||
| } | ||
| } | ||
| } | ||
| checkUnusedArgs() { | ||
| const maximumArgsCount = this.args.some((arg)=>arg.variadic) ? 1 / 0 : this.args.length; | ||
| if (maximumArgsCount < this.cli.args.length) throw new CACError(`Unused args: ${this.cli.args.slice(maximumArgsCount).map((arg)=>`\`${arg}\``).join(", ")}`); | ||
| } | ||
| }; | ||
| var GlobalCommand = class extends Command { | ||
| constructor(cli){ | ||
| super("@@global@@", "", {}, cli); | ||
| } | ||
| }; | ||
| var CAC = class extends EventTarget { | ||
| name; | ||
| commands; | ||
| globalCommand; | ||
| matchedCommand; | ||
| matchedCommandName; | ||
| rawArgs; | ||
| args; | ||
| options; | ||
| showHelpOnExit; | ||
| showVersionOnExit; | ||
| constructor(name = ""){ | ||
| super(); | ||
| this.name = name; | ||
| this.commands = []; | ||
| this.rawArgs = []; | ||
| this.args = []; | ||
| this.options = {}; | ||
| this.globalCommand = new GlobalCommand(this); | ||
| this.globalCommand.usage("<command> [options]"); | ||
| } | ||
| usage(text) { | ||
| this.globalCommand.usage(text); | ||
| return this; | ||
| } | ||
| command(rawName, description, config) { | ||
| const command = new Command(rawName, description || "", config, this); | ||
| command.globalCommand = this.globalCommand; | ||
| this.commands.push(command); | ||
| return command; | ||
| } | ||
| option(rawName, description, config) { | ||
| this.globalCommand.option(rawName, description, config); | ||
| return this; | ||
| } | ||
| help(callback) { | ||
| this.globalCommand.option("-h, --help", "Display this message"); | ||
| this.globalCommand.helpCallback = callback; | ||
| this.showHelpOnExit = true; | ||
| return this; | ||
| } | ||
| version(version, customFlags = "-v, --version") { | ||
| this.globalCommand.version(version, customFlags); | ||
| this.showVersionOnExit = true; | ||
| return this; | ||
| } | ||
| example(example) { | ||
| this.globalCommand.example(example); | ||
| return this; | ||
| } | ||
| outputHelp() { | ||
| if (this.matchedCommand) this.matchedCommand.outputHelp(); | ||
| else this.globalCommand.outputHelp(); | ||
| } | ||
| outputVersion() { | ||
| this.globalCommand.outputVersion(); | ||
| } | ||
| setParsedInfo({ args, options }, matchedCommand, matchedCommandName) { | ||
| this.args = args; | ||
| this.options = options; | ||
| if (matchedCommand) this.matchedCommand = matchedCommand; | ||
| if (matchedCommandName) this.matchedCommandName = matchedCommandName; | ||
| return this; | ||
| } | ||
| unsetMatchedCommand() { | ||
| this.matchedCommand = void 0; | ||
| this.matchedCommandName = void 0; | ||
| } | ||
| parse(argv, { run = true } = {}) { | ||
| if (!argv) { | ||
| if (!runtimeProcessArgs) throw new Error("No argv provided and runtime process argv is not available."); | ||
| argv = runtimeProcessArgs; | ||
| } | ||
| this.rawArgs = argv; | ||
| if (!this.name) this.name = argv[1] ? getFileName(argv[1]) : "cli"; | ||
| let shouldParse = true; | ||
| for (const command of this.commands){ | ||
| const parsed = this.mri(argv.slice(2), command); | ||
| const commandName = parsed.args[0]; | ||
| if (command.isMatched(commandName)) { | ||
| shouldParse = false; | ||
| const parsedInfo = { | ||
| ...parsed, | ||
| args: parsed.args.slice(1) | ||
| }; | ||
| this.setParsedInfo(parsedInfo, command, commandName); | ||
| this.dispatchEvent(new CustomEvent(`command:${commandName}`, { | ||
| detail: command | ||
| })); | ||
| } | ||
| } | ||
| if (shouldParse) { | ||
| for (const command of this.commands)if (command.isDefaultCommand) { | ||
| shouldParse = false; | ||
| const parsed = this.mri(argv.slice(2), command); | ||
| this.setParsedInfo(parsed, command); | ||
| this.dispatchEvent(new CustomEvent("command:!", { | ||
| detail: command | ||
| })); | ||
| } | ||
| } | ||
| if (shouldParse) { | ||
| const parsed = this.mri(argv.slice(2)); | ||
| this.setParsedInfo(parsed); | ||
| } | ||
| if (this.options.help && this.showHelpOnExit) { | ||
| this.outputHelp(); | ||
| run = false; | ||
| this.unsetMatchedCommand(); | ||
| } | ||
| if (this.options.version && this.showVersionOnExit && null == this.matchedCommandName) { | ||
| this.outputVersion(); | ||
| run = false; | ||
| this.unsetMatchedCommand(); | ||
| } | ||
| const parsedArgv = { | ||
| args: this.args, | ||
| options: this.options | ||
| }; | ||
| if (run) this.runMatchedCommand(); | ||
| if (!this.matchedCommand && this.args[0]) this.dispatchEvent(new CustomEvent("command:*", { | ||
| detail: this.args[0] | ||
| })); | ||
| return parsedArgv; | ||
| } | ||
| mri(argv, command) { | ||
| const cliOptions = [ | ||
| ...this.globalCommand.options, | ||
| ...command ? command.options : [] | ||
| ]; | ||
| const mriOptions = getMriOptions(cliOptions); | ||
| let argsAfterDoubleDashes = []; | ||
| const doubleDashesIndex = argv.indexOf("--"); | ||
| if (-1 !== doubleDashesIndex) { | ||
| argsAfterDoubleDashes = argv.slice(doubleDashesIndex + 1); | ||
| argv = argv.slice(0, doubleDashesIndex); | ||
| } | ||
| let parsed = lib_default(argv, mriOptions); | ||
| parsed = Object.keys(parsed).reduce((res, name)=>({ | ||
| ...res, | ||
| [camelcaseOptionName(name)]: parsed[name] | ||
| }), { | ||
| _: [] | ||
| }); | ||
| const args = parsed._; | ||
| const options = { | ||
| "--": argsAfterDoubleDashes | ||
| }; | ||
| const ignoreDefault = command && command.config.ignoreOptionDefaultValue ? command.config.ignoreOptionDefaultValue : this.globalCommand.config.ignoreOptionDefaultValue; | ||
| const transforms = Object.create(null); | ||
| for (const cliOption of cliOptions){ | ||
| if (!ignoreDefault && void 0 !== cliOption.config.default) for (const name of cliOption.names)options[name] = cliOption.config.default; | ||
| if (Array.isArray(cliOption.config.type) && void 0 === transforms[cliOption.name]) { | ||
| transforms[cliOption.name] = Object.create(null); | ||
| transforms[cliOption.name].shouldTransform = true; | ||
| transforms[cliOption.name].transformFunction = cliOption.config.type[0]; | ||
| } | ||
| } | ||
| for (const key of Object.keys(parsed))if ("_" !== key) { | ||
| setDotProp(options, key.split("."), parsed[key]); | ||
| setByType(options, transforms); | ||
| } | ||
| return { | ||
| args, | ||
| options | ||
| }; | ||
| } | ||
| runMatchedCommand() { | ||
| const { args, options, matchedCommand: command } = this; | ||
| if (!command || !command.commandAction) return; | ||
| command.checkUnknownOptions(); | ||
| command.checkOptionValue(); | ||
| command.checkRequiredArgs(); | ||
| command.checkUnusedArgs(); | ||
| const actionArgs = []; | ||
| command.args.forEach((arg, index)=>{ | ||
| if (arg.variadic) actionArgs.push(args.slice(index)); | ||
| else actionArgs.push(args[index]); | ||
| }); | ||
| actionArgs.push(options); | ||
| return command.commandAction.apply(this, actionArgs); | ||
| } | ||
| }; | ||
| const cac = (name = "")=>new CAC(name); | ||
| const commonOptions = (command)=>command.option('-c, --config <path>', 'config file').option('--config-name <name>', 'Name(s) of the configuration to use.', { | ||
| type: [ | ||
| String | ||
| ], | ||
| default: [] | ||
| }).option('--config-loader <loader>', 'Specify the loader to load the config file, can be `auto`, `jiti` or `native`.', { | ||
| default: 'auto' | ||
| }).option('--env <env>', 'env passed to config function', { | ||
| type: [ | ||
| String | ||
| ], | ||
| default: [] | ||
| }).option('--node-env <value>', 'sets `process.env.NODE_ENV` to be specified value'); | ||
| function normalizeDevtoolOption(value) { | ||
| if ('string' == typeof value) { | ||
| const trimmed = value.trim(); | ||
| if ('' === trimmed || 'false' === trimmed) return false; | ||
| if ('true' === trimmed) return 'source-map'; | ||
| return trimmed; | ||
| } | ||
| if ('boolean' == typeof value) return value ? 'source-map' : false; | ||
| } | ||
| const normalizeCommonOptions = (options, action)=>{ | ||
| const isEmptyArray = (arr)=>Array.isArray(arr) && 0 === arr.length; | ||
| for (const key of [ | ||
| 'entry', | ||
| 'configName' | ||
| ]){ | ||
| const val = options[key]; | ||
| if (isEmptyArray(val)) options[key] = void 0; | ||
| } | ||
| const env = Array.isArray(options.env) ? normalizeEnvToObject(options) : {}; | ||
| options.env = env; | ||
| if ('serve' === action) setBuiltinEnvArg(env, 'SERVE', true); | ||
| else if ('build' === action) if (options.watch) setBuiltinEnvArg(env, 'WATCH', true); | ||
| else { | ||
| setBuiltinEnvArg(env, 'BUNDLE', true); | ||
| setBuiltinEnvArg(env, 'BUILD', true); | ||
| } | ||
| if ('devtool' in options) options.devtool = normalizeDevtoolOption(options.devtool); | ||
| }; | ||
| const commonOptionsForBuildAndServe = (command)=>command.option('-d, --devtool <value>', 'specify a developer tool for debugging. Defaults to `cheap-module-source-map` in development and `source-map` in production.').option('--entry <entry>', 'entry file', { | ||
| type: [ | ||
| String | ||
| ], | ||
| default: [] | ||
| }).option('-m, --mode <mode>', 'mode').option('-o, --output-path <dir>', 'output path dir').option('-w, --watch', 'watch'); | ||
| function setBuiltinEnvArg(env, envNameSuffix, value) { | ||
| const envName = `RSPACK_${envNameSuffix}`; | ||
| if (!(envName in env)) env[envName] = value; | ||
| } | ||
| function normalizeEnvToObject(options) { | ||
| function parseValue(previous, value) { | ||
| const [allKeys, val] = value.split(/=(.+)/, 2); | ||
| const splitKeys = allKeys.split(/\.(?!$)/); | ||
| let prevRef = previous; | ||
| splitKeys.forEach((key, index)=>{ | ||
| let someKey = key; | ||
| if (someKey.endsWith('=')) { | ||
| someKey = someKey.slice(0, -1); | ||
| prevRef[someKey] = void 0; | ||
| return; | ||
| } | ||
| if (!prevRef[someKey] || 'string' == typeof prevRef[someKey]) prevRef[someKey] = {}; | ||
| if (index === splitKeys.length - 1) if ('string' == typeof val) prevRef[someKey] = val; | ||
| else prevRef[someKey] = true; | ||
| prevRef = prevRef[someKey]; | ||
| }); | ||
| return previous; | ||
| } | ||
| return (options.env ?? []).reduce(parseValue, {}); | ||
| } | ||
| function setDefaultNodeEnv(options, defaultEnv) { | ||
| if (void 0 === process.env.NODE_ENV) process.env.NODE_ENV = 'string' == typeof options.nodeEnv ? options.nodeEnv : defaultEnv; | ||
| } | ||
| async function runBuild(cli, options) { | ||
| setDefaultNodeEnv(options, 'production'); | ||
| normalizeCommonOptions(options, 'build'); | ||
| const logger = cli.getLogger(); | ||
| let createJsonStringifyStream; | ||
| if (options.json) { | ||
| const jsonExt = await import("./json-ext.js").then(__webpack_require__.t.bind(__webpack_require__, "../../node_modules/.pnpm/@discoveryjs+json-ext@0.5.7/node_modules/@discoveryjs/json-ext/src/index.js", 23)); | ||
| createJsonStringifyStream = jsonExt.default.stringifyStream; | ||
| } | ||
| const errorHandler = (error, stats)=>{ | ||
| if (error) { | ||
| logger.error(error); | ||
| process.exit(2); | ||
| } | ||
| if (stats?.hasErrors()) process.exitCode = 1; | ||
| if (!compiler || !stats) return; | ||
| const getStatsOptions = ()=>{ | ||
| if (cli.isMultipleCompiler(compiler)) return { | ||
| children: compiler.compilers.map((item)=>item.options ? item.options.stats : void 0) | ||
| }; | ||
| return compiler.options?.stats; | ||
| }; | ||
| const statsOptions = getStatsOptions(); | ||
| if (options.json && createJsonStringifyStream) { | ||
| const handleWriteError = (error)=>{ | ||
| logger.error(error); | ||
| process.exit(2); | ||
| }; | ||
| if (true === options.json) createJsonStringifyStream(stats.toJson(statsOptions)).on('error', handleWriteError).pipe(process.stdout).on('error', handleWriteError).on('close', ()=>process.stdout.write('\n')); | ||
| else if ('string' == typeof options.json) createJsonStringifyStream(stats.toJson(statsOptions)).on('error', handleWriteError).pipe(node_fs.createWriteStream(options.json)).on('error', handleWriteError).on('close', ()=>{ | ||
| process.stderr.write(`[rspack-cli] ${cli.colors.green(`stats are successfully stored as json to ${options.json}`)}\n`); | ||
| }); | ||
| } else { | ||
| const printedStats = stats.toString(statsOptions); | ||
| if (printedStats) logger.raw(printedStats); | ||
| } | ||
| }; | ||
| const userOption = await cli.buildCompilerConfig(options, 'build'); | ||
| const compiler = await cli.createCompiler(userOption, errorHandler); | ||
| if (!compiler || cli.isWatch(compiler)) return; | ||
| compiler.run((error, stats)=>{ | ||
| compiler.close((closeErr)=>{ | ||
| if (closeErr) logger.error(closeErr); | ||
| errorHandler(error, stats); | ||
| }); | ||
| }); | ||
| } | ||
| class BuildCommand { | ||
| async apply(cli) { | ||
| const command = cli.program.command('', 'run the Rspack build').alias('build').alias('bundle').alias('b'); | ||
| commonOptionsForBuildAndServe(commonOptions(command)).option('--json [path]', 'emit stats json'); | ||
| command.action(cli.wrapAction(async (options)=>{ | ||
| await runBuild(cli, options); | ||
| })); | ||
| } | ||
| } | ||
| class PreviewCommand { | ||
| async apply(cli) { | ||
| const command = cli.program.command('preview [dir]', 'run the Rspack server for build output').alias('p'); | ||
| commonOptions(command).option('--public-path <path>', 'static resource server path').option('--port <port>', 'preview server port').option('--host <host>', 'preview server host').option('--open', 'open browser').option('--server <config>', 'Configuration items for the server.'); | ||
| command.action(cli.wrapAction(async (dir, options)=>{ | ||
| setDefaultNodeEnv(options, 'production'); | ||
| normalizeCommonOptions(options, 'preview'); | ||
| let RspackDevServer; | ||
| try { | ||
| const devServerModule = await import("@rspack/dev-server"); | ||
| RspackDevServer = devServerModule.RspackDevServer; | ||
| } catch (error) { | ||
| const logger = cli.getLogger(); | ||
| if (error?.code === 'MODULE_NOT_FOUND' || error?.code === 'ERR_MODULE_NOT_FOUND') logger.error('The "@rspack/dev-server" package is required to use the preview command.\nPlease install it by running:\n pnpm add -D @rspack/dev-server\n or\n npm install -D @rspack/dev-server'); | ||
| else logger.error('Failed to load "@rspack/dev-server":\n' + (error?.message || String(error))); | ||
| process.exit(1); | ||
| } | ||
| let { config } = await cli.loadConfig(options); | ||
| config = await getPreviewConfig(config, options, dir); | ||
| if (!Array.isArray(config)) config = [ | ||
| config | ||
| ]; | ||
| const singleConfig = config.find((item)=>item.devServer) || config[0]; | ||
| const devServerOptions = singleConfig.devServer; | ||
| try { | ||
| const compiler = rspack({ | ||
| entry: {} | ||
| }); | ||
| if (!compiler) return; | ||
| const server = new RspackDevServer(devServerOptions, compiler); | ||
| await server.start(); | ||
| } catch (error) { | ||
| const logger = cli.getLogger(); | ||
| logger.error(error); | ||
| process.exit(2); | ||
| } | ||
| })); | ||
| } | ||
| } | ||
| async function getPreviewConfig(item, options, dir) { | ||
| const DEFAULT_ROOT = 'dist'; | ||
| const internalPreviewConfig = async (item)=>{ | ||
| const devServer = false === item.devServer ? void 0 : item.devServer; | ||
| item.devServer = { | ||
| static: { | ||
| directory: dir ? node_path.join(item.context ?? process.cwd(), dir) : item.output?.path ?? node_path.join(item.context ?? process.cwd(), DEFAULT_ROOT), | ||
| publicPath: options.publicPath ?? '/' | ||
| }, | ||
| hot: false, | ||
| port: options.port ?? devServer?.port ?? 8080, | ||
| proxy: devServer?.proxy, | ||
| host: options.host ?? devServer?.host, | ||
| open: options.open ?? devServer?.open, | ||
| server: options.server ?? devServer?.server, | ||
| historyApiFallback: devServer?.historyApiFallback | ||
| }; | ||
| return item; | ||
| }; | ||
| if (Array.isArray(item)) return Promise.all(item.map(internalPreviewConfig)); | ||
| return internalPreviewConfig(item); | ||
| } | ||
| function normalizeHotOption(value) { | ||
| if ('false' === value) return false; | ||
| if ('true' === value) return true; | ||
| return value; | ||
| } | ||
| class ServeCommand { | ||
| async apply(cli) { | ||
| const command = cli.program.command('serve', 'run the rspack dev server.').alias('server').alias('s').alias('dev'); | ||
| commonOptionsForBuildAndServe(commonOptions(command)).option('--hot [mode]', 'enables hot module replacement').option('--port <port>', 'allows to specify a port to use').option('--host <host>', 'allows to specify a hostname to use').option('--open [value]', 'open browser on server start; pass --no-open to disable, or --open <url> to open a specific URL'); | ||
| command.action(cli.wrapAction(async (cliOptions)=>{ | ||
| setDefaultNodeEnv(cliOptions, 'development'); | ||
| normalizeCommonOptions(cliOptions, 'serve'); | ||
| cliOptions.hot = normalizeHotOption(cliOptions.hot); | ||
| let RspackDevServer; | ||
| try { | ||
| const devServerModule = await import("@rspack/dev-server"); | ||
| RspackDevServer = devServerModule.RspackDevServer; | ||
| } catch (error) { | ||
| const logger = cli.getLogger(); | ||
| if (error?.code === 'MODULE_NOT_FOUND' || error?.code === 'ERR_MODULE_NOT_FOUND') logger.error('The "@rspack/dev-server" package is required to use the serve command.\nPlease install it by running:\n pnpm add -D @rspack/dev-server\n or\n npm install -D @rspack/dev-server'); | ||
| else logger.error('Failed to load "@rspack/dev-server":\n' + (error?.message || String(error))); | ||
| process.exit(1); | ||
| } | ||
| const userConfig = await cli.buildCompilerConfig(cliOptions, 'serve'); | ||
| const compiler = await cli.createCompiler(userConfig); | ||
| if (!compiler) return; | ||
| const isMultiCompiler = cli.isMultipleCompiler(compiler); | ||
| const compilers = isMultiCompiler ? compiler.compilers : [ | ||
| compiler | ||
| ]; | ||
| const userConfigs = isMultiCompiler ? userConfig : [ | ||
| userConfig | ||
| ]; | ||
| const possibleCompilers = compilers.filter((compiler)=>compiler.options.devServer); | ||
| const usedPorts = []; | ||
| const servers = []; | ||
| const compilerForDevServer = possibleCompilers.length > 0 ? possibleCompilers[0] : compilers[0]; | ||
| for (const [index, compiler] of compilers.entries()){ | ||
| const userConfig = userConfigs[index]; | ||
| const existingDevServer = compiler.options.devServer; | ||
| if (false === existingDevServer) continue; | ||
| const devServer = existingDevServer ?? (compiler.options.devServer = {}); | ||
| const isWebAppOnly = compiler.platform.web && !compiler.platform.node && !compiler.platform.nwjs && !compiler.platform.electron && !compiler.platform.webworker; | ||
| if (isWebAppOnly && void 0 === userConfig.lazyCompilation) compiler.options.lazyCompilation = { | ||
| imports: true, | ||
| entries: false | ||
| }; | ||
| devServer.hot = cliOptions.hot ?? devServer.hot ?? true; | ||
| if (false !== devServer.client) { | ||
| if (true === devServer.client || null == devServer.client) devServer.client = {}; | ||
| devServer.client = { | ||
| overlay: { | ||
| errors: true, | ||
| warnings: false | ||
| }, | ||
| ...devServer.client | ||
| }; | ||
| } | ||
| } | ||
| const compilerForDevServerOptions = compilerForDevServer.options.devServer; | ||
| const devServerOptions = false === compilerForDevServerOptions ? {} : compilerForDevServerOptions ?? (compilerForDevServer.options.devServer = {}); | ||
| const { setupMiddlewares } = devServerOptions; | ||
| const lazyCompileMiddleware = rspack.lazyCompilationMiddleware(compiler); | ||
| devServerOptions.setupMiddlewares = (middlewares, server)=>{ | ||
| let finalMiddlewares = middlewares; | ||
| if (setupMiddlewares) finalMiddlewares = setupMiddlewares(finalMiddlewares, server); | ||
| return [ | ||
| ...finalMiddlewares, | ||
| lazyCompileMiddleware | ||
| ]; | ||
| }; | ||
| devServerOptions.hot = cliOptions.hot ?? devServerOptions.hot ?? true; | ||
| devServerOptions.host = cliOptions.host || devServerOptions.host; | ||
| devServerOptions.port = cliOptions.port ?? devServerOptions.port; | ||
| if (void 0 !== cliOptions.open) devServerOptions.open = cliOptions.open; | ||
| if (false !== devServerOptions.client) { | ||
| if (true === devServerOptions.client || null == devServerOptions.client) devServerOptions.client = {}; | ||
| devServerOptions.client = { | ||
| overlay: { | ||
| errors: true, | ||
| warnings: false | ||
| }, | ||
| ...devServerOptions.client | ||
| }; | ||
| } | ||
| if (devServerOptions.port) { | ||
| const portNumber = Number(devServerOptions.port); | ||
| if (!Number.isNaN(portNumber)) { | ||
| if (usedPorts.find((port)=>portNumber === port)) throw new Error('Unique ports must be specified for each devServer option in your rspack configuration. Alternatively, run only 1 devServer config using the --config-name flag to specify your desired config.'); | ||
| usedPorts.push(portNumber); | ||
| } | ||
| } | ||
| try { | ||
| const server = new RspackDevServer(devServerOptions, compiler); | ||
| await server.start(); | ||
| servers.push(server); | ||
| } catch (error) { | ||
| const logger = cli.getLogger(); | ||
| logger.error(error); | ||
| process.exit(2); | ||
| } | ||
| })); | ||
| } | ||
| } | ||
| const DEFAULT_EXTENSIONS = [ | ||
| '.ts', | ||
| '.js', | ||
| '.mts', | ||
| '.mjs', | ||
| '.cts', | ||
| '.cjs' | ||
| ]; | ||
| const findConfig = (basePath)=>DEFAULT_EXTENSIONS.map((ext)=>basePath + ext).find(node_fs.existsSync); | ||
| const utils_findConfig = findConfig; | ||
| const loadConfig_require = createRequire(import.meta.url); | ||
| const loadConfig_DEFAULT_CONFIG_NAME = 'rspack.config'; | ||
| const JS_CONFIG_EXTENSION_REGEXP = /\.(?:js|mjs|cjs)$/; | ||
| const CONFIG_LOADER_VALUES = [ | ||
| 'auto', | ||
| 'jiti', | ||
| 'native' | ||
| ]; | ||
| const PREBUNDLED_JITI_PATH = new URL('../compiled/jiti/index.js', import.meta.url).href; | ||
| const supportsNativeTypeScript = ()=>{ | ||
| const features = process.features; | ||
| return Boolean(features.typescript || process.versions.bun || process.versions.deno); | ||
| }; | ||
| const normalizeConfigLoader = (configLoader)=>{ | ||
| const normalizedLoader = configLoader ?? 'auto'; | ||
| if (CONFIG_LOADER_VALUES.includes(normalizedLoader)) return normalizedLoader; | ||
| throw new Error(`config loader "${normalizedLoader}" is not supported. Expected one of: ${CONFIG_LOADER_VALUES.join(', ')}.`); | ||
| }; | ||
| const resolveDefaultExport = (result)=>result && 'object' == typeof result && 'default' in result ? result.default : result; | ||
| const loadConfigWithNativeLoader = async (configPath)=>{ | ||
| const configFileURL = pathToFileURL(configPath).href; | ||
| const loadedModule = await import(`${configFileURL}?t=${Date.now()}`); | ||
| return resolveDefaultExport(loadedModule); | ||
| }; | ||
| let jitiInstancePromise; | ||
| const getJiti = async ()=>{ | ||
| if (!jitiInstancePromise) jitiInstancePromise = import(PREBUNDLED_JITI_PATH).then((module)=>{ | ||
| const createJiti = 'createJiti' in module ? module.createJiti : module.default; | ||
| return createJiti(import.meta.filename, { | ||
| moduleCache: false, | ||
| interopDefault: true, | ||
| nativeModules: [ | ||
| "typescript" | ||
| ] | ||
| }); | ||
| }); | ||
| return jitiInstancePromise; | ||
| }; | ||
| const loadConfigWithJiti = async (configPath)=>{ | ||
| const jiti = await getJiti(); | ||
| return jiti.import(configPath, { | ||
| default: true | ||
| }); | ||
| }; | ||
| const loadConfigByPath = async (configPath, options)=>{ | ||
| const configLoader = normalizeConfigLoader(options.configLoader); | ||
| const useNative = Boolean('native' === configLoader || 'auto' === configLoader && supportsNativeTypeScript()); | ||
| if (useNative || JS_CONFIG_EXTENSION_REGEXP.test(configPath)) try { | ||
| return await loadConfigWithNativeLoader(configPath); | ||
| } catch (error) { | ||
| if ('native' === configLoader) throw error; | ||
| } | ||
| return loadConfigWithJiti(configPath); | ||
| }; | ||
| const isConfigObject = (value)=>Boolean(value) && 'object' == typeof value && !Array.isArray(value); | ||
| const isRspackConfig = (value)=>Array.isArray(value) || isConfigObject(value); | ||
| const resolveRspackConfigExport = async (configExport, options)=>{ | ||
| let loadedConfig = configExport; | ||
| if ('function' == typeof loadedConfig) { | ||
| let functionResult = loadedConfig(options.env, options); | ||
| if ('function' == typeof functionResult.then) functionResult = await functionResult; | ||
| if (void 0 === functionResult) throw new Error('[rspack-cli:loadConfig] The config function must return a config object.'); | ||
| loadedConfig = functionResult; | ||
| } | ||
| if (!isRspackConfig(loadedConfig)) throw new Error(`[rspack-cli:loadConfig] The config must be an object, an array, or a function that returns one, get ${String(loadedConfig)}`); | ||
| return loadedConfig; | ||
| }; | ||
| const checkIsMultiRspackOptions = (config)=>Array.isArray(config); | ||
| async function loadExtendedConfig(config, configPath, cwd, options) { | ||
| if (checkIsMultiRspackOptions(config)) { | ||
| const resultPathMap = new WeakMap(); | ||
| const extendedConfigs = await Promise.all(config.map(async (item)=>{ | ||
| const { config, pathMap } = await loadExtendedConfig(item, configPath, cwd, options); | ||
| resultPathMap.set(config, pathMap.get(config)); | ||
| return config; | ||
| })); | ||
| extendedConfigs.parallelism = config.parallelism; | ||
| return { | ||
| config: extendedConfigs, | ||
| pathMap: resultPathMap | ||
| }; | ||
| } | ||
| const pathMap = new WeakMap(); | ||
| pathMap.set(config, [ | ||
| configPath | ||
| ]); | ||
| if (!('extends' in config) || !config.extends) return { | ||
| config, | ||
| pathMap | ||
| }; | ||
| const extendsList = Array.isArray(config.extends) ? config.extends : [ | ||
| config.extends | ||
| ]; | ||
| const { extends: _, ...configWithoutExtends } = config; | ||
| const baseDir = node_path.dirname(configPath); | ||
| let resultConfig = configWithoutExtends; | ||
| pathMap.set(resultConfig, [ | ||
| configPath | ||
| ]); | ||
| for (const extendPath of extendsList){ | ||
| let resolvedPath; | ||
| if (extendPath.startsWith('.') || extendPath.startsWith('/') || extendPath.includes(':\\')) { | ||
| resolvedPath = node_path.resolve(baseDir, extendPath); | ||
| if (!node_path.extname(resolvedPath)) { | ||
| const foundConfig = utils_findConfig(resolvedPath); | ||
| if (foundConfig) resolvedPath = foundConfig; | ||
| else throw new Error(`Extended configuration file "${resolvedPath}" not found.`); | ||
| } | ||
| } else try { | ||
| resolvedPath = loadConfig_require.resolve(extendPath, { | ||
| paths: [ | ||
| baseDir, | ||
| cwd | ||
| ] | ||
| }); | ||
| } catch { | ||
| throw new Error(`Cannot find module '${extendPath}' to extend from.`); | ||
| } | ||
| if (!node_fs.existsSync(resolvedPath)) throw new Error(`Extended configuration file "${resolvedPath}" not found.`); | ||
| const loadedConfig = await loadConfigByPath(resolvedPath, options); | ||
| const resolvedConfig = await resolveRspackConfigExport(loadedConfig, options); | ||
| const { config: extendedConfig, pathMap: extendedPathMap } = await loadExtendedConfig(resolvedConfig, resolvedPath, cwd, options); | ||
| const configPaths = [ | ||
| ...pathMap.get(resultConfig) || [], | ||
| ...extendedPathMap.get(extendedConfig) || [] | ||
| ]; | ||
| resultConfig = rspack.util.cleverMerge(extendedConfig, resultConfig); | ||
| pathMap.set(resultConfig, configPaths); | ||
| } | ||
| return { | ||
| config: resultConfig, | ||
| pathMap | ||
| }; | ||
| } | ||
| async function loadRspackConfig(options, cwd = process.cwd()) { | ||
| let configPath = ''; | ||
| if (options.config) { | ||
| configPath = node_path.resolve(cwd, options.config); | ||
| if (!node_fs.existsSync(configPath)) throw new Error(`config file "${configPath}" not found.`); | ||
| } else { | ||
| const defaultConfig = utils_findConfig(node_path.resolve(cwd, loadConfig_DEFAULT_CONFIG_NAME)); | ||
| if (!defaultConfig) return null; | ||
| configPath = defaultConfig; | ||
| } | ||
| const loadedConfig = await loadConfigByPath(configPath, options); | ||
| return { | ||
| loadedConfig, | ||
| configPath | ||
| }; | ||
| } | ||
| function isEnvColorSupported() { | ||
| if ("u" < typeof process) return false; | ||
| const p = process; | ||
| const argv = p.argv ?? []; | ||
| const env = p.env ?? {}; | ||
| return !('NO_COLOR' in env || argv.includes('--no-color')) && ('FORCE_COLOR' in env || argv.includes('--color') || 'win32' === p.platform || p.stdout?.isTTY && 'dumb' !== env.TERM || 'CI' in env); | ||
| } | ||
| function createAnsiFormatter(open, close, replace = open) { | ||
| const closeLength = close.length; | ||
| return (input)=>{ | ||
| const string = String(input); | ||
| let index = string.indexOf(close, open.length); | ||
| if (-1 === index) return open + string + close; | ||
| let result = ''; | ||
| let cursor = 0; | ||
| do { | ||
| result += string.substring(cursor, index) + replace; | ||
| cursor = index + closeLength; | ||
| index = string.indexOf(close, cursor); | ||
| }while (-1 !== index); | ||
| return open + result + string.substring(cursor) + close; | ||
| }; | ||
| } | ||
| class RspackCLI { | ||
| colors; | ||
| program; | ||
| _actionPromise; | ||
| constructor(){ | ||
| const program = cac('rspack'); | ||
| this.colors = this.createColors(); | ||
| this.program = program; | ||
| program.help(); | ||
| program.version("2.0.1"); | ||
| } | ||
| wrapAction(fn) { | ||
| return (...args)=>{ | ||
| this._actionPromise = fn(...args); | ||
| return this._actionPromise; | ||
| }; | ||
| } | ||
| async buildCompilerConfig(options, rspackCommand) { | ||
| let { config, pathMap } = await this.loadConfig(options); | ||
| config = await this.buildConfig(config, pathMap, options, rspackCommand); | ||
| return config; | ||
| } | ||
| async createCompiler(config, callback) { | ||
| const isWatch = Array.isArray(config) ? config.some((i)=>i.watch) : config.watch; | ||
| let compiler; | ||
| try { | ||
| compiler = rspack(config, isWatch ? callback : void 0); | ||
| if (!isWatch && compiler) compiler.unsafeFastDrop = true; | ||
| } catch (e) { | ||
| if (e instanceof rspack.ValidationError) { | ||
| this.getLogger().error(e.message); | ||
| process.exit(2); | ||
| } else if (e instanceof Error) { | ||
| if ('function' == typeof callback) callback(e); | ||
| else this.getLogger().error(e); | ||
| return null; | ||
| } | ||
| throw e; | ||
| } | ||
| return compiler; | ||
| } | ||
| createColors(useColor) { | ||
| const envSupported = isEnvColorSupported(); | ||
| const enabled = useColor ?? envSupported; | ||
| if (!enabled) { | ||
| const passthrough = (text)=>String(text); | ||
| return { | ||
| isColorSupported: false, | ||
| red: passthrough, | ||
| yellow: passthrough, | ||
| cyan: passthrough, | ||
| green: passthrough | ||
| }; | ||
| } | ||
| return { | ||
| isColorSupported: true, | ||
| red: createAnsiFormatter('\x1b[31m', '\x1b[39m'), | ||
| green: createAnsiFormatter('\x1b[32m', '\x1b[39m'), | ||
| yellow: createAnsiFormatter('\x1b[33m', '\x1b[39m'), | ||
| cyan: createAnsiFormatter('\x1b[36m', '\x1b[39m') | ||
| }; | ||
| } | ||
| getLogger() { | ||
| return { | ||
| error: (val)=>console.error(`[rspack-cli] ${this.colors.red(node_util.format(val))}`), | ||
| warn: (val)=>console.warn(`[rspack-cli] ${this.colors.yellow(val)}`), | ||
| info: (val)=>console.info(`[rspack-cli] ${this.colors.cyan(val)}`), | ||
| success: (val)=>console.log(`[rspack-cli] ${this.colors.green(val)}`), | ||
| log: (val)=>console.log(`[rspack-cli] ${val}`), | ||
| raw: (val)=>console.log(val) | ||
| }; | ||
| } | ||
| async run(argv) { | ||
| await this.registerCommands(); | ||
| this.program.parse(argv); | ||
| if (this._actionPromise) await this._actionPromise; | ||
| } | ||
| async registerCommands() { | ||
| const builtinCommands = [ | ||
| new BuildCommand(), | ||
| new ServeCommand(), | ||
| new PreviewCommand() | ||
| ]; | ||
| for (const command of builtinCommands)await command.apply(this); | ||
| } | ||
| async buildConfig(item, pathMap, options, command) { | ||
| const isBuild = 'build' === command; | ||
| const isServe = 'serve' === command; | ||
| const internalBuildConfig = async (item)=>{ | ||
| if (options.entry) item.entry = { | ||
| main: options.entry.map((x)=>node_path.resolve(process.cwd(), x))[0] | ||
| }; | ||
| item.output = item.output || {}; | ||
| if (options.outputPath) item.output.path = node_path.resolve(process.cwd(), options.outputPath); | ||
| if (process.env.RSPACK_PROFILE) { | ||
| const { applyProfile } = await import("./profile.js"); | ||
| await applyProfile(process.env.RSPACK_PROFILE, process.env.RSPACK_TRACE_LAYER, process.env.RSPACK_TRACE_OUTPUT); | ||
| } | ||
| if (options.watch) item.watch = options.watch; | ||
| if (!item.mode) item.mode = isBuild ? 'production' : 'development'; | ||
| if (options.mode) item.mode = options.mode; | ||
| if (void 0 === item.devtool) item.devtool = isBuild ? false : 'cheap-module-source-map'; | ||
| if (void 0 !== options.devtool) item.devtool = options.devtool; | ||
| if (isServe) { | ||
| const installed = (item.plugins ||= []).find((item)=>item instanceof rspack.ProgressPlugin); | ||
| if (!installed) (item.plugins ??= []).push(new rspack.ProgressPlugin()); | ||
| } | ||
| const cacheOptions = item.cache; | ||
| if ('object' == typeof cacheOptions && 'persistent' === cacheOptions.type) { | ||
| const configPaths = pathMap.get(item); | ||
| if (configPaths) cacheOptions.buildDependencies = [ | ||
| ...configPaths, | ||
| ...cacheOptions.buildDependencies || [] | ||
| ]; | ||
| } | ||
| if (void 0 === item.stats) item.stats = { | ||
| preset: 'errors-warnings', | ||
| timings: true | ||
| }; | ||
| else if ('boolean' == typeof item.stats) item.stats = item.stats ? { | ||
| preset: 'normal' | ||
| } : { | ||
| preset: 'none' | ||
| }; | ||
| else if ('string' == typeof item.stats) item.stats = { | ||
| preset: item.stats | ||
| }; | ||
| return item; | ||
| }; | ||
| if (Array.isArray(item)) return Promise.all(item.map(internalBuildConfig)); | ||
| return internalBuildConfig(item); | ||
| } | ||
| async loadConfig(options) { | ||
| const config = await loadRspackConfig(options); | ||
| if (!config) return { | ||
| config: this.filterConfig(options, {}), | ||
| pathMap: new WeakMap() | ||
| }; | ||
| const { loadedConfig, configPath } = config; | ||
| const resolvedConfig = await resolveRspackConfigExport(loadedConfig, options); | ||
| const { config: extendedConfig, pathMap } = await loadExtendedConfig(resolvedConfig, configPath, process.cwd(), options); | ||
| return { | ||
| config: this.filterConfig(options, extendedConfig), | ||
| pathMap | ||
| }; | ||
| } | ||
| filterConfig(options, config) { | ||
| if (options.configName) { | ||
| const notFoundConfigNames = []; | ||
| config = options.configName.map((configName)=>{ | ||
| let found; | ||
| found = Array.isArray(config) ? config.find((options)=>options.name === configName) : config.name === configName ? config : void 0; | ||
| if (!found) notFoundConfigNames.push(configName); | ||
| return found; | ||
| }); | ||
| if (notFoundConfigNames.length > 0) { | ||
| this.getLogger().error(notFoundConfigNames.map((configName)=>`Configuration with the name "${configName}" was not found.`).join(' ')); | ||
| process.exit(2); | ||
| } | ||
| } | ||
| return config; | ||
| } | ||
| isMultipleCompiler(compiler) { | ||
| return Boolean(compiler.compilers); | ||
| } | ||
| isWatch(compiler) { | ||
| return Boolean(this.isMultipleCompiler(compiler) ? compiler.compilers.some((compiler)=>compiler.options.watch) : compiler.options.watch); | ||
| } | ||
| } | ||
| function defineConfig(config) { | ||
| return config; | ||
| } | ||
| function definePlugin(plugin) { | ||
| return plugin; | ||
| } | ||
| export { __webpack_require__temp as __webpack_require__, RspackCLI, defineConfig, definePlugin }; |
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 7 instances in 1 package
High entropy strings
Supply chain riskContains high entropy strings. This could be a sign of encrypted data, leaked secrets or obfuscated code.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 7 instances in 1 package
High entropy strings
Supply chain riskContains high entropy strings. This could be a sign of encrypted data, leaked secrets or obfuscated code.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
56
-1.75%1757302
-1.78%15
-6.25%8195
-7.12%