@modern-js/core 1.3.2 → 1.4.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,48 @@
1
1
  # @modern-js/core
2
2
 
3
+ ## 1.4.2
4
+
5
+ ### Patch Changes
6
+
7
+ - b376c8d6: feat: enhance custom env
8
+ - e62c4efd: fix error typo for 'styledComponents'
9
+ - e2a8233f: support add schem error hook to core.init
10
+
11
+ ## 1.4.1
12
+
13
+ ### Patch Changes
14
+
15
+ - 53aca274: modify garfish-plugin config type
16
+ - 78279953: compiler entry bug fix and dev build console
17
+ - e116ace5: fix: coreOptions types
18
+ - 4d72edea: support dev compiler by entry
19
+ - Updated dependencies [78279953]
20
+ - Updated dependencies [4d72edea]
21
+ - @modern-js/utils@1.3.1
22
+
23
+ ## 1.4.0
24
+
25
+ ### Minor Changes
26
+
27
+ - bada2879: refactor plugin-garfish:
28
+ - change @modern-js/plugin-micro-frontend => @modern-js/plugin-garfish
29
+ - remove disableCustomerRouter logic
30
+ - adding unit test
31
+ - fix plugin-garfish type error
32
+
33
+ ### Patch Changes
34
+
35
+ - d9cc5ea9: support resatrt options transfer
36
+ - bd819a8d: fix: file route changed not trigger hot reload
37
+ - d099e5c5: fix error when modify modern.config.js
38
+ - 24f616ca: feat: support custom meta info
39
+ - Updated dependencies [ec4dbffb]
40
+ - Updated dependencies [d099e5c5]
41
+ - Updated dependencies [bada2879]
42
+ - Updated dependencies [24f616ca]
43
+ - Updated dependencies [bd819a8d]
44
+ - @modern-js/utils@1.3.0
45
+
3
46
  ## 1.3.2
4
47
 
5
48
  ### Patch Changes
@@ -33,8 +33,8 @@ export const loadUserConfig = async (appDirectory, filePath, packageJsonConfig)
33
33
  };
34
34
 
