@modern-js/core 1.0.0 → 1.1.2

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,5 +1,39 @@
1
1
  # @modern-js/core
2
2
 
3
+ ## 1.1.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 6f7fe574: modern-js/core support extra options
8
+ - 0fa83663: support more .env files
9
+ - Updated dependencies [0fa83663]
10
+ - Updated dependencies [f594fbc8]
11
+ - @modern-js/load-config@1.1.1
12
+ - @modern-js/plugin@1.1.2
13
+ - @modern-js/utils@1.1.2
14
+
15
+ ## 1.1.1
16
+
17
+ ### Patch Changes
18
+
19
+ - 687c92c7: refactor: generator input questions
20
+ feat: add eslint generator
21
+ - Updated dependencies [c0fc0700]
22
+ - Updated dependencies [6ffd1a50]
23
+ - @modern-js/utils@1.1.1
24
+ - @modern-js/plugin@1.1.1
25
+
26
+ ## 1.1.0
27
+
28
+ ### Minor Changes
29
+
30
+ - 96119db2: Relese v1.1.0### Patch Changes
31
+
32
+ - Updated dependencies [96119db2]
33
+ - @modern-js/load-config@1.1.0
34
+ - @modern-js/plugin@1.1.0
35
+ - @modern-js/utils@1.1.0
36
+
3
37
  ## 1.0.0
4
38
 
5
39
  ### Patch Changes
package/README.md CHANGED
@@ -17,10 +17,7 @@
17
17
 
18
18
  > 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.
19
19
 
