@modern-js/plugin-v2 0.0.0-next-20241113090110
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/LICENSE +21 -0
- package/README.md +26 -0
- package/dist/cjs/cli/api.js +107 -0
- package/dist/cjs/cli/context.js +75 -0
- package/dist/cjs/cli/hooks.js +65 -0
- package/dist/cjs/cli/index.js +43 -0
- package/dist/cjs/cli/run/config/createLoadedConfig.js +99 -0
- package/dist/cjs/cli/run/config/createResolvedConfig.js +40 -0
- package/dist/cjs/cli/run/config/loadConfig.js +117 -0
- package/dist/cjs/cli/run/create.js +125 -0
- package/dist/cjs/cli/run/index.js +29 -0
- package/dist/cjs/cli/run/run.js +58 -0
- package/dist/cjs/cli/run/types.js +16 -0
- package/dist/cjs/cli/run/utils/checkIsDuplicationPlugin.js +45 -0
- package/dist/cjs/cli/run/utils/commander.js +50 -0
- package/dist/cjs/cli/run/utils/createFileWatcher.js +114 -0
- package/dist/cjs/cli/run/utils/initAppDir.js +49 -0
- package/dist/cjs/cli/run/utils/loadEnv.js +53 -0
- package/dist/cjs/cli/run/utils/mergeConfig.js +62 -0
- package/dist/cjs/hooks.js +69 -0
- package/dist/cjs/index.js +38 -0
- package/dist/cjs/manager.js +141 -0
- package/dist/cjs/types/cli/api.js +16 -0
- package/dist/cjs/types/cli/context.js +16 -0
- package/dist/cjs/types/cli/hooks.js +16 -0
- package/dist/cjs/types/cli/index.js +16 -0
- package/dist/cjs/types/cli/plugin.js +16 -0
- package/dist/cjs/types/hooks.js +16 -0
- package/dist/cjs/types/index.js +24 -0
- package/dist/cjs/types/plugin.js +16 -0
- package/dist/cjs/types/utils.js +16 -0
- package/dist/esm/index.js +1499 -0
- package/dist/esm-node/cli/api.js +83 -0
- package/dist/esm-node/cli/context.js +40 -0
- package/dist/esm-node/cli/hooks.js +41 -0
- package/dist/esm-node/cli/index.js +14 -0
- package/dist/esm-node/cli/run/config/createLoadedConfig.js +74 -0
- package/dist/esm-node/cli/run/config/createResolvedConfig.js +16 -0
- package/dist/esm-node/cli/run/config/loadConfig.js +80 -0
- package/dist/esm-node/cli/run/create.js +101 -0
- package/dist/esm-node/cli/run/index.js +5 -0
- package/dist/esm-node/cli/run/run.js +34 -0
- package/dist/esm-node/cli/run/types.js +0 -0
- package/dist/esm-node/cli/run/utils/checkIsDuplicationPlugin.js +21 -0
- package/dist/esm-node/cli/run/utils/commander.js +24 -0
- package/dist/esm-node/cli/run/utils/createFileWatcher.js +80 -0
- package/dist/esm-node/cli/run/utils/initAppDir.js +15 -0
- package/dist/esm-node/cli/run/utils/loadEnv.js +19 -0
- package/dist/esm-node/cli/run/utils/mergeConfig.js +38 -0
- package/dist/esm-node/hooks.js +44 -0
- package/dist/esm-node/index.js +9 -0
- package/dist/esm-node/manager.js +117 -0
- package/dist/esm-node/types/cli/api.js +0 -0
- package/dist/esm-node/types/cli/context.js +0 -0
- package/dist/esm-node/types/cli/hooks.js +0 -0
- package/dist/esm-node/types/cli/index.js +0 -0
- package/dist/esm-node/types/cli/plugin.js +0 -0
- package/dist/esm-node/types/hooks.js +0 -0
- package/dist/esm-node/types/index.js +2 -0
- package/dist/esm-node/types/plugin.js +0 -0
- package/dist/esm-node/types/utils.js +0 -0
- package/dist/types/cli/api.d.ts +7 -0
- package/dist/types/cli/context.d.ts +18 -0
- package/dist/types/cli/hooks.d.ts +39 -0
- package/dist/types/cli/index.d.ts +6 -0
- package/dist/types/cli/run/config/createLoadedConfig.d.ts +6 -0
- package/dist/types/cli/run/config/createResolvedConfig.d.ts +3 -0
- package/dist/types/cli/run/config/loadConfig.d.ts +25 -0
- package/dist/types/cli/run/create.d.ts +7 -0
- package/dist/types/cli/run/index.d.ts +6 -0
- package/dist/types/cli/run/run.d.ts +2 -0
- package/dist/types/cli/run/types.d.ts +29 -0
- package/dist/types/cli/run/utils/checkIsDuplicationPlugin.d.ts +1 -0
- package/dist/types/cli/run/utils/commander.d.ts +5 -0
- package/dist/types/cli/run/utils/createFileWatcher.d.ts +2 -0
- package/dist/types/cli/run/utils/initAppDir.d.ts +1 -0
- package/dist/types/cli/run/utils/loadEnv.d.ts +1 -0
- package/dist/types/cli/run/utils/mergeConfig.d.ts +2 -0
- package/dist/types/hooks.d.ts +3 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/manager.d.ts +2 -0
- package/dist/types/types/cli/api.d.ts +42 -0
- package/dist/types/types/cli/context.d.ts +40 -0
- package/dist/types/types/cli/hooks.d.ts +41 -0
- package/dist/types/types/cli/index.d.ts +3 -0
- package/dist/types/types/cli/plugin.d.ts +6 -0
- package/dist/types/types/hooks.d.ts +10 -0
- package/dist/types/types/index.d.ts +3 -0
- package/dist/types/types/plugin.d.ts +40 -0
- package/dist/types/types/utils.d.ts +5 -0
- package/package.json +85 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { merge } from "@modern-js/utils/lodash";
|
|
2
|
+
function initPluginAPI({ context }) {
|
|
3
|
+
const { hooks, extendsHooks, plugins } = context;
|
|
4
|
+
function getAppContext() {
|
|
5
|
+
if (context) {
|
|
6
|
+
const { hooks: hooks2, config, normalizedConfig, pluginAPI, ...appContext } = context;
|
|
7
|
+
return appContext;
|
|
8
|
+
}
|
|
9
|
+
throw new Error("Cannot access context");
|
|
10
|
+
}
|
|
11
|
+
function getConfig() {
|
|
12
|
+
if (context.config) {
|
|
13
|
+
return context.config;
|
|
14
|
+
}
|
|
15
|
+
throw new Error("Cannot access config");
|
|
16
|
+
}
|
|
17
|
+
function getNormalizedConfig() {
|
|
18
|
+
if (context.normalizedConfig) {
|
|
19
|
+
return context.normalizedConfig;
|
|
20
|
+
}
|
|
21
|
+
throw new Error("Cannot access normalized config");
|
|
22
|
+
}
|
|
23
|
+
function getHooks() {
|
|
24
|
+
return {
|
|
25
|
+
...context.hooks,
|
|
26
|
+
...context.extendsHooks
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
const extendsPluginApi = {};
|
|
30
|
+
function updateRegistryApi() {
|
|
31
|
+
plugins.forEach((plugin) => {
|
|
32
|
+
const { registryApi } = plugin;
|
|
33
|
+
if (registryApi) {
|
|
34
|
+
const apis = registryApi(context, updateAppContext);
|
|
35
|
+
Object.keys(apis).forEach((apiName) => {
|
|
36
|
+
extendsPluginApi[apiName] = apis[apiName];
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
updateRegistryApi();
|
|
42
|
+
Object.keys(extendsHooks).forEach((hookName) => {
|
|
43
|
+
extendsPluginApi[hookName] = extendsHooks[hookName].tap;
|
|
44
|
+
});
|
|
45
|
+
function updateAppContext(updateContext) {
|
|
46
|
+
context = merge(context, updateContext);
|
|
47
|
+
updateRegistryApi();
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
getAppContext,
|
|
51
|
+
getConfig,
|
|
52
|
+
getNormalizedConfig,
|
|
53
|
+
getHooks,
|
|
54
|
+
updateAppContext,
|
|
55
|
+
config: hooks.config.tap,
|
|
56
|
+
modifyConfig: hooks.modifyConfig.tap,
|
|
57
|
+
modifyResolvedConfig: hooks.modifyResolvedConfig.tap,
|
|
58
|
+
modifyRsbuildConfig: hooks.modifyRsbuildConfig.tap,
|
|
59
|
+
modifyBundlerChain: hooks.modifyBundlerChain.tap,
|
|
60
|
+
modifyRspackConfig: hooks.modifyRspackConfig.tap,
|
|
61
|
+
modifyWebpackChain: hooks.modifyWebpackChain.tap,
|
|
62
|
+
modifyWebpackConfig: hooks.modifyWebpackConfig.tap,
|
|
63
|
+
modifyHtmlPartials: hooks.modifyHtmlPartials.tap,
|
|
64
|
+
addCommand: hooks.addCommand.tap,
|
|
65
|
+
onPrepare: hooks.onPrepare.tap,
|
|
66
|
+
onWatchFiles: hooks.addWatchFiles.tap,
|
|
67
|
+
onFileChanged: hooks.onFileChanged.tap,
|
|
68
|
+
onBeforeRestart: hooks.onBeforeRestart.tap,
|
|
69
|
+
onBeforeCreateCompiler: hooks.onBeforeCreateCompiler.tap,
|
|
70
|
+
onAfterCreateCompiler: hooks.onAfterCreateCompiler.tap,
|
|
71
|
+
onBeforeBuild: hooks.onBeforeBuild.tap,
|
|
72
|
+
onAfterBuild: hooks.onAfterBuild.tap,
|
|
73
|
+
onBeforeDev: hooks.onBeforeDev.tap,
|
|
74
|
+
onAfterDev: hooks.onAfterDev.tap,
|
|
75
|
+
onBeforeDeploy: hooks.onBeforeDeploy.tap,
|
|
76
|
+
onAfterDeploy: hooks.onAfterDeploy.tap,
|
|
77
|
+
onBeforeExit: hooks.onBeforeExit.tap,
|
|
78
|
+
...extendsPluginApi
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
export {
|
|
82
|
+
initPluginAPI
|
|
83
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { initHooks } from "./hooks";
|
|
3
|
+
function initAppContext(params) {
|
|
4
|
+
const { appDirectory, srcDir = "src", distDir = "dist" } = params;
|
|
5
|
+
return {
|
|
6
|
+
packageName: params.packageName,
|
|
7
|
+
configFile: params.configFile,
|
|
8
|
+
command: params.command,
|
|
9
|
+
isProd: process.env.NODE_ENV === "production",
|
|
10
|
+
appDirectory,
|
|
11
|
+
srcDirectory: path.resolve(appDirectory, srcDir),
|
|
12
|
+
distDirectory: path.resolve(appDirectory, distDir),
|
|
13
|
+
nodeModulesDirectory: path.resolve(appDirectory, "node_modules"),
|
|
14
|
+
plugins: params.plugins
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
async function createContext({ appContext, config, normalizedConfig }) {
|
|
18
|
+
const { plugins } = appContext;
|
|
19
|
+
const extendsHooks = {};
|
|
20
|
+
plugins.forEach((plugin) => {
|
|
21
|
+
const { registryHooks = {} } = plugin;
|
|
22
|
+
Object.keys(registryHooks).forEach((hookName) => {
|
|
23
|
+
extendsHooks[hookName] = registryHooks[hookName];
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
return {
|
|
27
|
+
...appContext,
|
|
28
|
+
hooks: {
|
|
29
|
+
...initHooks(),
|
|
30
|
+
...extendsHooks
|
|
31
|
+
},
|
|
32
|
+
extendsHooks,
|
|
33
|
+
config,
|
|
34
|
+
normalizedConfig
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export {
|
|
38
|
+
createContext,
|
|
39
|
+
initAppContext
|
|
40
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { createAsyncHook, createCollectAsyncHook } from "../hooks";
|
|
2
|
+
function initHooks() {
|
|
3
|
+
return {
|
|
4
|
+
/**
|
|
5
|
+
* add config for this cli plugin
|
|
6
|
+
*/
|
|
7
|
+
config: createCollectAsyncHook(),
|
|
8
|
+
/**
|
|
9
|
+
* @private
|
|
10
|
+
* modify config for this cli plugin
|
|
11
|
+
*/
|
|
12
|
+
modifyConfig: createAsyncHook(),
|
|
13
|
+
/**
|
|
14
|
+
* modify final config
|
|
15
|
+
*/
|
|
16
|
+
modifyResolvedConfig: createAsyncHook(),
|
|
17
|
+
modifyRsbuildConfig: createAsyncHook(),
|
|
18
|
+
modifyBundlerChain: createAsyncHook(),
|
|
19
|
+
modifyRspackConfig: createAsyncHook(),
|
|
20
|
+
modifyWebpackChain: createAsyncHook(),
|
|
21
|
+
modifyWebpackConfig: createAsyncHook(),
|
|
22
|
+
modifyHtmlPartials: createAsyncHook(),
|
|
23
|
+
addCommand: createAsyncHook(),
|
|
24
|
+
addWatchFiles: createCollectAsyncHook(),
|
|
25
|
+
onPrepare: createAsyncHook(),
|
|
26
|
+
onFileChanged: createAsyncHook(),
|
|
27
|
+
onBeforeRestart: createAsyncHook(),
|
|
28
|
+
onBeforeCreateCompiler: createAsyncHook(),
|
|
29
|
+
onAfterCreateCompiler: createAsyncHook(),
|
|
30
|
+
onBeforeBuild: createAsyncHook(),
|
|
31
|
+
onAfterBuild: createAsyncHook(),
|
|
32
|
+
onBeforeDev: createAsyncHook(),
|
|
33
|
+
onAfterDev: createAsyncHook(),
|
|
34
|
+
onBeforeDeploy: createAsyncHook(),
|
|
35
|
+
onAfterDeploy: createAsyncHook(),
|
|
36
|
+
onBeforeExit: createAsyncHook()
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export {
|
|
40
|
+
initHooks
|
|
41
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { initPluginAPI } from "./api";
|
|
2
|
+
import { initAppContext } from "./context";
|
|
3
|
+
import { initHooks } from "./hooks";
|
|
4
|
+
import { cli } from "./run";
|
|
5
|
+
import { initAppDir } from "./run/utils/initAppDir";
|
|
6
|
+
import { createLoadedConfig } from "../cli/run/config/createLoadedConfig";
|
|
7
|
+
export {
|
|
8
|
+
cli,
|
|
9
|
+
createLoadedConfig,
|
|
10
|
+
initAppContext,
|
|
11
|
+
initAppDir,
|
|
12
|
+
initHooks,
|
|
13
|
+
initPluginAPI
|
|
14
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { fs, CONFIG_FILE_EXTENSIONS, chalk, getCommand, getNodeEnv, isDevCommand, isPlainObject, logger } from "@modern-js/utils";
|
|
2
|
+
import { mergeWith } from "@modern-js/utils/lodash";
|
|
3
|
+
import { mergeConfig } from "../utils/mergeConfig";
|
|
4
|
+
import { getConfigFilePath, loadConfig } from "./loadConfig";
|
|
5
|
+
async function getConfigObject(config) {
|
|
6
|
+
if (typeof config === "function") {
|
|
7
|
+
return await config({
|
|
8
|
+
env: getNodeEnv(),
|
|
9
|
+
command: getCommand()
|
|
10
|
+
}) || {};
|
|
11
|
+
}
|
|
12
|
+
return config || {};
|
|
13
|
+
}
|
|
14
|
+
async function loadLocalConfig(appDirectory, configFile) {
|
|
15
|
+
let localConfigFile = false;
|
|
16
|
+
if (typeof configFile === "string") {
|
|
17
|
+
for (const ext of CONFIG_FILE_EXTENSIONS) {
|
|
18
|
+
if (configFile.endsWith(ext)) {
|
|
19
|
+
const replacedPath = configFile.replace(ext, `.local${ext}`);
|
|
20
|
+
if (fs.existsSync(replacedPath)) {
|
|
21
|
+
localConfigFile = replacedPath;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (localConfigFile) {
|
|
27
|
+
const loaded = await loadConfig(appDirectory, localConfigFile);
|
|
28
|
+
return getConfigObject(loaded.config);
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
function assignPkgConfig(userConfig, pkgConfig) {
|
|
33
|
+
return mergeWith({}, userConfig, pkgConfig, (objValue, srcValue) => {
|
|
34
|
+
if (objValue === void 0 && isPlainObject(srcValue)) {
|
|
35
|
+
return {
|
|
36
|
+
...srcValue
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return void 0;
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
async function createLoadedConfig(appDirectory, configFilePath, packageJsonConfig, loadedConfig) {
|
|
43
|
+
const configFile = getConfigFilePath(appDirectory, configFilePath);
|
|
44
|
+
const loaded = await loadConfig(appDirectory, configFile, packageJsonConfig, loadedConfig);
|
|
45
|
+
if (!loaded.config && !loaded.pkgConfig) {
|
|
46
|
+
logger.warn(`Can not find any config file in the current project, please check if you have a correct config file.`);
|
|
47
|
+
logger.warn(`Current project path: ${chalk.yellow(appDirectory)}`);
|
|
48
|
+
}
|
|
49
|
+
const config = await getConfigObject(loaded.config);
|
|
50
|
+
let mergedConfig = config;
|
|
51
|
+
if (loaded.pkgConfig) {
|
|
52
|
+
mergedConfig = assignPkgConfig(config, loaded === null || loaded === void 0 ? void 0 : loaded.pkgConfig);
|
|
53
|
+
}
|
|
54
|
+
if (isDevCommand()) {
|
|
55
|
+
const localConfig = await loadLocalConfig(appDirectory, configFile);
|
|
56
|
+
if (localConfig) {
|
|
57
|
+
mergedConfig = mergeConfig([
|
|
58
|
+
mergedConfig,
|
|
59
|
+
localConfig
|
|
60
|
+
]);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
packageName: loaded.packageName,
|
|
65
|
+
config: mergedConfig,
|
|
66
|
+
configFile: loaded.configFile,
|
|
67
|
+
pkgConfig: loaded.pkgConfig,
|
|
68
|
+
jsConfig: loaded.config
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export {
|
|
72
|
+
assignPkgConfig,
|
|
73
|
+
createLoadedConfig
|
|
74
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { createDebugger } from "@modern-js/utils";
|
|
2
|
+
import { mergeConfig } from "../utils/mergeConfig";
|
|
3
|
+
const debug = createDebugger("resolve-config");
|
|
4
|
+
const createResolveConfig = async (loaded, configs) => {
|
|
5
|
+
const { config: userConfig } = loaded;
|
|
6
|
+
const resolved = mergeConfig([
|
|
7
|
+
{},
|
|
8
|
+
...configs,
|
|
9
|
+
userConfig
|
|
10
|
+
]);
|
|
11
|
+
debug("resolved %o", resolved);
|
|
12
|
+
return resolved;
|
|
13
|
+
};
|
|
14
|
+
export {
|
|
15
|
+
createResolveConfig
|
|
16
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { bundleRequire, defaultGetOutputFile } from "@modern-js/node-bundle-require";
|
|
3
|
+
import { fs, CONFIG_CACHE_DIR, globby } from "@modern-js/utils";
|
|
4
|
+
const getPackageConfig = (appDirectory, packageJsonConfig) => {
|
|
5
|
+
const json = JSON.parse(fs.readFileSync(path.resolve(appDirectory, "./package.json"), "utf8"));
|
|
6
|
+
return json[packageJsonConfig];
|
|
7
|
+
};
|
|
8
|
+
const getConfigFilePath = (appDirectory, configFilePath) => {
|
|
9
|
+
if (path.isAbsolute(configFilePath)) {
|
|
10
|
+
return configFilePath;
|
|
11
|
+
}
|
|
12
|
+
return path.resolve(appDirectory, configFilePath);
|
|
13
|
+
};
|
|
14
|
+
const clearFilesOverTime = async (targetDir, overtime) => {
|
|
15
|
+
try {
|
|
16
|
+
const files = await globby(`${targetDir}/**/*`, {
|
|
17
|
+
stats: true,
|
|
18
|
+
absolute: true
|
|
19
|
+
});
|
|
20
|
+
const currentTime = Date.now();
|
|
21
|
+
if (files.length > 0) {
|
|
22
|
+
for (const file of files) {
|
|
23
|
+
if (currentTime - file.stats.birthtimeMs >= overtime * 1e3) {
|
|
24
|
+
fs.unlinkSync(file.path);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
} catch (err) {
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
const bundleRequireWithCatch = async (configFile, { appDirectory }) => {
|
|
32
|
+
try {
|
|
33
|
+
const mod = await bundleRequire(configFile, {
|
|
34
|
+
autoClear: false,
|
|
35
|
+
getOutputFile: async (filePath) => {
|
|
36
|
+
const defaultOutputFileName = path.basename(await defaultGetOutputFile(filePath));
|
|
37
|
+
const outputPath = path.join(appDirectory, CONFIG_CACHE_DIR);
|
|
38
|
+
const timeLimit = 10 * 60;
|
|
39
|
+
await clearFilesOverTime(outputPath, timeLimit);
|
|
40
|
+
return path.join(outputPath, defaultOutputFileName);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
return mod;
|
|
44
|
+
} catch (e) {
|
|
45
|
+
if (e instanceof Error) {
|
|
46
|
+
e.message = `Get Error while loading config file: ${configFile}, please check it and retry.
|
|
47
|
+
${e.message || ""}`;
|
|
48
|
+
}
|
|
49
|
+
throw e;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const loadConfig = async (appDirectory, configFile, packageJsonConfig, loadedConfig) => {
|
|
53
|
+
let pkgConfig;
|
|
54
|
+
if (packageJsonConfig) {
|
|
55
|
+
pkgConfig = getPackageConfig(appDirectory, packageJsonConfig);
|
|
56
|
+
}
|
|
57
|
+
const packageName = require(path.resolve(appDirectory, "./package.json")).name;
|
|
58
|
+
let config;
|
|
59
|
+
if (loadedConfig) {
|
|
60
|
+
config = loadedConfig;
|
|
61
|
+
} else if (configFile) {
|
|
62
|
+
delete require.cache[configFile];
|
|
63
|
+
const mod = await bundleRequireWithCatch(configFile, {
|
|
64
|
+
appDirectory
|
|
65
|
+
});
|
|
66
|
+
config = mod.default || mod;
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
packageName,
|
|
70
|
+
configFile,
|
|
71
|
+
config,
|
|
72
|
+
pkgConfig
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
export {
|
|
76
|
+
clearFilesOverTime,
|
|
77
|
+
getConfigFilePath,
|
|
78
|
+
getPackageConfig,
|
|
79
|
+
loadConfig
|
|
80
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { logger } from "@modern-js/utils";
|
|
2
|
+
import { program } from "@modern-js/utils/commander";
|
|
3
|
+
import { createPluginManager } from "../../manager";
|
|
4
|
+
import { initPluginAPI } from "../api";
|
|
5
|
+
import { createContext, initAppContext } from "../context";
|
|
6
|
+
import { createLoadedConfig } from "./config/createLoadedConfig";
|
|
7
|
+
import { createResolveConfig } from "./config/createResolvedConfig";
|
|
8
|
+
import { checkIsDuplicationPlugin } from "./utils/checkIsDuplicationPlugin";
|
|
9
|
+
import { initCommandsMap, setProgramVersion } from "./utils/commander";
|
|
10
|
+
import { createFileWatcher } from "./utils/createFileWatcher";
|
|
11
|
+
import { initAppDir } from "./utils/initAppDir";
|
|
12
|
+
import { loadEnv } from "./utils/loadEnv";
|
|
13
|
+
const createCli = () => {
|
|
14
|
+
const pluginManager = createPluginManager();
|
|
15
|
+
async function init(options) {
|
|
16
|
+
const { metaName = "MODERN", configFile, command, version, packageJsonConfig, loadedConfig, internalPlugins, handleSetupResult } = options;
|
|
17
|
+
const appDirectory = await initAppDir(options === null || options === void 0 ? void 0 : options.cwd);
|
|
18
|
+
initCommandsMap();
|
|
19
|
+
setProgramVersion(version);
|
|
20
|
+
loadEnv(appDirectory, process.env[`${metaName.toUpperCase()}_ENV`]);
|
|
21
|
+
const loaded = await createLoadedConfig(appDirectory, configFile, packageJsonConfig, loadedConfig);
|
|
22
|
+
const allPlugins = [
|
|
23
|
+
...internalPlugins || [],
|
|
24
|
+
...loaded.config.plugins || []
|
|
25
|
+
];
|
|
26
|
+
checkIsDuplicationPlugin(allPlugins.map((plugin) => plugin.name), loaded.config.autoLoadPlugins);
|
|
27
|
+
pluginManager.addPlugins(allPlugins);
|
|
28
|
+
const plugins = await pluginManager.getPlugins();
|
|
29
|
+
const context = await createContext({
|
|
30
|
+
appContext: initAppContext({
|
|
31
|
+
packageName: loaded.packageName,
|
|
32
|
+
configFile: loaded.configFile,
|
|
33
|
+
command,
|
|
34
|
+
appDirectory,
|
|
35
|
+
plugins
|
|
36
|
+
}),
|
|
37
|
+
config: loaded.config,
|
|
38
|
+
normalizedConfig: {}
|
|
39
|
+
});
|
|
40
|
+
const pluginAPI = initPluginAPI({
|
|
41
|
+
context,
|
|
42
|
+
pluginManager
|
|
43
|
+
});
|
|
44
|
+
context.pluginAPI = pluginAPI;
|
|
45
|
+
for (const plugin of plugins) {
|
|
46
|
+
const setupResult = await plugin.setup(pluginAPI);
|
|
47
|
+
if (handleSetupResult) {
|
|
48
|
+
await handleSetupResult(setupResult, pluginAPI);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
[
|
|
52
|
+
"SIGINT",
|
|
53
|
+
"SIGTERM",
|
|
54
|
+
"unhandledRejection",
|
|
55
|
+
"uncaughtException"
|
|
56
|
+
].forEach((event) => {
|
|
57
|
+
process.on(event, async (err) => {
|
|
58
|
+
await context.hooks.onBeforeExit.call();
|
|
59
|
+
let hasError = false;
|
|
60
|
+
if (err instanceof Error) {
|
|
61
|
+
logger.error(err.stack);
|
|
62
|
+
hasError = true;
|
|
63
|
+
} else if (err && (event === "unhandledRejection" || event === "uncaughtException")) {
|
|
64
|
+
console.trace("Unknown Error", err);
|
|
65
|
+
hasError = true;
|
|
66
|
+
}
|
|
67
|
+
process.nextTick(() => {
|
|
68
|
+
process.exit(hasError ? 1 : 0);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
const extraConfigs = await context.hooks.config.call();
|
|
73
|
+
const normalizedConfig = await createResolveConfig(loaded, extraConfigs);
|
|
74
|
+
const resolved = await context.hooks.modifyResolvedConfig.call(normalizedConfig);
|
|
75
|
+
context.normalizedConfig = resolved[0] || normalizedConfig;
|
|
76
|
+
await pluginAPI.updateAppContext(context);
|
|
77
|
+
await context.hooks.onPrepare.call();
|
|
78
|
+
return {
|
|
79
|
+
appContext: context
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
async function run(options) {
|
|
83
|
+
var _program_commands;
|
|
84
|
+
const { appContext } = await init(options);
|
|
85
|
+
await appContext.hooks.addCommand.call({
|
|
86
|
+
program
|
|
87
|
+
});
|
|
88
|
+
await createFileWatcher(appContext);
|
|
89
|
+
program.parse(process.argv);
|
|
90
|
+
if (!((_program_commands = program.commands) === null || _program_commands === void 0 ? void 0 : _program_commands.length)) {
|
|
91
|
+
logger.warn("No command found, please make sure you have registered plugins correctly.");
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
init,
|
|
96
|
+
run
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
export {
|
|
100
|
+
createCli
|
|
101
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { logger } from "@modern-js/utils";
|
|
2
|
+
import { cli } from ".";
|
|
3
|
+
const run = async (options) => {
|
|
4
|
+
const { initialLog, version, cwd, configFile, ...params } = options;
|
|
5
|
+
if (initialLog) {
|
|
6
|
+
logger.greet(` ${initialLog}
|
|
7
|
+
`);
|
|
8
|
+
}
|
|
9
|
+
const command = process.argv[2];
|
|
10
|
+
if (!process.env.NODE_ENV) {
|
|
11
|
+
if ([
|
|
12
|
+
"build",
|
|
13
|
+
"serve",
|
|
14
|
+
"deploy",
|
|
15
|
+
"analyze"
|
|
16
|
+
].includes(command)) {
|
|
17
|
+
process.env.NODE_ENV = "production";
|
|
18
|
+
} else if (command === "test") {
|
|
19
|
+
process.env.NODE_ENV = "test";
|
|
20
|
+
} else {
|
|
21
|
+
process.env.NODE_ENV = "development";
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
await cli.run({
|
|
25
|
+
version,
|
|
26
|
+
cwd,
|
|
27
|
+
command,
|
|
28
|
+
configFile,
|
|
29
|
+
...params
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
export {
|
|
33
|
+
run
|
|
34
|
+
};
|
|
File without changes
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { logger } from "@modern-js/utils";
|
|
2
|
+
function checkIsDuplicationPlugin(plugins, autoLoadPlugin = false) {
|
|
3
|
+
const set = /* @__PURE__ */ new Set();
|
|
4
|
+
const duplicationPlugins = [];
|
|
5
|
+
plugins.filter((plugin) => typeof plugin === "string").forEach((plugin) => {
|
|
6
|
+
if (set.has(plugin)) {
|
|
7
|
+
duplicationPlugins.push(plugin);
|
|
8
|
+
} else {
|
|
9
|
+
set.add(plugin);
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
if (duplicationPlugins.length > 0) {
|
|
13
|
+
logger.warn(`Duplicate registration plugins: ${duplicationPlugins.join(",")}.`);
|
|
14
|
+
if (autoLoadPlugin) {
|
|
15
|
+
logger.warn("This is probably because you enabled `autoLoadPlugin` configuration and also registered these plugins manually");
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export {
|
|
20
|
+
checkIsDuplicationPlugin
|
|
21
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { program } from "@modern-js/utils";
|
|
2
|
+
const setProgramVersion = (version = "unknown") => {
|
|
3
|
+
const name = process.argv[1];
|
|
4
|
+
program.name(name).usage("<command> [options]").version(version);
|
|
5
|
+
};
|
|
6
|
+
function initCommandsMap() {
|
|
7
|
+
if (!program.hasOwnProperty("commandsMap")) {
|
|
8
|
+
Object.defineProperty(program, "commandsMap", {
|
|
9
|
+
get() {
|
|
10
|
+
const map = /* @__PURE__ */ new Map();
|
|
11
|
+
for (const command of program.commands) {
|
|
12
|
+
map.set(command._name, command);
|
|
13
|
+
}
|
|
14
|
+
return map;
|
|
15
|
+
},
|
|
16
|
+
configurable: false
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export {
|
|
21
|
+
initCommandsMap,
|
|
22
|
+
program,
|
|
23
|
+
setProgramVersion
|
|
24
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import crypto from "crypto";
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
import * as path from "path";
|
|
4
|
+
import { chokidar, createDebugger, isDevCommand } from "@modern-js/utils";
|
|
5
|
+
const debug = createDebugger("watch-files");
|
|
6
|
+
const hashMap = /* @__PURE__ */ new Map();
|
|
7
|
+
const md5 = (data) => crypto.createHash("md5").update(data).digest("hex");
|
|
8
|
+
const createFileWatcher = async (appContext) => {
|
|
9
|
+
if (isDevCommand()) {
|
|
10
|
+
const { appDirectory } = appContext;
|
|
11
|
+
const extraFiles = await appContext.hooks.addWatchFiles.call();
|
|
12
|
+
const watched = extraFiles.filter((extra) => {
|
|
13
|
+
return Array.isArray(extra);
|
|
14
|
+
}).flat();
|
|
15
|
+
const privateWatched = extraFiles.filter((extra) => {
|
|
16
|
+
return !Array.isArray(extra) && extra.isPrivate;
|
|
17
|
+
}).map((extra) => {
|
|
18
|
+
return extra.files;
|
|
19
|
+
}).flat();
|
|
20
|
+
const isPrivate = (filename) => privateWatched.some((ff) => {
|
|
21
|
+
return path.resolve(appDirectory, filename).startsWith(ff);
|
|
22
|
+
});
|
|
23
|
+
debug(`watched: %o`, watched);
|
|
24
|
+
const watcher = chokidar.watch([
|
|
25
|
+
...watched,
|
|
26
|
+
...privateWatched
|
|
27
|
+
], {
|
|
28
|
+
cwd: appDirectory,
|
|
29
|
+
ignoreInitial: true,
|
|
30
|
+
ignorePermissionErrors: true,
|
|
31
|
+
ignored: [
|
|
32
|
+
"**/__test__/**",
|
|
33
|
+
"**/*.test.(js|jsx|ts|tsx)",
|
|
34
|
+
"**/*.spec.(js|jsx|ts|tsx)",
|
|
35
|
+
"**/*.stories.(js|jsx|ts|tsx)"
|
|
36
|
+
]
|
|
37
|
+
});
|
|
38
|
+
watcher.on("change", (changed) => {
|
|
39
|
+
const lastHash = hashMap.get(changed);
|
|
40
|
+
const currentHash = md5(fs.readFileSync(path.join(appDirectory, changed), "utf8"));
|
|
41
|
+
if (currentHash !== lastHash) {
|
|
42
|
+
debug(`file change: %s`, changed);
|
|
43
|
+
hashMap.set(changed, currentHash);
|
|
44
|
+
appContext.hooks.onFileChanged.call({
|
|
45
|
+
filename: changed,
|
|
46
|
+
eventType: "change",
|
|
47
|
+
isPrivate: isPrivate(changed)
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
watcher.on("add", (changed) => {
|
|
52
|
+
debug(`add file: %s`, changed);
|
|
53
|
+
const currentHash = md5(fs.readFileSync(path.join(appDirectory, changed), "utf8"));
|
|
54
|
+
hashMap.set(changed, currentHash);
|
|
55
|
+
appContext.hooks.onFileChanged.call({
|
|
56
|
+
filename: changed,
|
|
57
|
+
eventType: "add",
|
|
58
|
+
isPrivate: isPrivate(changed)
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
watcher.on("unlink", (changed) => {
|
|
62
|
+
debug(`remove file: %s`, changed);
|
|
63
|
+
if (hashMap.has(changed)) {
|
|
64
|
+
hashMap.delete(changed);
|
|
65
|
+
}
|
|
66
|
+
appContext.hooks.onFileChanged.call({
|
|
67
|
+
filename: changed,
|
|
68
|
+
eventType: "unlink",
|
|
69
|
+
isPrivate: isPrivate(changed)
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
watcher.on("error", (err) => {
|
|
73
|
+
throw err;
|
|
74
|
+
});
|
|
75
|
+
return watcher;
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
export {
|
|
79
|
+
createFileWatcher
|
|
80
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { pkgUp } from "@modern-js/utils";
|
|
3
|
+
const initAppDir = async (currentDir) => {
|
|
4
|
+
const cwd = currentDir || process.cwd();
|
|
5
|
+
const pkg = await pkgUp({
|
|
6
|
+
cwd
|
|
7
|
+
});
|
|
8
|
+
if (!pkg) {
|
|
9
|
+
throw new Error(`no package.json found in current work dir: ${cwd}`);
|
|
10
|
+
}
|
|
11
|
+
return path.dirname(pkg);
|
|
12
|
+
};
|
|
13
|
+
export {
|
|
14
|
+
initAppDir
|
|
15
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { dotenv, dotenvExpand } from "@modern-js/utils";
|
|
4
|
+
const loadEnv = (appDirectory, mode = process.env.NODE_ENV) => {
|
|
5
|
+
[
|
|
6
|
+
`.env.${mode}.local`,
|
|
7
|
+
".env.local",
|
|
8
|
+
`.env.${mode}`,
|
|
9
|
+
".env"
|
|
10
|
+
].map((name) => path.resolve(appDirectory, name)).filter((filePath) => fs.existsSync(filePath) && !fs.statSync(filePath).isDirectory()).forEach((filePath) => {
|
|
11
|
+
const envConfig = dotenv.config({
|
|
12
|
+
path: filePath
|
|
13
|
+
});
|
|
14
|
+
dotenvExpand(envConfig);
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
export {
|
|
18
|
+
loadEnv
|
|
19
|
+
};
|