@modern-js/utils 1.1.6 → 1.2.2
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +23 -0
- package/dist/js/modern/constants.js +2 -1
- package/dist/js/modern/getBrowserslist.js +1 -1
- package/dist/js/modern/prettyInstructions.js +1 -1
- package/dist/js/node/constants.js +2 -1
- package/dist/js/node/getBrowserslist.js +2 -2
- package/dist/js/node/prettyInstructions.js +1 -1
- package/dist/js/treeshaking/constants.js +2 -1
- package/dist/js/treeshaking/getBrowserslist.js +1 -1
- package/dist/js/treeshaking/prettyInstructions.js +1 -1
- package/dist/types/getBrowserslist.d.ts +1 -1
- package/jest.config.js +8 -0
- package/package.json +18 -12
- package/tests/applyOptionsChain.test.ts +1 -1
- package/tests/compatRequire.test.ts +1 -1
- package/tests/debug.test.ts +4 -2
- package/tests/ensureAbsolutePath.test.ts +1 -1
- package/tests/findExists.test.ts +1 -1
- package/tests/getBrowserslist.test.ts +1 -1
- package/tests/getCacheIdentifier.test.ts +1 -1
- package/tests/getEntryOptions.test.ts +1 -1
- package/tests/index.test.ts +1 -1
- package/tests/logger.test.ts +1 -1
- package/tests/removeSlash.test.ts +1 -1
- package/tests/tsconfig.json +1 -3
- package/tsconfig.json +1 -3
- package/src/FileSizeReporter.ts +0 -181
- package/src/alias.ts +0 -90
- package/src/applyOptionsChain.ts +0 -44
- package/src/chalk.ts +0 -3
- package/src/clearConsole.ts +0 -5
- package/src/compatRequire.ts +0 -25
- package/src/constants.ts +0 -262
- package/src/debug.ts +0 -8
- package/src/ensureAbsolutePath.ts +0 -10
- package/src/findExists.ts +0 -15
- package/src/formatWebpackMessages.ts +0 -131
- package/src/generateMetaTags.ts +0 -75
- package/src/getBrowserslist.ts +0 -6
- package/src/getCacheIdentifier.ts +0 -30
- package/src/getEntryOptions.ts +0 -37
- package/src/getPackageManager.ts +0 -30
- package/src/getPort.ts +0 -62
- package/src/import.ts +0 -10
- package/src/index.ts +0 -31
- package/src/is/index.ts +0 -78
- package/src/is/node-env.ts +0 -9
- package/src/is/platform.ts +0 -7
- package/src/is/type.ts +0 -43
- package/src/logger.ts +0 -184
- package/src/monorepo.ts +0 -106
- package/src/nodeEnv.ts +0 -28
- package/src/path.ts +0 -9
- package/src/pkgUp.ts +0 -3
- package/src/prettyInstructions.ts +0 -88
- package/src/printBuildError.ts +0 -47
- package/src/readTsConfig.ts +0 -21
- package/src/removeSlash.ts +0 -6
- package/src/runtimeExports.ts +0 -68
- package/src/types.d.ts +0 -1
- package/src/watch.ts +0 -56
package/src/getPort.ts
DELETED
@@ -1,62 +0,0 @@
|
|
1
|
-
import net from 'net';
|
2
|
-
import { chalk } from './chalk';
|
3
|
-
import { logger } from './logger';
|
4
|
-
|
5
|
-
/**
|
6
|
-
* Get available free port.
|
7
|
-
* @param port - Current port want to use.
|
8
|
-
* @param tryLimits - Maximum number of retries.
|
9
|
-
* @returns Available port number.
|
10
|
-
*/
|
11
|
-
/* eslint-disable no-param-reassign, @typescript-eslint/no-loop-func */
|
12
|
-
export const getPort = async (
|
13
|
-
port: string | number,
|
14
|
-
tryLimits = 20,
|
15
|
-
): Promise<number> => {
|
16
|
-
if (typeof port === 'string') {
|
17
|
-
port = parseInt(port, 10);
|
18
|
-
}
|
19
|
-
|
20
|
-
const original = port;
|
21
|
-
|
22
|
-
let found = false;
|
23
|
-
let attempts = 0;
|
24
|
-
while (!found && attempts <= tryLimits) {
|
25
|
-
try {
|
26
|
-
await new Promise((resolve, reject) => {
|
27
|
-
const server = net.createServer();
|
28
|
-
server.unref();
|
29
|
-
server.on('error', reject);
|
30
|
-
server.listen(
|
31
|
-
{
|
32
|
-
port,
|
33
|
-
host: '0.0.0.0',
|
34
|
-
},
|
35
|
-
() => {
|
36
|
-
found = true;
|
37
|
-
server.close(resolve);
|
38
|
-
},
|
39
|
-
);
|
40
|
-
});
|
41
|
-
} catch (e: any) {
|
42
|
-
if (e.code !== 'EADDRINUSE') {
|
43
|
-
throw e;
|
44
|
-
}
|
45
|
-
port++;
|
46
|
-
attempts++;
|
47
|
-
}
|
48
|
-
}
|
49
|
-
|
50
|
-
if (port !== original) {
|
51
|
-
logger.info(
|
52
|
-
chalk.red(
|
53
|
-
`Something is already running on port ${original}. ${chalk.yellow(
|
54
|
-
`Use port ${port} instead.`,
|
55
|
-
)}`,
|
56
|
-
),
|
57
|
-
);
|
58
|
-
}
|
59
|
-
|
60
|
-
return port;
|
61
|
-
};
|
62
|
-
/* eslint-enable no-param-reassign, @typescript-eslint/no-loop-func */
|
package/src/import.ts
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
// cover: https://rushstack.io/pages/api/node-core-library.import.lazy/
|
2
|
-
const lazy = (moduleName: string, requireFn: (id: string) => unknown): any => {
|
3
|
-
const importLazyLocal: (moduleName: string) => unknown =
|
4
|
-
require('import-lazy')(requireFn);
|
5
|
-
return importLazyLocal(moduleName);
|
6
|
-
};
|
7
|
-
|
8
|
-
export { lazy as lazyImport };
|
9
|
-
|
10
|
-
export const Import = { lazy };
|
package/src/index.ts
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
export * as fs from 'fs-extra';
|
2
|
-
export * from './chalk';
|
3
|
-
export * from './formatWebpackMessages';
|
4
|
-
export * from './FileSizeReporter';
|
5
|
-
export * from './printBuildError';
|
6
|
-
export * from './debug';
|
7
|
-
export * from './findExists';
|
8
|
-
export * from './is';
|
9
|
-
export * from './compatRequire';
|
10
|
-
export * from './logger';
|
11
|
-
export * from './constants';
|
12
|
-
export * from './ensureAbsolutePath';
|
13
|
-
export * from './getCacheIdentifier';
|
14
|
-
export * from './clearConsole';
|
15
|
-
export * from './pkgUp';
|
16
|
-
export * from './applyOptionsChain';
|
17
|
-
export * from './getBrowserslist';
|
18
|
-
export * from './removeSlash';
|
19
|
-
export * from './getEntryOptions';
|
20
|
-
export * from './getPort';
|
21
|
-
export * from './monorepo';
|
22
|
-
export * from './getPackageManager';
|
23
|
-
export * from './runtimeExports';
|
24
|
-
export * from './readTsConfig';
|
25
|
-
export * from './path';
|
26
|
-
export * from './generateMetaTags';
|
27
|
-
export * from './prettyInstructions';
|
28
|
-
export * from './alias';
|
29
|
-
export * from './import';
|
30
|
-
export * from './watch';
|
31
|
-
export * from './nodeEnv';
|
package/src/is/index.ts
DELETED
@@ -1,78 +0,0 @@
|
|
1
|
-
import fs from 'fs';
|
2
|
-
import path from 'path';
|
3
|
-
import { isDev } from './node-env';
|
4
|
-
|
5
|
-
/**
|
6
|
-
* Check if the package name is in dependencies or devDependencies.
|
7
|
-
*
|
8
|
-
* @param appDirectory - Project root directory.
|
9
|
-
* @param name - Package name.
|
10
|
-
* @returns True if the name is in dependencies or devDependencies, false otherwise.
|
11
|
-
*/
|
12
|
-
export const isDepExists = (appDirectory: string, name: string): boolean => {
|
13
|
-
const json = require(path.resolve(appDirectory, './package.json'));
|
14
|
-
|
15
|
-
const { dependencies = {}, devDependencies = {} } = json;
|
16
|
-
|
17
|
-
return (
|
18
|
-
dependencies.hasOwnProperty(name) || devDependencies.hasOwnProperty(name)
|
19
|
-
);
|
20
|
-
};
|
21
|
-
|
22
|
-
/**
|
23
|
-
* Is typescript project.
|
24
|
-
*
|
25
|
-
* @param root - App directory.
|
26
|
-
* @returns Whether to use typescript.
|
27
|
-
*/
|
28
|
-
export const isTypescript = (root: string): boolean =>
|
29
|
-
fs.existsSync(path.resolve(root, './tsconfig.json'));
|
30
|
-
|
31
|
-
/**
|
32
|
-
* Is Empty object
|
33
|
-
*
|
34
|
-
* @param o - Any object.
|
35
|
-
* @returns Whether it is empty object.
|
36
|
-
*/
|
37
|
-
export const isEmpty = (o: Record<string, unknown>) =>
|
38
|
-
Object.entries(o).length === 0 && o.constructor === Object;
|
39
|
-
|
40
|
-
/**
|
41
|
-
* Is SSR project
|
42
|
-
*
|
43
|
-
* @param config - User config.
|
44
|
-
* @returns Whether to use server side render.
|
45
|
-
*/
|
46
|
-
export const isSSR = (config: any): boolean => {
|
47
|
-
const { server } = config;
|
48
|
-
|
49
|
-
if (server?.ssr) {
|
50
|
-
return true;
|
51
|
-
}
|
52
|
-
|
53
|
-
if (server?.ssrByEntries && !isEmpty(server.ssrByEntries)) {
|
54
|
-
for (const name of Object.keys(server.ssrByEntries)) {
|
55
|
-
if (server.ssrByEntries[name]) {
|
56
|
-
return true;
|
57
|
-
}
|
58
|
-
}
|
59
|
-
}
|
60
|
-
|
61
|
-
return false;
|
62
|
-
};
|
63
|
-
|
64
|
-
export const isUseSSRBundle = (config: any): boolean => {
|
65
|
-
const { output } = config;
|
66
|
-
if (output?.ssg) {
|
67
|
-
return true;
|
68
|
-
}
|
69
|
-
|
70
|
-
return isSSR(config);
|
71
|
-
};
|
72
|
-
|
73
|
-
export const isFastRefresh = () =>
|
74
|
-
isDev() && process.env.FAST_REFRESH !== 'false';
|
75
|
-
|
76
|
-
export * from './node-env';
|
77
|
-
export * from './platform';
|
78
|
-
export * from './type';
|
package/src/is/node-env.ts
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
export const isDev = (): boolean => process.env.NODE_ENV === 'development';
|
2
|
-
|
3
|
-
export const isProd = (): boolean => process.env.NODE_ENV === 'production';
|
4
|
-
|
5
|
-
export const isTest = () => process.env.NODE_ENV === 'test';
|
6
|
-
|
7
|
-
// Variable used for enabling profiling in Production.
|
8
|
-
export const isProdProfile = () =>
|
9
|
-
isProd() && process.argv.includes('--profile');
|
package/src/is/platform.ts
DELETED
package/src/is/type.ts
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
export function isString(str: any): str is string {
|
2
|
-
return typeof str === 'string';
|
3
|
-
}
|
4
|
-
|
5
|
-
export function isUndefined(obj: any): obj is undefined {
|
6
|
-
return typeof obj === 'undefined';
|
7
|
-
}
|
8
|
-
|
9
|
-
export function isArray(obj: any): obj is any[] {
|
10
|
-
return Object.prototype.toString.call(obj) === '[object Array]';
|
11
|
-
}
|
12
|
-
|
13
|
-
// eslint-disable-next-line @typescript-eslint/ban-types
|
14
|
-
export function isFunction(func: any): func is Function {
|
15
|
-
return typeof func === 'function';
|
16
|
-
}
|
17
|
-
|
18
|
-
// eslint-disable-next-line @typescript-eslint/ban-types
|
19
|
-
export function isObject(obj: any): obj is object {
|
20
|
-
return typeof obj === 'object';
|
21
|
-
}
|
22
|
-
|
23
|
-
export function isPlainObject(obj: any): obj is Record<string, any> {
|
24
|
-
return (
|
25
|
-
obj &&
|
26
|
-
typeof obj === 'object' &&
|
27
|
-
Object.prototype.toString.call(obj) === '[object Object]'
|
28
|
-
);
|
29
|
-
}
|
30
|
-
|
31
|
-
export function isPromise(obj: any): obj is Promise<any> {
|
32
|
-
/* eslint-disable promise/prefer-await-to-then */
|
33
|
-
return (
|
34
|
-
Boolean(obj) &&
|
35
|
-
(typeof obj === 'object' || typeof obj === 'function') &&
|
36
|
-
typeof obj.then === 'function'
|
37
|
-
);
|
38
|
-
/* eslint-enable promise/prefer-await-to-then */
|
39
|
-
}
|
40
|
-
|
41
|
-
export function isRegExp(obj: any): obj is RegExp {
|
42
|
-
return Object.prototype.toString.call(obj) === '[object RegExp]';
|
43
|
-
}
|
package/src/logger.ts
DELETED
@@ -1,184 +0,0 @@
|
|
1
|
-
import chalk, { Color } from 'chalk';
|
2
|
-
|
3
|
-
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
4
|
-
|
5
|
-
type LogMsg = number | string | Error;
|
6
|
-
|
7
|
-
interface LoggerConfiguration {
|
8
|
-
color?: typeof Color;
|
9
|
-
label?: string;
|
10
|
-
level?: LogLevel;
|
11
|
-
}
|
12
|
-
|
13
|
-
interface InstanceConfiguration {
|
14
|
-
displayLabel?: boolean;
|
15
|
-
underlineLabel?: boolean;
|
16
|
-
uppercaseLabel?: boolean;
|
17
|
-
}
|
18
|
-
|
19
|
-
interface ConstructorOptions {
|
20
|
-
config?: InstanceConfiguration;
|
21
|
-
types?: Record<string, LoggerConfiguration>;
|
22
|
-
}
|
23
|
-
|
24
|
-
type LoggerFunction = (
|
25
|
-
message?: number | string | Error,
|
26
|
-
...args: any[]
|
27
|
-
) => void;
|
28
|
-
|
29
|
-
const { grey, underline } = chalk;
|
30
|
-
|
31
|
-
const LOG_TYPES = {
|
32
|
-
error: {
|
33
|
-
color: 'red',
|
34
|
-
label: 'error',
|
35
|
-
level: 'error',
|
36
|
-
},
|
37
|
-
info: {
|
38
|
-
color: 'blue',
|
39
|
-
label: 'info',
|
40
|
-
level: 'info',
|
41
|
-
},
|
42
|
-
warn: {
|
43
|
-
color: 'yellow',
|
44
|
-
label: 'warning',
|
45
|
-
level: 'warn',
|
46
|
-
},
|
47
|
-
debug: {
|
48
|
-
color: 'red',
|
49
|
-
label: 'debug',
|
50
|
-
level: 'debug',
|
51
|
-
},
|
52
|
-
log: { level: 'info' },
|
53
|
-
};
|
54
|
-
|
55
|
-
const DEFAULT_CONFIG = {
|
56
|
-
displayLabel: true,
|
57
|
-
underlineLabel: true,
|
58
|
-
uppercaseLabel: false,
|
59
|
-
};
|
60
|
-
|
61
|
-
class Logger {
|
62
|
-
private readonly logCount: number = 200;
|
63
|
-
|
64
|
-
private history: Partial<Record<string, Array<string>>> = {};
|
65
|
-
|
66
|
-
private readonly config: InstanceConfiguration;
|
67
|
-
|
68
|
-
private readonly types: Record<string, LoggerConfiguration>;
|
69
|
-
|
70
|
-
private readonly longestLabel: string;
|
71
|
-
|
72
|
-
[key: string]: any;
|
73
|
-
|
74
|
-
constructor(options: ConstructorOptions = {}) {
|
75
|
-
this.config = { ...DEFAULT_CONFIG, ...(options.config || {}) };
|
76
|
-
this.types = {
|
77
|
-
...(LOG_TYPES as Record<string, LoggerConfiguration>),
|
78
|
-
...(options.types || {}),
|
79
|
-
};
|
80
|
-
this.longestLabel = this.getLongestLabel();
|
81
|
-
|
82
|
-
Object.keys(this.types).forEach(type => {
|
83
|
-
this[type] = this._log.bind(this, type);
|
84
|
-
});
|
85
|
-
}
|
86
|
-
|
87
|
-
private retainLog(type: string, message: string) {
|
88
|
-
if (!this.history[type]) {
|
89
|
-
this.history[type] = [];
|
90
|
-
}
|
91
|
-
this.history[type]!.push(message);
|
92
|
-
while (this.history[type]!.length > this.logCount) {
|
93
|
-
this.history[type]!.shift();
|
94
|
-
}
|
95
|
-
}
|
96
|
-
|
97
|
-
// eslint-disable-next-line max-statements
|
98
|
-
private _log(type: string, message?: LogMsg) {
|
99
|
-
if (message === undefined) {
|
100
|
-
// eslint-disable-next-line no-console
|
101
|
-
console.log();
|
102
|
-
return;
|
103
|
-
}
|
104
|
-
|
105
|
-
let label = '';
|
106
|
-
let text = '';
|
107
|
-
const logType = this.types[type];
|
108
|
-
|
109
|
-
if (this.config.displayLabel && logType.label) {
|
110
|
-
label = this.config.uppercaseLabel
|
111
|
-
? logType.label.toUpperCase()
|
112
|
-
: logType.label;
|
113
|
-
|
114
|
-
if (this.config.underlineLabel) {
|
115
|
-
label = underline(label).padEnd(this.longestUnderlinedLabel.length + 1);
|
116
|
-
} else {
|
117
|
-
label = label.padEnd(this.longestLabel.length + 1);
|
118
|
-
}
|
119
|
-
|
120
|
-
label = logType.color ? chalk[logType.color](label) : label;
|
121
|
-
}
|
122
|
-
|
123
|
-
if (message instanceof Error) {
|
124
|
-
if (message.stack) {
|
125
|
-
const [name, ...rest] = message.stack.split('\n');
|
126
|
-
text = `${name}\n${grey(rest.join('\n'))}`;
|
127
|
-
} else {
|
128
|
-
text = message.message;
|
129
|
-
}
|
130
|
-
} else {
|
131
|
-
text = `${message}`;
|
132
|
-
}
|
133
|
-
|
134
|
-
// only retain logs of warn/error level
|
135
|
-
if (logType.level === 'warn' || logType.level === 'error') {
|
136
|
-
// retain log text without label
|
137
|
-
this.retainLog(type, text);
|
138
|
-
}
|
139
|
-
|
140
|
-
const log = label.length > 0 ? `${label} ${text}` : text;
|
141
|
-
// eslint-disable-next-line no-console
|
142
|
-
console.log(log);
|
143
|
-
}
|
144
|
-
|
145
|
-
private getLongestLabel() {
|
146
|
-
let longestLabel = '';
|
147
|
-
Object.keys(this.types).forEach(type => {
|
148
|
-
const { label = '' } = this.types[type];
|
149
|
-
if (label.length > longestLabel.length) {
|
150
|
-
longestLabel = label;
|
151
|
-
}
|
152
|
-
});
|
153
|
-
return longestLabel;
|
154
|
-
}
|
155
|
-
|
156
|
-
private get longestUnderlinedLabel() {
|
157
|
-
return underline(this.longestLabel);
|
158
|
-
}
|
159
|
-
|
160
|
-
getRetainedLogs(type: string) {
|
161
|
-
return this.history[type] || [];
|
162
|
-
}
|
163
|
-
|
164
|
-
clearRetainedLogs(type: string) {
|
165
|
-
if (type) {
|
166
|
-
if (this.history[type]) {
|
167
|
-
this.history[type] = [];
|
168
|
-
}
|
169
|
-
} else {
|
170
|
-
this.history = {};
|
171
|
-
}
|
172
|
-
}
|
173
|
-
}
|
174
|
-
|
175
|
-
type LoggerInterface = {
|
176
|
-
[key in keyof typeof LOG_TYPES]: LoggerFunction;
|
177
|
-
};
|
178
|
-
|
179
|
-
const logger = new Logger() as Logger & LoggerInterface;
|
180
|
-
|
181
|
-
logger.Logger = Logger;
|
182
|
-
|
183
|
-
export { logger };
|
184
|
-
export type { LoggerInterface };
|
package/src/monorepo.ts
DELETED
@@ -1,106 +0,0 @@
|
|
1
|
-
import fs from 'fs';
|
2
|
-
import path from 'path';
|
3
|
-
import glob from 'glob';
|
4
|
-
import yaml from 'yaml';
|
5
|
-
|
6
|
-
const PACKAGE_MAX_DEPTH = 5;
|
7
|
-
|
8
|
-
const WOKRSPACES_FILES = {
|
9
|
-
YARN: 'package.json',
|
10
|
-
PNPM: 'pnpm-workspaces.yaml',
|
11
|
-
LERNA: 'lerna.json',
|
12
|
-
};
|
13
|
-
|
14
|
-
export const isLerna = (root: string) =>
|
15
|
-
fs.existsSync(path.join(root, WOKRSPACES_FILES.LERNA));
|
16
|
-
|
17
|
-
export const isYarnWorkspaces = (root: string) => {
|
18
|
-
const pkg = path.join(root, WOKRSPACES_FILES.YARN);
|
19
|
-
|
20
|
-
if (!fs.existsSync(pkg)) {
|
21
|
-
return false;
|
22
|
-
}
|
23
|
-
|
24
|
-
const json = JSON.parse(fs.readFileSync(pkg, 'utf8'));
|
25
|
-
|
26
|
-
return Boolean(json.workspaces?.packages);
|
27
|
-
};
|
28
|
-
|
29
|
-
export const isPnpmWorkspaces = (root: string) =>
|
30
|
-
fs.existsSync(path.join(root, WOKRSPACES_FILES.PNPM));
|
31
|
-
|
32
|
-
export const isMonorepo = (root: string) =>
|
33
|
-
isLerna(root) || isYarnWorkspaces(root) || isPnpmWorkspaces(root);
|
34
|
-
|
35
|
-
export const isModernjsMonorepo = (root: string) => {
|
36
|
-
const json = JSON.parse(
|
37
|
-
fs.readFileSync(path.join(root, 'package.json'), 'utf8'),
|
38
|
-
);
|
39
|
-
|
40
|
-
const deps = {
|
41
|
-
...(json.dependencies || {}),
|
42
|
-
...(json.devDependencies || {}),
|
43
|
-
};
|
44
|
-
|
45
|
-
return Boolean(deps['@modern-js/monorepo-tools']);
|
46
|
-
};
|
47
|
-
|
48
|
-
export const findMonorepoRoot = (
|
49
|
-
appDirectory: string,
|
50
|
-
maxDepth: number = PACKAGE_MAX_DEPTH,
|
51
|
-
) => {
|
52
|
-
let inMonorepo = false;
|
53
|
-
|
54
|
-
for (let depth = 0; depth < maxDepth; depth++) {
|
55
|
-
if (isMonorepo(appDirectory)) {
|
56
|
-
inMonorepo = true;
|
57
|
-
break;
|
58
|
-
}
|
59
|
-
// eslint-disable-next-line no-param-reassign
|
60
|
-
appDirectory = path.dirname(appDirectory);
|
61
|
-
}
|
62
|
-
|
63
|
-
return inMonorepo ? appDirectory : undefined;
|
64
|
-
};
|
65
|
-
|
66
|
-
export const getMonorepoPackages = (
|
67
|
-
root: string,
|
68
|
-
): { name: string; path: string }[] => {
|
69
|
-
let packages: string[] = [];
|
70
|
-
|
71
|
-
if (isYarnWorkspaces(root)) {
|
72
|
-
const json = JSON.parse(
|
73
|
-
fs.readFileSync(path.join(root, 'package.json'), 'utf8'),
|
74
|
-
);
|
75
|
-
({ packages } = json.workspaces);
|
76
|
-
} else if (isLerna(root)) {
|
77
|
-
const json = JSON.parse(
|
78
|
-
fs.readFileSync(path.resolve(root, 'lerna.json'), 'utf8'),
|
79
|
-
);
|
80
|
-
({ packages } = json);
|
81
|
-
} else {
|
82
|
-
({ packages } = yaml.parse(
|
83
|
-
fs.readFileSync(path.join(root, WOKRSPACES_FILES.PNPM), 'utf8'),
|
84
|
-
));
|
85
|
-
}
|
86
|
-
|
87
|
-
if (packages) {
|
88
|
-
return packages
|
89
|
-
.map(name =>
|
90
|
-
// The trailing / ensures only dirs are picked up
|
91
|
-
glob.sync(path.join(root, `${name}/`), {
|
92
|
-
ignore: ['**/node_modules/**'],
|
93
|
-
}),
|
94
|
-
)
|
95
|
-
.flat()
|
96
|
-
.filter(filepath => fs.existsSync(path.resolve(filepath, 'package.json')))
|
97
|
-
.map(filepath => ({
|
98
|
-
path: filepath,
|
99
|
-
name: JSON.parse(
|
100
|
-
fs.readFileSync(path.resolve(filepath, 'package.json'), 'utf8'),
|
101
|
-
).name,
|
102
|
-
}));
|
103
|
-
}
|
104
|
-
|
105
|
-
return [];
|
106
|
-
};
|
package/src/nodeEnv.ts
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
import execa from 'execa';
|
2
|
-
|
3
|
-
export async function canUseNpm() {
|
4
|
-
try {
|
5
|
-
await execa('npm', ['--version'], { env: process.env });
|
6
|
-
return true;
|
7
|
-
} catch (e) {
|
8
|
-
return false;
|
9
|
-
}
|
10
|
-
}
|
11
|
-
|
12
|
-
export async function canUseYarn() {
|
13
|
-
try {
|
14
|
-
await execa('yarn', ['--version'], { env: process.env });
|
15
|
-
return true;
|
16
|
-
} catch (e) {
|
17
|
-
return false;
|
18
|
-
}
|
19
|
-
}
|
20
|
-
|
21
|
-
export async function canUsePnpm() {
|
22
|
-
try {
|
23
|
-
await execa('pnpm', ['--version'], { env: process.env });
|
24
|
-
return true;
|
25
|
-
} catch (e) {
|
26
|
-
return false;
|
27
|
-
}
|
28
|
-
}
|
package/src/path.ts
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
import path from 'path';
|
2
|
-
import upath from 'upath';
|
3
|
-
|
4
|
-
export const isRelativePath = (test: string): boolean =>
|
5
|
-
/^\.\.?($|[\\/])/.test(test);
|
6
|
-
|
7
|
-
export const normalizeOutputPath = (s: string) => s.replace(/\\/g, '\\\\');
|
8
|
-
export const normalizeToPosixPath = (p: string) =>
|
9
|
-
upath.normalizeSafe(path.normalize(p));
|
package/src/pkgUp.ts
DELETED
@@ -1,88 +0,0 @@
|
|
1
|
-
import os from 'os';
|
2
|
-
import chalk from 'chalk';
|
3
|
-
import { isDev } from './is';
|
4
|
-
|
5
|
-
// TODO: type
|
6
|
-
interface EntryPoint {
|
7
|
-
entryName: string;
|
8
|
-
}
|
9
|
-
|
10
|
-
interface ServerRoute {
|
11
|
-
entryName: string;
|
12
|
-
isSSR: boolean;
|
13
|
-
urlPath: string;
|
14
|
-
}
|
15
|
-
|
16
|
-
// TODO: remove hard code 'main'
|
17
|
-
export const isSingleEntry = (entrypoints: EntryPoint[]) =>
|
18
|
-
entrypoints.length === 1 && entrypoints[0].entryName === 'main';
|
19
|
-
|
20
|
-
const normalizeUrl = (url: string) => url.replace(/([^:]\/)\/+/g, '$1');
|
21
|
-
|
22
|
-
const getAddressUrls = (protocol = 'http', port: number) => {
|
23
|
-
const interfaces = os.networkInterfaces();
|
24
|
-
const ipv4Interfaces: os.NetworkInterfaceInfo[] = [];
|
25
|
-
Object.keys(interfaces).forEach(key => {
|
26
|
-
interfaces[key]!.forEach(detail => {
|
27
|
-
if (detail.family === 'IPv4') {
|
28
|
-
ipv4Interfaces.push(detail);
|
29
|
-
}
|
30
|
-
});
|
31
|
-
});
|
32
|
-
|
33
|
-
return ipv4Interfaces.reduce(
|
34
|
-
(memo: { type: string; url: string }[], detail) => {
|
35
|
-
let type = 'Network: ';
|
36
|
-
let url = `${protocol}://${detail.address}:${port}`;
|
37
|
-
if (detail.address.includes(`127.0.0.1`)) {
|
38
|
-
type = 'Local: ';
|
39
|
-
url = `${protocol}://localhost:${port}`;
|
40
|
-
}
|
41
|
-
|
42
|
-
memo.push({ type, url });
|
43
|
-
return memo;
|
44
|
-
},
|
45
|
-
[],
|
46
|
-
);
|
47
|
-
};
|
48
|
-
|
49
|
-
export const prettyInstructions = (appContext: any, config: any) => {
|
50
|
-
const { entrypoints, serverRoutes, port } = appContext as {
|
51
|
-
entrypoints: EntryPoint[];
|
52
|
-
serverRoutes: ServerRoute[];
|
53
|
-
port: number;
|
54
|
-
};
|
55
|
-
|
56
|
-
const urls = getAddressUrls(
|
57
|
-
config.dev.https && isDev() ? 'https' : 'http',
|
58
|
-
port,
|
59
|
-
);
|
60
|
-
|
61
|
-
const routes = serverRoutes.filter(route => route.entryName);
|
62
|
-
|
63
|
-
let message = 'App running at:\n\n';
|
64
|
-
|
65
|
-
if (isSingleEntry(entrypoints)) {
|
66
|
-
message += urls
|
67
|
-
.map(
|
68
|
-
({ type, url }) =>
|
69
|
-
` ${chalk.bold(`> ${type.padEnd(10)}`)}${chalk.cyanBright(
|
70
|
-
normalizeUrl(`${url}/${routes[0].urlPath}`),
|
71
|
-
)}\n`,
|
72
|
-
)
|
73
|
-
.join('');
|
74
|
-
} else {
|
75
|
-
const maxNameLength = Math.max(...routes.map(r => r.entryName.length));
|
76
|
-
|
77
|
-
urls.forEach(({ type, url }) => {
|
78
|
-
message += ` ${chalk.bold(`> ${type}`)}\n`;
|
79
|
-
routes.forEach(({ entryName, urlPath }) => {
|
80
|
-
message += ` ${chalk.yellowBright(
|
81
|
-
entryName.padEnd(maxNameLength + 8),
|
82
|
-
)}${chalk.cyanBright(normalizeUrl(`${url}/${urlPath}`))}\n`;
|
83
|
-
});
|
84
|
-
});
|
85
|
-
}
|
86
|
-
|
87
|
-
return message;
|
88
|
-
};
|