@modern-js/core 1.2.1-rc.0 → 1.3.0

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/CHANGELOG.md CHANGED
@@ -1,13 +1,21 @@
1
1
  # @modern-js/core
2
2
 
3
- ## 1.2.1-rc.0
3
+ ## 1.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - fc71e36f: support custom property name for the config in package.json
8
+ - cfe11628: Make Modern.js self bootstraping
4
9
 
5
10
  ### Patch Changes
6
11
 
7
- - Updated dependencies [b7fb82ec]
8
- - @modern-js/utils@1.1.6-rc.0
9
- - @modern-js/load-config@1.1.2-rc.0
10
- - @modern-js/plugin@1.1.2
12
+ - Updated dependencies [2da09c69]
13
+ - Updated dependencies [fc71e36f]
14
+ - Updated dependencies [c3d46ee4]
15
+ - Updated dependencies [cfe11628]
16
+ - @modern-js/utils@1.2.0
17
+ - @modern-js/load-config@1.2.0
18
+ - @modern-js/plugin@1.2.0
11
19
 
12
20
  ## 1.2.0
13
21
 
@@ -0,0 +1,29 @@
1
+ // 这个文件跟 bin/modern-js.js 基本一样
2
+ // 在开发阶段,因为 package.json 的 exports['./bin']['jsnext:source'] 配置
3
+ // 了这个文件,所以需要保留, 后续如果找到更好的方式之后会移除这个文件
4
+ import path from 'path';
5
+ import { cli } from ".";
6
+
7
+ const {
8
+ version
9
+ } = require("../../package.json"); // XXX: 通过这个方式去掉了 package.json 里面对于 @modern-js/module-tools 的 devDependencies 依赖
10
+ // 然后可以正常的执行 modern build
11
+
12
+
13
+ const kModuleToolsCliPath = path.resolve(__dirname, '../../../solutions/module-tools/src/index.ts');
14
+ process.env.MODERN_JS_VERSION = version;
15
+
16
+ if (!process.env.NODE_ENV) {
17
+ process.env.NODE_ENV = // eslint-disable-next-line no-nested-ternary
18
+ ['build', 'start', 'deploy'].includes(process.argv[2]) ? 'production' : process.argv[2] === 'test' ? 'test' : 'development';
19
+ }
20
+
21
+ cli.run(process.argv.slice(2), {
22
+ plugins: {
23
+ '@modern-js/module-tools': {
24
+ cli: kModuleToolsCliPath,
25
+ // 是否需要强制加载这个组件,跳过 loadPlugins 里面 filter 的检测逻辑
26
+ forced: true
27
+ }
28
+ }
29
+ });
@@ -20,8 +20,8 @@ const debug = createDebugger('resolve-config');
20
20
  export { defaults as defaultsConfig };
21
21
  export { mergeConfig };
22
22
  export const defineConfig = config => config;