35
35
  const showAdditionalPropertiesError = error => {
36
- if (error.keyword === 'additionalProperties' && error.instancePath && error.params.additionalProperty) {
37
- const target = `${error.instancePath.substr(1)}.${error.params.additionalProperty}`;
36
+ if (error.keyword === 'additionalProperties' && error.params.additionalProperty) {
37
+ const target = [error.instancePath.slice(1), error.params.additionalProperty].filter(Boolean).join('.');
38
38
  const name = Object.keys(PLUGIN_SCHEMAS).find(key => PLUGIN_SCHEMAS[key].some(schemaItem => schemaItem.target === target));
39
39
 
40
40
  if (name) {
@@ -45,7 +45,7 @@ const showAdditionalPropertiesError = error => {
45
45
  /* eslint-disable max-statements, max-params */
46
46
 
47
47
 
48
- export const resolveConfig = async (loaded, configs, schemas, restartWithExistingPort, argv) => {
48
+ export const resolveConfig = async (loaded, configs, schemas, restartWithExistingPort, argv, onSchemaError = showAdditionalPropertiesError) => {
49
49
  var _validate$errors;
50
50
 
51
51
  const {
@@ -67,7 +67,7 @@ export const resolveConfig = async (loaded, configs, schemas, restartWithExistin
67
67
  if (!valid && (_validate$errors = validate.errors) !== null && _validate$errors !== void 0 && _validate$errors.length) {
68
68
  var _validate$errors2;
69
69
 
70
- showAdditionalPropertiesError(validate === null || validate === void 0 ? void 0 : validate.errors[0]);
70
+ onSchemaError(validate === null || validate === void 0 ? void 0 : validate.errors[0]);
71
71
  const errors = betterAjvErrors(validateSchema, userConfig, (_validate$errors2 = validate.errors) === null || _validate$errors2 === void 0 ? void 0 : _validate$errors2.map(e => _objectSpread(_objectSpread({}, e), {}, {
72
72
  dataPath: e.instancePath
73
73
  })), {
@@ -28,6 +28,9 @@ export const tools = {
28
28
  },
29
29
  minifyCss: {
30
30
  typeof: ['object', 'function']
31
+ },
32
+ styledComponents: {
33
+ typeof: ['object', 'function']
31
34
  }
32
35
  }
33
36
  };
@@ -9,12 +9,13 @@ export const useConfigContext = () => ConfigContext.use().value;
9
9
  export const useResolvedConfigContext = () => ResolvedConfigContext.use().value;
10
10
  export const initAppContext = (appDirectory, plugins, configFile, options) => {
11
11
  const {
12
+ metaName = 'modern-js',
12
13
  srcDir = 'src',
13
14
  distDir = '',
14
- sharedDir = 'shared',
15
- internalDir = '.modern-js'
15
+ sharedDir = 'shared'
16
16
  } = options || {};
17
17
  return {
18
+ metaName,
18
19
  appDirectory,
19
20
  configFile,
20
21
  ip: address.ip(),
@@ -24,10 +25,14 @@ export const initAppContext = (appDirectory, plugins, configFile, options) => {
24
25
  distDirectory: distDir,
25
26
  sharedDirectory: path.resolve(appDirectory, sharedDir),
26
27
  nodeModulesDirectory: path.resolve(appDirectory, './node_modules'),
27
- internalDirectory: path.resolve(appDirectory, `./node_modules/${internalDir}`),
28
+ internalDirectory: path.resolve(appDirectory, `./node_modules/.${metaName}`),
28
29
  plugins,
29
30
  htmlTemplates: {},
30
31
  serverRoutes: [],
31
- entrypoints: []
32
+ entrypoints: [],
33
+ checkedEntries: [],
34
+ existSrc: true,
35
+ internalDirAlias: `@_${metaName.replace(/-/g, '_')}_internal`,
36
+ internalSrcAlias: `@_${metaName.replace(/-/g, '_')}_src`
32
37
  };
33
38
  };
@@ -28,7 +28,9 @@ const hooksMap = {
28
28
  watchFiles: createParallelWorkflow(),
29
29
  fileChange: createAsyncWorkflow(),
30
30
  // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
31
- beforeExit: createAsyncWorkflow()
31
+ beforeExit: createAsyncWorkflow(),
32
+ // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
33
+ beforeRestart: createAsyncWorkflow()
32
34
  };
33
35
  export const manager = createAsyncManager(hooksMap);
34
36
  export const {
@@ -60,12 +62,17 @@ const createCli = () => {
60
62
  let hooksRunner;
61
63
  let isRestart = false;
62
64
  let restartWithExistingPort = 0;
65
+ let restartOptions; // eslint-disable-next-line max-statements
63
66
 
64
67
  const init = async (argv = [], options) => {
68
+ var _options$options$meta, _options$options;
69
+
65
70
  enable();
66
71
  manager.clear();
72
+ restartOptions = options;
67
73
  const appDirectory = await initAppDir();
68
- loadEnv(appDirectory);
74
+ const metaName = (_options$options$meta = options === null || options === void 0 ? void 0 : (_options$options = options.options) === null || _options$options === void 0 ? void 0 : _options$options.metaName) !== null && _options$options$meta !== void 0 ? _options$options$meta : 'MODERN';
75
+ loadEnv(appDirectory, process.env[`${metaName.toUpperCase()}_ENV`]);
69
76
  const loaded = await loadUserConfig(appDirectory, options === null || options === void 0 ? void 0 : options.configFile, options === null || options === void 0 ? void 0 : options.packageJsonConfig);
70
77
  let plugins = loadPlugins(appDirectory, loaded.config.plugins || [], options === null || options === void 0 ? void 0 : options.plugins);
71
78
 
@@ -96,7 +103,7 @@ const createCli = () => {
96
103
  });
97
104
  const extraConfigs = await hooksRunner.config();
98
105
  const extraSchemas = await hooksRunner.validateSchema();
99
- const config = await resolveConfig(loaded, extraConfigs, extraSchemas, restartWithExistingPort, argv);
106
+ const config = await resolveConfig(loaded, extraConfigs, extraSchemas, restartWithExistingPort, argv, options === null || options === void 0 ? void 0 : options.onSchemaError);
100
107
  const {
101
108
  resolved
102
109
  } = await hooksRunner.resolvedConfig({
@@ -139,9 +146,11 @@ const createCli = () => {
139
146
  restartWithExistingPort = isRestart ? (_AppContext$use$value = (_AppContext$use$value2 = AppContext.use().value) === null || _AppContext$use$value2 === void 0 ? void 0 : _AppContext$use$value2.port) !== null && _AppContext$use$value !== void 0 ? _AppContext$use$value : 0 : 0;
140
147
  logger.info('Restart...\n');
141
148
  let hasGetError = false;
149
+ const runner = manager.useRunner();
150
+ await runner.beforeRestart();
142
151
 
143
152
  try {
144
- await init(process.argv.slice(2));
153
+ await init(process.argv.slice(2), restartOptions);
145
154
  } catch (err) {
146
155
  console.error(err);
147
156
  hasGetError = true;
@@ -1,7 +1,7 @@
1
1
  import crypto from 'crypto';
2
2
  import fs from 'fs';
3
3
  import path from 'path';
4
- import { isDev, createDebugger } from '@modern-js/utils';
4
+ import { isDev, createDebugger, isTest } from '@modern-js/utils';
5
5
  import chokidar from 'chokidar';
6
6
  const debug = createDebugger('watch-files');
7
7
 
@@ -10,7 +10,7 @@ const md5 = data => crypto.createHash('md5').update(data).digest('hex');
10
10
  const hashMap = new Map();
11
11
  export const initWatcher = async (loaded, appDirectory, configDir, hooksRunner, argv) => {
12
12
  // only add fs watcher on dev mode.
13
- if (isDev() && argv[0] === 'dev') {
13
+ if ((isDev() || isTest()) && argv[0] === 'dev') {
14
14
  const extraFiles = await hooksRunner.watchFiles();
15
15
  const configPath = path.join(appDirectory, configDir);
16
16
  const watched = [`${configPath}/html`, ...extraFiles, loaded === null || loaded === void 0 ? void 0 : loaded.filePath, ...loaded.dependencies].filter(Boolean);
@@ -28,19 +28,35 @@ export const initWatcher = async (loaded, appDirectory, configDir, hooksRunner,
28
28
  debug(`file change: %s`, changed);
29
29
  hashMap.set(changed, currentHash);
30
30
  hooksRunner.fileChange({
31
- filename: changed
31
+ filename: changed,
32
+ eventType: 'change'
32
33
  });
33
34
  }
34
35
  });
36
+ watcher.on('add', name => {
37
+ debug(`add file: %s`, name);
38
+ const currentHash = md5(fs.readFileSync(path.join(appDirectory, name), 'utf8'));
39
+ hashMap.set(name, currentHash);
40
+ hooksRunner.fileChange({
41
+ filename: name,
42
+ eventType: 'add'
43
+ });
44
+ });
35
45
  watcher.on('unlink', name => {
36
46
  debug(`remove file: %s`, name);
37
47
 
38
48
  if (hashMap.has(name)) {
39
49
  hashMap.delete(name);
40
50
  }
51
+
52
+ hooksRunner.fileChange({
53
+ filename: name,
54
+ eventType: 'unlink'
55
+ });
41
56
  });
42
57
  watcher.on('error', err => {
43
58
  throw err;
44
59
  });
60
+ return watcher;
45
61
  }
46
62
  };
@@ -81,12 +81,13 @@ export const loadPlugins = (appDirectory, pluginConfig, internalPlugins) => {
81
81
 
82
82
  const cliPlugin = cli && _objectSpread(_objectSpread({}, compatRequire(cli)), {}, {
83
83
  pluginPath: cli
84
- });
84
+ }); // server plugin should be required by server
85
85
 
86
- const serverPlugin = server && _objectSpread(_objectSpread({}, compatRequire(server)), {}, {
87
- pluginPath: server
88
- });
89
86
 
87
+ const serverPlugin = server && {
88
+ // ...compatRequire(server),
89
+ pluginPath: server
90
+ };
90
91
  return {
91
92
  cli: cliPlugin,
92
93
  cliPath: typeof plugin === 'string' ? plugin : plugin.cli,
@@ -71,8 +71,8 @@ const loadUserConfig = async (appDirectory, filePath, packageJsonConfig) => {
71
71
  exports.loadUserConfig = loadUserConfig;
72
72
 
73
73
  const showAdditionalPropertiesError = error => {
74
- if (error.keyword === 'additionalProperties' && error.instancePath && error.params.additionalProperty) {
75
- const target = `${error.instancePath.substr(1)}.${error.params.additionalProperty}`;
74
+ if (error.keyword === 'additionalProperties' && error.params.additionalProperty) {
75
+ const target = [error.instancePath.slice(1), error.params.additionalProperty].filter(Boolean).join('.');
76
76
  const name = Object.keys(_utils.PLUGIN_SCHEMAS).find(key => _utils.PLUGIN_SCHEMAS[key].some(schemaItem => schemaItem.target === target));
77
77
 
78
78
  if (name) {
@@ -83,7 +83,7 @@ const showAdditionalPropertiesError = error => {
83
83
  /* eslint-disable max-statements, max-params */
84
84
 
85
85
 
86
- const resolveConfig = async (loaded, configs, schemas, restartWithExistingPort, argv) => {
86
+ const resolveConfig = async (loaded, configs, schemas, restartWithExistingPort, argv, onSchemaError = showAdditionalPropertiesError) => {
87
87
  var _validate$errors;
88
88
 
89
89
  const {
@@ -105,7 +105,7 @@ const resolveConfig = async (loaded, configs, schemas, restartWithExistingPort,
105
105
  if (!valid && (_validate$errors = validate.errors) !== null && _validate$errors !== void 0 && _validate$errors.length) {
106
106
  var _validate$errors2;
107
107
 
108
- showAdditionalPropertiesError(validate === null || validate === void 0 ? void 0 : validate.errors[0]);
108
+ onSchemaError(validate === null || validate === void 0 ? void 0 : validate.errors[0]);
109
109
  const errors = (0, _betterAjvErrors.default)(validateSchema, userConfig, (_validate$errors2 = validate.errors) === null || _validate$errors2 === void 0 ? void 0 : _validate$errors2.map(e => _objectSpread(_objectSpread({}, e), {}, {
110
110
  dataPath: e.instancePath
111
111
  })), {
@@ -34,6 +34,9 @@ const tools = {
34
34
  },
35
35
  minifyCss: {
36
36
  typeof: ['object', 'function']
37
+ },
38
+ styledComponents: {
39
+ typeof: ['object', 'function']
37
40
  }
38
41
  }
39
42
  };
@@ -34,12 +34,13 @@ exports.useResolvedConfigContext = useResolvedConfigContext;
34
34
 
35
35
  const initAppContext = (appDirectory, plugins, configFile, options) => {
36
36
  const {
37
+ metaName = 'modern-js',
37
38
  srcDir = 'src',
38
39
  distDir = '',
39
- sharedDir = 'shared',
40
- internalDir = '.modern-js'
40
+ sharedDir = 'shared'
41
41
  } = options || {};
42
42
  return {
43
+ metaName,
43
44
  appDirectory,
44
45
  configFile,
45
46
  ip: _address.default.ip(),
@@ -49,11 +50,15 @@ const initAppContext = (appDirectory, plugins, configFile, options) => {
49
50
  distDirectory: distDir,
50
51
  sharedDirectory: _path.default.resolve(appDirectory, sharedDir),
51
52
  nodeModulesDirectory: _path.default.resolve(appDirectory, './node_modules'),
52
- internalDirectory: _path.default.resolve(appDirectory, `./node_modules/${internalDir}`),
53
+ internalDirectory: _path.default.resolve(appDirectory, `./node_modules/.${metaName}`),
53
54
  plugins,
54
55
  htmlTemplates: {},
55
56
  serverRoutes: [],
56
- entrypoints: []
57
+ entrypoints: [],
58
+ checkedEntries: [],
59
+ existSrc: true,
60
+ internalDirAlias: `@_${metaName.replace(/-/g, '_')}_internal`,
61
+ internalSrcAlias: `@_${metaName.replace(/-/g, '_')}_src`
57
62
  };
58
63
  };
59
64
 
@@ -141,7 +141,9 @@ const hooksMap = {
141
141
  watchFiles: (0, _plugin.createParallelWorkflow)(),
142
142
  fileChange: (0, _plugin.createAsyncWorkflow)(),
143
143
  // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
144
- beforeExit: (0, _plugin.createAsyncWorkflow)()
144
+ beforeExit: (0, _plugin.createAsyncWorkflow)(),
145
+ // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
146
+ beforeRestart: (0, _plugin.createAsyncWorkflow)()
145
147
  };
146
148
  const manager = (0, _plugin.createAsyncManager)(hooksMap);
147
149
  exports.manager = manager;
@@ -181,12 +183,17 @@ const createCli = () => {
181
183
  let hooksRunner;
182
184
  let isRestart = false;
183
185
  let restartWithExistingPort = 0;
186
+ let restartOptions; // eslint-disable-next-line max-statements
184
187
 
185
188
  const init = async (argv = [], options) => {
189
+ var _options$options$meta, _options$options;
190
+
186
191
  (0, _node.enable)();
187
192
  manager.clear();
193
+ restartOptions = options;
188
194
  const appDirectory = await initAppDir();
189
- (0, _loadEnv.loadEnv)(appDirectory);
195
+ const metaName = (_options$options$meta = options === null || options === void 0 ? void 0 : (_options$options = options.options) === null || _options$options === void 0 ? void 0 : _options$options.metaName) !== null && _options$options$meta !== void 0 ? _options$options$meta : 'MODERN';
196
+ (0, _loadEnv.loadEnv)(appDirectory, process.env[`${metaName.toUpperCase()}_ENV`]);
190
197
  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);
191
198
  let plugins = (0, _loadPlugins.loadPlugins)(appDirectory, loaded.config.plugins || [], options === null || options === void 0 ? void 0 : options.plugins);
192
199
 
@@ -218,7 +225,7 @@ const createCli = () => {
218
225
  });
219
226
  const extraConfigs = await hooksRunner.config();
220
227
  const extraSchemas = await hooksRunner.validateSchema();
221
- const config = await (0, _config.resolveConfig)(loaded, extraConfigs, extraSchemas, restartWithExistingPort, argv);
228
+ const config = await (0, _config.resolveConfig)(loaded, extraConfigs, extraSchemas, restartWithExistingPort, argv, options === null || options === void 0 ? void 0 : options.onSchemaError);
222
229
  const {
223
230
  resolved
224
231
  } = await hooksRunner.resolvedConfig({
@@ -265,9 +272,11 @@ const createCli = () => {
265
272
  _utils.logger.info('Restart...\n');
266
273
 
267
274
  let hasGetError = false;
275
+ const runner = manager.useRunner();
276
+ await runner.beforeRestart();
268
277
 
269
278
  try {
270
- await init(process.argv.slice(2));
279
+ await init(process.argv.slice(2), restartOptions);
271
280
  } catch (err) {
272
281
  console.error(err);
273
282
  hasGetError = true;
@@ -25,7 +25,7 @@ const hashMap = new Map();
25
25
 
26
26
  const initWatcher = async (loaded, appDirectory, configDir, hooksRunner, argv) => {
27
27
  // only add fs watcher on dev mode.
28
- if ((0, _utils.isDev)() && argv[0] === 'dev') {
28
+ if (((0, _utils.isDev)() || (0, _utils.isTest)()) && argv[0] === 'dev') {
29
29
  const extraFiles = await hooksRunner.watchFiles();
30
30
 
31
31
  const configPath = _path.default.join(appDirectory, configDir);
@@ -47,20 +47,36 @@ const initWatcher = async (loaded, appDirectory, configDir, hooksRunner, argv) =
47
47
  debug(`file change: %s`, changed);
48
48
  hashMap.set(changed, currentHash);
49
49
  hooksRunner.fileChange({
50
- filename: changed
50
+ filename: changed,
51
+ eventType: 'change'
51
52
  });
52
53
  }
53
54
  });
55
+ watcher.on('add', name => {
56
+ debug(`add file: %s`, name);
57
+ const currentHash = md5(_fs.default.readFileSync(_path.default.join(appDirectory, name), 'utf8'));
58
+ hashMap.set(name, currentHash);
59
+ hooksRunner.fileChange({
60
+ filename: name,
61
+ eventType: 'add'
62
+ });
63
+ });
54
64
  watcher.on('unlink', name => {
55
65
  debug(`remove file: %s`, name);
56
66
 
57
67
  if (hashMap.has(name)) {
58
68
  hashMap.delete(name);
59
69
  }
70
+
71
+ hooksRunner.fileChange({
72
+ filename: name,
73
+ eventType: 'unlink'
74
+ });
60
75
  });
61
76
  watcher.on('error', err => {
62
77
  throw err;
63
78
  });
79
+ return watcher;
64
80
  }
65
81
  };
66
82
 
@@ -91,12 +91,13 @@ const loadPlugins = (appDirectory, pluginConfig, internalPlugins) => {
91
91
 
92
92
  const cliPlugin = cli && _objectSpread(_objectSpread({}, (0, _utils.compatRequire)(cli)), {}, {
93
93
  pluginPath: cli
94
- });
94
+ }); // server plugin should be required by server
95
95
 
96
- const serverPlugin = server && _objectSpread(_objectSpread({}, (0, _utils.compatRequire)(server)), {}, {
97
- pluginPath: server
98
- });
99
96
 
97
+ const serverPlugin = server && {
98
+ // ...compatRequire(server),
99
+ pluginPath: server
100
+ };
100
101
  return {
101
102
  cli: cliPlugin,
102
103
  cliPath: typeof plugin === 'string' ? plugin : plugin.cli,
@@ -1,3 +1,4 @@
1
+ import { ErrorObject } from 'ajv';
1
2
  import { MetaOptions } from '@modern-js/utils';
2
3
  import { PluginConfig } from '../loadPlugins';
3
4
  import { defaults } from './defaults';
@@ -80,8 +81,13 @@ interface DevConfig {
80
81
  assetPrefix?: string | boolean;
81
82
  https?: boolean;
82
83
  }
84
+ interface MicroFrontend {
85
+ enableHtmlEntry?: boolean;
86
+ externalBasicLibrary?: boolean;
87
+ moduleApp?: string;
88
+ }
83
89
  interface DeployConfig {
84
- microFrontend?: boolean & Record<string, unknown>;
90
+ microFrontend?: false | MicroFrontend;
85
91
  domain?: string | Array<string>;
86
92
  domainByEntries?: Record<string, string | Array<string>>;
87
93
  }
@@ -123,5 +129,5 @@ interface LoadedConfig {
123
129
  }
124
130
  export declare const defineConfig: (config: ConfigParam) => ConfigParam;
125
131
  export declare const loadUserConfig: (appDirectory: string, filePath?: string | undefined, packageJsonConfig?: string | undefined) => Promise<LoadedConfig>;
126
- export declare const resolveConfig: (loaded: LoadedConfig, configs: UserConfig[], schemas: PluginValidateSchema[], restartWithExistingPort: number, argv: string[]) => Promise<NormalizedConfig>;
132
+ export declare const resolveConfig: (loaded: LoadedConfig, configs: UserConfig[], schemas: PluginValidateSchema[], restartWithExistingPort: number, argv: string[], onSchemaError?: (error: ErrorObject) => void) => Promise<NormalizedConfig>;
127
133
  export type { SourceConfig, OutputConfig, ServerConfig, DevConfig, DeployConfig, ToolsConfig, RuntimeConfig, RuntimeByEntriesConfig, UserConfig, ConfigParam, LoadedConfig };
@@ -456,6 +456,9 @@ export declare const patchSchema: (pluginSchemas: Array<PluginValidateSchema | P
456
456
  minifyCss: {
457
457
  typeof: string[];
458
458
  };
459
+ styledComponents: {
460
+ typeof: string[];
461
+ };
459
462
  };
460
463
  };
461
464
  };
@@ -29,5 +29,8 @@ export declare const tools: {
29
29
  minifyCss: {
30
30
  typeof: string[];
31
31
  };
32
+ styledComponents: {
33
+ typeof: string[];
34
+ };
32
35
  };
33
36
  };
@@ -12,8 +12,8 @@ export declare const initAppContext: (appDirectory: string, plugins: Array<{
12
12
  cli: any;
13
13
  server: any;
14
14
  }>, configFile: string | false, options?: {
15
+ metaName?: string | undefined;
15
16
  srcDir?: string | undefined;
16
17
  distDir?: string | undefined;
17
18
  sharedDir?: string | undefined;
18
- internalDir?: string | undefined;
19
19
  } | undefined) => IAppContext;
@@ -1,6 +1,7 @@
1
1
  import { INTERNAL_PLUGINS } from '@modern-js/utils';
2
2
  import { ParallelWorkflow, AsyncWorkflow, Progresses2Runners, AsyncWaterfall } from '@modern-js/plugin';
3
3
  import type { Hooks } from '@modern-js/types';
4
+ import { ErrorObject } from 'ajv';
4
5
  import { Command } from './utils/commander';
5
6
  import { AppContext, ConfigContext, IAppContext, initAppContext, ResolvedConfigContext, useAppContext, useConfigContext, useResolvedConfigContext } from './context';
6
7
  import { NormalizedConfig } from './config/mergeConfig';
@@ -21,6 +22,7 @@ export declare type HooksRunner = Progresses2Runners<{
21
22
  watchFiles: ParallelWorkflow<void>;
22
23
  fileChange: AsyncWorkflow<{
23
24
  filename: string;
25
+ eventType: 'add' | 'change' | 'unlink';
24
26
  }, void>;
25
27
  beforeExit: AsyncWorkflow<void, void>;
26
28
  }>;
@@ -37,8 +39,10 @@ export declare const manager: import("@modern-js/plugin").AsyncManager<Hooks, {
37
39
  watchFiles: ParallelWorkflow<void, unknown>;
38
40
  fileChange: AsyncWorkflow<{
39
41
  filename: string;
42
+ eventType: 'add' | 'change' | 'unlink';
40
43
  }, void>;
41
44
  beforeExit: AsyncWorkflow<void, void>;
45
+ beforeRestart: AsyncWorkflow<void, void>;
42
46
  }>;
43
47
  export declare const createPlugin: (initializer: import("@modern-js/plugin").AsyncInitializer<Partial<import("@modern-js/plugin").Progresses2Threads<{
44
48
  config: ParallelWorkflow<void, unknown>;
@@ -53,8 +57,10 @@ export declare const createPlugin: (initializer: import("@modern-js/plugin").Asy
53
57
  watchFiles: ParallelWorkflow<void, unknown>;
54
58
  fileChange: AsyncWorkflow<{
55
59
  filename: string;
60
+ eventType: 'add' | 'change' | 'unlink';
56
61
  }, void>;
57
62
  beforeExit: AsyncWorkflow<void, void>;
63
+ beforeRestart: AsyncWorkflow<void, void>;
58
64
  } & import("@modern-js/plugin").ClearDraftProgress<Hooks>>>>, options?: import("@modern-js/plugin").PluginOptions | undefined) => import("@modern-js/plugin").AsyncPlugin<Partial<import("@modern-js/plugin").Progresses2Threads<{
59
65
  config: ParallelWorkflow<void, unknown>;
60
66
  resolvedConfig: AsyncWaterfall<{
@@ -68,8 +74,10 @@ export declare const createPlugin: (initializer: import("@modern-js/plugin").Asy
68
74
  watchFiles: ParallelWorkflow<void, unknown>;
69
75
  fileChange: AsyncWorkflow<{
70
76
  filename: string;
77
+ eventType: 'add' | 'change' | 'unlink';
71
78
  }, void>;
72
79
  beforeExit: AsyncWorkflow<void, void>;
80
+ beforeRestart: AsyncWorkflow<void, void>;
73
81
  } & import("@modern-js/plugin").ClearDraftProgress<Hooks>>>>, registerHook: (newShape: Partial<Hooks>) => void, mountHook: () => Progresses2Runners<{
74
82
  config: ParallelWorkflow<void, unknown>;
75
83
  resolvedConfig: AsyncWaterfall<{
@@ -83,8 +91,10 @@ export declare const createPlugin: (initializer: import("@modern-js/plugin").Asy
83
91
  watchFiles: ParallelWorkflow<void, unknown>;
84
92
  fileChange: AsyncWorkflow<{
85
93
  filename: string;
94
+ eventType: 'add' | 'change' | 'unlink';
86
95
  }, void>;
87
96
  beforeExit: AsyncWorkflow<void, void>;
97
+ beforeRestart: AsyncWorkflow<void, void>;
88
98
  } & import("@modern-js/plugin").ClearDraftProgress<Hooks>>;
89
99
  export declare const usePlugins: (plugins: string[]) => void;
90
100
  export { AppContext, ResolvedConfigContext, useAppContext, useConfigContext, useResolvedConfigContext, ConfigContext };
@@ -100,11 +110,12 @@ export interface CoreOptions {
100
110
  server: any;
101
111
  serverPath: any;
102
112
  }[];
113
+ onSchemaError?: (error: ErrorObject) => void;
103
114
  options?: {
115
+ metaName?: string;
104
116
  srcDir?: string;
105
117
  distDir?: string;
106
118
  sharedDir?: string;
107
- internalDir?: string;
108
119
  };
109
120
  }
110
121
  export declare const cli: {
@@ -1,3 +1,4 @@
1
+ import chokidar from 'chokidar';
1
2
  import { LoadedConfig } from './config';
2
3
  import { HooksRunner } from '.';
3
- export declare const initWatcher: (loaded: LoadedConfig, appDirectory: string, configDir: string | undefined, hooksRunner: HooksRunner, argv: string[]) => Promise<void>;
4
+ export declare const initWatcher: (loaded: LoadedConfig, appDirectory: string, configDir: string | undefined, hooksRunner: HooksRunner, argv: string[]) => Promise<chokidar.FSWatcher | undefined>;
@@ -23,6 +23,8 @@ export declare const loadPlugins: (appDirectory: string, pluginConfig: PluginCon
23
23
  } | undefined) => {
24
24
  cli: any;
25
25
  cliPath: string | undefined;
26
- server: any;
26
+ server: "" | {
27
+ pluginPath: string;
28
+ } | undefined;
27
29
  serverPath: string | undefined;
28
30
  }[];
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "modern",
12
12
  "modern.js"
13
13
  ],
14
- "version": "1.3.2",
14
+ "version": "1.4.2",
15
15
  "jsnext:source": "./src/index.ts",
16
16
  "types": "./dist/types/index.d.ts",
17
17
  "main": "./dist/js/node/index.js",
@@ -44,7 +44,7 @@
44
44
  "@babel/runtime": "^7",
45
45
  "@modern-js/load-config": "^1.2.1",
46
46
  "@modern-js/plugin": "^1.2.1",
47
- "@modern-js/utils": "^1.2.2",
47
+ "@modern-js/utils": "^1.3.1",
48
48
  "address": "^1.1.2",
49
49
  "ajv": "^8.6.2",
50
50
  "ajv-keywords": "^5.0.0",
@@ -62,7 +62,7 @@
62
62
  "devDependencies": {
63
63
  "btsm": "2.2.2",
64
64
  "@types/babel__code-frame": "^7.0.3",
65
- "@modern-js/types": "^1.2.1",
65
+ "@modern-js/types": "^1.3.2",
66
66
  "@types/jest": "^26",
67
67
  "@types/lodash.clonedeep": "^4.5.6",
68
68
  "@types/lodash.mergewith": "^4.6.6",
@@ -83,8 +83,7 @@
83
83
  },
84
84
  "publishConfig": {
85
85
  "registry": "https://registry.npmjs.org/",
86
- "access": "public",
87
- "types": "./dist/types/index.d.ts"
86
+ "access": "public"
88
87
  },
89
88
  "scripts": {
90
89
  "new": "modern new",
@@ -23,6 +23,11 @@ describe('context', () => {
23
23
  htmlTemplates: {},
24
24
  serverRoutes: [],
25
25
  entrypoints: [],
26
+ checkedEntries: [],
27
+ existSrc: true,
28
+ internalDirAlias: '@_modern_js_internal',
29
+ internalSrcAlias: '@_modern_js_src',
30
+ metaName: 'modern-js',
26
31
  });
27
32
  });
28
33
 
@@ -36,7 +41,7 @@ describe('context', () => {
36
41
  srcDir: 'source',
37
42
  distDir: 'dist',
38
43
  sharedDir: 'myShared',
39
- internalDir: 'myInternal',
44
+ metaName: 'jupiter',
40
45
  };
41
46
 
42
47
  const appContext = initAppContext(appDirectory, [], false, customOptions);
@@ -50,14 +55,16 @@ describe('context', () => {
50
55
  distDirectory: 'dist',
51
56
  sharedDirectory: path.resolve(appDirectory, './myShared'),
52
57
  nodeModulesDirectory: expect.any(String),
53
- internalDirectory: path.resolve(
54
- appDirectory,
55
- './node_modules/myInternal',
56
- ),
58
+ internalDirectory: path.resolve(appDirectory, './node_modules/.jupiter'),
57
59
  plugins: [],
58
60
  htmlTemplates: {},
59
61
  serverRoutes: [],
60
62
  entrypoints: [],
63
+ checkedEntries: [],
64
+ existSrc: true,
65
+ internalDirAlias: '@_jupiter_internal',
66
+ internalSrcAlias: '@_jupiter_src',
67
+ metaName: 'jupiter',
61
68
  });
62
69
  });
63
70
  });
@@ -67,7 +67,7 @@ describe('@modern-js/core test', () => {
67
67
  };
68
68
  options.beforeUsePlugins.mockImplementation((plugins, _) => plugins);
69
69
  await cli.init(['dev'], options);
70
- expect(loadEnv).toHaveBeenCalledWith(cwd);
70
+ expect(loadEnv).toHaveBeenCalledWith(cwd, undefined);
71
71
  expect(options.beforeUsePlugins).toHaveBeenCalledWith([], {});
72
72
  // TODO: add more test cases
73
73
  });
@@ -0,0 +1,63 @@
1
+ import * as path from 'path';
2
+ import { fs, wait } from '@modern-js/utils';
3
+ import { initWatcher } from '../src/initWatcher';
4
+
5
+ jest.useRealTimers();
6
+
7
+ const mockAppDirectory = path.join(__dirname, './fixtures/index-test');
8
+ const mockConfigDir = './config';
9
+ const mockSrcDirectory = path.join(mockAppDirectory, './src');
10
+
11
+ describe('initWatcher', () => {
12
+ afterAll(() => {
13
+ const file = path.join(mockSrcDirectory, './index.ts');
14
+ if (fs.existsSync(file)) {
15
+ fs.unlinkSync(file);
16
+ }
17
+ });
18
+
19
+ test('will trigger add event', async () => {
20
+ let triggeredType = '';
21
+ let triggeredFile = '';
22
+ const loaded = {
23
+ filePath: '',
24
+ dependencies: [],
25
+ };
26
+ const hooksRunner = {
27
+ watchFiles: async () => [mockSrcDirectory],
28
+ fileChange: jest.fn(({ filename, eventType }) => {
29
+ triggeredType = eventType;
30
+ triggeredFile = filename;
31
+ }),
32
+ };
33
+
34
+ if (await fs.pathExists(mockSrcDirectory)) {
35
+ await fs.remove(mockSrcDirectory);
36
+ }
37
+
38
+ const watcher = await initWatcher(
39
+ loaded as any,
40
+ mockAppDirectory,
41
+ mockConfigDir,
42
+ hooksRunner as any,
43
+ ['dev'],
44
+ );
45
+ await wait(100);
46
+
47
+ const file = path.join(mockSrcDirectory, './index.ts');
48
+ await fs.outputFile(file, '');
49
+ await wait(100);
50
+ // expect(hooksRunner.fileChange).toBeCalledTimes(1);
51
+ // expect(triggeredType).toBe('add');
52
+ expect(file.includes(triggeredFile)).toBeTruthy();
53
+
54
+ await wait(100);
55
+ await fs.remove(file);
56
+ await wait(200);
57
+ expect(hooksRunner.fileChange).toBeCalledTimes(2);
58
+ expect(triggeredType).toBe('unlink');
59
+ expect(file.includes(triggeredFile)).toBeTruthy();
60
+
61
+ watcher?.close();
62
+ });
63
+ });
@@ -124,6 +124,34 @@ describe('load environment variables', () => {
124
124
  delete process.env.NODE_ENV;
125
125
  });
126
126
 
127
+ test(`get custom .env file by MODERN_ENV`, () => {
128
+ createFixtures('custom_environment', [
129
+ {
130
+ name: '.env',
131
+ content: `DB_HOST=localhost
132
+ DB_USER=root
133
+ DB_PASS=root
134
+ `,
135
+ },
136
+ {
137
+ name: '.env.staging',
138
+ content: `DB_HOST=localhost
139
+ DB_USER=root-local-dev
140
+ `,
141
+ },
142
+ ]);
143
+
144
+ loadEnv(path.join(fixture, 'custom_environment'), 'staging');
145
+
146
+ expect(process.env.DB_HOST).toBe('localhost');
147
+
148
+ expect(process.env.DB_USER).toBe('root-local-dev');
149
+
150
+ expect(process.env.DB_PASS).toBe('root');
151
+
152
+ delete process.env.MODERN_ENV;
153
+ });
154
+
127
155
  test(`support dotenv-expand`, () => {
128
156
  createFixtures('expand', [
129
157
  {
@@ -37,7 +37,6 @@ describe('load plugins', () => {
37
37
  },
38
38
  {
39
39
  server: {
40
- name: 'b',
41
40
  pluginPath: path.join(fixture, './test-plugin-b.js'),
42
41
  },
43
42
  serverPath: './test-plugin-b',