@modern-js/utils 2.26.0 → 2.27.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
};
|