@mui/internal-code-infra 0.0.2-canary.5 → 0.0.2-canary.7
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 +4 -2
- package/src/cli/cmdJsonLint.mjs +80 -0
- package/src/cli/cmdListWorkspaces.mjs +66 -0
- package/src/cli/cmdPublish.mjs +1 -1
- package/src/cli/cmdPublishCanary.mjs +4 -2
- package/src/cli/index.mjs +10 -1
- package/src/cli/pnpm.mjs +16 -8
- package/src/eslint/baseConfig.mjs +2 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mui/internal-code-infra",
|
|
3
|
-
"version": "0.0.2-canary.
|
|
3
|
+
"version": "0.0.2-canary.7",
|
|
4
4
|
"description": "Infra scripts and configs to be used across MUI repos.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"@next/eslint-plugin-next": "^15.3.3",
|
|
26
26
|
"@octokit/rest": "^22.0.0",
|
|
27
27
|
"@eslint/compat": "^1.3.1",
|
|
28
|
+
"chalk": "^5.4.1",
|
|
28
29
|
"eslint-config-airbnb": "^19.0.4",
|
|
29
30
|
"eslint-config-airbnb-base": "^15.0.0",
|
|
30
31
|
"eslint-config-prettier": "^10.1.5",
|
|
@@ -40,6 +41,7 @@
|
|
|
40
41
|
"execa": "^7.2.0",
|
|
41
42
|
"git-url-parse": "^16.1.0",
|
|
42
43
|
"globals": "^16.2.0",
|
|
44
|
+
"globby": "^14.1.0",
|
|
43
45
|
"minimatch": "^10.0.3",
|
|
44
46
|
"semver": "^7.7.2",
|
|
45
47
|
"typescript-eslint": "^8.35.1",
|
|
@@ -69,7 +71,7 @@
|
|
|
69
71
|
"publishConfig": {
|
|
70
72
|
"access": "public"
|
|
71
73
|
},
|
|
72
|
-
"gitSha": "
|
|
74
|
+
"gitSha": "2c91642f426d2b1c7e7d8419b76933bc3fc18390",
|
|
73
75
|
"scripts": {
|
|
74
76
|
"typescript": "tsc -p tsconfig.json",
|
|
75
77
|
"test": "pnpm -w test --project @mui/internal-code-infra"
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import fs from 'node:fs/promises';
|
|
5
|
+
import { globby } from 'globby';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {Object} Args
|
|
10
|
+
* @property {boolean} [silent] Run in silent mode without logging
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @param {string} message
|
|
15
|
+
* @returns {string}
|
|
16
|
+
*/
|
|
17
|
+
const passMessage = (message) => `✓ ${chalk.gray(message)}`;
|
|
18
|
+
/**
|
|
19
|
+
* @param {string} message
|
|
20
|
+
* @returns {string}
|
|
21
|
+
*/
|
|
22
|
+
const failMessage = (message) => `❌ ${chalk.whiteBright(message)}`;
|
|
23
|
+
|
|
24
|
+
export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
25
|
+
command: 'jsonlint',
|
|
26
|
+
describe: 'Lint JSON files',
|
|
27
|
+
builder: (yargs) => {
|
|
28
|
+
return yargs.option('silent', {
|
|
29
|
+
type: 'boolean',
|
|
30
|
+
default: false,
|
|
31
|
+
description: "Don't log file names.",
|
|
32
|
+
});
|
|
33
|
+
},
|
|
34
|
+
handler: async (args) => {
|
|
35
|
+
const cwd = process.cwd();
|
|
36
|
+
const lintIgnoreContent = await (async () => {
|
|
37
|
+
// Reads both for backwards compatibility in the desired order
|
|
38
|
+
for (const ignoreFile of ['.lintignore', '.eslintignore']) {
|
|
39
|
+
const lintIgnorePath = path.join(cwd, ignoreFile);
|
|
40
|
+
try {
|
|
41
|
+
// eslint-disable-next-line no-await-in-loop
|
|
42
|
+
return await fs.readFile(lintIgnorePath, { encoding: 'utf8' });
|
|
43
|
+
} catch (ex) {
|
|
44
|
+
console.error(ex);
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return '';
|
|
49
|
+
})();
|
|
50
|
+
|
|
51
|
+
const lintignore = lintIgnoreContent.split(/\r?\n/).filter(Boolean);
|
|
52
|
+
|
|
53
|
+
const filenames = await globby('**/*.json', {
|
|
54
|
+
cwd,
|
|
55
|
+
gitignore: true,
|
|
56
|
+
ignore: [...lintignore, '**/tsconfig*.json'],
|
|
57
|
+
followSymbolicLinks: false,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
let passed = true;
|
|
61
|
+
const checks = filenames.map(async (filename) => {
|
|
62
|
+
const content = await fs.readFile(path.join(cwd, filename), { encoding: 'utf8' });
|
|
63
|
+
try {
|
|
64
|
+
JSON.parse(content);
|
|
65
|
+
if (!args.silent) {
|
|
66
|
+
// eslint-disable-next-line no-console
|
|
67
|
+
console.log(passMessage(filename));
|
|
68
|
+
}
|
|
69
|
+
} catch (error) {
|
|
70
|
+
passed = false;
|
|
71
|
+
console.error(failMessage(`Error parsing ${filename}:\n\n${String(error)}`));
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
await Promise.allSettled(checks);
|
|
76
|
+
if (!passed) {
|
|
77
|
+
throw new Error('❌ At least one file did not pass. Check the console output');
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/* eslint-disable no-console */
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {import('./pnpm.mjs').Package} Package
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { getWorkspacePackages } from './pnpm.mjs';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @typedef {Object} Args
|
|
13
|
+
* @property {boolean} [publicOnly] - Whether to filter to only public packages
|
|
14
|
+
* @property {'json'|'path'|'name'} [output] - Output format (name, path, or json)
|
|
15
|
+
* @property {string} [sinceRef] - Git reference to filter changes since
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
19
|
+
command: 'list-workspaces',
|
|
20
|
+
describe: 'List all pnpm workspaces in the repository',
|
|
21
|
+
builder: (yargs) => {
|
|
22
|
+
return yargs
|
|
23
|
+
.option('public-only', {
|
|
24
|
+
type: 'boolean',
|
|
25
|
+
default: false,
|
|
26
|
+
description: 'Filter to only public packages',
|
|
27
|
+
})
|
|
28
|
+
.option('output', {
|
|
29
|
+
type: 'string',
|
|
30
|
+
choices: ['json', 'path', 'name'],
|
|
31
|
+
default: 'name',
|
|
32
|
+
description:
|
|
33
|
+
'Output format: name (package names), path (package paths), or json (full JSON)',
|
|
34
|
+
})
|
|
35
|
+
.option('since-ref', {
|
|
36
|
+
type: 'string',
|
|
37
|
+
description: 'Filter packages changed since git reference',
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
handler: async (argv) => {
|
|
41
|
+
const { publicOnly = false, output = 'name', sinceRef } = argv;
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
// Get packages using our helper function
|
|
45
|
+
const packages = await getWorkspacePackages({ sinceRef, publicOnly });
|
|
46
|
+
|
|
47
|
+
if (output === 'json') {
|
|
48
|
+
// Serialize packages to JSON
|
|
49
|
+
console.log(JSON.stringify(packages, null, 2));
|
|
50
|
+
} else if (output === 'path') {
|
|
51
|
+
// Print package paths
|
|
52
|
+
packages.forEach((pkg) => {
|
|
53
|
+
console.log(pkg.path);
|
|
54
|
+
});
|
|
55
|
+
} else {
|
|
56
|
+
// Print package names (default)
|
|
57
|
+
packages.forEach((pkg) => {
|
|
58
|
+
console.log(pkg.name);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
} catch (/** @type {any} */ error) {
|
|
62
|
+
console.error('Error listing workspaces:', error.message);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
});
|
package/src/cli/cmdPublish.mjs
CHANGED
|
@@ -293,7 +293,7 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
|
293
293
|
|
|
294
294
|
// Get all packages
|
|
295
295
|
console.log('🔍 Discovering all workspace packages...');
|
|
296
|
-
const allPackages = await getWorkspacePackages();
|
|
296
|
+
const allPackages = await getWorkspacePackages({ publicOnly: true });
|
|
297
297
|
|
|
298
298
|
if (allPackages.length === 0) {
|
|
299
299
|
console.log('⚠️ No public packages found in workspace');
|
|
@@ -208,7 +208,7 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
|
208
208
|
|
|
209
209
|
// Always get all packages first
|
|
210
210
|
console.log('🔍 Discovering all workspace packages...');
|
|
211
|
-
const allPackages = await getWorkspacePackages();
|
|
211
|
+
const allPackages = await getWorkspacePackages({ publicOnly: true });
|
|
212
212
|
|
|
213
213
|
if (allPackages.length === 0) {
|
|
214
214
|
console.log('⚠️ No public packages found in workspace');
|
|
@@ -223,7 +223,9 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
|
223
223
|
? '🔍 Checking for packages changed since canary tag...'
|
|
224
224
|
: '🔍 No canary tag found, will publish all packages',
|
|
225
225
|
);
|
|
226
|
-
const packages = canaryTag
|
|
226
|
+
const packages = canaryTag
|
|
227
|
+
? await getWorkspacePackages({ sinceRef: canaryTag, publicOnly: true })
|
|
228
|
+
: allPackages;
|
|
227
229
|
|
|
228
230
|
console.log(`📋 Found ${packages.length} packages that need canary publishing:`);
|
|
229
231
|
packages.forEach((pkg) => {
|
package/src/cli/index.mjs
CHANGED
|
@@ -3,5 +3,14 @@ import { hideBin } from 'yargs/helpers';
|
|
|
3
3
|
|
|
4
4
|
import cmdPublish from './cmdPublish.mjs';
|
|
5
5
|
import cmdPublishCanary from './cmdPublishCanary.mjs';
|
|
6
|
+
import cmdListWorkspaces from './cmdListWorkspaces.mjs';
|
|
7
|
+
import cmdJsonLint from './cmdJsonLint.mjs';
|
|
6
8
|
|
|
7
|
-
yargs()
|
|
9
|
+
yargs()
|
|
10
|
+
.command(cmdPublish)
|
|
11
|
+
.command(cmdPublishCanary)
|
|
12
|
+
.command(cmdListWorkspaces)
|
|
13
|
+
.command(cmdJsonLint)
|
|
14
|
+
.demandCommand(1, 'You need at least one command before moving on')
|
|
15
|
+
.help()
|
|
16
|
+
.parse(hideBin(process.argv));
|
package/src/cli/pnpm.mjs
CHANGED
|
@@ -34,20 +34,28 @@ import * as semver from 'semver';
|
|
|
34
34
|
*/
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
|
-
*
|
|
38
|
-
* @
|
|
39
|
-
* @
|
|
37
|
+
* @typedef {Object} GetWorkspacePackagesOptions
|
|
38
|
+
* @property {string|null} [sinceRef] - Git reference to filter changes since
|
|
39
|
+
* @property {boolean} [publicOnly=false] - Whether to filter to only public packages
|
|
40
40
|
*/
|
|
41
|
-
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Get workspace packages with optional filtering
|
|
44
|
+
* @param {GetWorkspacePackagesOptions} [options={}] - Options for filtering packages
|
|
45
|
+
* @returns {Promise<Package[]>} Array of packages
|
|
46
|
+
*/
|
|
47
|
+
export async function getWorkspacePackages(options = {}) {
|
|
48
|
+
const { sinceRef = null, publicOnly = false } = options;
|
|
49
|
+
|
|
42
50
|
// Build command with conditional filter
|
|
43
51
|
const filterArg = sinceRef ? ['--filter', `...[${sinceRef}]`] : [];
|
|
44
52
|
const result = await $`pnpm ls -r --json --depth -1 ${filterArg}`;
|
|
45
53
|
/** @type {PnpmListResultItem[]} */
|
|
46
54
|
const packageData = JSON.parse(result.stdout);
|
|
47
55
|
|
|
48
|
-
// Filter
|
|
49
|
-
const
|
|
50
|
-
.filter((pkg) => !pkg.private)
|
|
56
|
+
// Filter packages based on options
|
|
57
|
+
const filteredPackages = packageData
|
|
58
|
+
.filter((pkg) => !publicOnly || !pkg.private)
|
|
51
59
|
.map((pkg) => {
|
|
52
60
|
if (!pkg.name || !pkg.version) {
|
|
53
61
|
throw new Error(`Invalid package data: ${JSON.stringify(pkg)}`);
|
|
@@ -59,7 +67,7 @@ export async function getWorkspacePackages(sinceRef = null) {
|
|
|
59
67
|
};
|
|
60
68
|
});
|
|
61
69
|
|
|
62
|
-
return
|
|
70
|
+
return filteredPackages;
|
|
63
71
|
}
|
|
64
72
|
|
|
65
73
|
/**
|
|
@@ -22,7 +22,8 @@ export function createBaseConfig(
|
|
|
22
22
|
) {
|
|
23
23
|
const ignoreRules = /** @type {import('@eslint/compat').FlatConfig[]} */ (
|
|
24
24
|
// All repos should use .lintignore going forward.
|
|
25
|
-
|
|
25
|
+
// .eslintignore is for backward compatibility. Should be removed in future.
|
|
26
|
+
['.gitignore', '.lintignore', '.eslintignore']
|
|
26
27
|
.map((file) => {
|
|
27
28
|
if (fs.existsSync(`${baseDirectory}/${file}`)) {
|
|
28
29
|
return includeIgnoreFile(path.join(baseDirectory, file), `Ignore rules from ${file}`);
|