@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.
Files changed (86) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/cjs/universal/formatWebpack.js +0 -4
  3. package/dist/esm/cli/alias.js +26 -22
  4. package/dist/esm/cli/applyOptionsChain.js +8 -6
  5. package/dist/esm/cli/babel.js +50 -35
  6. package/dist/esm/cli/commands.js +7 -7
  7. package/dist/esm/cli/common.js +10 -5
  8. package/dist/esm/cli/constants/chainId.js +1 -1
  9. package/dist/esm/cli/constants/index.js +33 -37
  10. package/dist/esm/cli/ensure.js +4 -2
  11. package/dist/esm/cli/fs.js +56 -9
  12. package/dist/esm/cli/get/config.js +7 -7
  13. package/dist/esm/cli/get/data.js +93 -55
  14. package/dist/esm/cli/get/index.js +21 -6
  15. package/dist/esm/cli/is/config.js +33 -14
  16. package/dist/esm/cli/is/env.js +18 -6
  17. package/dist/esm/cli/is/platform.js +6 -2
  18. package/dist/esm/cli/is/project.js +73 -36
  19. package/dist/esm/cli/is/type.js +3 -1
  20. package/dist/esm/cli/logger.js +49 -38
  21. package/dist/esm/cli/monorepo.js +49 -36
  22. package/dist/esm/cli/package.js +156 -38
  23. package/dist/esm/cli/path.js +44 -20
  24. package/dist/esm/cli/pathSerializer.js +29 -15
  25. package/dist/esm/cli/port.js +89 -40
  26. package/dist/esm/cli/prettyInstructions.js +42 -31
  27. package/dist/esm/cli/require.js +21 -16
  28. package/dist/esm/cli/runtimeExports.js +21 -15
  29. package/dist/esm/cli/watch.js +94 -27
  30. package/dist/esm/compiled.js +3 -3
  31. package/dist/esm/import.js +4 -4
  32. package/dist/esm/runtime/nestedRoutes.js +42 -29
  33. package/dist/esm/runtime-browser/parsed.js +5 -5
  34. package/dist/esm/runtime-node/index.js +1 -1
  35. package/dist/esm/runtime-node/nestedRoutes.js +6 -4
  36. package/dist/esm/runtime-node/serialize.js +1 -1
  37. package/dist/esm/runtime-node/storage.js +12 -14
  38. package/dist/esm/universal/constants.js +3 -3
  39. package/dist/esm/universal/formatWebpack.js +20 -26
  40. package/dist/esm/universal/pluginDagSort.js +49 -26
  41. package/dist/esm-node/cli/alias.js +51 -0
  42. package/dist/esm-node/cli/applyOptionsChain.js +24 -0
  43. package/dist/esm-node/cli/babel.js +103 -0
  44. package/dist/esm-node/cli/commands.js +16 -0
  45. package/dist/esm-node/cli/common.js +10 -0
  46. package/dist/esm-node/cli/constants/chainId.js +180 -0
  47. package/dist/esm-node/cli/constants/index.js +103 -0
  48. package/dist/esm-node/cli/ensure.js +10 -0
  49. package/dist/esm-node/cli/fs.js +14 -0
  50. package/dist/esm-node/cli/get/config.js +16 -0
  51. package/dist/esm-node/cli/get/data.js +86 -0
  52. package/dist/esm-node/cli/get/index.js +13 -0
  53. package/dist/esm-node/cli/index.js +20 -0
  54. package/dist/esm-node/cli/is/config.js +40 -0
  55. package/dist/esm-node/cli/is/env.js +6 -0
  56. package/dist/esm-node/cli/is/index.js +5 -0
  57. package/dist/esm-node/cli/is/platform.js +2 -0
  58. package/dist/esm-node/cli/is/project.js +73 -0
  59. package/dist/esm-node/cli/is/type.js +25 -0
  60. package/dist/esm-node/cli/logger.js +103 -0
  61. package/dist/esm-node/cli/monorepo.js +70 -0
  62. package/dist/esm-node/cli/package.js +43 -0
  63. package/dist/esm-node/cli/path.js +49 -0
  64. package/dist/esm-node/cli/pathSerializer.js +46 -0
  65. package/dist/esm-node/cli/port.js +44 -0
  66. package/dist/esm-node/cli/prettyInstructions.js +77 -0
  67. package/dist/esm-node/cli/require.js +52 -0
  68. package/dist/esm-node/cli/runtimeExports.js +35 -0
  69. package/dist/esm-node/cli/watch.js +41 -0
  70. package/dist/esm-node/compiled.js +33 -0
  71. package/dist/esm-node/import.js +8 -0
  72. package/dist/esm-node/index.js +3 -0
  73. package/dist/esm-node/runtime/nestedRoutes.js +112 -0
  74. package/dist/esm-node/runtime/remixRouter.js +1 -0
  75. package/dist/esm-node/runtime/router.js +1 -0
  76. package/dist/esm-node/runtime-browser/index.js +1 -0
  77. package/dist/esm-node/runtime-browser/parsed.js +17 -0
  78. package/dist/esm-node/runtime-node/index.js +5 -0
  79. package/dist/esm-node/runtime-node/nestedRoutes.js +18 -0
  80. package/dist/esm-node/runtime-node/router.js +1 -0
  81. package/dist/esm-node/runtime-node/serialize.js +6 -0
  82. package/dist/esm-node/runtime-node/storage.js +38 -0
  83. package/dist/esm-node/universal/constants.js +3 -0
  84. package/dist/esm-node/universal/formatWebpack.js +61 -0
  85. package/dist/esm-node/universal/pluginDagSort.js +50 -0
  86. 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,5 @@
1
+ export * from "./env";
2
+ export * from "./platform";
3
+ export * from "./type";
4
+ export * from "./config";
5
+ export * from "./project";
@@ -0,0 +1,2 @@
1
+ export const isNodeJS = () => typeof process !== "undefined" && process.versions != null && process.versions.node != null && process.versions.electron == null;
2
+ export const isBrowser = () => typeof window !== "undefined";
@@ -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
+ };