@rspack/cli 2.0.2 → 2.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/rspack.js CHANGED
@@ -12,9 +12,6 @@ if (enableCompileCache) {
12
12
  }
13
13
  }
14
14
 
15
- // make it easier to identify the process via activity monitor or other tools
16
- process.title = 'rspack-node';
17
-
18
15
  import { RspackCLI } from '../dist/index.js';
19
16
 
20
17
  async function runCLI() {
package/dist/index.d.ts CHANGED
@@ -256,7 +256,7 @@ export declare class RspackCLI {
256
256
  */
257
257
  wrapAction<T extends (...args: any[]) => Promise<void>>(fn: T): T;
258
258
  buildCompilerConfig(options: CommonOptionsForBuildAndServe, rspackCommand: Command_2): Promise<RspackOptions | MultiRspackOptions>;
259
- createCompiler(config: RspackOptions | MultiRspackOptions, callback?: (e: Error | null, res?: Stats | MultiStats) => void): Promise<MultiCompiler | Compiler | null>;
259
+ createCompiler(config: RspackOptions | MultiRspackOptions, callback?: (e: Error | null, res?: Stats | MultiStats) => void): Compiler | MultiCompiler | null;
260
260
  private createColors;
261
261
  getLogger(): RspackCLILogger;
262
262
  run(argv: string[]): Promise<void>;
@@ -289,7 +289,7 @@ export declare interface RspackCLILogger {
289
289
  }
290
290
 
291
291
  export declare interface RspackCommand {
292
- apply(cli: RspackCLI): Promise<void>;
292
+ apply(cli: RspackCLI): void | Promise<void>;
293
293
  }
294
294
 
295
295
  declare type RspackConfigAsyncFn = (env: Record<string, any>, argv: Record<string, any>) => Promise<RspackOptions | MultiRspackOptions>;
package/dist/index.js CHANGED
@@ -2,9 +2,8 @@ import node_path from "node:path";
2
2
  import node_util from "node:util";
3
3
  import { rspack } from "@rspack/core";
4
4
  import node_fs from "node:fs";
5
- import { Readable } from "node:stream";
6
5
  import { createRequire } from "node:module";
7
- import { pathToFileURL } from "node:url";
6
+ import { fileURLToPath, pathToFileURL } from "node:url";
8
7
  function toArr(any) {
9
8
  return null == any ? [] : Array.isArray(any) ? any : [
10
9
  any
@@ -593,7 +592,7 @@ const normalizeCommonOptions = (options, action)=>{
593
592
  }
594
593
  if ('devtool' in options) options.devtool = normalizeDevtoolOption(options.devtool);
595
594
  };
596
- 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', {
595
+ const commonOptionsForBuildAndServe = (command)=>command.option('-d, --devtool <value>', 'set source map style for debugging. Use `false` to disable source maps.').option('--entry <entry>', 'entry file', {
597
596
  type: [
598
597
  String
599
598
  ],
@@ -633,8 +632,9 @@ async function runBuild(cli, options) {
633
632
  const logger = cli.getLogger();
634
633
  let createJsonStringifyStream;
635
634
  if (options.json) {
635
+ const stream = await import("node:stream");
636
636
  const jsonExt = await import("./json-ext.js");
637
- createJsonStringifyStream = (value)=>Readable.from(jsonExt.stringifyChunked(value));
637
+ createJsonStringifyStream = (value)=>stream.Readable.from(jsonExt.stringifyChunked(value));
638
638
  }
639
639
  const errorHandler = (error, stats)=>{
640
640
  if (error) {
@@ -675,7 +675,7 @@ async function runBuild(cli, options) {
675
675
  });
676
676
  }
677
677
  class BuildCommand {
678
- async apply(cli) {
678
+ apply(cli) {
679
679
  const command = cli.program.command('', 'run the Rspack build').alias('build').alias('bundle').alias('b');
680
680
  commonOptionsForBuildAndServe(commonOptions(command)).option('--json [path]', 'emit stats json');
681
681
  command.action(cli.wrapAction(async (options)=>{
@@ -684,7 +684,7 @@ class BuildCommand {
684
684
  }
685
685
  }
686
686
  class PreviewCommand {
687
- async apply(cli) {
687
+ apply(cli) {
688
688
  const command = cli.program.command('preview [dir]', 'run the Rspack server for build output').alias('p');
689
689
  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.');
690
690
  command.action(cli.wrapAction(async (dir, options)=>{
@@ -724,7 +724,7 @@ class PreviewCommand {
724
724
  }
725
725
  async function getPreviewConfig(item, options, dir) {
726
726
  const DEFAULT_ROOT = 'dist';
727
- const internalPreviewConfig = async (item)=>{
727
+ const internalPreviewConfig = (item)=>{
728
728
  const devServer = false === item.devServer ? void 0 : item.devServer;
729
729
  item.devServer = {
730
730
  static: {
@@ -750,7 +750,7 @@ function normalizeHotOption(value) {
750
750
  return value;
751
751
  }
752
752
  class ServeCommand {
753
- async apply(cli) {
753
+ apply(cli) {
754
754
  const command = cli.program.command('serve', 'run the rspack dev server.').alias('server').alias('s').alias('dev');
755
755
  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');
756
756
  command.action(cli.wrapAction(async (cliOptions)=>{
@@ -848,6 +848,100 @@ class ServeCommand {
848
848
  }));
849
849
  }
850
850
  }
851
+ function mergeWith(objects, customizer) {
852
+ const [first, ...rest] = objects;
853
+ let ret = first;
854
+ rest.forEach((a)=>{
855
+ ret = mergeTo(ret, a, customizer);
856
+ });
857
+ return ret;
858
+ }
859
+ function mergeTo(a, b, customizer) {
860
+ const ret = {};
861
+ Object.keys(a).concat(Object.keys(b)).forEach((k)=>{
862
+ const v = customizer(a[k], b[k], k);
863
+ ret[k] = void 0 === v ? a[k] : v;
864
+ });
865
+ return ret;
866
+ }
867
+ const merge_with = mergeWith;
868
+ function isRegex(o) {
869
+ return o instanceof RegExp;
870
+ }
871
+ function isPlainObject(value) {
872
+ if ('[object Object]' !== Object.prototype.toString.call(value)) return false;
873
+ const proto = Object.getPrototypeOf(value);
874
+ if (null === proto) return true;
875
+ let baseProto = proto;
876
+ while(null !== Object.getPrototypeOf(baseProto))baseProto = Object.getPrototypeOf(baseProto);
877
+ return proto === baseProto;
878
+ }
879
+ function isUndefined(value) {
880
+ return void 0 === value;
881
+ }
882
+ function isPromiseLike(value) {
883
+ return null !== value && ('object' == typeof value || 'function' == typeof value) && 'function' == typeof value.then;
884
+ }
885
+ const isArray = Array.isArray;
886
+ function joinArrays({ customizeArray, customizeObject, key } = {}) {
887
+ return function _joinArrays(a, b, k) {
888
+ const newKey = key ? `${key}.${k}` : k;
889
+ if ('function' == typeof a && 'function' == typeof b) return (...args)=>_joinArrays(a(...args), b(...args), k);
890
+ if (isArray(a) && isArray(b)) {
891
+ const customResult = customizeArray && customizeArray(a, b, newKey);
892
+ return customResult || [
893
+ ...a,
894
+ ...b
895
+ ];
896
+ }
897
+ if (isRegex(b)) return b;
898
+ if (isPlainObject(a) && isPlainObject(b)) {
899
+ const customResult = customizeObject && customizeObject(a, b, newKey);
900
+ return customResult || merge_with([
901
+ a,
902
+ b
903
+ ], joinArrays({
904
+ customizeArray,
905
+ customizeObject,
906
+ key: newKey
907
+ }));
908
+ }
909
+ if (isPlainObject(b)) return merge_with([
910
+ {},
911
+ b
912
+ ], joinArrays({
913
+ customizeArray,
914
+ customizeObject,
915
+ key: newKey
916
+ }));
917
+ if (isArray(b)) return [
918
+ ...b
919
+ ];
920
+ return b;
921
+ };
922
+ }
923
+ function merge(firstConfiguration, ...configurations) {
924
+ return mergeWithCustomize({})(firstConfiguration, ...configurations);
925
+ }
926
+ function mergeWithCustomize(options) {
927
+ return function(firstConfiguration, ...configurations) {
928
+ if (isUndefined(firstConfiguration) || configurations.some(isUndefined)) throw new TypeError('Merging undefined is not supported');
929
+ if (isPromiseLike(firstConfiguration)) throw new TypeError('Promises are not supported');
930
+ if (!firstConfiguration) return {};
931
+ if (0 === configurations.length) {
932
+ if (Array.isArray(firstConfiguration)) {
933
+ if (0 === firstConfiguration.length) return {};
934
+ if (firstConfiguration.some(isUndefined)) throw new TypeError('Merging undefined is not supported');
935
+ if (isPromiseLike(firstConfiguration[0])) throw new TypeError('Promises are not supported');
936
+ return merge_with(firstConfiguration, joinArrays(options));
937
+ }
938
+ return firstConfiguration;
939
+ }
940
+ return merge_with([
941
+ firstConfiguration
942
+ ].concat(configurations), joinArrays(options));
943
+ };
944
+ }
851
945
  const DEFAULT_EXTENSIONS = [
852
946
  '.ts',
853
947
  '.js',
@@ -926,11 +1020,13 @@ const resolveRspackConfigExport = async (configExport, options)=>{
926
1020
  return loadedConfig;
927
1021
  };
928
1022
  const checkIsMultiRspackOptions = (config)=>Array.isArray(config);
929
- async function loadExtendedConfig(config, configPath, cwd, options) {
1023
+ async function loadExtendedConfig(config, configPath, cwd, options, visitedPaths) {
1024
+ const currentVisitedPaths = visitedPaths ?? new Set();
930
1025
  if (checkIsMultiRspackOptions(config)) {
931
1026
  const resultPathMap = new WeakMap();
932
1027
  const extendedConfigs = await Promise.all(config.map(async (item)=>{
933
- const { config, pathMap } = await loadExtendedConfig(item, configPath, cwd, options);
1028
+ const itemVisitedPaths = new Set(currentVisitedPaths);
1029
+ const { config, pathMap } = await loadExtendedConfig(item, configPath, cwd, options, itemVisitedPaths);
934
1030
  resultPathMap.set(config, pathMap.get(config));
935
1031
  return config;
936
1032
  }));
@@ -940,6 +1036,8 @@ async function loadExtendedConfig(config, configPath, cwd, options) {
940
1036
  pathMap: resultPathMap
941
1037
  };
942
1038
  }
1039
+ if (currentVisitedPaths.has(configPath)) throw new Error(`Recursive configuration detected. Config file "${configPath}" extends itself.`);
1040
+ currentVisitedPaths.add(configPath);
943
1041
  const pathMap = new WeakMap();
944
1042
  pathMap.set(config, [
945
1043
  configPath
@@ -959,7 +1057,12 @@ async function loadExtendedConfig(config, configPath, cwd, options) {
959
1057
  ]);
960
1058
  for (const extendPath of extendsList){
961
1059
  let resolvedPath;
962
- if (extendPath.startsWith('.') || extendPath.startsWith('/') || extendPath.includes(':\\')) {
1060
+ if (extendPath.startsWith('file://')) try {
1061
+ resolvedPath = fileURLToPath(extendPath);
1062
+ } catch {
1063
+ throw new Error(`Invalid file URL '${extendPath}' in extends configuration.`);
1064
+ }
1065
+ else if (extendPath.startsWith('.') || extendPath.startsWith('/') || extendPath.includes(':\\')) {
963
1066
  resolvedPath = node_path.resolve(baseDir, extendPath);
964
1067
  if (!node_path.extname(resolvedPath)) {
965
1068
  const foundConfig = utils_findConfig(resolvedPath);
@@ -979,12 +1082,12 @@ async function loadExtendedConfig(config, configPath, cwd, options) {
979
1082
  if (!node_fs.existsSync(resolvedPath)) throw new Error(`Extended configuration file "${resolvedPath}" not found.`);
980
1083
  const loadedConfig = await loadConfigByPath(resolvedPath, options);
981
1084
  const resolvedConfig = await resolveRspackConfigExport(loadedConfig, options);
982
- const { config: extendedConfig, pathMap: extendedPathMap } = await loadExtendedConfig(resolvedConfig, resolvedPath, cwd, options);
1085
+ const { config: extendedConfig, pathMap: extendedPathMap } = await loadExtendedConfig(resolvedConfig, resolvedPath, cwd, options, currentVisitedPaths);
983
1086
  const configPaths = [
984
1087
  ...pathMap.get(resultConfig) || [],
985
1088
  ...extendedPathMap.get(extendedConfig) || []
986
1089
  ];
987
- resultConfig = rspack.util.cleverMerge(extendedConfig, resultConfig);
1090
+ resultConfig = merge(extendedConfig, resultConfig);
988
1091
  pathMap.set(resultConfig, configPaths);
989
1092
  }
990
1093
  return {
@@ -1040,7 +1143,7 @@ class RspackCLI {
1040
1143
  this.colors = this.createColors();
1041
1144
  this.program = program;
1042
1145
  program.help();
1043
- program.version("2.0.2");
1146
+ program.version("2.0.4");
1044
1147
  }
1045
1148
  wrapAction(fn) {
1046
1149
  return (...args)=>{
@@ -1049,11 +1152,11 @@ class RspackCLI {
1049
1152
  };
1050
1153
  }
1051
1154
  async buildCompilerConfig(options, rspackCommand) {
1052
- let { config, pathMap } = await this.loadConfig(options);
1053
- config = await this.buildConfig(config, pathMap, options, rspackCommand);
1155
+ const { config: rawConfig, pathMap } = await this.loadConfig(options);
1156
+ const config = await this.buildConfig(rawConfig, pathMap, options, rspackCommand);
1054
1157
  return config;
1055
1158
  }
1056
- async createCompiler(config, callback) {
1159
+ createCompiler(config, callback) {
1057
1160
  const isWatch = Array.isArray(config) ? config.some((i)=>i.watch) : config.watch;
1058
1161
  let compiler;
1059
1162
  try {
package/dist/profile.js CHANGED
@@ -1,21 +1,25 @@
1
1
  import node_fs from "node:fs";
2
2
  import node_path from "node:path";
3
3
  import { rspack } from "@rspack/core";
4
- const DEFAULT_RUST_TRACE_LAYER = 'perfetto';
4
+ const DEFAULT_RUST_TRACE_LAYER = 'logger';
5
+ const DEFAULT_RUST_TRACE_LOGGER_OUTPUT = 'rspack.log';
6
+ const DEFAULT_RUST_TRACE_PERFETTO_OUTPUT = 'rspack.pftrace';
7
+ function isTerminalTraceOutput(output) {
8
+ return 'stdout' === output || 'stderr' === output;
9
+ }
5
10
  async function applyProfile(filterValue, traceLayer = DEFAULT_RUST_TRACE_LAYER, traceOutput) {
6
11
  const { asyncExitHook } = await import("./exit-hook.js");
7
12
  if ('logger' !== traceLayer && 'perfetto' !== traceLayer) throw new Error(`unsupported trace layer: ${traceLayer}`);
13
+ if (traceOutput && 'perfetto' === traceLayer && isTerminalTraceOutput(traceOutput)) throw new Error('RSPACK_TRACE_OUTPUT=stdout|stderr is only supported for the logger trace layer. The perfetto trace layer requires a file path.');
8
14
  const timestamp = Date.now();
9
15
  const defaultOutputDir = node_path.resolve(`.rspack-profile-${timestamp}-${process.pid}`);
10
16
  if (traceOutput) {
11
- if ('stdout' !== traceOutput && 'stderr' !== traceOutput) traceOutput = node_path.resolve(defaultOutputDir, traceOutput);
17
+ if (!isTerminalTraceOutput(traceOutput)) traceOutput = node_path.resolve(defaultOutputDir, traceOutput);
12
18
  } else {
13
- const defaultRustTracePerfettoOutput = node_path.resolve(defaultOutputDir, 'rspack.pftrace');
14
- const defaultRustTraceLoggerOutput = 'stdout';
15
- const defaultTraceOutput = 'perfetto' === traceLayer ? defaultRustTracePerfettoOutput : defaultRustTraceLoggerOutput;
16
- traceOutput = defaultTraceOutput;
19
+ const defaultRustTraceOutput = 'perfetto' === traceLayer ? DEFAULT_RUST_TRACE_PERFETTO_OUTPUT : DEFAULT_RUST_TRACE_LOGGER_OUTPUT;
20
+ traceOutput = node_path.resolve(defaultOutputDir, defaultRustTraceOutput);
17
21
  }
18
- await ensureFileDir(traceOutput);
22
+ if (!isTerminalTraceOutput(traceOutput)) await ensureFileDir(traceOutput);
19
23
  await rspack.experiments.globalTrace.register(filterValue, traceLayer, traceOutput);
20
24
  asyncExitHook(rspack.experiments.globalTrace.cleanup, {
21
25
  wait: 500
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rspack/cli",
3
- "version": "2.0.2",
3
+ "version": "2.0.4",
4
4
  "description": "CLI for rspack",
5
5
  "homepage": "https://rspack.rs",
6
6
  "bugs": "https://github.com/web-infra-dev/rspack/issues",
@@ -30,7 +30,7 @@
30
30
  "devDependencies": {
31
31
  "@discoveryjs/json-ext": "^1.1.0",
32
32
  "@microsoft/api-extractor": "^7.58.7",
33
- "@rslib/core": "0.21.3",
33
+ "@rslib/core": "^0.21.5",
34
34
  "@rspack/dev-server": "^2.0.1",
35
35
  "cac": "^7.0.0",
36
36
  "concat-stream": "^2.0.0",
@@ -39,9 +39,10 @@
39
39
  "exit-hook": "^5.1.0",
40
40
  "jiti": "^2.6.1",
41
41
  "prebundle": "^1.6.4",
42
+ "rspack-merge": "0.1.1",
42
43
  "typescript": "^6.0.3",
43
- "@rspack/core": "2.0.2",
44
- "@rspack/test-tools": "2.0.2"
44
+ "@rspack/core": "2.0.4",
45
+ "@rspack/test-tools": "2.0.4"
45
46
  },
46
47
  "peerDependencies": {
47
48
  "@rspack/core": "^2.0.0-0",