20
- - 介绍 Modern.js (即将上线)
21
- - [迈入现代 Web 开发](https://zhuanlan.zhihu.com/p/386607009)
22
- - [现代 Web 开发者问卷调查报告](https://zhuanlan.zhihu.com/p/403206195)
23
- - [字节跳动是如何落地微前端的](https://mp.weixin.qq.com/s/L9wbfNG5fTXF5bx7dcgj4Q)
20
+ - [Modern.js: Hello, World!](https://zhuanlan.zhihu.com/p/426707646)
24
21
 
25
22
  ## Getting Started
26
23
 
@@ -18,6 +18,7 @@ import { mergeConfig } from "./mergeConfig";
18
18
  import { patchSchema } from "./schema";
19
19
  const debug = createDebugger('resolve-config');
20
20
  export { defaults as defaultsConfig };
21
+ export { mergeConfig };
21
22
  export const defineConfig = config => config;
22
23
  export const loadUserConfig = async (appDirectory, filePath) => {
23
24
  const loaded = await loadConfig(appDirectory, filePath);
@@ -1,4 +1,4 @@
1
- import { path } from '@modern-js/utils';
1
+ import path from 'path';
2
2
  import { createContext } from '@modern-js/plugin';
3
3
  import address from 'address';
4
4
  export const AppContext = createContext({});
@@ -4,7 +4,8 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
4
4
 
5
5
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
6
6
 
7
- import { path, upath, compatRequire, pkgUp, ensureAbsolutePath, logger } from '@modern-js/utils';
7
+ import path from 'path';
8
+ import { compatRequire, pkgUp, ensureAbsolutePath, logger } from '@modern-js/utils';
8
9
  import { createAsyncManager, createAsyncWorkflow, createParallelWorkflow } from '@modern-js/plugin';
9
10
  import { enable } from '@modern-js/plugin/node';
10
11
  import { program } from "./utils/commander";
@@ -13,7 +14,7 @@ import { loadPlugins } from "./loadPlugins";
13
14
  import { AppContext, ConfigContext, initAppContext, ResolvedConfigContext, useAppContext, useConfigContext, useResolvedConfigContext } from "./context";
14
15
  import { initWatcher } from "./initWatcher";
15
16
  import { loadEnv } from "./loadEnv";
16
- export { defaultsConfig } from "./config";
17
+ export { defaultsConfig, mergeConfig } from "./config";
17
18
  export * from '@modern-js/plugin';
18
19
  export * from '@modern-js/plugin/node';
19
20
  program.name('modern').usage('<command> [options]').version(process.env.MODERN_JS_VERSION || '0.1.0');
@@ -34,7 +35,7 @@ export const {
34
35
  registe: registerHook,
35
36
  useRunner: mountHook
36
37
  } = manager;
37
- export const usePlugins = plugins => plugins.forEach(plugin => manager.usePlugin(compatRequire(upath.normalize(require.resolve(plugin)))));
38
+ export const usePlugins = plugins => plugins.forEach(plugin => manager.usePlugin(compatRequire(require.resolve(plugin))));
38
39
  export { defineConfig, AppContext, useAppContext, useConfigContext, useResolvedConfigContext };
39
40
 
40
41
  const initAppDir = async () => {
@@ -53,13 +54,18 @@ const createCli = () => {
53
54
  let hooksRunner;
54
55
  let isRestart = false;
55
56
 
56
- const init = async (argv = []) => {
57
+ const init = async (argv = [], options) => {
57
58
  enable();
58
59
  manager.clear();
59
60
  const appDirectory = await initAppDir();
60
61
  loadEnv(appDirectory);
61
62
  const loaded = await loadUserConfig(appDirectory);
62
- const plugins = loadPlugins(appDirectory, loaded.config.plugins || []);
63
+ let plugins = loadPlugins(appDirectory, loaded.config.plugins || []);
64
+
65
+ if (options !== null && options !== void 0 && options.beforeUsePlugins) {
66
+ plugins = options.beforeUsePlugins(plugins, loaded.config);
67
+ }
68
+
63
69
  plugins.forEach(plugin => plugin.cli && manager.usePlugin(plugin.cli));
64
70
  const appContext = initAppContext(appDirectory, plugins, loaded.filePath);
65
71
  manager.run(() => {
@@ -101,12 +107,12 @@ const createCli = () => {
101
107
  };
102
108
  };
103
109
 
104
- async function run(argv) {
110
+ async function run(argv, options) {
105
111
  const {
106
112
  loadedConfig,
107
113
  appContext,
108
114
  resolved
109
- } = await init(argv);
115
+ } = await init(argv, options);
110
116
  await hooksRunner.commands({
111
117
  program
112
118
  });
@@ -1,6 +1,7 @@
1
1
  import crypto from 'crypto';
2
2
  import fs from 'fs';
3
- import { path, isDev, createDebugger } from '@modern-js/utils';
3
+ import path from 'path';
4
+ import { isDev, createDebugger } from '@modern-js/utils';
4
5
  import chokidar from 'chokidar';
5
6
  const debug = createDebugger('watch-files');
6
7
 
@@ -1,9 +1,11 @@
1
1
  import fs from 'fs';
2
- import { path } from '@modern-js/utils';
2
+ import path from 'path';
3
3
  import dotenv from 'dotenv';
4
4
  import dotenvExpand from 'dotenv-expand';
5
5
  export const loadEnv = (appDirectory, mode = process.env.NODE_ENV) => {
6
- [`.env.${mode}`, '.env'].map(name => path.resolve(appDirectory, name)).filter(filePath => fs.existsSync(filePath) && !fs.statSync(filePath).isDirectory()).forEach(filePath => {
6
+ // Don't change the order of the filenames, since they are ordered by the priority.
7
+ // Files on the left have more priority than files on the right.
8
+ [`.env.${mode}.local`, '.env.local', `.env.${mode}`, '.env'].map(name => path.resolve(appDirectory, name)).filter(filePath => fs.existsSync(filePath) && !fs.statSync(filePath).isDirectory()).forEach(filePath => {
7
9
  const envConfig = dotenv.config({
8
10
  path: filePath
9
11
  });
@@ -1,4 +1,4 @@
1
- import { isDepExists, createDebugger, compatRequire, INTERNAL_PLUGINS, upath } from '@modern-js/utils';
1
+ import { isDepExists, createDebugger, compatRequire, INTERNAL_PLUGINS } from '@modern-js/utils';
2
2
  const debug = createDebugger('load-plugins');
3
3
 
4
4
  /**
@@ -12,9 +12,9 @@ const resolvePlugin = (appDirectory, plugin) => {
12
12
  let filePath = '';
13
13
 
14
14
  try {
15
- filePath = upath.normalizeSafe(require.resolve(name, {
15
+ filePath = require.resolve(name, {
16
16
  paths: [appDirectory]
17
- }));
17
+ });
18
18
  delete require.cache[filePath];
19
19
  } catch (err) {
20
20
  if (err.code === 'MODULE_NOT_FOUND') {
@@ -29,8 +29,8 @@ const resolvePlugin = (appDirectory, plugin) => {
29
29
 
30
30
  const resolved = {};
31
31
 
32
- if (plugin.cli) {
33
- resolved.cli = tryResolve(plugin.cli);
32
+ if (typeof plugin === 'string' || plugin.cli) {
33
+ resolved.cli = typeof plugin === 'string' ? tryResolve(plugin) : tryResolve(plugin.cli);
34
34
  }
35
35
 
36
36
  if (plugin.server) {
@@ -47,8 +47,8 @@ const resolvePlugin = (appDirectory, plugin) => {
47
47
  */
48
48
 
49
49
 
50
- export const loadPlugins = (appDirectory, pluginConfig) => {
51
- const plugins = [...Object.keys(INTERNAL_PLUGINS).filter(name => isDepExists(appDirectory, name)).map(name => INTERNAL_PLUGINS[name]), ...pluginConfig];
50
+ export const loadPlugins = (appDirectory, pluginConfig, internalPlugins) => {
51
+ const plugins = [...Object.keys(internalPlugins || INTERNAL_PLUGINS).filter(name => isDepExists(appDirectory, name)).map(name => (internalPlugins || INTERNAL_PLUGINS)[name]), ...pluginConfig];
52
52
  return plugins.map(plugin => {
53
53
  const {
54
54
  cli,
@@ -9,7 +9,14 @@ Object.defineProperty(exports, "defaultsConfig", {
9
9
  return _defaults.defaults;
10
10
  }
11
11
  });
12
- exports.resolveConfig = exports.loadUserConfig = exports.defineConfig = void 0;
12
+ exports.loadUserConfig = exports.defineConfig = void 0;
13
+ Object.defineProperty(exports, "mergeConfig", {
14
+ enumerable: true,
15
+ get: function () {
16
+ return _mergeConfig.mergeConfig;
17
+ }
18
+ });
19
+ exports.resolveConfig = void 0;
13
20
 
14
21
  var _loadConfig = require("@modern-js/load-config");
15
22
 
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.useResolvedConfigContext = exports.useConfigContext = exports.useAppContext = exports.initAppContext = exports.ResolvedConfigContext = exports.ConfigContext = exports.AppContext = void 0;
7
7
 
8
- var _utils = require("@modern-js/utils");
8
+ var _path = _interopRequireDefault(require("path"));
9
9
 
10
10
  var _plugin = require("@modern-js/plugin");
11
11
 
@@ -37,12 +37,12 @@ const initAppContext = (appDirectory, plugins, configFile) => ({
37
37
  configFile,
38
38
  ip: _address.default.ip(),
39
39
  port: 0,
40
- packageName: require(_utils.path.resolve(appDirectory, './package.json')).name,
41
- srcDirectory: _utils.path.resolve(appDirectory, './src'),
40
+ packageName: require(_path.default.resolve(appDirectory, './package.json')).name,
41
+ srcDirectory: _path.default.resolve(appDirectory, './src'),
42
42
  distDirectory: '',
43
- sharedDirectory: _utils.path.resolve(appDirectory, './shared'),
44
- nodeModulesDirectory: _utils.path.resolve(appDirectory, './node_modules'),
45
- internalDirectory: _utils.path.resolve(appDirectory, './node_modules/.modern-js'),
43
+ sharedDirectory: _path.default.resolve(appDirectory, './shared'),
44
+ nodeModulesDirectory: _path.default.resolve(appDirectory, './node_modules'),
45
+ internalDirectory: _path.default.resolve(appDirectory, './node_modules/.modern-js'),
46
46
  plugins,
47
47
  htmlTemplates: {},
48
48
  serverRoutes: [],
@@ -12,6 +12,7 @@ var _exportNames = {
12
12
  cli: true,
13
13
  defineConfig: true,
14
14
  defaultsConfig: true,
15
+ mergeConfig: true,
15
16
  AppContext: true,
16
17
  useAppContext: true,
17
18
  useConfigContext: true,
@@ -36,7 +37,14 @@ Object.defineProperty(exports, "defineConfig", {
36
37
  return _config.defineConfig;
37
38
  }
38
39
  });
39
- exports.registerHook = exports.mountHook = exports.manager = void 0;
40
+ exports.manager = void 0;
41
+ Object.defineProperty(exports, "mergeConfig", {
42
+ enumerable: true,
43
+ get: function () {
44
+ return _config.mergeConfig;
45
+ }
46
+ });
47
+ exports.registerHook = exports.mountHook = void 0;
40
48
  Object.defineProperty(exports, "useAppContext", {
41
49
  enumerable: true,
42
50
  get: function () {
@@ -57,6 +65,8 @@ Object.defineProperty(exports, "useResolvedConfigContext", {
57
65
  }
58
66
  });
59
67
 
68
+ var _path = _interopRequireDefault(require("path"));
69
+
60
70
  var _utils = require("@modern-js/utils");
61
71
 
62
72
  var _plugin = require("@modern-js/plugin");
@@ -99,6 +109,8 @@ var _initWatcher = require("./initWatcher");
99
109
 
100
110
  var _loadEnv = require("./loadEnv");
101
111
 
112
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
113
+
102
114
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
103
115
 
104
116
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
@@ -129,7 +141,7 @@ exports.mountHook = mountHook;
129
141
  exports.registerHook = registerHook;
130
142
  exports.createPlugin = createPlugin;
131
143
 
132
- const usePlugins = plugins => plugins.forEach(plugin => manager.usePlugin((0, _utils.compatRequire)(_utils.upath.normalize(require.resolve(plugin)))));
144
+ const usePlugins = plugins => plugins.forEach(plugin => manager.usePlugin((0, _utils.compatRequire)(require.resolve(plugin))));
133
145
 
134
146
  exports.usePlugins = usePlugins;
135
147
 
@@ -142,20 +154,25 @@ const initAppDir = async () => {
142
154
  throw new Error(`no package.json found in current work dir: ${process.cwd()}`);
143
155
  }
144
156
 
145
- return _utils.path.dirname(pkg);
157
+ return _path.default.dirname(pkg);
146
158
  };
147
159
 
148
160
  const createCli = () => {
149
161
  let hooksRunner;
150
162
  let isRestart = false;
151
163
 
152
- const init = async (argv = []) => {
164
+ const init = async (argv = [], options) => {
153
165
  (0, _node.enable)();
154
166
  manager.clear();
155
167
  const appDirectory = await initAppDir();
156
168
  (0, _loadEnv.loadEnv)(appDirectory);
157
169
  const loaded = await (0, _config.loadUserConfig)(appDirectory);
158
- const plugins = (0, _loadPlugins.loadPlugins)(appDirectory, loaded.config.plugins || []);
170
+ let plugins = (0, _loadPlugins.loadPlugins)(appDirectory, loaded.config.plugins || []);
171
+
172
+ if (options !== null && options !== void 0 && options.beforeUsePlugins) {
173
+ plugins = options.beforeUsePlugins(plugins, loaded.config);
174
+ }
175
+
159
176
  plugins.forEach(plugin => plugin.cli && manager.usePlugin(plugin.cli));
160
177
  const appContext = (0, _context.initAppContext)(appDirectory, plugins, loaded.filePath);
161
178
  manager.run(() => {
@@ -200,12 +217,12 @@ const createCli = () => {
200
217
  };
201
218
  };
202
219
 
203
- async function run(argv) {
220
+ async function run(argv, options) {
204
221
  const {
205
222
  loadedConfig,
206
223
  appContext,
207
224
  resolved
208
- } = await init(argv);
225
+ } = await init(argv, options);
209
226
  await hooksRunner.commands({
210
227
  program: _commander.program
211
228
  });
@@ -9,6 +9,8 @@ var _crypto = _interopRequireDefault(require("crypto"));
9
9
 
10
10
  var _fs = _interopRequireDefault(require("fs"));
11
11
 
12
+ var _path = _interopRequireDefault(require("path"));
13
+
12
14
  var _utils = require("@modern-js/utils");
13
15
 
14
16
  var _chokidar = _interopRequireDefault(require("chokidar"));
@@ -26,7 +28,7 @@ const initWatcher = async (loaded, appDirectory, configDir, hooksRunner, argv) =
26
28
  if ((0, _utils.isDev)() && argv[0] === 'dev') {
27
29
  const extraFiles = await hooksRunner.watchFiles();
28
30
 
29
- const configPath = _utils.path.join(appDirectory, configDir);
31
+ const configPath = _path.default.join(appDirectory, configDir);
30
32
 
31
33
  const watched = [`${configPath}/html`, ...extraFiles, loaded === null || loaded === void 0 ? void 0 : loaded.filePath, ...loaded.dependencies].filter(Boolean);
32
34
  debug(`watched: %o`, watched);
@@ -39,7 +41,7 @@ const initWatcher = async (loaded, appDirectory, configDir, hooksRunner, argv) =
39
41
 
40
42
  watcher.on('change', changed => {
41
43
  const lastHash = hashMap.get(changed);
42
- const currentHash = md5(_fs.default.readFileSync(_utils.path.join(appDirectory, changed), 'utf8'));
44
+ const currentHash = md5(_fs.default.readFileSync(_path.default.join(appDirectory, changed), 'utf8'));
43
45
 
44
46
  if (currentHash !== lastHash) {
45
47
  debug(`file change: %s`, changed);
@@ -7,7 +7,7 @@ exports.loadEnv = void 0;
7
7
 
8
8
  var _fs = _interopRequireDefault(require("fs"));
9
9
 
10
- var _utils = require("@modern-js/utils");
10
+ var _path = _interopRequireDefault(require("path"));
11
11
 
12
12
  var _dotenv = _interopRequireDefault(require("dotenv"));
13
13
 
@@ -16,7 +16,9 @@ var _dotenvExpand = _interopRequireDefault(require("dotenv-expand"));
16
16
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
17
 
18
18
  const loadEnv = (appDirectory, mode = process.env.NODE_ENV) => {
19
- [`.env.${mode}`, '.env'].map(name => _utils.path.resolve(appDirectory, name)).filter(filePath => _fs.default.existsSync(filePath) && !_fs.default.statSync(filePath).isDirectory()).forEach(filePath => {
19
+ // Don't change the order of the filenames, since they are ordered by the priority.
20
+ // Files on the left have more priority than files on the right.
21
+ [`.env.${mode}.local`, '.env.local', `.env.${mode}`, '.env'].map(name => _path.default.resolve(appDirectory, name)).filter(filePath => _fs.default.existsSync(filePath) && !_fs.default.statSync(filePath).isDirectory()).forEach(filePath => {
20
22
  const envConfig = _dotenv.default.config({
21
23
  path: filePath
22
24
  });
@@ -20,9 +20,9 @@ const resolvePlugin = (appDirectory, plugin) => {
20
20
  let filePath = '';
21
21
 
22
22
  try {
23
- filePath = _utils.upath.normalizeSafe(require.resolve(name, {
23
+ filePath = require.resolve(name, {
24
24
  paths: [appDirectory]
25
- }));
25
+ });
26
26
  delete require.cache[filePath];
27
27
  } catch (err) {
28
28
  if (err.code === 'MODULE_NOT_FOUND') {
@@ -37,8 +37,8 @@ const resolvePlugin = (appDirectory, plugin) => {
37
37
 
38
38
  const resolved = {};
39
39
 
40
- if (plugin.cli) {
41
- resolved.cli = tryResolve(plugin.cli);
40
+ if (typeof plugin === 'string' || plugin.cli) {
41
+ resolved.cli = typeof plugin === 'string' ? tryResolve(plugin) : tryResolve(plugin.cli);
42
42
  }
43
43
 
44
44
  if (plugin.server) {
@@ -55,8 +55,8 @@ const resolvePlugin = (appDirectory, plugin) => {
55
55
  */
56
56
 
57
57
 
58
- const loadPlugins = (appDirectory, pluginConfig) => {
59
- const plugins = [...Object.keys(_utils.INTERNAL_PLUGINS).filter(name => (0, _utils.isDepExists)(appDirectory, name)).map(name => _utils.INTERNAL_PLUGINS[name]), ...pluginConfig];
58
+ const loadPlugins = (appDirectory, pluginConfig, internalPlugins) => {
59
+ const plugins = [...Object.keys(internalPlugins || _utils.INTERNAL_PLUGINS).filter(name => (0, _utils.isDepExists)(appDirectory, name)).map(name => (internalPlugins || _utils.INTERNAL_PLUGINS)[name]), ...pluginConfig];
60
60
  return plugins.map(plugin => {
61
61
  const {
62
62
  cli,
@@ -1,9 +1,10 @@
1
1
  import { MetaOptions } from '@modern-js/utils';
2
2
  import { PluginConfig } from '../loadPlugins';
3
3
  import { defaults } from './defaults';
4
- import { NormalizedConfig } from './mergeConfig';
4
+ import { mergeConfig, NormalizedConfig } from './mergeConfig';
5
5
  import { PluginValidateSchema } from './schema';
6
6
  export { defaults as defaultsConfig };
7
+ export { mergeConfig };
7
8
  export interface SourceConfig {
8
9
  entries?: Record<string, string | {
9
10
  entry: string;
@@ -1,3 +1,4 @@
1
+ import { INTERNAL_PLUGINS } from '@modern-js/utils';
1
2
  import { ParallelWorkflow, AsyncWorkflow, Progresses2Runners } from '@modern-js/plugin';
2
3
  import type { Hooks } from '@modern-js/types';
3
4
  import { Command } from './utils/commander';
@@ -5,7 +6,7 @@ import { defineConfig, UserConfig, ToolsConfig } from './config';
5
6
  import { AppContext, IAppContext, useAppContext, useConfigContext, useResolvedConfigContext } from './context';
6
7
  import { NormalizedConfig } from './config/mergeConfig';
7
8
  export type { Hooks };
8
- export { defaultsConfig } from './config';
9
+ export { defaultsConfig, mergeConfig } from './config';
9
10
  export * from '@modern-js/plugin';
10
11
  export * from '@modern-js/plugin/node';
11
12
  export declare type HooksRunner = Progresses2Runners<{
@@ -74,15 +75,20 @@ export declare const createPlugin: (initializer: import("@modern-js/plugin").Asy
74
75
  export declare const usePlugins: (plugins: string[]) => void;
75
76
  export { defineConfig, AppContext, useAppContext, useConfigContext, useResolvedConfigContext };
76
77
  export type { NormalizedConfig, IAppContext, UserConfig, ToolsConfig };
77
- export interface CoreOption {
78
- dryRun?: boolean;
78
+ export interface CoreOptions {
79
+ name?: string;
80
+ plugins?: typeof INTERNAL_PLUGINS;
81
+ beforeUsePlugins: (plugins: any, config: any) => {
82
+ cli: any;
83
+ server: any;
84
+ }[];
79
85
  }
80
86
  export declare const cli: {
81
- init: (argv?: string[]) => Promise<{
87
+ init: (argv?: string[], options?: CoreOptions | undefined) => Promise<{
82
88
  loadedConfig: import("./config").LoadedConfig;
83
89
  appContext: IAppContext;
84
90
  resolved: NormalizedConfig;
85
91
  }>;
86
- run: (argv: string[]) => Promise<void>;
92
+ run: (argv: string[], options?: CoreOptions | undefined) => Promise<void>;
87
93
  restart: () => Promise<void>;
88
94
  };
@@ -10,7 +10,12 @@ export declare type PluginConfig = Array<PluginConfigItem>;
10
10
  * @returns Plugin Objects has been required.
11
11
  */
12
12
 
13
- export declare const loadPlugins: (appDirectory: string, pluginConfig: PluginConfig) => {
13
+ export declare const loadPlugins: (appDirectory: string, pluginConfig: PluginConfig, internalPlugins?: {
14
+ [name: string]: {
15
+ cli?: string | undefined;
16
+ server?: string | undefined;
17
+ };
18
+ } | undefined) => {
14
19
  cli: any;
15
20
  server: any;
16
21
  }[];
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "modern",
12
12
  "modern.js"
13
13
  ],
14
- "version": "1.0.0",
14
+ "version": "1.1.2",
15
15
  "jsnext:source": "./src/index.ts",
16
16
  "types": "./dist/types/index.d.ts",
17
17
  "main": "./dist/js/node/index.js",
@@ -38,9 +38,9 @@
38
38
  "dependencies": {
39
39
  "@babel/code-frame": "^7.14.5",
40
40
  "@babel/runtime": "^7",
41
- "@modern-js/load-config": "^1.0.0",
42
- "@modern-js/plugin": "^1.0.0",
43
- "@modern-js/utils": "^1.0.0",
41
+ "@modern-js/load-config": "^1.1.1",
42
+ "@modern-js/plugin": "^1.1.2",
43
+ "@modern-js/utils": "^1.1.2",
44
44
  "address": "^1.1.2",
45
45
  "ajv": "^8.6.2",
46
46
  "ajv-keywords": "^5.0.0",
@@ -57,7 +57,7 @@
57
57
  },
58
58
  "devDependencies": {
59
59
  "@types/babel__code-frame": "^7.0.3",
60
- "@modern-js/types": "^1.0.0",
60
+ "@modern-js/types": "^1.1.2",
61
61
  "@types/jest": "^26",
62
62
  "@types/lodash.clonedeep": "^4.5.6",
63
63
  "@types/lodash.mergewith": "^4.6.6",
@@ -66,8 +66,8 @@
66
66
  "@types/react-dom": "^17",
67
67
  "@types/signale": "^1.4.2",
68
68
  "typescript": "^4",
69
- "@modern-js/plugin-testing": "^1.0.0",
70
- "@modern-js/module-tools": "^1.0.0"
69
+ "@modern-js/plugin-testing": "^1.1.0",
70
+ "@modern-js/module-tools": "^1.1.0"
71
71
  },
72
72
  "sideEffects": false,
73
73
  "modernConfig": {
@@ -22,6 +22,7 @@ import { patchSchema, PluginValidateSchema } from './schema';
22
22
  const debug = createDebugger('resolve-config');
23
23
 
24
24
  export { defaults as defaultsConfig };
25
+ export { mergeConfig };
25
26
 
26
27
  export interface SourceConfig {
27
28
  entries?: Record<
package/src/context.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { path } from '@modern-js/utils';
1
+ import path from 'path';
2
2
  import { createContext } from '@modern-js/plugin';
3
3
  import address from 'address';
4
4
  import type { IAppContext } from '@modern-js/types';
package/src/index.ts CHANGED
@@ -1,10 +1,10 @@
1
+ import path from 'path';
1
2
  import {
2
- path,
3
- upath,
4
3
  compatRequire,
5
4
  pkgUp,
6
5
  ensureAbsolutePath,
7
6
  logger,
7
+ INTERNAL_PLUGINS,
8
8
  } from '@modern-js/utils';
9
9
  import {
10
10
  createAsyncManager,
@@ -41,7 +41,7 @@ import { NormalizedConfig } from './config/mergeConfig';
41
41
  import { loadEnv } from './loadEnv';
42
42
 
43
43
  export type { Hooks };
44
- export { defaultsConfig } from './config';
44
+ export { defaultsConfig, mergeConfig } from './config';
45
45
 
46
46
  export * from '@modern-js/plugin';
47
47
  export * from '@modern-js/plugin/node';
@@ -105,7 +105,7 @@ export const {
105
105
 
106
106
  export const usePlugins = (plugins: string[]) =>
107
107
  plugins.forEach(plugin =>
108
- manager.usePlugin(compatRequire(upath.normalize(require.resolve(plugin)))),
108
+ manager.usePlugin(compatRequire(require.resolve(plugin))),
109
109
  );
110
110
 
111
111
  export {
@@ -130,15 +130,17 @@ const initAppDir = async (): Promise<string> => {
130
130
  return path.dirname(pkg);
131
131
  };
132
132
 
133
- export interface CoreOption {
134
- dryRun?: boolean;
133
+ export interface CoreOptions {
134
+ name?: string;
135
+ plugins?: typeof INTERNAL_PLUGINS;
136
+ beforeUsePlugins: (plugins: any, config: any) => { cli: any; server: any }[];
135
137
  }
136
138
 
137
139
  const createCli = () => {
138
140
  let hooksRunner: HooksRunner;
139
141
  let isRestart = false;
140
142
 
141
- const init = async (argv: string[] = []) => {
143
+ const init = async (argv: string[] = [], options?: CoreOptions) => {
142
144
  enable();
143
145
 
144
146
  manager.clear();
@@ -149,7 +151,11 @@ const createCli = () => {
149
151
 
150
152
  const loaded = await loadUserConfig(appDirectory);
151
153
 
152
- const plugins = loadPlugins(appDirectory, loaded.config.plugins || []);
154
+ let plugins = loadPlugins(appDirectory, loaded.config.plugins || []);
155
+
156
+ if (options?.beforeUsePlugins) {
157
+ plugins = options.beforeUsePlugins(plugins, loaded.config);
158
+ }
153
159
 
154
160
  plugins.forEach(plugin => plugin.cli && manager.usePlugin(plugin.cli));
155
161
 
@@ -205,8 +211,8 @@ const createCli = () => {
205
211
  return { loadedConfig: loaded, appContext, resolved };
206
212
  };
207
213
 
208
- async function run(argv: string[]) {
209
- const { loadedConfig, appContext, resolved } = await init(argv);
214
+ async function run(argv: string[], options?: CoreOptions) {
215
+ const { loadedConfig, appContext, resolved } = await init(argv, options);
210
216
 
211
217
  await hooksRunner.commands({ program });
212
218
 
@@ -225,12 +231,12 @@ const createCli = () => {
225
231
 
226
232
  logger.info('Restart...\n');
227
233
 
228
- let hasGetError = false
234
+ let hasGetError = false;
229
235
  try {
230
236
  await init(process.argv.slice(2));
231
- } catch(err) {
232
- console.error(err)
233
- hasGetError = true
237
+ } catch (err) {
238
+ console.error(err);
239
+ hasGetError = true;
234
240
  } finally {
235
241
  if (!hasGetError) {
236
242
  manager.run(() => program.parse(process.argv));
@@ -1,8 +1,8 @@
1
1
  import crypto from 'crypto';
2
2
  import fs from 'fs';
3
- import { path, isDev, createDebugger } from '@modern-js/utils';
3
+ import path from 'path';
4
+ import { isDev, createDebugger } from '@modern-js/utils';
4
5
  import chokidar from 'chokidar';
5
- import { NormalizedConfig } from './config/mergeConfig';
6
6
  import { LoadedConfig } from './config';
7
7
  import { HooksRunner } from '.';
8
8
 
@@ -19,10 +19,10 @@ export const initWatcher = async (
19
19
  configDir: string | undefined,
20
20
  hooksRunner: HooksRunner,
21
21
  argv: string[],
22
+ // eslint-disable-next-line max-params
22
23
  ) => {
23
24
  // only add fs watcher on dev mode.
24
25
  if (isDev() && argv[0] === 'dev') {
25
-
26
26
  const extraFiles = await hooksRunner.watchFiles();
27
27
 
28
28
  const configPath = path.join(appDirectory, configDir!);
package/src/loadEnv.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import fs from 'fs';
2
- import { path } from '@modern-js/utils';
2
+ import path from 'path';
3
3
  import dotenv from 'dotenv';
4
4
  import dotenvExpand from 'dotenv-expand';
5
5
 
@@ -7,7 +7,9 @@ export const loadEnv = (
7
7
  appDirectory: string,
8
8
  mode: string = process.env.NODE_ENV as string,
9
9
  ) => {
10
- [`.env.${mode}`, '.env']
10
+ // Don't change the order of the filenames, since they are ordered by the priority.
11
+ // Files on the left have more priority than files on the right.
12
+ [`.env.${mode}.local`, '.env.local', `.env.${mode}`, '.env']
11
13
  .map(name => path.resolve(appDirectory, name))
12
14
  .filter(
13
15
  filePath =>
@@ -3,7 +3,6 @@ import {
3
3
  createDebugger,
4
4
  compatRequire,
5
5
  INTERNAL_PLUGINS,
6
- upath
7
6
  } from '@modern-js/utils';
8
7
 
9
8
  const debug = createDebugger('load-plugins');
@@ -25,7 +24,7 @@ const resolvePlugin = (appDirectory: string, plugin: PluginConfigItem) => {
25
24
  const tryResolve = (name: string) => {
26
25
  let filePath = '';
27
26
  try {
28
- filePath = upath.normalizeSafe(require.resolve(name, { paths: [appDirectory] }));
27
+ filePath = require.resolve(name, { paths: [appDirectory] });
29
28
  delete require.cache[filePath];
30
29
  } catch (err) {
31
30
  if ((err as any).code === 'MODULE_NOT_FOUND') {
@@ -38,8 +37,9 @@ const resolvePlugin = (appDirectory: string, plugin: PluginConfigItem) => {
38
37
 
39
38
  const resolved: PluginConfigItem = {};
40
39
 
41
- if (plugin.cli) {
42
- resolved.cli = tryResolve(plugin.cli);
40
+ if (typeof plugin === 'string' || plugin.cli) {
41
+ resolved.cli =
42
+ typeof plugin === 'string' ? tryResolve(plugin) : tryResolve(plugin.cli!);
43
43
  }
44
44
 
45
45
  if (plugin.server) {
@@ -58,11 +58,12 @@ const resolvePlugin = (appDirectory: string, plugin: PluginConfigItem) => {
58
58
  export const loadPlugins = (
59
59
  appDirectory: string,
60
60
  pluginConfig: PluginConfig,
61
+ internalPlugins?: typeof INTERNAL_PLUGINS,
61
62
  ) => {
62
63
  const plugins = [
63
- ...Object.keys(INTERNAL_PLUGINS)
64
+ ...Object.keys(internalPlugins || INTERNAL_PLUGINS)
64
65
  .filter(name => isDepExists(appDirectory, name))
65
- .map(name => INTERNAL_PLUGINS[name]),
66
+ .map(name => (internalPlugins || INTERNAL_PLUGINS)[name]),
66
67
  ...pluginConfig,
67
68
  ];
68
69
 
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ extends: ['@modern-js'],
3
+ parserOptions: {
4
+ project: require.resolve('./tsconfig.json'),
5
+ },
6
+ };
@@ -1,6 +1,5 @@
1
1
  import fs from 'fs';
2
- import { exec } from 'child_process';
3
- import { path } from '@modern-js/utils';
2
+ import path from 'path';
4
3
  import { loadEnv } from '@/loadEnv';
5
4
 
6
5
  const fixture = path.resolve(__dirname, './fixtures/load-env');
@@ -27,7 +26,7 @@ describe('load environment variables', () => {
27
26
 
28
27
  afterAll(() => {
29
28
  process.env = { ...defaultEnv };
30
- exec(`rm -rf ${fixture}`);
29
+ fs.rmSync(fixture, { force: true, recursive: true });
31
30
  });
32
31
 
33
32
  test(`support .env file`, () => {
@@ -79,6 +78,52 @@ describe('load environment variables', () => {
79
78
  delete process.env.NODE_ENV;
80
79
  });
81
80
 
81
+ test(`should have correct priority`, () => {
82
+ createFixtures('priority', [
83
+ {
84
+ name: '.env',
85
+ content: `DB_HOST=localhost
86
+ DB_USER=user
87
+ DB_PASS=pass
88
+ `,
89
+ },
90
+ {
91
+ name: '.env.production',
92
+ content: `DB_USER=user_production
93
+ DB_PASS=pass_production
94
+ FOO=foo
95
+ BAR=bar
96
+ `,
97
+ },
98
+ {
99
+ name: '.env.local',
100
+ content: `FOO=foo_local
101
+ BAR=bar_local
102
+ `,
103
+ },
104
+ {
105
+ name: '.env.production.local',
106
+ content: `BAR=bar_production_local`,
107
+ },
108
+ ]);
109
+
110
+ process.env.NODE_ENV = 'production';
111
+
112
+ loadEnv(path.join(fixture, 'priority'));
113
+
114
+ expect(process.env.DB_HOST).toBe('localhost');
115
+
116
+ expect(process.env.DB_USER).toBe('user_production');
117
+
118
+ expect(process.env.DB_PASS).toBe('pass_production');
119
+
120
+ expect(process.env.FOO).toBe('foo_local');
121
+
122
+ expect(process.env.BAR).toBe('bar_production_local');
123
+
124
+ delete process.env.NODE_ENV;
125
+ });
126
+
82
127
  test(`support dotenv-expand`, () => {
83
128
  createFixtures('expand', [
84
129
  {
@@ -1,4 +1,4 @@
1
- import { path } from '@modern-js/utils';
1
+ import path from 'path';
2
2
  import { loadPlugins } from '@/loadPlugins';
3
3
 
4
4
  describe('load plugins', () => {