23
- export const loadUserConfig = async (appDirectory, filePath) => {
24
- const loaded = await loadConfig(appDirectory, filePath);
23
+ export const loadUserConfig = async (appDirectory, filePath, packageJsonConfig) => {
24
+ const loaded = await loadConfig(appDirectory, filePath, packageJsonConfig);
25
25
  const config = !loaded ? {} : await (typeof loaded.config === 'function' ? loaded.config(0) : loaded.config);
26
26
  return {
27
27
  config: mergeWith({}, config || {}, (loaded === null || loaded === void 0 ? void 0 : loaded.pkgConfig) || {}),
@@ -39,13 +39,18 @@ export const {
39
39
  export const usePlugins = plugins => plugins.forEach(plugin => manager.usePlugin(compatRequire(require.resolve(plugin))));
40
40
  export { defineConfig, AppContext, ResolvedConfigContext, useAppContext, useConfigContext, useResolvedConfigContext, ConfigContext };
41
41
 
42
- const initAppDir = async () => {
42
+ const initAppDir = async cwd => {
43
+ if (!cwd) {
44
+ // eslint-disable-next-line no-param-reassign
45
+ cwd = process.cwd();
46
+ }
47
+
43
48
  const pkg = await pkgUp({
44
- cwd: process.cwd()
49
+ cwd
45
50
  });
46
51
 
47
52
  if (!pkg) {
48
- throw new Error(`no package.json found in current work dir: ${process.cwd()}`);
53
+ throw new Error(`no package.json found in current work dir: ${cwd}`);
49
54
  }
50
55
 
51
56
  return path.dirname(pkg);
@@ -60,7 +65,7 @@ const createCli = () => {
60
65
  manager.clear();
61
66
  const appDirectory = await initAppDir();
62
67
  loadEnv(appDirectory);
63
- const loaded = await loadUserConfig(appDirectory, options === null || options === void 0 ? void 0 : options.configFile);
68
+ const loaded = await loadUserConfig(appDirectory, options === null || options === void 0 ? void 0 : options.configFile, options === null || options === void 0 ? void 0 : options.packageJsonConfig);
64
69
  let plugins = loadPlugins(appDirectory, loaded.config.plugins || [], options === null || options === void 0 ? void 0 : options.plugins);
65
70
 
66
71
  if (options !== null && options !== void 0 && options.beforeUsePlugins) {
@@ -45,6 +45,21 @@ const resolvePlugin = (appDirectory, plugin) => {
45
45
 
46
46
  return resolved;
47
47
  };
48
+
49
+ export function getAppPlugins(appDirectory, pluginConfig, internalPlugins) {
50
+ const allPlugins = internalPlugins || INTERNAL_PLUGINS;
51
+ const appPlugins = [...Object.keys(allPlugins).filter(name => {
52
+ const config = allPlugins[name];
53
+
54
+ if (config.forced === true) {
55
+ // 参考 packages/cli/core/src/cli.ts 文件
56
+ return true;
57
+ }
58
+
59
+ return isDepExists(appDirectory, name);
60
+ }).map(name => allPlugins[name]), ...pluginConfig];
61
+ return appPlugins;
62
+ }
48
63
  /**
49
64
  * Load internal plugins which in @modern-js scope and user's custom plugins.
50
65
  * @param appDirectory - Application root directory.
@@ -52,9 +67,8 @@ const resolvePlugin = (appDirectory, plugin) => {
52
67
  * @returns Plugin Objects has been required.
53
68
  */
54
69
 
55
-
56
70
  export const loadPlugins = (appDirectory, pluginConfig, internalPlugins) => {
57
- const plugins = [...Object.keys(internalPlugins || INTERNAL_PLUGINS).filter(name => isDepExists(appDirectory, name)).map(name => (internalPlugins || INTERNAL_PLUGINS)[name]), ...pluginConfig];
71
+ const plugins = getAppPlugins(appDirectory, pluginConfig, internalPlugins);
58
72
  return plugins.map(plugin => {
59
73
  const {
60
74
  cli,
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+
3
+ var _path = _interopRequireDefault(require("path"));
4
+
5
+ var _ = require(".");
6
+
7
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
8
+
9
+ // 这个文件跟 bin/modern-js.js 基本一样
10
+ // 在开发阶段,因为 package.json 的 exports['./bin']['jsnext:source'] 配置
11
+ // 了这个文件,所以需要保留, 后续如果找到更好的方式之后会移除这个文件
12
+ const {
13
+ version
14
+ } = require("../../package.json"); // XXX: 通过这个方式去掉了 package.json 里面对于 @modern-js/module-tools 的 devDependencies 依赖
15
+ // 然后可以正常的执行 modern build
16
+
17
+
18
+ const kModuleToolsCliPath = _path.default.resolve(__dirname, '../../../solutions/module-tools/src/index.ts');
19
+
20
+ process.env.MODERN_JS_VERSION = version;
21
+
22
+ if (!process.env.NODE_ENV) {
23
+ process.env.NODE_ENV = // eslint-disable-next-line no-nested-ternary
24
+ ['build', 'start', 'deploy'].includes(process.argv[2]) ? 'production' : process.argv[2] === 'test' ? 'test' : 'development';
25
+ }
26
+
27
+ _.cli.run(process.argv.slice(2), {
28
+ plugins: {
29
+ '@modern-js/module-tools': {
30
+ cli: kModuleToolsCliPath,
31
+ // 是否需要强制加载这个组件,跳过 loadPlugins 里面 filter 的检测逻辑
32
+ forced: true
33
+ }
34
+ }
35
+ });
@@ -56,8 +56,8 @@ const defineConfig = config => config;
56
56
 
57
57
  exports.defineConfig = defineConfig;
58
58
 
59
- const loadUserConfig = async (appDirectory, filePath) => {
60
- const loaded = await (0, _loadConfig.loadConfig)(appDirectory, filePath);
59
+ const loadUserConfig = async (appDirectory, filePath, packageJsonConfig) => {
60
+ const loaded = await (0, _loadConfig.loadConfig)(appDirectory, filePath, packageJsonConfig);
61
61
  const config = !loaded ? {} : await (typeof loaded.config === 'function' ? loaded.config(0) : loaded.config);
62
62
  return {
63
63
  config: (0, _lodash.default)({}, config || {}, (loaded === null || loaded === void 0 ? void 0 : loaded.pkgConfig) || {}),
@@ -176,13 +176,18 @@ const usePlugins = plugins => plugins.forEach(plugin => manager.usePlugin((0, _u
176
176
 
177
177
  exports.usePlugins = usePlugins;
178
178
 
179
- const initAppDir = async () => {
179
+ const initAppDir = async cwd => {
180
+ if (!cwd) {
181
+ // eslint-disable-next-line no-param-reassign
182
+ cwd = process.cwd();
183
+ }
184
+
180
185
  const pkg = await (0, _utils.pkgUp)({
181
- cwd: process.cwd()
186
+ cwd
182
187
  });
183
188
 
184
189
  if (!pkg) {
185
- throw new Error(`no package.json found in current work dir: ${process.cwd()}`);
190
+ throw new Error(`no package.json found in current work dir: ${cwd}`);
186
191
  }
187
192
 
188
193
  return _path.default.dirname(pkg);
@@ -199,7 +204,7 @@ const createCli = () => {
199
204
  manager.clear();
200
205
  const appDirectory = await initAppDir();
201
206
  (0, _loadEnv.loadEnv)(appDirectory);
202
- const loaded = await (0, _config.loadUserConfig)(appDirectory, options === null || options === void 0 ? void 0 : options.configFile);
207
+ const loaded = await (0, _config.loadUserConfig)(appDirectory, options === null || options === void 0 ? void 0 : options.configFile, options === null || options === void 0 ? void 0 : options.packageJsonConfig);
203
208
  let plugins = (0, _loadPlugins.loadPlugins)(appDirectory, loaded.config.plugins || [], options === null || options === void 0 ? void 0 : options.plugins);
204
209
 
205
210
  if (options !== null && options !== void 0 && options.beforeUsePlugins) {
@@ -3,6 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ exports.getAppPlugins = getAppPlugins;
6
7
  exports.loadPlugins = void 0;
7
8
 
8
9
  var _utils = require("@modern-js/utils");
@@ -53,6 +54,21 @@ const resolvePlugin = (appDirectory, plugin) => {
53
54
 
54
55
  return resolved;
55
56
  };
57
+
58
+ function getAppPlugins(appDirectory, pluginConfig, internalPlugins) {
59
+ const allPlugins = internalPlugins || _utils.INTERNAL_PLUGINS;
60
+ const appPlugins = [...Object.keys(allPlugins).filter(name => {
61
+ const config = allPlugins[name];
62
+
63
+ if (config.forced === true) {
64
+ // 参考 packages/cli/core/src/cli.ts 文件
65
+ return true;
66
+ }
67
+
68
+ return (0, _utils.isDepExists)(appDirectory, name);
69
+ }).map(name => allPlugins[name]), ...pluginConfig];
70
+ return appPlugins;
71
+ }
56
72
  /**
57
73
  * Load internal plugins which in @modern-js scope and user's custom plugins.
58
74
  * @param appDirectory - Application root directory.
@@ -62,7 +78,7 @@ const resolvePlugin = (appDirectory, plugin) => {
62
78
 
63
79
 
64
80
  const loadPlugins = (appDirectory, pluginConfig, internalPlugins) => {
65
- const plugins = [...Object.keys(internalPlugins || _utils.INTERNAL_PLUGINS).filter(name => (0, _utils.isDepExists)(appDirectory, name)).map(name => (internalPlugins || _utils.INTERNAL_PLUGINS)[name]), ...pluginConfig];
81
+ const plugins = getAppPlugins(appDirectory, pluginConfig, internalPlugins);
66
82
  return plugins.map(plugin => {
67
83
  const {
68
84
  cli,
@@ -0,0 +1 @@
1
+ export {};
@@ -122,5 +122,5 @@ export interface LoadedConfig {
122
122
  jsConfig: UserConfig;
123
123
  }
124
124
  export declare const defineConfig: (config: ConfigParam) => ConfigParam;
125
- export declare const loadUserConfig: (appDirectory: string, filePath?: string | undefined) => Promise<LoadedConfig>;
125
+ export declare const loadUserConfig: (appDirectory: string, filePath?: string | undefined, packageJsonConfig?: string | undefined) => Promise<LoadedConfig>;
126
126
  export declare const resolveConfig: (loaded: LoadedConfig, configs: UserConfig[], schemas: PluginValidateSchema[], isRestart: boolean, argv: string[]) => Promise<NormalizedConfig>;
@@ -90,11 +90,12 @@ export declare const createPlugin: (initializer: import("@modern-js/plugin").Asy
90
90
  export declare const usePlugins: (plugins: string[]) => void;
91
91
  export { defineConfig, AppContext, ResolvedConfigContext, useAppContext, useConfigContext, useResolvedConfigContext, ConfigContext };
92
92
  export type { NormalizedConfig, IAppContext, UserConfig, ToolsConfig };
93
- declare const initAppDir: () => Promise<string>;
93
+ declare const initAppDir: (cwd?: string | undefined) => Promise<string>;
94
94
  export interface CoreOptions {
95
95
  configFile?: string;
96
+ packageJsonConfig?: string;
96
97
  plugins?: typeof INTERNAL_PLUGINS;
97
- beforeUsePlugins: (plugins: any, config: any) => {
98
+ beforeUsePlugins?: (plugins: any, config: any) => {
98
99
  cli: any;
99
100
  cliPath: any;
100
101
  server: any;
@@ -1,8 +1,13 @@
1
+ import { INTERNAL_PLUGINS } from '@modern-js/utils';
1
2
  export interface PluginConfigItem {
2
3
  cli?: string;
3
4
  server?: string;
4
5
  }
5
6
  export declare type PluginConfig = Array<PluginConfigItem>;
7
+ export declare function getAppPlugins(appDirectory: string, pluginConfig: PluginConfig, internalPlugins?: typeof INTERNAL_PLUGINS): {
8
+ cli?: string | undefined;
9
+ server?: string | undefined;
10
+ }[];
6
11
  /**
7
12
  * Load internal plugins which in @modern-js scope and user's custom plugins.
8
13
  * @param appDirectory - Application root directory.
package/jest.config.js ADDED
@@ -0,0 +1,8 @@
1
+ const sharedConfig = require('@scripts/jest-config');
2
+
3
+ /** @type {import('@jest/types').Config.InitialOptions} */
4
+ module.exports = {
5
+ // eslint-disable-next-line node/no-unsupported-features/es-syntax
6
+ ...sharedConfig,
7
+ rootDir: __dirname,
8
+ };
package/modern.config.js CHANGED
@@ -3,11 +3,4 @@ module.exports = {
3
3
  output: {
4
4
  disableSourceMap: true,
5
5
  },
6
- testing: {
7
- jest: {
8
- collectCoverage: true,
9
- collectCoverageFrom: ['src/**/*.ts'],
10
- coveragePathIgnorePatterns: ['/node_modules/'],
11
- },
12
- },
13
6
  };
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "modern",
12
12
  "modern.js"
13
13
  ],
14
- "version": "1.2.1-rc.0",
14
+ "version": "1.3.0",
15
15
  "jsnext:source": "./src/index.ts",
16
16
  "types": "./dist/types/index.d.ts",
17
17
  "main": "./dist/js/node/index.js",
@@ -20,12 +20,16 @@
20
20
  "exports": {
21
21
  ".": {
22
22
  "node": {
23
+ "jsnext:source": "./src/index.ts",
23
24
  "import": "./dist/js/modern/index.js",
24
25
  "require": "./dist/js/node/index.js"
25
26
  },
26
27
  "default": "./dist/js/treeshaking/index.js"
27
28
  },
28
- "./bin": "./bin/modern-js.js"
29
+ "./bin": {
30
+ "jsnext:source": "./src/cli.ts",
31
+ "default": "./bin/modern-js.js"
32
+ }
29
33
  },
30
34
  "typesVersions": {
31
35
  "*": {
@@ -38,9 +42,9 @@
38
42
  "dependencies": {
39
43
  "@babel/code-frame": "^7.14.5",
40
44
  "@babel/runtime": "^7",
41
- "@modern-js/load-config": "^1.1.2-rc.0",
42
- "@modern-js/plugin": "^1.1.2",
43
- "@modern-js/utils": "^1.1.6-rc.0",
45
+ "@modern-js/load-config": "^1.2.0",
46
+ "@modern-js/plugin": "^1.2.0",
47
+ "@modern-js/utils": "^1.2.0",
44
48
  "address": "^1.1.2",
45
49
  "ajv": "^8.6.2",
46
50
  "ajv-keywords": "^5.0.0",
@@ -56,8 +60,9 @@
56
60
  "v8-compile-cache": "^2.3.0"
57
61
  },
58
62
  "devDependencies": {
63
+ "btsm": "2.2.2",
59
64
  "@types/babel__code-frame": "^7.0.3",
60
- "@modern-js/types": "^1.1.5-rc.0",
65
+ "@modern-js/types": "^1.2.0",
61
66
  "@types/jest": "^26",
62
67
  "@types/lodash.clonedeep": "^4.5.6",
63
68
  "@types/lodash.mergewith": "^4.6.6",
@@ -66,8 +71,9 @@
66
71
  "@types/react-dom": "^17",
67
72
  "@types/signale": "^1.4.2",
68
73
  "typescript": "^4",
69
- "@modern-js/plugin-testing": "^1.2.2",
70
- "@modern-js/module-tools": "^1.1.4"
74
+ "jest": "^27",
75
+ "@scripts/build": "0.0.0",
76
+ "@scripts/jest-config": "0.0.0"
71
77
  },
72
78
  "sideEffects": false,
73
79
  "modernConfig": {
@@ -77,13 +83,14 @@
77
83
  },
78
84
  "publishConfig": {
79
85
  "registry": "https://registry.npmjs.org/",
80
- "access": "public"
86
+ "access": "public",
87
+ "types": "./dist/types/index.d.ts"
81
88
  },
82
89
  "scripts": {
83
90
  "new": "modern new",
84
91
  "build": "modern build",
85
92
  "dev": "modern build --watch",
86
- "test": "modern test --passWithNoTests"
93
+ "test": "jest"
87
94
  },
88
95
  "readme": "\n<p align=\"center\">\n <a href=\"https://modernjs.dev\" target=\"blank\"><img src=\"https://lf3-static.bytednsdoc.com/obj/eden-cn/ylaelkeh7nuhfnuhf/modernjs-cover.png\" width=\"300\" alt=\"Modern.js Logo\" /></a>\n</p>\n<p align=\"center\">\n现代 Web 工程体系\n <br/>\n <a href=\"https://modernjs.dev\" target=\"blank\">\n modernjs.dev\n </a>\n</p>\n<p align=\"center\">\n The meta-framework suite designed from scratch for frontend-focused modern web development\n</p>\n\n# Introduction\n\n> The doc site ([modernjs.dev](https://modernjs.dev)) and articles are only available in Chinese for now, we are planning to add English versions soon.\n\n- [Modern.js: Hello, World!](https://zhuanlan.zhihu.com/p/426707646)\n\n## Getting Started\n\n- [Quick Start](https://modernjs.dev/docs/start)\n- [Guides](https://modernjs.dev/docs/guides)\n- [API References](https://modernjs.dev/docs/apis)\n\n## Contributing\n\n- [Contributing Guide](https://github.com/modern-js-dev/modern.js/blob/main/CONTRIBUTING.md)\n"
89
96
  }
package/src/cli.ts ADDED
@@ -0,0 +1,36 @@
1
+ // 这个文件跟 bin/modern-js.js 基本一样
2
+ // 在开发阶段,因为 package.json 的 exports['./bin']['jsnext:source'] 配置
3
+ // 了这个文件,所以需要保留, 后续如果找到更好的方式之后会移除这个文件
4
+
5
+ import path from 'path';
6
+ import { cli } from '.';
7
+
8
+ const { version } = require('../package.json');
9
+
10
+ // XXX: 通过这个方式去掉了 package.json 里面对于 @modern-js/module-tools 的 devDependencies 依赖
11
+ // 然后可以正常的执行 modern build
12
+ const kModuleToolsCliPath = path.resolve(
13
+ __dirname,
14
+ '../../../solutions/module-tools/src/index.ts',
15
+ );
16
+
17
+ process.env.MODERN_JS_VERSION = version;
18
+ if (!process.env.NODE_ENV) {
19
+ process.env.NODE_ENV =
20
+ // eslint-disable-next-line no-nested-ternary
21
+ ['build', 'start', 'deploy'].includes(process.argv[2])
22
+ ? 'production'
23
+ : process.argv[2] === 'test'
24
+ ? 'test'
25
+ : 'development';
26
+ }
27
+
28
+ cli.run(process.argv.slice(2), {
29
+ plugins: {
30
+ '@modern-js/module-tools': {
31
+ cli: kModuleToolsCliPath,
32
+ // 是否需要强制加载这个组件,跳过 loadPlugins 里面 filter 的检测逻辑
33
+ forced: true,
34
+ } as any,
35
+ },
36
+ });
@@ -175,8 +175,13 @@ export const defineConfig = (config: ConfigParam): ConfigParam => config;
175
175
  export const loadUserConfig = async (
176
176
  appDirectory: string,
177
177
  filePath?: string,
178
+ packageJsonConfig?: string,
178
179
  ): Promise<LoadedConfig> => {
179
- const loaded = await loadConfig<ConfigParam>(appDirectory, filePath);
180
+ const loaded = await loadConfig<ConfigParam>(
181
+ appDirectory,
182
+ filePath,
183
+ packageJsonConfig,
184
+ );
180
185
 
181
186
  const config = !loaded
182
187
  ? {}
@@ -186,7 +191,7 @@ export const loadUserConfig = async (
186
191
 
187
192
  return {
188
193
  config: mergeWith({}, config || {}, loaded?.pkgConfig || {}),
189
- jsConfig: config || {},
194
+ jsConfig: (config || {}) as any,
190
195
  pkgConfig: (loaded?.pkgConfig || {}) as UserConfig,
191
196
  filePath: loaded?.path,
192
197
  dependencies: loaded?.dependencies || [],
@@ -282,7 +287,7 @@ export const resolveConfig = async (
282
287
  throw new Error(`Validate configuration error.`);
283
288
  }
284
289
  }
285
- const resolved = mergeConfig([defaults, ...configs, userConfig]);
290
+ const resolved = mergeConfig([defaults as any, ...configs, userConfig]);
286
291
 
287
292
  resolved._raw = loaded.config;
288
293
 
package/src/index.ts CHANGED
@@ -128,13 +128,15 @@ export {
128
128
 
129
129
  export type { NormalizedConfig, IAppContext, UserConfig, ToolsConfig };
130
130
 
131
- const initAppDir = async (): Promise<string> => {
132
- const pkg = await pkgUp({ cwd: process.cwd() });
131
+ const initAppDir = async (cwd?: string): Promise<string> => {
132
+ if (!cwd) {
133
+ // eslint-disable-next-line no-param-reassign
134
+ cwd = process.cwd();
135
+ }
136
+ const pkg = await pkgUp({ cwd });
133
137
 
134
138
  if (!pkg) {
135
- throw new Error(
136
- `no package.json found in current work dir: ${process.cwd()}`,
137
- );
139
+ throw new Error(`no package.json found in current work dir: ${cwd}`);
138
140
  }
139
141
 
140
142
  return path.dirname(pkg);
@@ -142,8 +144,9 @@ const initAppDir = async (): Promise<string> => {
142
144
 
143
145
  export interface CoreOptions {
144
146
  configFile?: string;
147
+ packageJsonConfig?: string;
145
148
  plugins?: typeof INTERNAL_PLUGINS;
146
- beforeUsePlugins: (
149
+ beforeUsePlugins?: (
147
150
  plugins: any,
148
151
  config: any,
149
152
  ) => { cli: any; cliPath: any; server: any; serverPath: any }[];
@@ -162,7 +165,11 @@ const createCli = () => {
162
165
 
163
166
  loadEnv(appDirectory);
164
167
 
165
- const loaded = await loadUserConfig(appDirectory, options?.configFile);
168
+ const loaded = await loadUserConfig(
169
+ appDirectory,
170
+ options?.configFile,
171
+ options?.packageJsonConfig,
172
+ );
166
173
 
167
174
  let plugins = loadPlugins(
168
175
  appDirectory,
@@ -49,6 +49,28 @@ const resolvePlugin = (appDirectory: string, plugin: PluginConfigItem) => {
49
49
  return resolved;
50
50
  };
51
51
 
52
+ export function getAppPlugins(
53
+ appDirectory: string,
54
+ pluginConfig: PluginConfig,
55
+ internalPlugins?: typeof INTERNAL_PLUGINS,
56
+ ) {
57
+ const allPlugins = internalPlugins || INTERNAL_PLUGINS;
58
+ const appPlugins = [
59
+ ...Object.keys(allPlugins)
60
+ .filter(name => {
61
+ const config: any = allPlugins[name];
62
+ if (config.forced === true) {
63
+ // 参考 packages/cli/core/src/cli.ts 文件
64
+ return true;
65
+ }
66
+ return isDepExists(appDirectory, name);
67
+ })
68
+ .map(name => allPlugins[name]),
69
+ ...pluginConfig,
70
+ ];
71
+ return appPlugins;
72
+ }
73
+
52
74
  /**
53
75
  * Load internal plugins which in @modern-js scope and user's custom plugins.
54
76
  * @param appDirectory - Application root directory.
@@ -60,12 +82,7 @@ export const loadPlugins = (
60
82
  pluginConfig: PluginConfig,
61
83
  internalPlugins?: typeof INTERNAL_PLUGINS,
62
84
  ) => {
63
- const plugins = [
64
- ...Object.keys(internalPlugins || INTERNAL_PLUGINS)
65
- .filter(name => isDepExists(appDirectory, name))
66
- .map(name => (internalPlugins || INTERNAL_PLUGINS)[name]),
67
- ...pluginConfig,
68
- ];
85
+ const plugins = getAppPlugins(appDirectory, pluginConfig, internalPlugins);
69
86
 
70
87
  return plugins.map(plugin => {
71
88
  const { cli, server } = resolvePlugin(appDirectory, plugin);
@@ -0,0 +1,20 @@
1
+ import path from 'path';
2
+ import { spawnSync } from 'child_process';
3
+
4
+ const kPackageDir = path.resolve(__dirname, '..');
5
+
6
+ describe('jsnext:source', () => {
7
+ test('process exit status is 0', () => {
8
+ const { status, stdout, stderr } = spawnSync(
9
+ process.execPath,
10
+ ['--conditions=jsnext:source', '-r', 'btsm', 'src/cli.ts'],
11
+ {
12
+ cwd: kPackageDir,
13
+ encoding: 'utf-8',
14
+ },
15
+ );
16
+ expect(stdout).toBe('');
17
+ expect(stderr.startsWith('Usage: modern <command> [options]')).toBe(true);
18
+ expect(status).toBe(1);
19
+ });
20
+ });
@@ -0,0 +1,43 @@
1
+ import path from 'path';
2
+ // import os from 'os';
3
+ import { resolveConfig } from '../src/config';
4
+ import {
5
+ cli,
6
+ loadUserConfig,
7
+ initAppContext,
8
+ initAppDir,
9
+ manager,
10
+ createPlugin,
11
+ registerHook,
12
+ useRunner,
13
+ } from '../src';
14
+
15
+ // const kOSRootDir =
16
+ // os.platform() === 'win32' ? process.cwd().split(path.sep)[0] : '/';
17
+
18
+ describe('config', () => {
19
+ it('default', () => {
20
+ expect(resolveConfig).toBeDefined();
21
+ expect(cli).toBeDefined();
22
+ expect(loadUserConfig).toBeDefined();
23
+ expect(initAppContext).toBeDefined();
24
+ expect(initAppDir).toBeDefined();
25
+ expect(manager).toBeDefined();
26
+ expect(createPlugin).toBeDefined();
27
+ expect(registerHook).toBeDefined();
28
+ expect(useRunner).toBeDefined();
29
+ });
30
+
31
+ it('initAppDir', async () => {
32
+ expect(await initAppDir(__dirname)).toBe(path.resolve(__dirname, '..'));
33
+ // expect(await initAppDir()).toBe(path.resolve(__dirname, '..'));
34
+
35
+ // FIXME: windows 下面会失败,先忽略这个测试
36
+ // try {
37
+ // await initAppDir(kOSRootDir);
38
+ // expect(true).toBe(false); // SHOULD NOT BE HERE
39
+ // } catch (err: any) {
40
+ // expect(err.message).toMatch(/no package.json found in current work dir/);
41
+ // }
42
+ });
43
+ });
@@ -0,0 +1,28 @@
1
+ import path from 'path';
2
+ import { initAppContext } from '../src/context';
3
+
4
+ describe('context', () => {
5
+ it('initAppContext', () => {
6
+ const appDirectory = path.resolve(
7
+ __dirname,
8
+ './fixtures/load-plugin/user-plugins',
9
+ );
10
+ const appContext = initAppContext(appDirectory, [], false);
11
+ expect(appContext).toEqual({
12
+ appDirectory,
13
+ configFile: false,
14
+ ip: expect.any(String),
15
+ port: 0,
16
+ packageName: expect.any(String),
17
+ srcDirectory: expect.any(String),
18
+ distDirectory: expect.any(String),
19
+ sharedDirectory: expect.any(String),
20
+ nodeModulesDirectory: expect.any(String),
21
+ internalDirectory: expect.any(String),
22
+ plugins: [],
23
+ htmlTemplates: {},
24
+ serverRoutes: [],
25
+ entrypoints: [],
26
+ });
27
+ });
28
+ });
@@ -1,6 +1,6 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
- import { loadEnv } from '@/loadEnv';
3
+ import { loadEnv } from '../src/loadEnv';
4
4
 
5
5
  const fixture = path.resolve(__dirname, './fixtures/load-env');
6
6
 
@@ -1,7 +1,21 @@
1
1
  import path from 'path';
2
- import { loadPlugins } from '@/loadPlugins';
2
+ import { loadPlugins, getAppPlugins } from '../src/loadPlugins';
3
3
 
4
4
  describe('load plugins', () => {
5
+ test('getAppPlugins', () => {
6
+ const appDirectory = path.resolve(
7
+ __dirname,
8
+ './fixtures/load-plugin/user-plugins',
9
+ );
10
+ const plugins = getAppPlugins(appDirectory, ['foo' as any], {
11
+ x: {
12
+ cli: 'x',
13
+ forced: true,
14
+ } as any,
15
+ });
16
+ expect(plugins).toEqual([{ cli: 'x', forced: true }, 'foo']);
17
+ });
18
+
5
19
  test('should load user plugin successfully', () => {
6
20
  const fixture = path.resolve(
7
21
  __dirname,
@@ -31,6 +45,27 @@ describe('load plugins', () => {
31
45
  ]);
32
46
  });
33
47
 
48
+ test('should load user string plugin successfully', () => {
49
+ const fixture = path.resolve(
50
+ __dirname,
51
+ './fixtures/load-plugin/user-plugins',
52
+ );
53
+
54
+ const plugins = loadPlugins(fixture, [
55
+ path.join(fixture, './test-plugin-a.js') as any,
56
+ ]);
57
+
58
+ expect(plugins).toEqual([
59
+ {
60
+ cli: {
61
+ name: 'a',
62
+ pluginPath: path.join(fixture, './test-plugin-a.js'),
63
+ },
64
+ cliPath: path.join(fixture, './test-plugin-a.js'),
65
+ },
66
+ ]);
67
+ });
68
+
34
69
  test(`should throw error when plugin not found `, () => {
35
70
  const fixture = path.resolve(__dirname, './fixtures/load-plugin/not-found');
36
71
 
@@ -1,4 +1,4 @@
1
- import { mergeConfig } from '@/config/mergeConfig';
1
+ import { mergeConfig } from '../src/config/mergeConfig';
2
2
 
3
3
  describe('load plugins', () => {
4
4
  test('should replace property deeply', () => {
@@ -1,5 +1,5 @@
1
- import { repeatKeyWarning } from '@/utils/repeatKeyWarning';
2
- import { UserConfig } from '@/config';
1
+ import { repeatKeyWarning } from '../src/utils/repeatKeyWarning';
2
+ import { UserConfig } from '../src/config';
3
3
 
4
4
  jest.spyOn(process, 'exit').mockImplementation();
5
5
 
@@ -1,4 +1,4 @@
1
- import { patchSchema, traverseSchema } from '@/config/schema';
1
+ import { patchSchema, traverseSchema } from '../src/config/schema';
2
2
 
3
3
  describe('patch schemas', () => {
4
4
  test('should add schema succcessfully', () => {
@@ -6,8 +6,6 @@
6
6
  "baseUrl": "./",
7
7
  "isolatedModules": true,
8
8
  "esModuleInterop": true,
9
- "paths": {
10
- "@/*": ["../src/*"]
11
- }
9
+ "paths": {}
12
10
  }
13
11
  }
@@ -0,0 +1,8 @@
1
+ import { program, Command } from '../src/utils/commander';
2
+
3
+ describe('utils', () => {
4
+ it('default', () => {
5
+ expect(program).toBeDefined();
6
+ expect(Command).toBeDefined();
7
+ });
8
+ });
package/tsconfig.json CHANGED
@@ -6,9 +6,7 @@
6
6
  "baseUrl": "./",
7
7
  "isolatedModules": true,
8
8
  "esModuleInterop": true,
9
- "paths": {
10
- "@/*": ["./src/*"]
11
- }
9
+ "paths": {}
12
10
  },
13
11
  "include": ["src"]
14
12
  }