@modern-js/utils 2.26.0 → 2.28.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +20 -0
- package/dist/cjs/cli/alias.js +3 -3
- package/dist/cjs/cli/constants/chainId.js +4 -0
- package/dist/cjs/cli/constants/index.js +0 -1
- package/dist/cjs/cli/is/config.js +11 -8
- package/dist/cjs/cli/prettyInstructions.js +3 -2
- package/dist/cjs/cli/require.js +2 -1
- package/dist/cjs/runtime/nestedRoutes.js +9 -5
- package/dist/cjs/runtime-browser/parsed.js +2 -1
- package/dist/cjs/universal/formatWebpack.js +55 -12
- package/dist/esm/cli/alias.js +27 -23
- 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 +5 -1
- package/dist/esm/cli/constants/index.js +33 -38
- 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 +102 -55
- package/dist/esm/cli/get/index.js +21 -6
- package/dist/esm/cli/is/config.js +43 -21
- 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 +44 -32
- package/dist/esm/cli/require.js +22 -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 +49 -32
- package/dist/esm/runtime-browser/parsed.js +6 -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 +54 -28
- 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 +184 -0
- package/dist/esm-node/cli/constants/index.js +102 -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 +43 -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 +78 -0
- package/dist/esm-node/cli/require.js +53 -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 +116 -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 +18 -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 +99 -0
- package/dist/esm-node/universal/pluginDagSort.js +50 -0
- package/dist/types/cli/constants/chainId.d.ts +4 -0
- package/dist/types/universal/formatWebpack.d.ts +14 -1
- package/package.json +4 -4
@@ -0,0 +1,43 @@
|
|
1
|
+
import { isEmpty } from "./type";
|
2
|
+
export const isSSR = (config) => {
|
3
|
+
var _server, _server1;
|
4
|
+
const { server } = config;
|
5
|
+
if ((_server = server) === null || _server === void 0 ? void 0 : _server.ssr) {
|
6
|
+
return true;
|
7
|
+
}
|
8
|
+
if (((_server1 = server) === null || _server1 === void 0 ? void 0 : _server1.ssrByEntries) && !isEmpty(server.ssrByEntries)) {
|
9
|
+
for (const name of Object.keys(server.ssrByEntries)) {
|
10
|
+
if (server.ssrByEntries[name]) {
|
11
|
+
return true;
|
12
|
+
}
|
13
|
+
}
|
14
|
+
}
|
15
|
+
return false;
|
16
|
+
};
|
17
|
+
export const isUseSSRBundle = (config) => {
|
18
|
+
var _output;
|
19
|
+
const { output } = config;
|
20
|
+
if ((_output = output) === null || _output === void 0 ? void 0 : _output.ssg) {
|
21
|
+
return true;
|
22
|
+
}
|
23
|
+
return isSSR(config);
|
24
|
+
};
|
25
|
+
export const isServiceWorker = (config) => {
|
26
|
+
var _deploy_worker, _deploy, _output;
|
27
|
+
const { output, deploy } = config;
|
28
|
+
if (((_deploy = deploy) === null || _deploy === void 0 ? void 0 : (_deploy_worker = _deploy.worker) === null || _deploy_worker === void 0 ? void 0 : _deploy_worker.ssr) && (((_output = output) === null || _output === void 0 ? void 0 : _output.ssg) || isSSR(config))) {
|
29
|
+
return true;
|
30
|
+
}
|
31
|
+
return false;
|
32
|
+
};
|
33
|
+
export const isRouterV5 = (config) => {
|
34
|
+
var _config_runtime, _config_runtime_router, _config_runtime1, _config;
|
35
|
+
return typeof ((_config_runtime = config.runtime) === null || _config_runtime === void 0 ? void 0 : _config_runtime.router) !== "boolean" && ((_config = 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";
|
36
|
+
};
|
37
|
+
export const isSSGEntry = (config, entryName, entrypoints) => {
|
38
|
+
var _ssgConfig, _ssgConfig1;
|
39
|
+
const ssgConfig = config.output.ssg;
|
40
|
+
const useSSG = isSingleEntry(entrypoints) ? Boolean(ssgConfig) : ssgConfig === true || typeof ((_ssgConfig = ssgConfig) === null || _ssgConfig === void 0 ? void 0 : _ssgConfig[0]) === "function" || Boolean((_ssgConfig1 = ssgConfig) === null || _ssgConfig1 === void 0 ? void 0 : _ssgConfig1[entryName]);
|
41
|
+
return useSSG;
|
42
|
+
};
|
43
|
+
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
|
+
};
|
@@ -0,0 +1,78 @@
|
|
1
|
+
import os from "os";
|
2
|
+
import { chalk } from "../compiled";
|
3
|
+
import { isDev, isSingleEntry } from "./is";
|
4
|
+
import { DEFAULT_DEV_HOST } from "./constants";
|
5
|
+
const normalizeUrl = (url) => url.replace(/([^:]\/)\/+/g, "$1");
|
6
|
+
const getIpv4Interfaces = () => {
|
7
|
+
const interfaces = os.networkInterfaces();
|
8
|
+
const ipv4Interfaces = [];
|
9
|
+
Object.keys(interfaces).forEach((key) => {
|
10
|
+
interfaces[key].forEach((detail) => {
|
11
|
+
const familyV4Value = typeof detail.family === "string" ? "IPv4" : 4;
|
12
|
+
if (detail.family === familyV4Value) {
|
13
|
+
ipv4Interfaces.push(detail);
|
14
|
+
}
|
15
|
+
});
|
16
|
+
});
|
17
|
+
return ipv4Interfaces;
|
18
|
+
};
|
19
|
+
export const getAddressUrls = (protocol = "http", port, host) => {
|
20
|
+
const LOCAL_LABEL = "Local: ";
|
21
|
+
const NETWORK_LABEL = "Network: ";
|
22
|
+
const isLocalhost = (url) => {
|
23
|
+
var _url;
|
24
|
+
return (_url = url) === null || _url === void 0 ? void 0 : _url.includes("localhost");
|
25
|
+
};
|
26
|
+
if (host && host !== DEFAULT_DEV_HOST) {
|
27
|
+
return [
|
28
|
+
{
|
29
|
+
label: isLocalhost(host) ? LOCAL_LABEL : NETWORK_LABEL,
|
30
|
+
url: `${protocol}://${host}:${port}`
|
31
|
+
}
|
32
|
+
];
|
33
|
+
}
|
34
|
+
const ipv4Interfaces = getIpv4Interfaces();
|
35
|
+
return ipv4Interfaces.reduce((memo, detail) => {
|
36
|
+
if (isLocalhost(detail.address) || detail.internal) {
|
37
|
+
memo.push({
|
38
|
+
label: LOCAL_LABEL,
|
39
|
+
url: `${protocol}://localhost:${port}`
|
40
|
+
});
|
41
|
+
} else {
|
42
|
+
memo.push({
|
43
|
+
label: NETWORK_LABEL,
|
44
|
+
url: `${protocol}://${detail.address}:${port}`
|
45
|
+
});
|
46
|
+
}
|
47
|
+
return memo;
|
48
|
+
}, []);
|
49
|
+
};
|
50
|
+
export const prettyInstructions = (appContext, config) => {
|
51
|
+
var _appContext_builder_context_devServer, _appContext_builder, _config_dev;
|
52
|
+
const { entrypoints, serverRoutes, port, apiOnly, checkedEntries } = appContext;
|
53
|
+
const isHttps = isDev() && ((_appContext_builder = appContext.builder) === null || _appContext_builder === void 0 ? void 0 : (_appContext_builder_context_devServer = _appContext_builder.context.devServer) === null || _appContext_builder_context_devServer === void 0 ? void 0 : _appContext_builder_context_devServer.https);
|
54
|
+
const urls = getAddressUrls(isHttps ? "https" : "http", port, (_config_dev = config.dev) === null || _config_dev === void 0 ? void 0 : _config_dev.host);
|
55
|
+
const routes = !apiOnly ? serverRoutes.filter((route) => route.entryName) : serverRoutes;
|
56
|
+
let message = "App running at:\n\n";
|
57
|
+
if (isSingleEntry(entrypoints) || apiOnly) {
|
58
|
+
message += urls.map(({ label, url }) => ` ${chalk.bold(`> ${label.padEnd(10)}`)}${chalk.cyanBright(normalizeUrl(`${url}/${routes[0].urlPath}`))}
|
59
|
+
`).join("");
|
60
|
+
} else {
|
61
|
+
const maxNameLength = Math.max(...routes.map((r) => r.entryName.length));
|
62
|
+
urls.forEach(({ label, url }) => {
|
63
|
+
message += ` ${chalk.bold(`> ${label}`)}
|
64
|
+
`;
|
65
|
+
routes.forEach(({ entryName, urlPath, isSSR }) => {
|
66
|
+
if (!checkedEntries.includes(entryName)) {
|
67
|
+
return;
|
68
|
+
}
|
69
|
+
message += ` ${chalk.yellowBright(isSSR ? "λ" : "○")} ${chalk.yellowBright(entryName.padEnd(maxNameLength + 8))}${chalk.cyanBright(normalizeUrl(`${url}/${urlPath}`))}
|
70
|
+
`;
|
71
|
+
});
|
72
|
+
});
|
73
|
+
message += "\n";
|
74
|
+
message += chalk.cyanBright(" λ (Server) server-side renders at runtime\n");
|
75
|
+
message += chalk.cyanBright(" ○ (Static) client-side renders as static HTML\n");
|
76
|
+
}
|
77
|
+
return message;
|
78
|
+
};
|
@@ -0,0 +1,53 @@
|
|
1
|
+
import { findExists } from "./fs";
|
2
|
+
export const compatRequire = (filePath, interop = true) => {
|
3
|
+
var _mod;
|
4
|
+
const mod = require(filePath);
|
5
|
+
const rtnESMDefault = interop && ((_mod = mod) === null || _mod === void 0 ? void 0 : _mod.__esModule);
|
6
|
+
return rtnESMDefault ? mod.default : mod;
|
7
|
+
};
|
8
|
+
export const dynamicImport = new Function("modulePath", "return import(modulePath)");
|
9
|
+
export const requireExistModule = (filename, opt) => {
|
10
|
+
const final = {
|
11
|
+
extensions: [
|
12
|
+
".ts",
|
13
|
+
".js"
|
14
|
+
],
|
15
|
+
interop: true,
|
16
|
+
...opt
|
17
|
+
};
|
18
|
+
const exist = findExists(final.extensions.map((ext) => `${filename}${ext}`));
|
19
|
+
if (!exist) {
|
20
|
+
return null;
|
21
|
+
}
|
22
|
+
return compatRequire(exist, final.interop);
|
23
|
+
};
|
24
|
+
export const cleanRequireCache = (filelist) => {
|
25
|
+
filelist.forEach((filepath) => {
|
26
|
+
delete require.cache[filepath];
|
27
|
+
});
|
28
|
+
};
|
29
|
+
export function deleteRequireCache(path) {
|
30
|
+
if (require.cache[path]) {
|
31
|
+
delete require.cache[path];
|
32
|
+
}
|
33
|
+
if (module.children) {
|
34
|
+
module.children = module.children.filter((item) => item.filename !== path);
|
35
|
+
}
|
36
|
+
}
|
37
|
+
export const tryResolve = (name, resolvePath) => {
|
38
|
+
let filePath = "";
|
39
|
+
try {
|
40
|
+
filePath = require.resolve(name, {
|
41
|
+
paths: [
|
42
|
+
resolvePath
|
43
|
+
]
|
44
|
+
});
|
45
|
+
delete require.cache[filePath];
|
46
|
+
} catch (err) {
|
47
|
+
if (err.code === "MODULE_NOT_FOUND") {
|
48
|
+
throw new Error(`Can not find module ${name}.`);
|
49
|
+
}
|
50
|
+
throw err;
|
51
|
+
}
|
52
|
+
return filePath;
|
53
|
+
};
|
@@ -0,0 +1,35 @@
|
|
1
|
+
import path from "path";
|
2
|
+
import { fs } from "../compiled";
|
3
|
+
import { normalizeOutputPath } from "./path";
|
4
|
+
const memo = (fn) => {
|
5
|
+
const cache = /* @__PURE__ */ new Map();
|
6
|
+
return (...params) => {
|
7
|
+
const stringifiedParams = JSON.stringify(params);
|
8
|
+
const cachedResult = cache.get(stringifiedParams);
|
9
|
+
if (cachedResult) {
|
10
|
+
return cachedResult;
|
11
|
+
}
|
12
|
+
const res = fn(...params);
|
13
|
+
cache.set(stringifiedParams, res);
|
14
|
+
return res;
|
15
|
+
};
|
16
|
+
};
|
17
|
+
export const createRuntimeExportsUtils = memo((pwd = "", namespace = "index") => {
|
18
|
+
const entryExportFile = path.join(pwd, `.runtime-exports/${namespace}.js`);
|
19
|
+
const addExport = (statement) => {
|
20
|
+
statement = normalizeOutputPath(statement);
|
21
|
+
try {
|
22
|
+
fs.ensureFileSync(entryExportFile);
|
23
|
+
if (!fs.readFileSync(entryExportFile, "utf8").includes(statement)) {
|
24
|
+
fs.appendFileSync(entryExportFile, `${statement}
|
25
|
+
`);
|
26
|
+
}
|
27
|
+
} catch {
|
28
|
+
}
|
29
|
+
};
|
30
|
+
const getPath = () => entryExportFile;
|
31
|
+
return {
|
32
|
+
addExport,
|
33
|
+
getPath
|
34
|
+
};
|
35
|
+
});
|