@mui/internal-code-infra 0.0.4-canary.98 → 0.1.1-canary.0
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/README.md +4 -0
- package/build/babel-config.d.mts +4 -4
- package/build/babelPluginInlineEnvironmentVariables.d.mts +11 -0
- package/build/brokenLinksChecker/index.d.mts +147 -0
- package/build/changelog/fetchChangelogs.d.mts +3 -0
- package/build/cli/cmdArgosPush.d.mts +6 -0
- package/build/cli/cmdBuild.d.mts +45 -0
- package/build/cli/cmdCopyFiles.d.mts +12 -0
- package/build/cli/cmdGenerateChangelog.d.mts +15 -0
- package/build/cli/cmdListWorkspaces.d.mts +14 -2
- package/build/cli/cmdNetlifyIgnore.d.mts +9 -0
- package/build/cli/cmdPublish.d.mts +20 -2
- package/build/cli/cmdPublishCanary.d.mts +18 -0
- package/build/cli/cmdPublishNewPackage.d.mts +6 -0
- package/build/cli/cmdRenameScope.d.mts +18 -0
- package/build/cli/cmdSetVersionOverrides.d.mts +3 -0
- package/build/eslint/mui/rules/no-restricted-resolved-imports.d.mts +6 -0
- package/build/eslint/testConfig.d.mts +1 -7
- package/build/utils/babel.d.mts +6 -0
- package/build/utils/build.d.mts +3 -15
- package/build/utils/extractErrorCodes.d.mts +16 -0
- package/build/utils/git.d.mts +9 -0
- package/build/utils/github.d.mts +12 -0
- package/build/utils/pnpm.d.mts +147 -9
- package/build/utils/testUtils.d.mts +21 -0
- package/build/utils/typescript.d.mts +2 -2
- package/package.json +54 -56
- package/src/babel-config.mjs +21 -11
- package/src/babelPluginInlineEnvironmentVariables.mjs +45 -0
- package/src/brokenLinksChecker/index.mjs +3 -3
- package/src/cli/cmdArgosPush.mjs +2 -4
- package/src/cli/cmdBuild.mjs +8 -9
- package/src/cli/cmdCopyFiles.mjs +3 -3
- package/src/cli/cmdListWorkspaces.mjs +3 -31
- package/src/cli/cmdPublish.mjs +23 -29
- package/src/cli/cmdRenameScope.mjs +77 -0
- package/src/cli/cmdSetVersionOverrides.mjs +32 -25
- package/src/cli/cmdVale.mjs +3 -6
- package/src/cli/cmdValidateBuiltTypes.mjs +3 -4
- package/src/cli/index.mjs +2 -0
- package/src/eslint/testConfig.mjs +3 -31
- package/src/untyped-plugins.d.ts +11 -49
- package/src/utils/build.mjs +0 -39
- package/src/utils/extractErrorCodes.mjs +12 -7
- package/src/utils/pnpm.mjs +380 -16
- package/src/utils/testUtils.mjs +35 -0
- package/src/utils/typescript.mjs +60 -42
package/src/cli/cmdArgosPush.mjs
CHANGED
|
@@ -46,8 +46,6 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
|
46
46
|
const { folder, verbose = false } = argv;
|
|
47
47
|
|
|
48
48
|
const argosToken = requireEnv('ARGOS_TOKEN');
|
|
49
|
-
const circleSha1 = requireEnv('CIRCLE_SHA1');
|
|
50
|
-
const circleBranch = requireEnv('CIRCLE_BRANCH');
|
|
51
49
|
const circleBuildNum = requireEnv('CIRCLE_BUILD_NUM');
|
|
52
50
|
|
|
53
51
|
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'argos-screenshots-'));
|
|
@@ -92,8 +90,8 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
|
92
90
|
// eslint-disable-next-line no-await-in-loop
|
|
93
91
|
const result = await upload({
|
|
94
92
|
root: `${tempDir}/${i}`,
|
|
95
|
-
commit
|
|
96
|
-
|
|
93
|
+
// The SDK resolves `commit` and `branch`: it reads `ARGOS_COMMIT` and `ARGOS_BRANCH`
|
|
94
|
+
// first and falls back to `CIRCLE_SHA1` and `CIRCLE_BRANCH`.
|
|
97
95
|
token: argosToken,
|
|
98
96
|
threshold,
|
|
99
97
|
parallel: {
|
package/src/cli/cmdBuild.mjs
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
2
|
import { findWorkspaceDir } from '@pnpm/find-workspace-dir';
|
|
3
|
-
import { $ } from 'execa';
|
|
4
3
|
import { globby } from 'globby';
|
|
5
4
|
import * as fs from 'node:fs/promises';
|
|
6
5
|
import * as path from 'node:path';
|
|
7
6
|
import { sep as posixSep } from 'node:path/posix';
|
|
8
7
|
import * as semver from 'semver';
|
|
8
|
+
import { mapAsync } from 'es-toolkit/array';
|
|
9
9
|
|
|
10
10
|
import {
|
|
11
11
|
createPackageBin,
|
|
12
12
|
createPackageExports,
|
|
13
13
|
createPackageImports,
|
|
14
14
|
getOutExtension,
|
|
15
|
-
mapConcurrently,
|
|
16
15
|
validatePkgJson,
|
|
17
16
|
} from '../utils/build.mjs';
|
|
17
|
+
import { readPnpmConfig } from '../utils/pnpm.mjs';
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* @typedef {Object} Args
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
* @property {string[]} ignore - Globs to be ignored by Babel.
|
|
31
31
|
* @property {string[]} [copy] - Files/Directories to be copied. Can be a glob pattern.
|
|
32
32
|
* @property {boolean} [enableReactCompiler] - Whether to use the React compiler.
|
|
33
|
-
* @property {boolean} [tsgo] - Whether to build types using
|
|
33
|
+
* @property {boolean} [tsgo] - Whether to build types using the native TypeScript compiler.
|
|
34
34
|
* @property {boolean} [flat] - Deprecated no-op; flat builds are always used.
|
|
35
35
|
* @property {boolean} expand - Whether to enumerate glob patterns in exports/imports into concrete entries.
|
|
36
36
|
*/
|
|
@@ -229,9 +229,9 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
|
229
229
|
})
|
|
230
230
|
.option('tsgo', {
|
|
231
231
|
type: 'boolean',
|
|
232
|
-
default:
|
|
232
|
+
default: false,
|
|
233
233
|
description:
|
|
234
|
-
'
|
|
234
|
+
'Use the native TypeScript compiler instead of the TS6 JS compiler for type generation',
|
|
235
235
|
})
|
|
236
236
|
.option('flat', {
|
|
237
237
|
type: 'boolean',
|
|
@@ -279,8 +279,7 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
|
279
279
|
if (babelRuntimeVersion === 'catalog:') {
|
|
280
280
|
// resolve the version from the given package
|
|
281
281
|
// outputs the pnpm-workspace.yaml config as json
|
|
282
|
-
const
|
|
283
|
-
const pnpmWorkspaceConfig = JSON.parse(configStdout);
|
|
282
|
+
const pnpmWorkspaceConfig = await readPnpmConfig();
|
|
284
283
|
babelRuntimeVersion = pnpmWorkspaceConfig.catalog['@babel/runtime'];
|
|
285
284
|
}
|
|
286
285
|
|
|
@@ -479,7 +478,7 @@ async function copyHandler({ cwd, globs = [], buildDir, verbose = false }) {
|
|
|
479
478
|
console.log('⓿ No files to copy.');
|
|
480
479
|
}
|
|
481
480
|
}
|
|
482
|
-
await
|
|
481
|
+
await mapAsync(
|
|
483
482
|
defaultFiles,
|
|
484
483
|
async (file) => {
|
|
485
484
|
if (typeof file === 'string') {
|
|
@@ -492,7 +491,7 @@ async function copyHandler({ cwd, globs = [], buildDir, verbose = false }) {
|
|
|
492
491
|
await recursiveCopy({ source: file.sourcePath, target: file.targetPath, verbose });
|
|
493
492
|
}
|
|
494
493
|
},
|
|
495
|
-
20,
|
|
494
|
+
{ concurrency: 20 },
|
|
496
495
|
);
|
|
497
496
|
console.log(`📋 Copied ${defaultFiles.length} files.`);
|
|
498
497
|
}
|
package/src/cli/cmdCopyFiles.mjs
CHANGED
|
@@ -2,7 +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 {
|
|
5
|
+
import { mapAsync } from 'es-toolkit/array';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* @typedef {Object} Args
|
|
@@ -106,12 +106,12 @@ async function processGlobs({ globs, cwd, silent = true, buildDir }) {
|
|
|
106
106
|
});
|
|
107
107
|
});
|
|
108
108
|
|
|
109
|
-
await
|
|
109
|
+
await mapAsync(
|
|
110
110
|
filesToProcess,
|
|
111
111
|
async (file) => {
|
|
112
112
|
await recursiveCopy({ source: file.sourcePath, target: file.targetPath, silent });
|
|
113
113
|
},
|
|
114
|
-
50,
|
|
114
|
+
{ concurrency: 50 },
|
|
115
115
|
);
|
|
116
116
|
return filesToProcess.length;
|
|
117
117
|
}
|
|
@@ -6,14 +6,12 @@
|
|
|
6
6
|
* @typedef {import('../utils/pnpm.mjs').PublicPackage} PublicPackage
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import * as fs from 'node:fs/promises';
|
|
10
|
-
import * as path from 'node:path';
|
|
11
9
|
import { getWorkspacePackages } from '../utils/pnpm.mjs';
|
|
12
10
|
|
|
13
11
|
/**
|
|
14
12
|
* @typedef {Object} Args
|
|
15
13
|
* @property {boolean} [publicOnly] - Whether to filter to only public packages
|
|
16
|
-
* @property {'json'|'path'|'name'
|
|
14
|
+
* @property {'json'|'path'|'name'} [output] - Output format (name, path, or json)
|
|
17
15
|
* @property {string} [sinceRef] - Git reference to filter changes since
|
|
18
16
|
* @property {string[]} [filter] - Same as filtering packages with --filter in pnpm. Only include packages matching the filter. See https://pnpm.io/filtering.
|
|
19
17
|
*/
|
|
@@ -30,10 +28,10 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
|
30
28
|
})
|
|
31
29
|
.option('output', {
|
|
32
30
|
type: 'string',
|
|
33
|
-
choices: ['json', 'path', 'name'
|
|
31
|
+
choices: ['json', 'path', 'name'],
|
|
34
32
|
default: 'path',
|
|
35
33
|
description:
|
|
36
|
-
'Output format: name (package names), path (package paths),
|
|
34
|
+
'Output format: name (package names), path (package paths), or json (full JSON)',
|
|
37
35
|
})
|
|
38
36
|
.option('since-ref', {
|
|
39
37
|
type: 'string',
|
|
@@ -60,32 +58,6 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
|
60
58
|
packages.forEach((pkg) => {
|
|
61
59
|
console.log(pkg.path);
|
|
62
60
|
});
|
|
63
|
-
} else if (output === 'publish-dir') {
|
|
64
|
-
// Works around https://github.com/stackblitz-labs/pkg.pr.new/issues/389: pkg-pr-new rewrites
|
|
65
|
-
// workspace:* deps to its URLs in the source package.json, but `pnpm pack` honors
|
|
66
|
-
// publishConfig.directory and packs the build package.json, whose workspace:* deps are left to
|
|
67
|
-
// resolve to plain versions. Pointing pkg-pr-new at the build dir makes both act on the same file.
|
|
68
|
-
// Note: #389 was closed by pkg-pr-new#499, but that only fixed the tarball location, not the dep
|
|
69
|
-
// resolution — verified still broken on 0.0.78. Do not remove until the packed deps are URLs
|
|
70
|
-
// without this. Removing it prematurely regressed publishing once (see mui-public#1354).
|
|
71
|
-
// Print publish directories (package.json publishConfig.directory or package path)
|
|
72
|
-
const publishDirs = await Promise.all(
|
|
73
|
-
packages.map(async (pkg) => {
|
|
74
|
-
const packageJsonPath = path.join(pkg.path, 'package.json');
|
|
75
|
-
const packageJsonContent = await fs.readFile(packageJsonPath, 'utf8');
|
|
76
|
-
const packageJson = JSON.parse(packageJsonContent);
|
|
77
|
-
|
|
78
|
-
if (packageJson.publishConfig?.directory) {
|
|
79
|
-
return path.join(pkg.path, packageJson.publishConfig.directory);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return pkg.path;
|
|
83
|
-
}),
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
publishDirs.forEach((dir) => {
|
|
87
|
-
console.log(dir);
|
|
88
|
-
});
|
|
89
61
|
} else if (output === 'name') {
|
|
90
62
|
// Print package names (default)
|
|
91
63
|
packages.forEach((pkg) => {
|
package/src/cli/cmdPublish.mjs
CHANGED
|
@@ -20,6 +20,7 @@ import * as semver from 'semver';
|
|
|
20
20
|
import { persistentAuthStrategy } from '../utils/github.mjs';
|
|
21
21
|
import {
|
|
22
22
|
getPackagesNeedingManualPublish,
|
|
23
|
+
getReleaseVersion,
|
|
23
24
|
getWorkspacePackages,
|
|
24
25
|
publishPackages,
|
|
25
26
|
validatePublishDependencies,
|
|
@@ -42,19 +43,6 @@ function getOctokit() {
|
|
|
42
43
|
* @property {string[]} [filter] Same as filtering packages with --filter in pnpm. Only publish packages matching the filter. See https://pnpm.io/filtering.
|
|
43
44
|
*/
|
|
44
45
|
|
|
45
|
-
/**
|
|
46
|
-
* Get the version to release from the root package.json
|
|
47
|
-
* @returns {Promise<string | null>} Version string
|
|
48
|
-
*/
|
|
49
|
-
async function getReleaseVersion() {
|
|
50
|
-
// `--json` is required: pnpm 11 returns the raw value (e.g. `9.4.0`) for a
|
|
51
|
-
// single field without it, which is not valid JSON. The flag forces quoted
|
|
52
|
-
// output (`"9.4.0"`) across pnpm 9/10/11.
|
|
53
|
-
const result = await $`pnpm pkg get version --json`;
|
|
54
|
-
const version = JSON.parse(result.stdout.trim());
|
|
55
|
-
return semver.valid(version);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
46
|
/**
|
|
59
47
|
* Parse changelog to extract content for a specific version
|
|
60
48
|
* @param {string} changelogPath - Path to CHANGELOG.md
|
|
@@ -510,6 +498,8 @@ async function determineGitSha(octokit, repoInfo) {
|
|
|
510
498
|
await octokit.search.issuesAndPullRequests({
|
|
511
499
|
advanced_search: 'true',
|
|
512
500
|
q: `is:pr is:merged label:release repo:${repoInfo.owner}/${repoInfo.repo}`,
|
|
501
|
+
sort: 'created',
|
|
502
|
+
order: 'desc',
|
|
513
503
|
per_page: 1,
|
|
514
504
|
})
|
|
515
505
|
).data.items;
|
|
@@ -522,29 +512,33 @@ async function determineGitSha(octokit, repoInfo) {
|
|
|
522
512
|
` Found the latest merged release PR: ${chalk.bold(pulls[0].title)} (${pulls[0].html_url})`,
|
|
523
513
|
);
|
|
524
514
|
|
|
525
|
-
const
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
})
|
|
530
|
-
).data.items;
|
|
531
|
-
|
|
532
|
-
if (!commits.length) {
|
|
533
|
-
console.error(
|
|
534
|
-
`❌🚨 Could not find any commits associated with the release PR: ${pulls[0].html_url}`,
|
|
535
|
-
);
|
|
515
|
+
const pull = (await octokit.pulls.get({ ...repoInfo, pull_number: pulls[0].number })).data;
|
|
516
|
+
const mergeCommitSha = pull.merge_commit_sha;
|
|
517
|
+
if (!mergeCommitSha) {
|
|
518
|
+
console.error(`❌🚨 Could not determine the merge commit of ${pulls[0].html_url}.`);
|
|
536
519
|
return undefined;
|
|
537
520
|
}
|
|
538
|
-
|
|
521
|
+
|
|
522
|
+
// Recent commits on the PR's target branch, to allow releasing from a different commit.
|
|
523
|
+
const commits = (
|
|
524
|
+
await octokit.repos.listCommits({ ...repoInfo, sha: pull.base.ref, per_page: 20 })
|
|
525
|
+
).data;
|
|
526
|
+
|
|
527
|
+
const toChoice = (/** @type {(typeof commits)[number]} */ commit) => ({
|
|
539
528
|
value: commit.sha,
|
|
540
529
|
name: `(${commit.sha.slice(0, 7)}) ${commit.commit.message.split('\n')[0]} by ${commit.author?.login ?? 'no author'} on ${new Date(commit.commit.committer?.date ?? '').toISOString()}`,
|
|
541
|
-
|
|
542
|
-
})
|
|
530
|
+
description: commit.commit.message,
|
|
531
|
+
});
|
|
532
|
+
const choices = commits.map(toChoice);
|
|
533
|
+
if (!choices.some((choice) => choice.value === mergeCommitSha)) {
|
|
534
|
+
const mergeCommit = (await octokit.repos.getCommit({ ...repoInfo, ref: mergeCommitSha })).data;
|
|
535
|
+
choices.unshift(toChoice(mergeCommit));
|
|
536
|
+
}
|
|
543
537
|
|
|
544
538
|
const result = await select({
|
|
545
539
|
message: 'Select the commit to release from:',
|
|
546
|
-
choices
|
|
547
|
-
default:
|
|
540
|
+
choices,
|
|
541
|
+
default: mergeCommitSha,
|
|
548
542
|
pageSize: 10,
|
|
549
543
|
});
|
|
550
544
|
return result;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/* eslint-disable no-console */
|
|
4
|
+
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
|
|
7
|
+
import { getWorkspacePackages, renameWorkspaceScope } from '../utils/pnpm.mjs';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A scope is a single `@`-prefixed segment. Letting a `/` through would build
|
|
11
|
+
* names like `@acme/private/pkg`, which only npm rejects, long after every
|
|
12
|
+
* matching manifest has been rewritten.
|
|
13
|
+
*/
|
|
14
|
+
const SCOPE_PATTERN = /^@[a-z0-9-~][a-z0-9-._~]*$/;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {Object} Args
|
|
18
|
+
* @property {[string, string]} alias Source and target scope
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @param {string} alias
|
|
23
|
+
* @returns {[string, string]}
|
|
24
|
+
*/
|
|
25
|
+
export function parseAlias(alias) {
|
|
26
|
+
const parts = alias.split(':');
|
|
27
|
+
const [from, to] = parts;
|
|
28
|
+
if (parts.length !== 2 || !SCOPE_PATTERN.test(from) || !SCOPE_PATTERN.test(to)) {
|
|
29
|
+
throw new Error(
|
|
30
|
+
`Invalid scope mapping "${alias}". Expected exactly two npm scopes separated by a colon, e.g. "@acme:@acme-private".`,
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
if (from === to) {
|
|
34
|
+
throw new Error(`Invalid scope mapping "${alias}". The source and target scope are the same.`);
|
|
35
|
+
}
|
|
36
|
+
return [from, to];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
40
|
+
command: 'rename-scope <alias>',
|
|
41
|
+
describe: 'Move publishable workspace packages to a different npm scope',
|
|
42
|
+
builder: (yargs) =>
|
|
43
|
+
yargs
|
|
44
|
+
.positional('alias', {
|
|
45
|
+
type: 'string',
|
|
46
|
+
describe: 'Scope mapping written as "@from:@to"',
|
|
47
|
+
coerce: parseAlias,
|
|
48
|
+
})
|
|
49
|
+
.example(
|
|
50
|
+
'$0 rename-scope @acme:@acme-private',
|
|
51
|
+
'Publish the workspace @acme packages under @acme-private',
|
|
52
|
+
),
|
|
53
|
+
handler: async (argv) => {
|
|
54
|
+
const [from, to] = argv.alias;
|
|
55
|
+
const packages = await getWorkspacePackages();
|
|
56
|
+
const renamed = await renameWorkspaceScope(packages, from, to);
|
|
57
|
+
|
|
58
|
+
// Matching nothing means the mapping is wrong or stale. Carrying on would
|
|
59
|
+
// publish under the original scope, so fail instead of reporting success.
|
|
60
|
+
if (renamed.size === 0) {
|
|
61
|
+
throw new Error(
|
|
62
|
+
`No publishable workspace packages found in ${from}. Check the scope mapping "${from}:${to}", or the workspace may already have been renamed.`,
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
for (const [oldName, newName] of renamed) {
|
|
67
|
+
console.log(`📦 ${oldName} → ${chalk.bold(newName)}`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
console.log(
|
|
71
|
+
chalk.yellow(
|
|
72
|
+
'\n⚠️ Workspace manifests were rewritten in place and are not restored. The next install\n' +
|
|
73
|
+
'rewrites pnpm-lock.yaml to match. Discard both before committing.',
|
|
74
|
+
),
|
|
75
|
+
);
|
|
76
|
+
},
|
|
77
|
+
});
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
import * as semver from 'semver';
|
|
4
4
|
import { $ } from 'execa';
|
|
5
5
|
import { findWorkspaceDir } from '@pnpm/find-workspace-dir';
|
|
6
|
+
import { parseWantedDependency } from '@pnpm/parse-wanted-dependency';
|
|
6
7
|
import {
|
|
8
|
+
getMinimumReleaseAgePolicy,
|
|
7
9
|
resolveVersion,
|
|
8
10
|
findDependencyVersionFromSpec,
|
|
9
11
|
writeOverridesToWorkspace,
|
|
@@ -17,61 +19,62 @@ import {
|
|
|
17
19
|
/**
|
|
18
20
|
* Process a single package override
|
|
19
21
|
* @param {string} packageSpec - Package specifier in format "package@version"
|
|
22
|
+
* @param {import('@pnpm/config.version-policy').PublishedByPolicy} policy - Registry cooldown to resolve within
|
|
20
23
|
* @returns {Promise<Record<string, string>>} Overrides object for this package
|
|
21
24
|
*/
|
|
22
|
-
async function processPackageOverride(packageSpec) {
|
|
25
|
+
async function processPackageOverride(packageSpec, policy) {
|
|
23
26
|
/** @type {Record<string, string>} */
|
|
24
27
|
const overrides = {};
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if (lastAtIndex === -1) {
|
|
29
|
+
const { alias: packageName, bareSpecifier: version } = parseWantedDependency(packageSpec);
|
|
30
|
+
if (!packageName || version === undefined) {
|
|
29
31
|
throw new Error(`Invalid package specifier: ${packageSpec}`);
|
|
30
32
|
}
|
|
31
33
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (!
|
|
34
|
+
// An empty version is distinct from a missing one: CI interpolates a matrix
|
|
35
|
+
// value into `--pkg pkg@<version>`, and the leg that leaves it unset must skip
|
|
36
|
+
// the override rather than fail the job.
|
|
37
|
+
if (!version || version === 'stable') {
|
|
36
38
|
return overrides;
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
// eslint-disable-next-line no-console
|
|
40
42
|
console.log(`Resolving overrides for ${packageName} version: ${version}`);
|
|
41
43
|
|
|
44
|
+
/** @param {string} spec */
|
|
45
|
+
const resolve = (spec) => resolveVersion(spec, policy);
|
|
46
|
+
|
|
42
47
|
if (packageName === 'react') {
|
|
43
48
|
// Special case for React - also override related packages
|
|
44
|
-
overrides.react = await
|
|
45
|
-
overrides['react-dom'] = await
|
|
46
|
-
overrides['react-is'] = await
|
|
49
|
+
overrides.react = await resolve(packageSpec);
|
|
50
|
+
overrides['react-dom'] = await resolve(`react-dom@${version}`);
|
|
51
|
+
overrides['react-is'] = await resolve(`react-is@${version}`);
|
|
47
52
|
overrides.scheduler = await findDependencyVersionFromSpec(
|
|
48
53
|
`react-dom@${overrides['react-dom']}`,
|
|
49
54
|
'scheduler',
|
|
55
|
+
policy,
|
|
50
56
|
);
|
|
51
57
|
|
|
52
58
|
const reactMajor = semver.major(overrides.react);
|
|
53
59
|
if (reactMajor === 17) {
|
|
54
|
-
overrides['@testing-library/react'] = await
|
|
60
|
+
overrides['@testing-library/react'] = await resolve('@testing-library/react@^12.1.0');
|
|
55
61
|
}
|
|
56
62
|
} else if (packageName === '@mui/material') {
|
|
57
63
|
// Special case for MUI - also override related packages
|
|
58
|
-
overrides['@mui/material'] = await
|
|
59
|
-
overrides['@mui/system'] = await
|
|
60
|
-
overrides['@mui/icons-material'] = await
|
|
61
|
-
overrides['@mui/utils'] = await
|
|
62
|
-
overrides['@mui/material-nextjs'] = await
|
|
64
|
+
overrides['@mui/material'] = await resolve(`@mui/material@${version}`);
|
|
65
|
+
overrides['@mui/system'] = await resolve(`@mui/system@${version}`);
|
|
66
|
+
overrides['@mui/icons-material'] = await resolve(`@mui/icons-material@${version}`);
|
|
67
|
+
overrides['@mui/utils'] = await resolve(`@mui/utils@${version}`);
|
|
68
|
+
overrides['@mui/material-nextjs'] = await resolve(`@mui/material-nextjs@${version}`);
|
|
63
69
|
|
|
64
|
-
const latest = await
|
|
70
|
+
const latest = await resolve(`@mui/material@latest`);
|
|
65
71
|
const latestMajor = semver.major(latest);
|
|
66
72
|
const muiMajor = semver.major(overrides['@mui/material']);
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
} else {
|
|
70
|
-
overrides['@mui/lab'] = await resolveVersion(`@mui/lab@latest`);
|
|
71
|
-
}
|
|
73
|
+
const labTag = muiMajor < latestMajor ? `latest-v${muiMajor}` : 'latest';
|
|
74
|
+
overrides['@mui/lab'] = await resolve(`@mui/lab@${labTag}`);
|
|
72
75
|
} else {
|
|
73
76
|
// Generic case for other packages
|
|
74
|
-
overrides[packageName] = await
|
|
77
|
+
overrides[packageName] = await resolve(packageSpec);
|
|
75
78
|
}
|
|
76
79
|
|
|
77
80
|
return overrides;
|
|
@@ -89,8 +92,12 @@ async function handler(args) {
|
|
|
89
92
|
return;
|
|
90
93
|
}
|
|
91
94
|
|
|
95
|
+
// Read once and thread through: every override must land on a version that
|
|
96
|
+
// clears the same cooldown the following `pnpm dedupe` enforces.
|
|
97
|
+
const policy = await getMinimumReleaseAgePolicy();
|
|
98
|
+
|
|
92
99
|
const packageOverridePromises = args.pkg.map((packageSpec) =>
|
|
93
|
-
processPackageOverride(packageSpec),
|
|
100
|
+
processPackageOverride(packageSpec, policy),
|
|
94
101
|
);
|
|
95
102
|
const packageOverrideResults = await Promise.all(packageOverridePromises);
|
|
96
103
|
|
package/src/cli/cmdVale.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import * as path from 'node:path';
|
|
|
7
7
|
import { pipeline } from 'node:stream/promises';
|
|
8
8
|
import { findWorkspaceDir } from '@pnpm/find-workspace-dir';
|
|
9
9
|
import { $ } from 'execa';
|
|
10
|
-
import {
|
|
10
|
+
import { mapAsync } from 'es-toolkit/array';
|
|
11
11
|
|
|
12
12
|
const LATEST_RELEASE_URL = 'https://api.github.com/repos/vale-cli/vale/releases/latest';
|
|
13
13
|
|
|
@@ -342,7 +342,7 @@ export function getReplacementText(alert) {
|
|
|
342
342
|
export async function applyFixes(results, fixLevel) {
|
|
343
343
|
const entries = Object.entries(results);
|
|
344
344
|
|
|
345
|
-
const perFileResults = await
|
|
345
|
+
const perFileResults = await mapAsync(
|
|
346
346
|
entries,
|
|
347
347
|
async ([filePath, alerts]) => {
|
|
348
348
|
const content = await fs.readFile(filePath, 'utf-8');
|
|
@@ -406,15 +406,12 @@ export async function applyFixes(results, fixLevel) {
|
|
|
406
406
|
|
|
407
407
|
return { fixed: fileFixed, skipped: alerts.length - fixableAlerts.length };
|
|
408
408
|
},
|
|
409
|
-
10,
|
|
409
|
+
{ concurrency: 10 },
|
|
410
410
|
);
|
|
411
411
|
|
|
412
412
|
let fixed = 0;
|
|
413
413
|
let skipped = 0;
|
|
414
414
|
for (const result of perFileResults) {
|
|
415
|
-
if (result instanceof Error) {
|
|
416
|
-
throw result;
|
|
417
|
-
}
|
|
418
415
|
fixed += result.fixed;
|
|
419
416
|
skipped += result.skipped;
|
|
420
417
|
}
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
import { globby } from 'globby';
|
|
3
3
|
import * as fs from 'node:fs/promises';
|
|
4
4
|
import { findWorkspaceDir } from '@pnpm/find-workspace-dir';
|
|
5
|
-
|
|
6
|
-
import { mapConcurrently } from '../utils/build.mjs';
|
|
5
|
+
import { mapAsync } from 'es-toolkit/array';
|
|
7
6
|
|
|
8
7
|
const DYNAMIC_PACKAGES_IMPORT_REGEX = /import\((['"])packages\//gm;
|
|
9
8
|
|
|
@@ -22,14 +21,14 @@ async function validateFiles() {
|
|
|
22
21
|
});
|
|
23
22
|
|
|
24
23
|
const invalidFiles = (
|
|
25
|
-
await
|
|
24
|
+
await mapAsync(
|
|
26
25
|
declarationFiles,
|
|
27
26
|
async (declarationFile) => {
|
|
28
27
|
const content = await fs.readFile(declarationFile, 'utf-8');
|
|
29
28
|
const matches = Array.from(content.matchAll(DYNAMIC_PACKAGES_IMPORT_REGEX));
|
|
30
29
|
return matches.length > 0 ? declarationFile : undefined;
|
|
31
30
|
},
|
|
32
|
-
20,
|
|
31
|
+
{ concurrency: 20 },
|
|
33
32
|
)
|
|
34
33
|
).filter((file) => typeof file === 'string');
|
|
35
34
|
|
package/src/cli/index.mjs
CHANGED
|
@@ -14,6 +14,7 @@ import cmdNetlifyIgnore from './cmdNetlifyIgnore.mjs';
|
|
|
14
14
|
import cmdPublish from './cmdPublish.mjs';
|
|
15
15
|
import cmdPublishCanary from './cmdPublishCanary.mjs';
|
|
16
16
|
import cmdPublishNewPackage from './cmdPublishNewPackage.mjs';
|
|
17
|
+
import cmdRenameScope from './cmdRenameScope.mjs';
|
|
17
18
|
import cmdSetVersionOverrides from './cmdSetVersionOverrides.mjs';
|
|
18
19
|
import cmdVale from './cmdVale.mjs';
|
|
19
20
|
import cmdValidateBuiltTypes from './cmdValidateBuiltTypes.mjs';
|
|
@@ -47,6 +48,7 @@ await yargs(hideBin(process.argv))
|
|
|
47
48
|
.command(cmdPublish)
|
|
48
49
|
.command(cmdPublishCanary)
|
|
49
50
|
.command(cmdPublishNewPackage)
|
|
51
|
+
.command(cmdRenameScope)
|
|
50
52
|
.command(cmdSetVersionOverrides)
|
|
51
53
|
.command(cmdVale)
|
|
52
54
|
.command(cmdValidateBuiltTypes)
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import mochaPlugin from 'eslint-plugin-mocha';
|
|
2
1
|
import vitestPlugin from '@vitest/eslint-plugin';
|
|
3
2
|
import testingLibrary from 'eslint-plugin-testing-library';
|
|
4
3
|
import { defineConfig } from 'eslint/config';
|
|
5
|
-
import globals from 'globals';
|
|
6
4
|
import * as tseslint from 'typescript-eslint';
|
|
7
5
|
import { EXTENSION_TS } from './extensions.mjs';
|
|
8
6
|
|
|
@@ -44,16 +42,11 @@ export const baseSpecRules = {
|
|
|
44
42
|
};
|
|
45
43
|
|
|
46
44
|
/**
|
|
47
|
-
* @param {Object} [options]
|
|
48
|
-
* @param {boolean} [options.useMocha]
|
|
49
|
-
* @param {boolean} [options.useVitest]
|
|
50
45
|
* @returns {import('eslint').Linter.Config[]}
|
|
51
46
|
*/
|
|
52
|
-
export function createTestConfig(
|
|
53
|
-
const { useMocha = true, useVitest = false } = options;
|
|
47
|
+
export function createTestConfig() {
|
|
54
48
|
return defineConfig(
|
|
55
|
-
|
|
56
|
-
useVitest ? vitestPlugin.configs.recommended : {},
|
|
49
|
+
vitestPlugin.configs.recommended,
|
|
57
50
|
testingLibrary.configs['flat/dom'],
|
|
58
51
|
testingLibrary.configs['flat/react'],
|
|
59
52
|
{
|
|
@@ -63,7 +56,6 @@ export function createTestConfig(options = {}) {
|
|
|
63
56
|
parserOptions: {
|
|
64
57
|
ecmaVersion: 7,
|
|
65
58
|
},
|
|
66
|
-
globals: globals.mocha,
|
|
67
59
|
},
|
|
68
60
|
rules: {
|
|
69
61
|
'compat/compat': 'off',
|
|
@@ -99,27 +91,7 @@ export function createTestConfig(options = {}) {
|
|
|
99
91
|
'testing-library/no-node-access': 'off',
|
|
100
92
|
'@typescript-eslint/no-non-null-asserted-optional-chain': 'off',
|
|
101
93
|
// end migration
|
|
102
|
-
|
|
103
|
-
? {
|
|
104
|
-
'mocha/consistent-spacing-between-blocks': 'off',
|
|
105
|
-
|
|
106
|
-
// upgraded level from recommended
|
|
107
|
-
'mocha/no-pending-tests': 'error',
|
|
108
|
-
|
|
109
|
-
// no rationale provided in /recommended
|
|
110
|
-
'mocha/no-mocha-arrows': 'off',
|
|
111
|
-
// definitely a useful rule but too many false positives
|
|
112
|
-
// due to `describeConformance`
|
|
113
|
-
// "If you're using dynamically generated tests, you should disable this rule.""
|
|
114
|
-
'mocha/no-setup-in-describe': 'off',
|
|
115
|
-
// `beforeEach` for a single case is optimized for change
|
|
116
|
-
// when we add a test we don't have to refactor the existing
|
|
117
|
-
// test to `beforeEach`.
|
|
118
|
-
// `beforeEach`+`afterEach` also means that the `beforeEach`
|
|
119
|
-
// is cleaned up in `afterEach` if the test causes a crash
|
|
120
|
-
'mocha/no-hooks-for-single-case': 'off',
|
|
121
|
-
}
|
|
122
|
-
: {}),
|
|
94
|
+
'vitest/prefer-importing-vitest-globals': 'error',
|
|
123
95
|
},
|
|
124
96
|
},
|
|
125
97
|
);
|