@mui/internal-code-infra 0.0.3-canary.2 → 0.0.3-canary.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +27 -22
- package/src/babel-config.mjs +27 -8
- package/src/cli/babel.mjs +1 -12
- package/src/cli/cmdBuild.mjs +203 -28
- package/src/cli/cmdCopyFiles.mjs +8 -14
- package/src/cli/cmdExtractErrorCodes.mjs +41 -0
- package/src/cli/cmdJsonLint.mjs +16 -23
- package/src/cli/cmdPublish.mjs +26 -10
- package/src/cli/cmdPublishCanary.mjs +1 -1
- package/src/cli/index.mjs +8 -5
- package/src/cli/packageJson.d.ts +723 -0
- package/src/cli/pnpm.mjs +3 -2
- package/src/cli/typescript.mjs +13 -7
- package/src/eslint/baseConfig.mjs +57 -58
- package/src/eslint/docsConfig.mjs +11 -13
- package/src/eslint/material-ui/config.mjs +8 -4
- package/src/eslint/testConfig.mjs +63 -64
- package/src/stylelint/index.mjs +46 -0
- package/src/untyped-plugins.d.ts +20 -0
- package/src/utils/build.mjs +79 -0
- package/src/utils/extractErrorCodes.mjs +168 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mui/internal-code-infra",
|
|
3
|
-
"version": "0.0.3-canary.
|
|
3
|
+
"version": "0.0.3-canary.20",
|
|
4
4
|
"description": "Infra scripts and configs to be used across MUI repos.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
},
|
|
12
12
|
"sideEffects": false,
|
|
13
13
|
"exports": {
|
|
14
|
+
"./stylelint": "./src/stylelint/index.mjs",
|
|
14
15
|
"./package.json": "./package.json",
|
|
15
16
|
"./prettier": "./src/prettier.mjs",
|
|
16
17
|
"./eslint": "./src/eslint/index.mjs",
|
|
@@ -21,25 +22,26 @@
|
|
|
21
22
|
"code-infra": "./bin/code-infra.mjs"
|
|
22
23
|
},
|
|
23
24
|
"dependencies": {
|
|
24
|
-
"@argos-ci/core": "^4.1.
|
|
25
|
+
"@argos-ci/core": "^4.1.6",
|
|
25
26
|
"@babel/cli": "^7.28.3",
|
|
26
|
-
"@babel/core": "^7.28.
|
|
27
|
+
"@babel/core": "^7.28.4",
|
|
28
|
+
"@babel/plugin-syntax-jsx": "^7.27.1",
|
|
27
29
|
"@babel/plugin-syntax-typescript": "^7.27.1",
|
|
28
30
|
"@babel/plugin-transform-runtime": "^7.28.3",
|
|
29
31
|
"@babel/preset-env": "^7.28.3",
|
|
30
32
|
"@babel/preset-react": "^7.27.1",
|
|
31
33
|
"@babel/preset-typescript": "^7.27.1",
|
|
32
34
|
"@eslint/compat": "^1.3.2",
|
|
33
|
-
"@eslint/js": "^9.
|
|
34
|
-
"@next/eslint-plugin-next": "^15.5.
|
|
35
|
+
"@eslint/js": "^9.36.0",
|
|
36
|
+
"@next/eslint-plugin-next": "^15.5.3",
|
|
35
37
|
"@octokit/auth-action": "^6.0.1",
|
|
36
38
|
"@octokit/rest": "^22.0.0",
|
|
37
|
-
"@pnpm/find-workspace-dir": "^1000.1.
|
|
39
|
+
"@pnpm/find-workspace-dir": "^1000.1.3",
|
|
38
40
|
"babel-plugin-optimize-clsx": "^2.6.2",
|
|
39
41
|
"babel-plugin-transform-inline-environment-variables": "^0.4.4",
|
|
40
42
|
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
|
|
41
|
-
"babel-plugin-transform-remove-imports": "^1.8.
|
|
42
|
-
"chalk": "^5.6.
|
|
43
|
+
"babel-plugin-transform-remove-imports": "^1.8.1",
|
|
44
|
+
"chalk": "^5.6.2",
|
|
43
45
|
"eslint-config-prettier": "^10.1.8",
|
|
44
46
|
"eslint-import-resolver-typescript": "^4.4.4",
|
|
45
47
|
"eslint-module-utils": "^2.12.1",
|
|
@@ -49,19 +51,22 @@
|
|
|
49
51
|
"eslint-plugin-react": "^7.37.5",
|
|
50
52
|
"eslint-plugin-react-compiler": "^19.1.0-rc.2",
|
|
51
53
|
"eslint-plugin-react-hooks": "^6.0.0-rc1",
|
|
52
|
-
"eslint-plugin-testing-library": "^7.
|
|
54
|
+
"eslint-plugin-testing-library": "^7.10.0",
|
|
53
55
|
"execa": "^9.6.0",
|
|
54
56
|
"git-url-parse": "^16.1.0",
|
|
55
|
-
"globals": "^16.
|
|
56
|
-
"globby": "^
|
|
57
|
-
"lodash-es": "^4.17.21",
|
|
57
|
+
"globals": "^16.4.0",
|
|
58
|
+
"globby": "^15.0.0",
|
|
58
59
|
"minimatch": "^10.0.3",
|
|
60
|
+
"postcss-styled-syntax": "^0.7.1",
|
|
61
|
+
"regexp.escape": "^2.0.1",
|
|
62
|
+
"resolve-pkg-maps": "^1.0.0",
|
|
59
63
|
"semver": "^7.7.2",
|
|
60
|
-
"
|
|
64
|
+
"stylelint-config-standard": "^39.0.0",
|
|
65
|
+
"typescript-eslint": "^8.44.1",
|
|
61
66
|
"yargs": "^18.0.0",
|
|
62
|
-
"@mui/internal-babel-plugin-
|
|
63
|
-
"@mui/internal-babel-plugin-
|
|
64
|
-
"@mui/internal-babel-plugin-
|
|
67
|
+
"@mui/internal-babel-plugin-resolve-imports": "2.0.7-canary.23",
|
|
68
|
+
"@mui/internal-babel-plugin-display-name": "1.0.4-canary.7",
|
|
69
|
+
"@mui/internal-babel-plugin-minify-errors": "2.0.8-canary.10"
|
|
65
70
|
},
|
|
66
71
|
"peerDependencies": {
|
|
67
72
|
"eslint": "^9.0.0",
|
|
@@ -74,13 +79,13 @@
|
|
|
74
79
|
"@types/eslint-plugin-jsx-a11y": "^6.10.0",
|
|
75
80
|
"@types/estree": "^1.0.8",
|
|
76
81
|
"@types/estree-jsx": "^1.0.5",
|
|
77
|
-
"@types/
|
|
82
|
+
"@types/regexp.escape": "^2.0.0",
|
|
78
83
|
"@types/yargs": "^17.0.33",
|
|
79
|
-
"@typescript-eslint/parser": "^8.
|
|
80
|
-
"@typescript-eslint/rule-tester": "^8.
|
|
81
|
-
"eslint": "^9.
|
|
84
|
+
"@typescript-eslint/parser": "^8.44.1",
|
|
85
|
+
"@typescript-eslint/rule-tester": "^8.44.1",
|
|
86
|
+
"eslint": "^9.36.0",
|
|
82
87
|
"prettier": "^3.6.2",
|
|
83
|
-
"typescript-eslint": "^8.
|
|
88
|
+
"typescript-eslint": "^8.44.1"
|
|
84
89
|
},
|
|
85
90
|
"files": [
|
|
86
91
|
"bin",
|
|
@@ -92,7 +97,7 @@
|
|
|
92
97
|
"publishConfig": {
|
|
93
98
|
"access": "public"
|
|
94
99
|
},
|
|
95
|
-
"gitSha": "
|
|
100
|
+
"gitSha": "8ad4cd1aec96d0977bb91fd233e4fd7cd3ebd298",
|
|
96
101
|
"scripts": {
|
|
97
102
|
"typescript": "tsc -p tsconfig.json",
|
|
98
103
|
"test": "pnpm -w test --project @mui/internal-code-infra",
|
package/src/babel-config.mjs
CHANGED
|
@@ -13,7 +13,7 @@ import pluginRemovePropTypes from 'babel-plugin-transform-react-remove-prop-type
|
|
|
13
13
|
* @param {boolean} [param0.debug]
|
|
14
14
|
* @param {boolean} [param0.optimizeClsx]
|
|
15
15
|
* @param {boolean} [param0.removePropTypes]
|
|
16
|
-
* @param {boolean} [param0.
|
|
16
|
+
* @param {boolean} [param0.noResolveImports]
|
|
17
17
|
* @param {'cjs' | 'esm'} param0.bundle
|
|
18
18
|
* @param {string | null} param0.outExtension - Specify the output file extension.
|
|
19
19
|
* @param {string} param0.runtimeVersion
|
|
@@ -23,7 +23,7 @@ export function getBaseConfig({
|
|
|
23
23
|
debug = false,
|
|
24
24
|
optimizeClsx = false,
|
|
25
25
|
removePropTypes = false,
|
|
26
|
-
|
|
26
|
+
noResolveImports = false,
|
|
27
27
|
bundle,
|
|
28
28
|
runtimeVersion,
|
|
29
29
|
outExtension,
|
|
@@ -81,7 +81,7 @@ export function getBaseConfig({
|
|
|
81
81
|
plugins.push([pluginOptimizeClsx, {}, 'babel-plugin-optimize-clsx']);
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
if (bundle === 'esm' && !
|
|
84
|
+
if (bundle === 'esm' && !noResolveImports) {
|
|
85
85
|
plugins.push([
|
|
86
86
|
pluginResolveImports,
|
|
87
87
|
{ outExtension },
|
|
@@ -119,20 +119,39 @@ export function getBaseConfig({
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
/**
|
|
122
|
-
* @
|
|
122
|
+
* @typedef {Object} Options
|
|
123
|
+
* @prop {'esm' | 'cjs'} [Options.bundle]
|
|
124
|
+
* @prop {boolean} [Options.noResolveImports]
|
|
125
|
+
* @prop {undefined} [options.env]
|
|
126
|
+
*/
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* @param {import('@babel/core').ConfigAPI | Options} api
|
|
130
|
+
* @returns {import('@babel/core').TransformOptions}
|
|
123
131
|
*/
|
|
124
132
|
export default function getBabelConfig(api) {
|
|
125
|
-
|
|
126
|
-
|
|
133
|
+
/** @type {'esm' | 'cjs'} */
|
|
134
|
+
let bundle;
|
|
135
|
+
/** @type {boolean} */
|
|
136
|
+
let noResolveImports;
|
|
137
|
+
|
|
138
|
+
if (api.env) {
|
|
139
|
+
// legacy
|
|
140
|
+
bundle = api.env(['regressions', 'stable']) ? 'esm' : 'cjs';
|
|
141
|
+
noResolveImports = api.env('test') || process.env.NODE_ENV === 'test';
|
|
142
|
+
} else {
|
|
143
|
+
bundle = api.bundle || 'esm';
|
|
144
|
+
noResolveImports = api.noResolveImports || false;
|
|
145
|
+
}
|
|
127
146
|
|
|
128
147
|
return getBaseConfig({
|
|
129
148
|
debug: process.env.MUI_BUILD_VERBOSE === 'true',
|
|
130
|
-
bundle
|
|
149
|
+
bundle,
|
|
131
150
|
outExtension: process.env.MUI_OUT_FILE_EXTENSION || null,
|
|
132
151
|
// any package needs to declare 7.25.0 as a runtime dependency. default is ^7.0.0
|
|
133
152
|
runtimeVersion: process.env.MUI_BABEL_RUNTIME_VERSION || '^7.25.0',
|
|
134
153
|
optimizeClsx: process.env.MUI_OPTIMIZE_CLSX === 'true',
|
|
135
154
|
removePropTypes: process.env.MUI_REMOVE_PROP_TYPES === 'true',
|
|
136
|
-
|
|
155
|
+
noResolveImports,
|
|
137
156
|
});
|
|
138
157
|
}
|
package/src/cli/babel.mjs
CHANGED
|
@@ -6,6 +6,7 @@ import { globby } from 'globby';
|
|
|
6
6
|
import * as fs from 'node:fs/promises';
|
|
7
7
|
import * as path from 'node:path';
|
|
8
8
|
import { $ } from 'execa';
|
|
9
|
+
import { BASE_IGNORES } from '../utils/build.mjs';
|
|
9
10
|
|
|
10
11
|
const TO_TRANSFORM_EXTENSIONS = ['.js', '.ts', '.tsx'];
|
|
11
12
|
|
|
@@ -64,18 +65,6 @@ export async function cjsCopy({ from, to }) {
|
|
|
64
65
|
* @property {string} [runtimeModule] - The runtime module to replace the errors with.
|
|
65
66
|
*/
|
|
66
67
|
|
|
67
|
-
const BASE_IGNORES = [
|
|
68
|
-
'**/*.test.js',
|
|
69
|
-
'**/*.test.ts',
|
|
70
|
-
'**/*.test.tsx',
|
|
71
|
-
'**/*.spec.js',
|
|
72
|
-
'**/*.spec.ts',
|
|
73
|
-
'**/*.spec.tsx',
|
|
74
|
-
'**/*.d.ts',
|
|
75
|
-
'**/*.test/*.*',
|
|
76
|
-
'**/test-cases/*.*',
|
|
77
|
-
];
|
|
78
|
-
|
|
79
68
|
/**
|
|
80
69
|
* @param {Object} options
|
|
81
70
|
* @param {boolean} [options.verbose=false] - Whether to enable verbose logging.
|
package/src/cli/cmdBuild.mjs
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
|
+
import { findWorkspaceDir } from '@pnpm/find-workspace-dir';
|
|
2
3
|
import { $ } from 'execa';
|
|
3
|
-
import
|
|
4
|
+
import { globby } from 'globby';
|
|
4
5
|
import * as fs from 'node:fs/promises';
|
|
5
6
|
import * as path from 'node:path';
|
|
6
|
-
import {
|
|
7
|
+
import { sep as posixSep } from 'node:path/posix';
|
|
8
|
+
|
|
9
|
+
import { getOutExtension, isMjsBuild, mapConcurrently, validatePkgJson } from '../utils/build.mjs';
|
|
7
10
|
|
|
8
11
|
/**
|
|
9
12
|
* @typedef {Object} Args
|
|
@@ -18,6 +21,7 @@ import { getOutExtension, isMjsBuild, validatePkgJson } from '../utils/build.mjs
|
|
|
18
21
|
* @property {boolean} skipPackageJson - Whether to skip generating the package.json file in the bundle output.
|
|
19
22
|
* @property {boolean} skipMainCheck - Whether to skip checking for main field in package.json.
|
|
20
23
|
* @property {string[]} ignore - Globs to be ignored by Babel.
|
|
24
|
+
* @property {string[]} [copy] - Files/Directories to be copied. Can be a glob pattern.
|
|
21
25
|
*/
|
|
22
26
|
|
|
23
27
|
const validBundles = [
|
|
@@ -64,16 +68,16 @@ ${content}`,
|
|
|
64
68
|
|
|
65
69
|
/**
|
|
66
70
|
* @param {Object} param0
|
|
67
|
-
* @param {
|
|
71
|
+
* @param {NonNullable<import('./packageJson').PackageJson.Exports>} param0.importPath
|
|
68
72
|
* @param {string} param0.key
|
|
69
73
|
* @param {string} param0.cwd
|
|
70
74
|
* @param {string} param0.dir
|
|
71
75
|
* @param {string} param0.type
|
|
72
|
-
* @param {
|
|
76
|
+
* @param {import('./packageJson').PackageJson.ExportConditions} param0.newExports
|
|
73
77
|
* @param {string} param0.typeOutExtension
|
|
74
78
|
* @param {string} param0.outExtension
|
|
75
79
|
* @param {boolean} param0.addTypes
|
|
76
|
-
* @returns {Promise<
|
|
80
|
+
* @returns {Promise<void>}
|
|
77
81
|
*/
|
|
78
82
|
async function createExportsFor({
|
|
79
83
|
importPath,
|
|
@@ -86,10 +90,22 @@ async function createExportsFor({
|
|
|
86
90
|
outExtension,
|
|
87
91
|
addTypes,
|
|
88
92
|
}) {
|
|
93
|
+
if (Array.isArray(importPath)) {
|
|
94
|
+
throw new Error(
|
|
95
|
+
`Array form of package.json exports is not supported yet. Found in export "${key}".`,
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
89
99
|
let srcPath = typeof importPath === 'string' ? importPath : importPath['mui-src'];
|
|
90
100
|
const rest = typeof importPath === 'string' ? {} : { ...importPath };
|
|
91
101
|
delete rest['mui-src'];
|
|
92
102
|
|
|
103
|
+
if (typeof srcPath !== 'string') {
|
|
104
|
+
throw new Error(
|
|
105
|
+
`Unsupported export for "${key}". Only a string or an object with "mui-src" field is supported for now.`,
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
93
109
|
const exportFileExists = srcPath.includes('*')
|
|
94
110
|
? true
|
|
95
111
|
: await fs.stat(path.join(cwd, srcPath)).then(
|
|
@@ -105,25 +121,25 @@ async function createExportsFor({
|
|
|
105
121
|
const ext = path.extname(srcPath);
|
|
106
122
|
|
|
107
123
|
if (ext === '.css') {
|
|
108
|
-
|
|
109
|
-
return
|
|
110
|
-
path: [key],
|
|
111
|
-
importPath: srcPath,
|
|
112
|
-
};
|
|
124
|
+
newExports[key] = srcPath;
|
|
125
|
+
return;
|
|
113
126
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
127
|
+
|
|
128
|
+
if (typeof newExports[key] === 'string' || Array.isArray(newExports[key])) {
|
|
129
|
+
throw new Error(`The export "${key}" is already defined as a string or Array.`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
newExports[key] ??= {};
|
|
133
|
+
newExports[key][type === 'cjs' ? 'require' : 'import'] = {
|
|
134
|
+
...rest,
|
|
135
|
+
...(addTypes ? { types: srcPath.replace(ext, typeOutExtension) } : {}),
|
|
136
|
+
default: srcPath.replace(ext, outExtension),
|
|
121
137
|
};
|
|
122
138
|
}
|
|
123
139
|
|
|
124
140
|
/**
|
|
125
141
|
* @param {Object} param0
|
|
126
|
-
* @param {
|
|
142
|
+
* @param {import('./packageJson').PackageJson} param0.packageJson - The package.json content.
|
|
127
143
|
* @param {{type: import('../utils/build.mjs').BundleType; dir: string}[]} param0.bundles
|
|
128
144
|
* @param {string} param0.outputDir
|
|
129
145
|
* @param {string} param0.cwd
|
|
@@ -138,12 +154,15 @@ async function writePackageJson({ packageJson, bundles, outputDir, cwd, addTypes
|
|
|
138
154
|
packageJson.type = packageJson.type || 'commonjs';
|
|
139
155
|
|
|
140
156
|
/**
|
|
141
|
-
* @type {
|
|
157
|
+
* @type {import('./packageJson').PackageJson.ExportConditions}
|
|
142
158
|
*/
|
|
143
|
-
const originalExports =
|
|
159
|
+
const originalExports =
|
|
160
|
+
typeof packageJson.exports === 'string' || Array.isArray(packageJson.exports)
|
|
161
|
+
? { '.': packageJson.exports }
|
|
162
|
+
: packageJson.exports || {};
|
|
144
163
|
delete packageJson.exports;
|
|
145
164
|
/**
|
|
146
|
-
* @type {
|
|
165
|
+
* @type {import('./packageJson').PackageJson.ExportConditions}
|
|
147
166
|
*/
|
|
148
167
|
const newExports = {
|
|
149
168
|
'./package.json': './package.json',
|
|
@@ -172,10 +191,16 @@ async function writePackageJson({ packageJson, bundles, outputDir, cwd, addTypes
|
|
|
172
191
|
if (type === 'cjs') {
|
|
173
192
|
packageJson.main = exportDir;
|
|
174
193
|
}
|
|
175
|
-
|
|
176
|
-
|
|
194
|
+
|
|
195
|
+
if (typeof newExports['.'] === 'string' || Array.isArray(newExports['.'])) {
|
|
196
|
+
throw new Error(`The export "." is already defined as a string or Array.`);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
newExports['.'] ??= {};
|
|
200
|
+
newExports['.'][type === 'cjs' ? 'require' : 'import'] = {
|
|
201
|
+
...(typeFileExists ? { types: typeExportDir } : {}),
|
|
177
202
|
default: exportDir,
|
|
178
|
-
}
|
|
203
|
+
};
|
|
179
204
|
}
|
|
180
205
|
if (typeFileExists && type === 'cjs') {
|
|
181
206
|
packageJson.types = typeExportDir;
|
|
@@ -185,11 +210,11 @@ async function writePackageJson({ packageJson, bundles, outputDir, cwd, addTypes
|
|
|
185
210
|
for (const key of exportKeys) {
|
|
186
211
|
const importPath = originalExports[key];
|
|
187
212
|
if (!importPath) {
|
|
188
|
-
|
|
189
|
-
|
|
213
|
+
newExports[key] = null;
|
|
214
|
+
continue;
|
|
190
215
|
}
|
|
191
216
|
// eslint-disable-next-line no-await-in-loop
|
|
192
|
-
|
|
217
|
+
await createExportsFor({
|
|
193
218
|
importPath,
|
|
194
219
|
key,
|
|
195
220
|
cwd,
|
|
@@ -200,7 +225,6 @@ async function writePackageJson({ packageJson, bundles, outputDir, cwd, addTypes
|
|
|
200
225
|
outExtension,
|
|
201
226
|
addTypes,
|
|
202
227
|
});
|
|
203
|
-
set(newExports, res.path, res.importPath);
|
|
204
228
|
}
|
|
205
229
|
}),
|
|
206
230
|
);
|
|
@@ -213,6 +237,11 @@ async function writePackageJson({ packageJson, bundles, outputDir, cwd, addTypes
|
|
|
213
237
|
// default condition should come last
|
|
214
238
|
Object.keys(newExports).forEach((key) => {
|
|
215
239
|
const exportVal = newExports[key];
|
|
240
|
+
if (Array.isArray(exportVal)) {
|
|
241
|
+
throw new Error(
|
|
242
|
+
`Array form of package.json exports is not supported yet. Found in export "${key}".`,
|
|
243
|
+
);
|
|
244
|
+
}
|
|
216
245
|
if (exportVal && typeof exportVal === 'object' && (exportVal.import || exportVal.require)) {
|
|
217
246
|
const defaultExport = exportVal.import || exportVal.require;
|
|
218
247
|
if (exportVal.import) {
|
|
@@ -298,6 +327,13 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
|
298
327
|
type: 'boolean',
|
|
299
328
|
default: false,
|
|
300
329
|
description: 'Skip checking for main field in package.json.',
|
|
330
|
+
})
|
|
331
|
+
.option('copy', {
|
|
332
|
+
type: 'string',
|
|
333
|
+
array: true,
|
|
334
|
+
description:
|
|
335
|
+
'Files/Directories to be copied to the output directory. Can be a glob pattern.',
|
|
336
|
+
default: [],
|
|
301
337
|
});
|
|
302
338
|
},
|
|
303
339
|
async handler(args) {
|
|
@@ -442,5 +478,144 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
|
442
478
|
outputDir: buildDir,
|
|
443
479
|
addTypes: buildTypes,
|
|
444
480
|
});
|
|
481
|
+
|
|
482
|
+
await copyHandler({
|
|
483
|
+
cwd,
|
|
484
|
+
globs: args.copy ?? [],
|
|
485
|
+
buildDir,
|
|
486
|
+
verbose: args.verbose,
|
|
487
|
+
});
|
|
445
488
|
},
|
|
446
489
|
});
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* @param {Object} param0
|
|
493
|
+
* @param {string} param0.cwd - The current working directory.
|
|
494
|
+
* @param {string[]} [param0.globs=[]] - Extra files to copy, can be specified as `source:target` pairs or just `source`.
|
|
495
|
+
* @param {string} param0.buildDir - The build directory to copy to.
|
|
496
|
+
* @param {boolean} [param0.verbose=false] - Whether to suppress output.
|
|
497
|
+
* @returns {Promise<void>}
|
|
498
|
+
*/
|
|
499
|
+
async function copyHandler({ cwd, globs = [], buildDir, verbose = false }) {
|
|
500
|
+
/**
|
|
501
|
+
* @type {(string|{targetPath: string; sourcePath: string})[]}
|
|
502
|
+
*/
|
|
503
|
+
const defaultFiles = [];
|
|
504
|
+
const workspaceDir = await findWorkspaceDir(cwd);
|
|
505
|
+
if (!workspaceDir) {
|
|
506
|
+
throw new Error('Workspace directory not found');
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
const localOrRootFiles = [
|
|
510
|
+
[path.join(cwd, 'README.md'), path.join(workspaceDir, 'README.md')],
|
|
511
|
+
[path.join(cwd, 'LICENSE'), path.join(workspaceDir, 'LICENSE')],
|
|
512
|
+
[path.join(cwd, 'CHANGELOG.md'), path.join(workspaceDir, 'CHANGELOG.md')],
|
|
513
|
+
];
|
|
514
|
+
await Promise.all(
|
|
515
|
+
localOrRootFiles.map(async (filesToCopy) => {
|
|
516
|
+
for (const file of filesToCopy) {
|
|
517
|
+
if (
|
|
518
|
+
// eslint-disable-next-line no-await-in-loop
|
|
519
|
+
await fs.stat(file).then(
|
|
520
|
+
() => true,
|
|
521
|
+
() => false,
|
|
522
|
+
)
|
|
523
|
+
) {
|
|
524
|
+
defaultFiles.push(file);
|
|
525
|
+
break;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
}),
|
|
529
|
+
);
|
|
530
|
+
|
|
531
|
+
if (globs.length) {
|
|
532
|
+
const res = globs.map((globPattern) => {
|
|
533
|
+
const [pattern, baseDir] = globPattern.split(':');
|
|
534
|
+
return { pattern, baseDir };
|
|
535
|
+
});
|
|
536
|
+
/**
|
|
537
|
+
* Avoids redundant globby calls for the same pattern.
|
|
538
|
+
*
|
|
539
|
+
* @type {Map<string, Promise<string[]>>}
|
|
540
|
+
*/
|
|
541
|
+
const globToResMap = new Map();
|
|
542
|
+
|
|
543
|
+
const result = await Promise.all(
|
|
544
|
+
res.map(async ({ pattern, baseDir }) => {
|
|
545
|
+
if (!globToResMap.has(pattern)) {
|
|
546
|
+
const promise = globby(pattern, { cwd });
|
|
547
|
+
globToResMap.set(pattern, promise);
|
|
548
|
+
}
|
|
549
|
+
const files = await globToResMap.get(pattern);
|
|
550
|
+
return { files: files ?? [], baseDir };
|
|
551
|
+
}),
|
|
552
|
+
);
|
|
553
|
+
globToResMap.clear();
|
|
554
|
+
|
|
555
|
+
result.forEach(({ files, baseDir }) => {
|
|
556
|
+
files.forEach((file) => {
|
|
557
|
+
const sourcePath = path.resolve(cwd, file);
|
|
558
|
+
// Use posix separator for the relative paths. So devs can only specify globs with `/` even on Windows.
|
|
559
|
+
const pathSegments = file.split(posixSep);
|
|
560
|
+
const relativePath =
|
|
561
|
+
// Use index 2 (when required) since users can also specify paths like `./src/index.js`
|
|
562
|
+
pathSegments.slice(pathSegments[0] === '.' ? 2 : 1).join(posixSep) || file;
|
|
563
|
+
const targetPath = baseDir
|
|
564
|
+
? path.resolve(buildDir, baseDir, relativePath)
|
|
565
|
+
: path.resolve(buildDir, relativePath);
|
|
566
|
+
defaultFiles.push({ sourcePath, targetPath });
|
|
567
|
+
});
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
if (!defaultFiles.length) {
|
|
572
|
+
if (verbose) {
|
|
573
|
+
console.log('⓿ No files to copy.');
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
await mapConcurrently(
|
|
577
|
+
defaultFiles,
|
|
578
|
+
async (file) => {
|
|
579
|
+
if (typeof file === 'string') {
|
|
580
|
+
const sourcePath = file;
|
|
581
|
+
const fileName = path.basename(file);
|
|
582
|
+
const targetPath = path.join(buildDir, fileName);
|
|
583
|
+
await recursiveCopy({ source: sourcePath, target: targetPath, verbose });
|
|
584
|
+
} else {
|
|
585
|
+
await fs.mkdir(path.dirname(file.targetPath), { recursive: true });
|
|
586
|
+
await recursiveCopy({ source: file.sourcePath, target: file.targetPath, verbose });
|
|
587
|
+
}
|
|
588
|
+
},
|
|
589
|
+
20,
|
|
590
|
+
);
|
|
591
|
+
console.log(`📋 Copied ${defaultFiles.length} files.`);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Recursively copies files and directories from a source path to a target path.
|
|
596
|
+
*
|
|
597
|
+
* @async
|
|
598
|
+
* @param {Object} options - The options for copying files.
|
|
599
|
+
* @param {string} options.source - The source path to copy from.
|
|
600
|
+
* @param {string} options.target - The target path to copy to.
|
|
601
|
+
* @param {boolean} [options.verbose=true] - If true, suppresses console output.
|
|
602
|
+
* @returns {Promise<boolean>} Resolves when the copy operation is complete.
|
|
603
|
+
* @throws {Error} Throws if an error occurs other than the source not existing.
|
|
604
|
+
*/
|
|
605
|
+
async function recursiveCopy({ source, target, verbose = true }) {
|
|
606
|
+
try {
|
|
607
|
+
await fs.cp(source, target, { recursive: true });
|
|
608
|
+
if (verbose) {
|
|
609
|
+
console.log(`Copied ${source} to ${target}`);
|
|
610
|
+
}
|
|
611
|
+
return true;
|
|
612
|
+
} catch (err) {
|
|
613
|
+
if (/** @type {{ code: string }} */ (err).code !== 'ENOENT') {
|
|
614
|
+
throw err;
|
|
615
|
+
}
|
|
616
|
+
if (verbose) {
|
|
617
|
+
console.warn(`Source does not exist: ${source}`);
|
|
618
|
+
}
|
|
619
|
+
throw err;
|
|
620
|
+
}
|
|
621
|
+
}
|
package/src/cli/cmdCopyFiles.mjs
CHANGED
|
@@ -2,6 +2,7 @@ import { findWorkspaceDir } from '@pnpm/find-workspace-dir';
|
|
|
2
2
|
import { globby } from 'globby';
|
|
3
3
|
import fs from 'node:fs/promises';
|
|
4
4
|
import path from 'node:path';
|
|
5
|
+
import { mapConcurrently } from '../utils/build.mjs';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* @typedef {Object} Args
|
|
@@ -105,20 +106,13 @@ async function processGlobs({ globs, cwd, silent = true, buildDir }) {
|
|
|
105
106
|
});
|
|
106
107
|
});
|
|
107
108
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
// eslint-disable-next-line no-await-in-loop
|
|
116
|
-
await recursiveCopy({ source: file.sourcePath, target: file.targetPath, silent });
|
|
117
|
-
}
|
|
118
|
-
}),
|
|
119
|
-
);
|
|
120
|
-
}
|
|
121
|
-
await Promise.all(workers);
|
|
109
|
+
await mapConcurrently(
|
|
110
|
+
filesToProcess,
|
|
111
|
+
async (file) => {
|
|
112
|
+
await recursiveCopy({ source: file.sourcePath, target: file.targetPath, silent });
|
|
113
|
+
},
|
|
114
|
+
50,
|
|
115
|
+
);
|
|
122
116
|
return filesToProcess.length;
|
|
123
117
|
}
|
|
124
118
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
|
|
3
|
+
import { markFn, measureFn } from '../utils/build.mjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {import('../utils/extractErrorCodes.mjs').Args} Args
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
10
|
+
command: 'extract-error-codes',
|
|
11
|
+
describe: 'Extracts error codes from package(s).',
|
|
12
|
+
builder(yargs) {
|
|
13
|
+
return yargs
|
|
14
|
+
.option('errorCodesPath', {
|
|
15
|
+
type: 'string',
|
|
16
|
+
describe: 'The output path to a json file to write the extracted error codes.',
|
|
17
|
+
demandOption: true,
|
|
18
|
+
})
|
|
19
|
+
.option('detection', {
|
|
20
|
+
type: 'string',
|
|
21
|
+
describe: 'The detection strategy to use when extracting error codes.',
|
|
22
|
+
choices: ['opt-in', 'opt-out'],
|
|
23
|
+
default: 'opt-in',
|
|
24
|
+
})
|
|
25
|
+
.option('skip', {
|
|
26
|
+
type: 'array',
|
|
27
|
+
describe: 'List of package names to skip.',
|
|
28
|
+
default: [],
|
|
29
|
+
});
|
|
30
|
+
},
|
|
31
|
+
async handler(args) {
|
|
32
|
+
const commandName = /** @type {string} */ (args._[0]);
|
|
33
|
+
await markFn(commandName, async () => {
|
|
34
|
+
const module = await import('../utils/extractErrorCodes.mjs');
|
|
35
|
+
await module.default(args);
|
|
36
|
+
});
|
|
37
|
+
console.log(
|
|
38
|
+
`✅ Extracted error codes in ${(measureFn(commandName).duration / 1000.0).toFixed(3)}s`,
|
|
39
|
+
);
|
|
40
|
+
},
|
|
41
|
+
});
|
package/src/cli/cmdJsonLint.mjs
CHANGED
|
@@ -4,6 +4,7 @@ import chalk from 'chalk';
|
|
|
4
4
|
import fs from 'node:fs/promises';
|
|
5
5
|
import { globby } from 'globby';
|
|
6
6
|
import path from 'node:path';
|
|
7
|
+
import { mapConcurrently } from '../utils/build.mjs';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* @typedef {Object} Args
|
|
@@ -42,33 +43,25 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
|
42
43
|
followSymbolicLinks: false,
|
|
43
44
|
});
|
|
44
45
|
|
|
45
|
-
const fileIterator = filenames[Symbol.iterator]();
|
|
46
|
-
const concurrency = Math.min(20, filenames.length);
|
|
47
46
|
let passed = true;
|
|
48
|
-
const workers = [];
|
|
49
47
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
// eslint-disable-next-line no-console
|
|
60
|
-
console.log(passMessage(filename));
|
|
61
|
-
}
|
|
62
|
-
} catch (error) {
|
|
63
|
-
passed = false;
|
|
64
|
-
console.error(failMessage(`Error parsing ${filename}:\n\n${String(error)}`));
|
|
48
|
+
await mapConcurrently(
|
|
49
|
+
filenames,
|
|
50
|
+
async (filename) => {
|
|
51
|
+
const content = await fs.readFile(path.join(cwd, filename), { encoding: 'utf8' });
|
|
52
|
+
try {
|
|
53
|
+
JSON.parse(content);
|
|
54
|
+
if (!args.silent) {
|
|
55
|
+
// eslint-disable-next-line no-console
|
|
56
|
+
console.log(passMessage(filename));
|
|
65
57
|
}
|
|
58
|
+
} catch (error) {
|
|
59
|
+
passed = false;
|
|
60
|
+
console.error(failMessage(`Error parsing ${filename}:\n\n${String(error)}`));
|
|
66
61
|
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
await Promise.allSettled(workers);
|
|
62
|
+
},
|
|
63
|
+
20,
|
|
64
|
+
);
|
|
72
65
|
if (!passed) {
|
|
73
66
|
throw new Error('❌ At least one file did not pass. Check the console output');
|
|
74
67
|
}
|