@modern-js/utils 2.26.0 → 2.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/cjs/universal/formatWebpack.js +0 -4
- package/dist/esm/cli/alias.js +26 -22
- package/dist/esm/cli/applyOptionsChain.js +8 -6
- package/dist/esm/cli/babel.js +50 -35
- package/dist/esm/cli/commands.js +7 -7
- package/dist/esm/cli/common.js +10 -5
- package/dist/esm/cli/constants/chainId.js +1 -1
- package/dist/esm/cli/constants/index.js +33 -37
- package/dist/esm/cli/ensure.js +4 -2
- package/dist/esm/cli/fs.js +56 -9
- package/dist/esm/cli/get/config.js +7 -7
- package/dist/esm/cli/get/data.js +93 -55
- package/dist/esm/cli/get/index.js +21 -6
- package/dist/esm/cli/is/config.js +33 -14
- package/dist/esm/cli/is/env.js +18 -6
- package/dist/esm/cli/is/platform.js +6 -2
- package/dist/esm/cli/is/project.js +73 -36
- package/dist/esm/cli/is/type.js +3 -1
- package/dist/esm/cli/logger.js +49 -38
- package/dist/esm/cli/monorepo.js +49 -36
- package/dist/esm/cli/package.js +156 -38
- package/dist/esm/cli/path.js +44 -20
- package/dist/esm/cli/pathSerializer.js +29 -15
- package/dist/esm/cli/port.js +89 -40
- package/dist/esm/cli/prettyInstructions.js +42 -31
- package/dist/esm/cli/require.js +21 -16
- package/dist/esm/cli/runtimeExports.js +21 -15
- package/dist/esm/cli/watch.js +94 -27
- package/dist/esm/compiled.js +3 -3
- package/dist/esm/import.js +4 -4
- package/dist/esm/runtime/nestedRoutes.js +42 -29
- package/dist/esm/runtime-browser/parsed.js +5 -5
- package/dist/esm/runtime-node/index.js +1 -1
- package/dist/esm/runtime-node/nestedRoutes.js +6 -4
- package/dist/esm/runtime-node/serialize.js +1 -1
- package/dist/esm/runtime-node/storage.js +12 -14
- package/dist/esm/universal/constants.js +3 -3
- package/dist/esm/universal/formatWebpack.js +20 -26
- package/dist/esm/universal/pluginDagSort.js +49 -26
- package/dist/esm-node/cli/alias.js +51 -0
- package/dist/esm-node/cli/applyOptionsChain.js +24 -0
- package/dist/esm-node/cli/babel.js +103 -0
- package/dist/esm-node/cli/commands.js +16 -0
- package/dist/esm-node/cli/common.js +10 -0
- package/dist/esm-node/cli/constants/chainId.js +180 -0
- package/dist/esm-node/cli/constants/index.js +103 -0
- package/dist/esm-node/cli/ensure.js +10 -0
- package/dist/esm-node/cli/fs.js +14 -0
- package/dist/esm-node/cli/get/config.js +16 -0
- package/dist/esm-node/cli/get/data.js +86 -0
- package/dist/esm-node/cli/get/index.js +13 -0
- package/dist/esm-node/cli/index.js +20 -0
- package/dist/esm-node/cli/is/config.js +40 -0
- package/dist/esm-node/cli/is/env.js +6 -0
- package/dist/esm-node/cli/is/index.js +5 -0
- package/dist/esm-node/cli/is/platform.js +2 -0
- package/dist/esm-node/cli/is/project.js +73 -0
- package/dist/esm-node/cli/is/type.js +25 -0
- package/dist/esm-node/cli/logger.js +103 -0
- package/dist/esm-node/cli/monorepo.js +70 -0
- package/dist/esm-node/cli/package.js +43 -0
- package/dist/esm-node/cli/path.js +49 -0
- package/dist/esm-node/cli/pathSerializer.js +46 -0
- package/dist/esm-node/cli/port.js +44 -0
- package/dist/esm-node/cli/prettyInstructions.js +77 -0
- package/dist/esm-node/cli/require.js +52 -0
- package/dist/esm-node/cli/runtimeExports.js +35 -0
- package/dist/esm-node/cli/watch.js +41 -0
- package/dist/esm-node/compiled.js +33 -0
- package/dist/esm-node/import.js +8 -0
- package/dist/esm-node/index.js +3 -0
- package/dist/esm-node/runtime/nestedRoutes.js +112 -0
- package/dist/esm-node/runtime/remixRouter.js +1 -0
- package/dist/esm-node/runtime/router.js +1 -0
- package/dist/esm-node/runtime-browser/index.js +1 -0
- package/dist/esm-node/runtime-browser/parsed.js +17 -0
- package/dist/esm-node/runtime-node/index.js +5 -0
- package/dist/esm-node/runtime-node/nestedRoutes.js +18 -0
- package/dist/esm-node/runtime-node/router.js +1 -0
- package/dist/esm-node/runtime-node/serialize.js +6 -0
- package/dist/esm-node/runtime-node/storage.js +38 -0
- package/dist/esm-node/universal/constants.js +3 -0
- package/dist/esm-node/universal/formatWebpack.js +61 -0
- package/dist/esm-node/universal/pluginDagSort.js +50 -0
- package/package.json +4 -4
@@ -0,0 +1,10 @@
|
|
1
|
+
import path from "path";
|
2
|
+
export const ensureAbsolutePath = (base, filePath) => path.isAbsolute(filePath) ? filePath : path.resolve(base, filePath);
|
3
|
+
export const ensureArray = (params) => {
|
4
|
+
if (Array.isArray(params)) {
|
5
|
+
return params;
|
6
|
+
}
|
7
|
+
return [
|
8
|
+
params
|
9
|
+
];
|
10
|
+
};
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import { fs } from "../compiled";
|
2
|
+
export const findExists = (files) => {
|
3
|
+
for (const file of files) {
|
4
|
+
if (fs.existsSync(file) && fs.statSync(file).isFile()) {
|
5
|
+
return file;
|
6
|
+
}
|
7
|
+
}
|
8
|
+
return false;
|
9
|
+
};
|
10
|
+
export const emptyDir = async (dir) => {
|
11
|
+
if (await fs.pathExists(dir)) {
|
12
|
+
await fs.emptyDir(dir);
|
13
|
+
}
|
14
|
+
};
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import { isPlainObject } from "../is";
|
2
|
+
export const getEntryOptions = (name, isMainEntry, baseOptions, optionsByEntries, packageName) => {
|
3
|
+
if (optionsByEntries) {
|
4
|
+
let optionsByEntry = getOptionsByEntryName(name, optionsByEntries);
|
5
|
+
if (optionsByEntry === void 0 && isMainEntry && packageName) {
|
6
|
+
optionsByEntry = getOptionsByEntryName(packageName, optionsByEntries);
|
7
|
+
}
|
8
|
+
return optionsByEntry !== void 0 ? isPlainObject(optionsByEntry) && isPlainObject(baseOptions) ? {
|
9
|
+
...baseOptions,
|
10
|
+
...optionsByEntry
|
11
|
+
} : optionsByEntry : baseOptions;
|
12
|
+
} else {
|
13
|
+
return baseOptions;
|
14
|
+
}
|
15
|
+
};
|
16
|
+
const getOptionsByEntryName = (name, optionsByEntries) => optionsByEntries.hasOwnProperty(name) ? optionsByEntries[name] : void 0;
|
@@ -0,0 +1,86 @@
|
|
1
|
+
import os from "os";
|
2
|
+
import path from "path";
|
3
|
+
import { browserslist, fs, json5 } from "../../compiled";
|
4
|
+
import { INTERNAL_CLI_PLUGINS } from "../constants";
|
5
|
+
import { isDepExists } from "../is";
|
6
|
+
import { canUsePnpm, canUseYarn } from "../package";
|
7
|
+
const MAX_TIMES = 5;
|
8
|
+
export async function getPackageManager(cwd = process.cwd()) {
|
9
|
+
let appDirectory = cwd;
|
10
|
+
let times = 0;
|
11
|
+
while (os.homedir() !== appDirectory && times < MAX_TIMES) {
|
12
|
+
times++;
|
13
|
+
if (fs.existsSync(path.resolve(appDirectory, "pnpm-lock.yaml"))) {
|
14
|
+
return "pnpm";
|
15
|
+
}
|
16
|
+
if (fs.existsSync(path.resolve(appDirectory, "yarn.lock"))) {
|
17
|
+
return "yarn";
|
18
|
+
}
|
19
|
+
if (fs.existsSync(path.resolve(appDirectory, "package-lock.json"))) {
|
20
|
+
return "npm";
|
21
|
+
}
|
22
|
+
appDirectory = path.join(appDirectory, "..");
|
23
|
+
}
|
24
|
+
if (await canUsePnpm()) {
|
25
|
+
return "pnpm";
|
26
|
+
}
|
27
|
+
if (await canUseYarn()) {
|
28
|
+
return "yarn";
|
29
|
+
}
|
30
|
+
return "npm";
|
31
|
+
}
|
32
|
+
export const getCoreJsVersion = (corejsPkgPath) => {
|
33
|
+
try {
|
34
|
+
const { version } = fs.readJSONSync(corejsPkgPath);
|
35
|
+
const [major, minor] = version.split(".");
|
36
|
+
return `${major}.${minor}`;
|
37
|
+
} catch (err) {
|
38
|
+
return "3";
|
39
|
+
}
|
40
|
+
};
|
41
|
+
export const getAntdMajorVersion = (appDirectory) => {
|
42
|
+
try {
|
43
|
+
const pkgJsonPath = require.resolve("antd/package.json", {
|
44
|
+
paths: [
|
45
|
+
appDirectory
|
46
|
+
]
|
47
|
+
});
|
48
|
+
const { version } = require(pkgJsonPath);
|
49
|
+
return Number(version.split(".")[0]);
|
50
|
+
} catch (err) {
|
51
|
+
return null;
|
52
|
+
}
|
53
|
+
};
|
54
|
+
export const defaults = [
|
55
|
+
"> 0.01%",
|
56
|
+
"not dead",
|
57
|
+
"not op_mini all"
|
58
|
+
];
|
59
|
+
export const getBrowserslist = (appDirectory) => browserslist.loadConfig({
|
60
|
+
path: appDirectory
|
61
|
+
}) || defaults;
|
62
|
+
export function getInternalPlugins(appDirectory, internalPlugins = INTERNAL_CLI_PLUGINS) {
|
63
|
+
return [
|
64
|
+
...Object.keys(internalPlugins).filter((name) => {
|
65
|
+
const config = internalPlugins[name];
|
66
|
+
if (typeof config !== "string" && config.forced === true) {
|
67
|
+
return true;
|
68
|
+
}
|
69
|
+
return isDepExists(appDirectory, name);
|
70
|
+
}).map((name) => {
|
71
|
+
const config = internalPlugins[name];
|
72
|
+
if (typeof config !== "string") {
|
73
|
+
return config.path;
|
74
|
+
} else {
|
75
|
+
return config;
|
76
|
+
}
|
77
|
+
})
|
78
|
+
];
|
79
|
+
}
|
80
|
+
export const readTsConfig = (root) => {
|
81
|
+
return readTsConfigByFile(path.resolve(root, "./tsconfig.json"));
|
82
|
+
};
|
83
|
+
export const readTsConfigByFile = (filename) => {
|
84
|
+
const content = fs.readFileSync(path.resolve(filename), "utf-8");
|
85
|
+
return json5.parse(content);
|
86
|
+
};
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import path from "path";
|
2
|
+
import { CONFIG_FILE_EXTENSIONS } from "../constants";
|
3
|
+
import { findExists } from "../fs";
|
4
|
+
export const getServerConfig = async (appDirectory, configFile) => {
|
5
|
+
const configFilePath = findExists(CONFIG_FILE_EXTENSIONS.map((extension) => path.resolve(appDirectory, `${configFile}${extension}`)));
|
6
|
+
return configFilePath;
|
7
|
+
};
|
8
|
+
export const getTargetDir = (from, baseDir, targetBaseDir) => {
|
9
|
+
const relativePath = path.relative(baseDir, from);
|
10
|
+
return path.resolve(targetBaseDir, relativePath);
|
11
|
+
};
|
12
|
+
export * from "./data";
|
13
|
+
export * from "./config";
|
@@ -0,0 +1,20 @@
|
|
1
|
+
export * from "./constants";
|
2
|
+
export * from "./get";
|
3
|
+
export * from "./is";
|
4
|
+
export * from "./alias";
|
5
|
+
export * from "./applyOptionsChain";
|
6
|
+
export * from "./babel";
|
7
|
+
export * from "./commands";
|
8
|
+
export * from "./common";
|
9
|
+
export * from "./ensure";
|
10
|
+
export * from "./fs";
|
11
|
+
export * from "./logger";
|
12
|
+
export * from "./monorepo";
|
13
|
+
export * from "./package";
|
14
|
+
export * from "./path";
|
15
|
+
export * from "./pathSerializer";
|
16
|
+
export * from "./port";
|
17
|
+
export * from "./prettyInstructions";
|
18
|
+
export * from "./require";
|
19
|
+
export * from "./runtimeExports";
|
20
|
+
export * from "./watch";
|
@@ -0,0 +1,40 @@
|
|
1
|
+
import { isEmpty } from "./type";
|
2
|
+
export const isSSR = (config) => {
|
3
|
+
const { server } = config;
|
4
|
+
if (server === null || server === void 0 ? void 0 : server.ssr) {
|
5
|
+
return true;
|
6
|
+
}
|
7
|
+
if ((server === null || server === void 0 ? void 0 : server.ssrByEntries) && !isEmpty(server.ssrByEntries)) {
|
8
|
+
for (const name of Object.keys(server.ssrByEntries)) {
|
9
|
+
if (server.ssrByEntries[name]) {
|
10
|
+
return true;
|
11
|
+
}
|
12
|
+
}
|
13
|
+
}
|
14
|
+
return false;
|
15
|
+
};
|
16
|
+
export const isUseSSRBundle = (config) => {
|
17
|
+
const { output } = config;
|
18
|
+
if (output === null || output === void 0 ? void 0 : output.ssg) {
|
19
|
+
return true;
|
20
|
+
}
|
21
|
+
return isSSR(config);
|
22
|
+
};
|
23
|
+
export const isServiceWorker = (config) => {
|
24
|
+
var _deploy_worker;
|
25
|
+
const { output, deploy } = config;
|
26
|
+
if ((deploy === null || deploy === void 0 ? void 0 : (_deploy_worker = deploy.worker) === null || _deploy_worker === void 0 ? void 0 : _deploy_worker.ssr) && ((output === null || output === void 0 ? void 0 : output.ssg) || isSSR(config))) {
|
27
|
+
return true;
|
28
|
+
}
|
29
|
+
return false;
|
30
|
+
};
|
31
|
+
export const isRouterV5 = (config) => {
|
32
|
+
var _config_runtime, _config_runtime1, _config_runtime_router;
|
33
|
+
return typeof ((_config_runtime = config.runtime) === null || _config_runtime === void 0 ? void 0 : _config_runtime.router) !== "boolean" && (config === null || config === void 0 ? void 0 : (_config_runtime1 = config.runtime) === null || _config_runtime1 === void 0 ? void 0 : (_config_runtime_router = _config_runtime1.router) === null || _config_runtime_router === void 0 ? void 0 : _config_runtime_router.mode) === "react-router-5";
|
34
|
+
};
|
35
|
+
export const isSSGEntry = (config, entryName, entrypoints) => {
|
36
|
+
const ssgConfig = config.output.ssg;
|
37
|
+
const useSSG = isSingleEntry(entrypoints) ? Boolean(ssgConfig) : ssgConfig === true || typeof (ssgConfig === null || ssgConfig === void 0 ? void 0 : ssgConfig[0]) === "function" || Boolean(ssgConfig === null || ssgConfig === void 0 ? void 0 : ssgConfig[entryName]);
|
38
|
+
return useSSG;
|
39
|
+
};
|
40
|
+
export const isSingleEntry = (entrypoints) => entrypoints.length === 1 && entrypoints[0].entryName === "main";
|
@@ -0,0 +1,6 @@
|
|
1
|
+
export const getNodeEnv = () => process.env.NODE_ENV || "development";
|
2
|
+
export const isDev = () => getNodeEnv() === "development";
|
3
|
+
export const isProd = () => getNodeEnv() === "production";
|
4
|
+
export const isTest = () => getNodeEnv() === "test";
|
5
|
+
export const isProdProfile = () => isProd() && process.argv.includes("--profile");
|
6
|
+
export const isFastRefresh = () => isDev() && process.env.FAST_REFRESH !== "false";
|
@@ -0,0 +1,73 @@
|
|
1
|
+
import path from "path";
|
2
|
+
import pkgUp from "../../../compiled/pkg-up";
|
3
|
+
import { getArgv } from "../commands";
|
4
|
+
import { fs, minimist, semver } from "../../compiled";
|
5
|
+
import { createDebugger } from "../common";
|
6
|
+
import { ensureArray } from "../ensure";
|
7
|
+
const debug = createDebugger("judge-depExists");
|
8
|
+
export const isDepExists = (appDirectory, name) => {
|
9
|
+
const pkgPath = path.resolve(appDirectory, "./package.json");
|
10
|
+
if (!fs.existsSync(pkgPath)) {
|
11
|
+
debug(`can't find package.json under: %s`, appDirectory);
|
12
|
+
return false;
|
13
|
+
}
|
14
|
+
const json = require(pkgPath);
|
15
|
+
const { dependencies = {}, devDependencies = {} } = json;
|
16
|
+
return dependencies.hasOwnProperty(name) || devDependencies.hasOwnProperty(name);
|
17
|
+
};
|
18
|
+
export const isPackageInstalled = (name, resolvePaths) => {
|
19
|
+
try {
|
20
|
+
require.resolve(name, {
|
21
|
+
paths: ensureArray(resolvePaths)
|
22
|
+
});
|
23
|
+
return true;
|
24
|
+
} catch (err) {
|
25
|
+
return false;
|
26
|
+
}
|
27
|
+
};
|
28
|
+
export const isApiOnly = async (appDirectory, entryDir, apiDir) => {
|
29
|
+
const existApi = await fs.pathExists(apiDir !== null && apiDir !== void 0 ? apiDir : path.join(appDirectory, "api"));
|
30
|
+
const existSrc = await fs.pathExists(path.join(appDirectory, entryDir !== null && entryDir !== void 0 ? entryDir : "src"));
|
31
|
+
const options = minimist(getArgv());
|
32
|
+
if (options["api-only"]) {
|
33
|
+
return true;
|
34
|
+
}
|
35
|
+
return existApi && !existSrc;
|
36
|
+
};
|
37
|
+
export const isWebOnly = async () => {
|
38
|
+
const options = minimist(getArgv());
|
39
|
+
return Boolean(options["web-only"]);
|
40
|
+
};
|
41
|
+
export const isBeyondReact17 = (cwd) => {
|
42
|
+
const pkgPath = pkgUp.sync({
|
43
|
+
cwd
|
44
|
+
});
|
45
|
+
if (!pkgPath) {
|
46
|
+
return false;
|
47
|
+
}
|
48
|
+
const pkgInfo = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
49
|
+
const deps = {
|
50
|
+
...pkgInfo.devDependencies,
|
51
|
+
...pkgInfo.dependencies
|
52
|
+
};
|
53
|
+
if (typeof deps.react !== "string") {
|
54
|
+
return false;
|
55
|
+
}
|
56
|
+
return semver.satisfies(semver.minVersion(deps.react), ">=17.0.0");
|
57
|
+
};
|
58
|
+
export const isReact18 = (cwd) => {
|
59
|
+
const pkgPath = path.join(cwd, "package.json");
|
60
|
+
if (!fs.existsSync(pkgPath)) {
|
61
|
+
return false;
|
62
|
+
}
|
63
|
+
const pkgInfo = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
64
|
+
const deps = {
|
65
|
+
...pkgInfo.devDependencies,
|
66
|
+
...pkgInfo.dependencies
|
67
|
+
};
|
68
|
+
if (typeof deps.react !== "string") {
|
69
|
+
return false;
|
70
|
+
}
|
71
|
+
return semver.satisfies(semver.minVersion(deps.react), ">=18.0.0");
|
72
|
+
};
|
73
|
+
export const isTypescript = (root) => fs.existsSync(path.resolve(root, "./tsconfig.json"));
|
@@ -0,0 +1,25 @@
|
|
1
|
+
export function isString(str) {
|
2
|
+
return typeof str === "string";
|
3
|
+
}
|
4
|
+
export function isUndefined(obj) {
|
5
|
+
return typeof obj === "undefined";
|
6
|
+
}
|
7
|
+
export function isArray(obj) {
|
8
|
+
return Array.isArray(obj);
|
9
|
+
}
|
10
|
+
export function isFunction(func) {
|
11
|
+
return typeof func === "function";
|
12
|
+
}
|
13
|
+
export function isObject(obj) {
|
14
|
+
return obj !== null && typeof obj === "object";
|
15
|
+
}
|
16
|
+
export function isPlainObject(obj) {
|
17
|
+
return isObject(obj) && Object.prototype.toString.call(obj) === "[object Object]";
|
18
|
+
}
|
19
|
+
export function isPromise(obj) {
|
20
|
+
return Boolean(obj) && (typeof obj === "object" || typeof obj === "function") && typeof obj.then === "function";
|
21
|
+
}
|
22
|
+
export function isRegExp(obj) {
|
23
|
+
return Object.prototype.toString.call(obj) === "[object RegExp]";
|
24
|
+
}
|
25
|
+
export const isEmpty = (o) => Object.entries(o).length === 0 && o.constructor === Object;
|
@@ -0,0 +1,103 @@
|
|
1
|
+
import chalk from "../../compiled/chalk";
|
2
|
+
const LOG_LEVEL = {
|
3
|
+
error: 0,
|
4
|
+
warn: 1,
|
5
|
+
info: 2,
|
6
|
+
debug: 3,
|
7
|
+
log: 4
|
8
|
+
};
|
9
|
+
const LOG_TYPES = {
|
10
|
+
error: {
|
11
|
+
color: "red",
|
12
|
+
label: "error",
|
13
|
+
level: "error"
|
14
|
+
},
|
15
|
+
info: {
|
16
|
+
color: "cyan",
|
17
|
+
label: "info",
|
18
|
+
level: "info"
|
19
|
+
},
|
20
|
+
success: {
|
21
|
+
color: "green",
|
22
|
+
label: "Success",
|
23
|
+
level: "info"
|
24
|
+
},
|
25
|
+
warn: {
|
26
|
+
color: "yellow",
|
27
|
+
label: "warn",
|
28
|
+
level: "warn"
|
29
|
+
},
|
30
|
+
debug: {
|
31
|
+
color: "red",
|
32
|
+
label: "debug",
|
33
|
+
level: "debug"
|
34
|
+
},
|
35
|
+
log: {
|
36
|
+
level: "log"
|
37
|
+
}
|
38
|
+
};
|
39
|
+
const DEFAULT_CONFIG = {
|
40
|
+
displayLabel: true,
|
41
|
+
uppercaseLabel: false
|
42
|
+
};
|
43
|
+
class Logger {
|
44
|
+
_log(type, message, ...args) {
|
45
|
+
if (message === void 0 || message === null) {
|
46
|
+
console.log();
|
47
|
+
return;
|
48
|
+
}
|
49
|
+
if (LOG_LEVEL[type] > LOG_LEVEL[this.level]) {
|
50
|
+
return;
|
51
|
+
}
|
52
|
+
let label = "";
|
53
|
+
let text = "";
|
54
|
+
const logType = this.types[type];
|
55
|
+
if (this.config.displayLabel && logType.label) {
|
56
|
+
label = this.config.uppercaseLabel ? logType.label.toUpperCase() : logType.label;
|
57
|
+
label = label.padEnd(this.longestLabel.length);
|
58
|
+
label = chalk.bold(logType.color ? chalk[logType.color](label) : label);
|
59
|
+
}
|
60
|
+
if (message instanceof Error) {
|
61
|
+
if (message.stack) {
|
62
|
+
const [name, ...rest] = message.stack.split("\n");
|
63
|
+
text = `${name}
|
64
|
+
${chalk.grey(rest.join("\n"))}`;
|
65
|
+
} else {
|
66
|
+
text = message.message;
|
67
|
+
}
|
68
|
+
} else {
|
69
|
+
text = `${message}`;
|
70
|
+
}
|
71
|
+
const log = label.length > 0 ? `${label} ${text}` : text;
|
72
|
+
console.log(log, ...args);
|
73
|
+
}
|
74
|
+
getLongestLabel() {
|
75
|
+
let longestLabel = "";
|
76
|
+
Object.keys(this.types).forEach((type) => {
|
77
|
+
const { label = "" } = this.types[type];
|
78
|
+
if (label.length > longestLabel.length) {
|
79
|
+
longestLabel = label;
|
80
|
+
}
|
81
|
+
});
|
82
|
+
return longestLabel;
|
83
|
+
}
|
84
|
+
constructor(options = {}) {
|
85
|
+
this.level = options.level || LOG_TYPES.log.level;
|
86
|
+
this.config = {
|
87
|
+
...DEFAULT_CONFIG,
|
88
|
+
...options.config || {}
|
89
|
+
};
|
90
|
+
this.types = {
|
91
|
+
...LOG_TYPES,
|
92
|
+
...options.types || {}
|
93
|
+
};
|
94
|
+
this.longestLabel = this.getLongestLabel();
|
95
|
+
Object.keys(this.types).forEach((type) => {
|
96
|
+
this[type] = this._log.bind(this, type);
|
97
|
+
});
|
98
|
+
}
|
99
|
+
}
|
100
|
+
const logger = new Logger();
|
101
|
+
logger.Logger = Logger;
|
102
|
+
export { Logger };
|
103
|
+
export { logger };
|
@@ -0,0 +1,70 @@
|
|
1
|
+
import fs from "fs";
|
2
|
+
import path from "path";
|
3
|
+
import { glob, yaml } from "../compiled";
|
4
|
+
const PACKAGE_MAX_DEPTH = 5;
|
5
|
+
const WORKSPACE_FILES = {
|
6
|
+
YARN: "package.json",
|
7
|
+
PNPM: "pnpm-workspace.yaml",
|
8
|
+
LERNA: "lerna.json"
|
9
|
+
};
|
10
|
+
export const isLerna = (root) => fs.existsSync(path.join(root, WORKSPACE_FILES.LERNA));
|
11
|
+
export const isYarnWorkspaces = (root) => {
|
12
|
+
var _json_workspaces;
|
13
|
+
const pkg = path.join(root, WORKSPACE_FILES.YARN);
|
14
|
+
if (!fs.existsSync(pkg)) {
|
15
|
+
return false;
|
16
|
+
}
|
17
|
+
const json = JSON.parse(fs.readFileSync(pkg, "utf8"));
|
18
|
+
return Boolean((_json_workspaces = json.workspaces) === null || _json_workspaces === void 0 ? void 0 : _json_workspaces.packages);
|
19
|
+
};
|
20
|
+
export const isPnpmWorkspaces = (root) => fs.existsSync(path.join(root, WORKSPACE_FILES.PNPM));
|
21
|
+
export const isMonorepo = (root) => isLerna(root) || isYarnWorkspaces(root) || isPnpmWorkspaces(root);
|
22
|
+
export const isModernjsMonorepo = (root) => {
|
23
|
+
const pkgJsonPath = path.join(root, "package.json");
|
24
|
+
if (!fs.existsSync(pkgJsonPath)) {
|
25
|
+
return false;
|
26
|
+
}
|
27
|
+
const json = JSON.parse(fs.readFileSync(pkgJsonPath, "utf8"));
|
28
|
+
const deps = {
|
29
|
+
...json.dependencies || {},
|
30
|
+
...json.devDependencies || {}
|
31
|
+
};
|
32
|
+
return Boolean(deps["@modern-js/monorepo-tools"]);
|
33
|
+
};
|
34
|
+
export const findMonorepoRoot = (appDirectory, maxDepth = PACKAGE_MAX_DEPTH) => {
|
35
|
+
let inMonorepo = false;
|
36
|
+
for (let depth = 0; depth < maxDepth; depth++) {
|
37
|
+
if (isMonorepo(appDirectory)) {
|
38
|
+
inMonorepo = true;
|
39
|
+
break;
|
40
|
+
}
|
41
|
+
appDirectory = path.dirname(appDirectory);
|
42
|
+
}
|
43
|
+
return inMonorepo ? appDirectory : void 0;
|
44
|
+
};
|
45
|
+
export const getMonorepoPackages = (root) => {
|
46
|
+
let packages = [];
|
47
|
+
if (isYarnWorkspaces(root)) {
|
48
|
+
const json = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf8"));
|
49
|
+
({ packages } = json.workspaces);
|
50
|
+
} else if (isLerna(root)) {
|
51
|
+
const json = JSON.parse(fs.readFileSync(path.resolve(root, "lerna.json"), "utf8"));
|
52
|
+
({ packages } = json);
|
53
|
+
} else {
|
54
|
+
({ packages } = yaml.load(fs.readFileSync(path.join(root, WORKSPACE_FILES.PNPM), "utf8")));
|
55
|
+
}
|
56
|
+
if (packages) {
|
57
|
+
return packages.map((name) => (
|
58
|
+
// The trailing / ensures only dirs are picked up
|
59
|
+
glob.sync(path.join(root, `${name}/`), {
|
60
|
+
ignore: [
|
61
|
+
"**/node_modules/**"
|
62
|
+
]
|
63
|
+
})
|
64
|
+
)).reduce((acc, val) => acc.concat(val), []).filter((filepath) => fs.existsSync(path.resolve(filepath, "package.json"))).map((filepath) => ({
|
65
|
+
path: filepath,
|
66
|
+
name: JSON.parse(fs.readFileSync(path.resolve(filepath, "package.json"), "utf8")).name
|
67
|
+
}));
|
68
|
+
}
|
69
|
+
return [];
|
70
|
+
};
|
@@ -0,0 +1,43 @@
|
|
1
|
+
import { execa } from "../compiled";
|
2
|
+
export async function getPnpmVersion() {
|
3
|
+
const { stdout } = await execa("pnpm", [
|
4
|
+
"--version"
|
5
|
+
]);
|
6
|
+
return stdout;
|
7
|
+
}
|
8
|
+
export async function canUseNpm() {
|
9
|
+
try {
|
10
|
+
await execa("npm", [
|
11
|
+
"--version"
|
12
|
+
], {
|
13
|
+
env: process.env
|
14
|
+
});
|
15
|
+
return true;
|
16
|
+
} catch (e) {
|
17
|
+
return false;
|
18
|
+
}
|
19
|
+
}
|
20
|
+
export async function canUseYarn() {
|
21
|
+
try {
|
22
|
+
await execa("yarn", [
|
23
|
+
"--version"
|
24
|
+
], {
|
25
|
+
env: process.env
|
26
|
+
});
|
27
|
+
return true;
|
28
|
+
} catch (e) {
|
29
|
+
return false;
|
30
|
+
}
|
31
|
+
}
|
32
|
+
export async function canUsePnpm() {
|
33
|
+
try {
|
34
|
+
await execa("pnpm", [
|
35
|
+
"--version"
|
36
|
+
], {
|
37
|
+
env: process.env
|
38
|
+
});
|
39
|
+
return true;
|
40
|
+
} catch (e) {
|
41
|
+
return false;
|
42
|
+
}
|
43
|
+
}
|
@@ -0,0 +1,49 @@
|
|
1
|
+
import path from "path";
|
2
|
+
import os from "os";
|
3
|
+
import fs from "fs";
|
4
|
+
import { nanoid, upath, lodash as _ } from "../compiled";
|
5
|
+
export const isPathString = (test) => path.posix.basename(test) !== test || path.win32.basename(test) !== test;
|
6
|
+
export const isRelativePath = (test) => /^\.\.?($|[\\/])/.test(test);
|
7
|
+
export const normalizeOutputPath = (s) => s.replace(/\\/g, "\\\\");
|
8
|
+
export const normalizeToPosixPath = (p) => upath.normalizeSafe(path.normalize(p || "")).replace(/^([a-zA-Z]+):/, (_2, m) => `/${m.toLowerCase()}`);
|
9
|
+
export const getTemplatePath = (prefix) => {
|
10
|
+
const tmpRoot = fs.realpathSync(os.tmpdir());
|
11
|
+
const parts = [
|
12
|
+
tmpRoot
|
13
|
+
];
|
14
|
+
prefix && parts.push(prefix);
|
15
|
+
parts.push(nanoid());
|
16
|
+
return path.resolve(...parts);
|
17
|
+
};
|
18
|
+
export function compilePathMatcherRegExp(match) {
|
19
|
+
if (typeof match !== "string") {
|
20
|
+
return match;
|
21
|
+
}
|
22
|
+
const escaped = _.escapeRegExp(match);
|
23
|
+
return new RegExp(`(?<=\\W|^)${escaped}(?=\\W|$)`);
|
24
|
+
}
|
25
|
+
export const _joinPathParts = (_part, i, parts) => _(parts).filter((part) => ![
|
26
|
+
"/",
|
27
|
+
"\\"
|
28
|
+
].includes(part)).tap((parts2) => parts2.unshift("")).slice(0, i + 2).join("/");
|
29
|
+
export function upwardPaths(start) {
|
30
|
+
return _(start).split(/[/\\]/).filter(Boolean).map(_joinPathParts).reverse().push("/").value();
|
31
|
+
}
|
32
|
+
export function getRealTemporaryDirectory() {
|
33
|
+
let ret = null;
|
34
|
+
try {
|
35
|
+
ret = os.tmpdir();
|
36
|
+
ret = fs.realpathSync(ret);
|
37
|
+
} catch {
|
38
|
+
}
|
39
|
+
return ret;
|
40
|
+
}
|
41
|
+
export function splitPathString(str) {
|
42
|
+
return str.split(/[\\/]/);
|
43
|
+
}
|
44
|
+
export const removeLeadingSlash = (s) => s.replace(/^\/+/, "");
|
45
|
+
export const removeTailSlash = (s) => s.replace(/\/+$/, "");
|
46
|
+
export const removeSlash = (s) => removeLeadingSlash(removeTailSlash(s));
|
47
|
+
export const cutNameByHyphen = (s) => {
|
48
|
+
return s.split(/[-_]/)[0];
|
49
|
+
};
|
@@ -0,0 +1,46 @@
|
|
1
|
+
import os from "os";
|
2
|
+
import _ from "../../compiled/lodash";
|
3
|
+
import { compilePathMatcherRegExp, normalizeToPosixPath, getRealTemporaryDirectory, splitPathString, upwardPaths } from "./path";
|
4
|
+
export const matchUpwardPathsAsUnknown = (p) => _(upwardPaths(normalizeToPosixPath(p))).map((match) => ({
|
5
|
+
match,
|
6
|
+
mark: "unknown"
|
7
|
+
})).slice(1, -1).value();
|
8
|
+
export function applyPathMatcher(matcher, str, options = {}) {
|
9
|
+
const regex = compilePathMatcherRegExp(matcher.match);
|
10
|
+
const replacer = (substring, ...args) => {
|
11
|
+
if (options.minPartials && splitPathString(substring).length < options.minPartials) {
|
12
|
+
return substring;
|
13
|
+
}
|
14
|
+
const ret = typeof matcher.mark === "string" ? matcher.mark : matcher.mark(substring, ...args);
|
15
|
+
return `<${_.snakeCase(ret).toUpperCase()}>`;
|
16
|
+
};
|
17
|
+
return str.replace(regex, replacer);
|
18
|
+
}
|
19
|
+
export function applyMatcherReplacement(matchers, str, options = {}) {
|
20
|
+
return matchers.reduce((ret, matcher) => {
|
21
|
+
return applyPathMatcher(matcher, ret, options);
|
22
|
+
}, str);
|
23
|
+
}
|
24
|
+
export const createDefaultPathMatchers = (root) => {
|
25
|
+
const ret = [
|
26
|
+
{
|
27
|
+
match: RegExp("(?<=\\/)(\\.pnpm\\/.+?\\/node_modules)(?=\\/)"),
|
28
|
+
mark: "pnpmInner"
|
29
|
+
}
|
30
|
+
];
|
31
|
+
const tmpdir = getRealTemporaryDirectory();
|
32
|
+
tmpdir && ret.push({
|
33
|
+
match: tmpdir,
|
34
|
+
mark: "temp"
|
35
|
+
});
|
36
|
+
ret.push({
|
37
|
+
match: os.tmpdir(),
|
38
|
+
mark: "temp"
|
39
|
+
});
|
40
|
+
ret.push({
|
41
|
+
match: os.homedir(),
|
42
|
+
mark: "home"
|
43
|
+
});
|
44
|
+
ret.push(...matchUpwardPathsAsUnknown(root));
|
45
|
+
return ret;
|
46
|
+
};
|
@@ -0,0 +1,44 @@
|
|
1
|
+
import net from "net";
|
2
|
+
import { chalk } from "../compiled";
|
3
|
+
import { logger } from "./logger";
|
4
|
+
export const getPort = async (port, { tryLimits = 20, strictPort = false } = {}) => {
|
5
|
+
if (typeof port === "string") {
|
6
|
+
port = parseInt(port, 10);
|
7
|
+
}
|
8
|
+
if (strictPort) {
|
9
|
+
tryLimits = 1;
|
10
|
+
}
|
11
|
+
const original = port;
|
12
|
+
let found = false;
|
13
|
+
let attempts = 0;
|
14
|
+
while (!found && attempts <= tryLimits) {
|
15
|
+
try {
|
16
|
+
await new Promise((resolve, reject) => {
|
17
|
+
const server = net.createServer();
|
18
|
+
server.unref();
|
19
|
+
server.on("error", reject);
|
20
|
+
server.listen({
|
21
|
+
port,
|
22
|
+
host: "0.0.0.0"
|
23
|
+
}, () => {
|
24
|
+
found = true;
|
25
|
+
server.close(resolve);
|
26
|
+
});
|
27
|
+
});
|
28
|
+
} catch (e) {
|
29
|
+
if (e.code !== "EADDRINUSE") {
|
30
|
+
throw e;
|
31
|
+
}
|
32
|
+
port++;
|
33
|
+
attempts++;
|
34
|
+
}
|
35
|
+
}
|
36
|
+
if (port !== original) {
|
37
|
+
if (strictPort) {
|
38
|
+
throw new Error(`Port "${original}" is occupied, please choose another one.`);
|
39
|
+
} else {
|
40
|
+
logger.info(`Something is already running on port ${original}. ${chalk.yellow(`Use port ${port} instead.`)}`);
|
41
|
+
}
|
42
|
+
}
|
43
|
+
return port;
|
44
|
+
};
|