@mui/internal-code-infra 0.0.4-canary.6 ā 0.0.4-canary.60
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/LICENSE +1 -1
- package/README.md +19 -8
- package/build/babel-config.d.mts +11 -3
- package/build/brokenLinksChecker/crawlWorker.d.mts +1 -0
- package/build/brokenLinksChecker/index.d.mts +45 -2
- package/build/changelog/types.d.ts +1 -1
- package/build/cli/cmdArgosPush.d.mts +2 -2
- package/build/cli/cmdBuild.d.mts +3 -2
- package/build/cli/cmdCopyFiles.d.mts +2 -2
- package/build/cli/cmdExtractErrorCodes.d.mts +2 -2
- package/build/cli/cmdGenerateChangelog.d.mts +2 -2
- package/build/cli/cmdGithubAuth.d.mts +2 -2
- package/build/cli/cmdListWorkspaces.d.mts +6 -4
- package/build/cli/cmdNetlifyIgnore.d.mts +3 -2
- package/build/cli/cmdPublish.d.mts +4 -2
- package/build/cli/cmdPublishCanary.d.mts +3 -3
- package/build/cli/cmdPublishNewPackage.d.mts +4 -2
- package/build/cli/cmdSetVersionOverrides.d.mts +2 -2
- package/build/cli/cmdVale.d.mts +46 -0
- package/build/cli/cmdValidateBuiltTypes.d.mts +2 -2
- package/build/eslint/baseConfig.d.mts +3 -1
- package/build/eslint/mui/rules/disallow-react-api-in-server-components.d.mts +2 -2
- package/build/eslint/mui/rules/docgen-ignore-before-comment.d.mts +2 -2
- package/build/eslint/mui/rules/no-guarded-throw.d.mts +31 -0
- package/build/eslint/mui/rules/no-presentation-role.d.mts +5 -0
- package/build/eslint/mui/rules/no-restricted-resolved-imports.d.mts +2 -2
- package/build/eslint/mui/rules/nodeEnvUtils.d.mts +18 -0
- package/build/markdownlint/duplicate-h1.d.mts +1 -1
- package/build/markdownlint/git-diff.d.mts +1 -1
- package/build/markdownlint/index.d.mts +1 -1
- package/build/markdownlint/straight-quotes.d.mts +1 -1
- package/build/markdownlint/table-alignment.d.mts +1 -1
- package/build/markdownlint/terminal-language.d.mts +1 -1
- package/build/remark/config.d.mts +43 -0
- package/build/remark/createLintTester.d.mts +10 -0
- package/build/remark/firstBlockHeading.d.mts +4 -0
- package/build/remark/gitDiff.d.mts +2 -0
- package/build/remark/noSpaceInLinks.d.mts +2 -0
- package/build/remark/straightQuotes.d.mts +2 -0
- package/build/remark/tableAlignment.d.mts +2 -0
- package/build/remark/terminalLanguage.d.mts +2 -0
- package/build/utils/babel.d.mts +1 -1
- package/build/utils/build.d.mts +61 -25
- package/build/utils/github.d.mts +1 -1
- package/build/utils/pnpm.d.mts +68 -2
- package/build/utils/testUtils.d.mts +7 -0
- package/build/utils/typescript.d.mts +2 -2
- package/package.json +61 -34
- package/src/babel-config.mjs +9 -3
- package/src/brokenLinksChecker/__fixtures__/static-site/index.html +1 -0
- package/src/brokenLinksChecker/__fixtures__/static-site/invalid-html.html +15 -0
- package/src/brokenLinksChecker/crawlWorker.mjs +217 -0
- package/src/brokenLinksChecker/index.mjs +217 -164
- package/src/brokenLinksChecker/index.test.ts +50 -13
- package/src/changelog/categorizeCommits.test.ts +5 -5
- package/src/changelog/fetchChangelogs.mjs +6 -2
- package/src/changelog/parseCommitLabels.test.ts +5 -5
- package/src/changelog/renderChangelog.mjs +1 -1
- package/src/changelog/types.ts +1 -1
- package/src/cli/cmdBuild.mjs +39 -16
- package/src/cli/cmdListWorkspaces.mjs +12 -27
- package/src/cli/cmdNetlifyIgnore.mjs +34 -93
- package/src/cli/cmdPublish.mjs +55 -15
- package/src/cli/cmdPublishCanary.mjs +128 -132
- package/src/cli/cmdPublishNewPackage.mjs +27 -6
- package/src/cli/cmdVale.mjs +513 -0
- package/src/cli/cmdVale.test.mjs +644 -0
- package/src/cli/index.mjs +2 -0
- package/src/cli/packageJson.d.ts +1 -1
- package/src/eslint/baseConfig.mjs +45 -20
- package/src/eslint/docsConfig.mjs +4 -2
- package/src/eslint/jsonConfig.mjs +2 -1
- package/src/eslint/mui/config.mjs +24 -4
- package/src/eslint/mui/index.mjs +4 -0
- package/src/eslint/mui/rules/no-guarded-throw.mjs +115 -0
- package/src/eslint/mui/rules/no-guarded-throw.test.mjs +206 -0
- package/src/eslint/mui/rules/no-presentation-role.mjs +60 -0
- package/src/eslint/mui/rules/no-presentation-role.test.mjs +33 -0
- package/src/eslint/mui/rules/nodeEnvUtils.mjs +52 -0
- package/src/eslint/mui/rules/require-dev-wrapper.mjs +25 -40
- package/src/eslint/testConfig.mjs +2 -1
- package/src/estree-typescript.d.ts +1 -1
- package/src/remark/config.mjs +157 -0
- package/src/remark/createLintTester.mjs +19 -0
- package/src/remark/firstBlockHeading.mjs +87 -0
- package/src/remark/firstBlockHeading.test.mjs +107 -0
- package/src/remark/gitDiff.mjs +43 -0
- package/src/remark/gitDiff.test.mjs +45 -0
- package/src/remark/noSpaceInLinks.mjs +42 -0
- package/src/remark/noSpaceInLinks.test.mjs +22 -0
- package/src/remark/straightQuotes.mjs +31 -0
- package/src/remark/straightQuotes.test.mjs +25 -0
- package/src/remark/tableAlignment.mjs +23 -0
- package/src/remark/tableAlignment.test.mjs +28 -0
- package/src/remark/terminalLanguage.mjs +19 -0
- package/src/remark/terminalLanguage.test.mjs +17 -0
- package/src/untyped-plugins.d.ts +11 -11
- package/src/utils/build.mjs +621 -256
- package/src/utils/build.test.mjs +1064 -485
- package/src/utils/git.mjs +16 -7
- package/src/utils/pnpm.mjs +192 -3
- package/src/utils/pnpm.test.mjs +580 -0
- package/src/utils/testUtils.mjs +18 -0
- package/src/utils/typescript.test.mjs +249 -272
- package/vale/.vale.ini +1 -0
- package/vale/styles/MUI/CorrectReferenceAllCases.yml +43 -0
- package/vale/styles/MUI/CorrectRererenceCased.yml +14 -0
- package/vale/styles/MUI/GoogleLatin.yml +11 -0
- package/vale/styles/MUI/MuiBrandName.yml +22 -0
- package/vale/styles/MUI/NoBritish.yml +112 -0
- package/vale/styles/MUI/NoCompanyName.yml +17 -0
|
@@ -210,11 +210,11 @@ describe('parseCommitLabels', () => {
|
|
|
210
210
|
|
|
211
211
|
describe('category overrides', () => {
|
|
212
212
|
it('should detect category override labels', () => {
|
|
213
|
-
const commit = createCommit({ labels: ['all components'] });
|
|
213
|
+
const commit = createCommit({ labels: ['scope: all components'] });
|
|
214
214
|
const config: LabelConfig = {
|
|
215
215
|
...baseLabelConfig,
|
|
216
216
|
categoryOverrides: {
|
|
217
|
-
'all components': 'General changes',
|
|
217
|
+
'scope: all components': 'General changes',
|
|
218
218
|
},
|
|
219
219
|
};
|
|
220
220
|
|
|
@@ -224,11 +224,11 @@ describe('parseCommitLabels', () => {
|
|
|
224
224
|
});
|
|
225
225
|
|
|
226
226
|
it('should use the last category override when multiple are present', () => {
|
|
227
|
-
const commit = createCommit({ labels: ['all components', 'docs'] });
|
|
227
|
+
const commit = createCommit({ labels: ['scope: all components', 'docs'] });
|
|
228
228
|
const config: LabelConfig = {
|
|
229
229
|
...baseLabelConfig,
|
|
230
230
|
categoryOverrides: {
|
|
231
|
-
'all components': 'General changes',
|
|
231
|
+
'scope: all components': 'General changes',
|
|
232
232
|
docs: 'Documentation',
|
|
233
233
|
},
|
|
234
234
|
};
|
|
@@ -243,7 +243,7 @@ describe('parseCommitLabels', () => {
|
|
|
243
243
|
const config: LabelConfig = {
|
|
244
244
|
...baseLabelConfig,
|
|
245
245
|
categoryOverrides: {
|
|
246
|
-
'all components': 'General changes',
|
|
246
|
+
'scope: all components': 'General changes',
|
|
247
247
|
},
|
|
248
248
|
};
|
|
249
249
|
|
|
@@ -438,7 +438,7 @@ function renderContributors(contributors, config, lines) {
|
|
|
438
438
|
const template = getTemplateString(
|
|
439
439
|
config.contributors?.message?.contributors,
|
|
440
440
|
allContributors.length,
|
|
441
|
-
`${allContributors.length !== 1 ? 'All contributors of this release in alphabetical order' : 'Contributor of this release'}
|
|
441
|
+
`${allContributors.length !== 1 ? 'All contributors of this release in alphabetical order' : 'Contributor of this release'}: {{contributors}}`,
|
|
442
442
|
);
|
|
443
443
|
const contributorsMessage = templateString(template, {
|
|
444
444
|
contributors: renderContributorsList(allContributors),
|
package/src/changelog/types.ts
CHANGED
|
@@ -233,7 +233,7 @@ export interface IntroConfig {
|
|
|
233
233
|
* - {{teamCount}}: Number of team members
|
|
234
234
|
* - {{communityCount}}: Number of community contributors
|
|
235
235
|
*
|
|
236
|
-
* Example: "
|
|
236
|
+
* Example: "A big thanks to the {{contributorCount}} contributors who made this release possible."
|
|
237
237
|
*
|
|
238
238
|
* Set to `false` or omit to disable the thank you message.
|
|
239
239
|
*/
|
package/src/cli/cmdBuild.mjs
CHANGED
|
@@ -10,6 +10,7 @@ import * as semver from 'semver';
|
|
|
10
10
|
import {
|
|
11
11
|
createPackageBin,
|
|
12
12
|
createPackageExports,
|
|
13
|
+
createPackageImports,
|
|
13
14
|
getOutExtension,
|
|
14
15
|
mapConcurrently,
|
|
15
16
|
validatePkgJson,
|
|
@@ -31,6 +32,7 @@ import {
|
|
|
31
32
|
* @property {boolean} [enableReactCompiler] - Whether to use the React compiler.
|
|
32
33
|
* @property {boolean} [tsgo] - Whether to build types using typescript native (tsgo).
|
|
33
34
|
* @property {boolean} [flat] - Builds the package in a flat structure without subdirectories for each module type.
|
|
35
|
+
* @property {boolean} expand - Whether to enumerate glob patterns in exports/imports into concrete entries.
|
|
34
36
|
*/
|
|
35
37
|
|
|
36
38
|
const validBundles = [
|
|
@@ -85,6 +87,7 @@ ${content}`,
|
|
|
85
87
|
* @param {string} param0.cwd
|
|
86
88
|
* @param {boolean} param0.addTypes - Whether to add type declarations for the package.
|
|
87
89
|
* @param {boolean} param0.isFlat - Whether the build is flat structure.
|
|
90
|
+
* @param {boolean} [param0.expand] - Whether to enumerate glob patterns into concrete entries.
|
|
88
91
|
* @param {'module' | 'commonjs'} param0.packageType - The package.json type field.
|
|
89
92
|
*/
|
|
90
93
|
async function writePackageJson({
|
|
@@ -94,36 +97,50 @@ async function writePackageJson({
|
|
|
94
97
|
cwd,
|
|
95
98
|
addTypes = false,
|
|
96
99
|
isFlat = false,
|
|
100
|
+
expand = true,
|
|
97
101
|
packageType,
|
|
98
102
|
}) {
|
|
99
103
|
delete packageJson.scripts;
|
|
100
104
|
delete packageJson.publishConfig?.directory;
|
|
101
105
|
delete packageJson.devDependencies;
|
|
102
|
-
delete packageJson.imports;
|
|
103
106
|
|
|
104
107
|
const resolvedPackageType = packageType || packageJson.type || 'commonjs';
|
|
105
108
|
packageJson.type = resolvedPackageType;
|
|
106
109
|
|
|
107
110
|
const originalExports = packageJson.exports;
|
|
108
111
|
delete packageJson.exports;
|
|
112
|
+
const originalImports = packageJson.imports;
|
|
113
|
+
delete packageJson.imports;
|
|
109
114
|
const originalBin = packageJson.bin;
|
|
110
115
|
delete packageJson.bin;
|
|
111
116
|
|
|
112
|
-
const {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
117
|
+
const [{ exports: packageExports, main, types }, packageImports] = await Promise.all([
|
|
118
|
+
createPackageExports(originalExports, {
|
|
119
|
+
bundles,
|
|
120
|
+
outputDir,
|
|
121
|
+
cwd,
|
|
122
|
+
addTypes,
|
|
123
|
+
isFlat,
|
|
124
|
+
expand,
|
|
125
|
+
packageType: resolvedPackageType,
|
|
126
|
+
}),
|
|
127
|
+
originalImports
|
|
128
|
+
? createPackageImports(originalImports, {
|
|
129
|
+
bundles,
|
|
130
|
+
cwd,
|
|
131
|
+
outputDir,
|
|
132
|
+
addTypes,
|
|
133
|
+
isFlat,
|
|
134
|
+
expand,
|
|
135
|
+
packageType: resolvedPackageType,
|
|
136
|
+
})
|
|
137
|
+
: Promise.resolve(undefined),
|
|
138
|
+
]);
|
|
125
139
|
|
|
126
140
|
packageJson.exports = packageExports;
|
|
141
|
+
if (packageImports) {
|
|
142
|
+
packageJson.imports = packageImports;
|
|
143
|
+
}
|
|
127
144
|
if (main) {
|
|
128
145
|
packageJson.main = main;
|
|
129
146
|
}
|
|
@@ -131,8 +148,7 @@ async function writePackageJson({
|
|
|
131
148
|
packageJson.types = types;
|
|
132
149
|
}
|
|
133
150
|
|
|
134
|
-
const bin = await createPackageBin({
|
|
135
|
-
bin: originalBin,
|
|
151
|
+
const bin = await createPackageBin(originalBin, {
|
|
136
152
|
bundles,
|
|
137
153
|
cwd,
|
|
138
154
|
isFlat,
|
|
@@ -228,6 +244,12 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
|
228
244
|
default: process.env.MUI_BUILD_FLAT === '1',
|
|
229
245
|
description:
|
|
230
246
|
'Builds the package in a flat structure without subdirectories for each module type.',
|
|
247
|
+
})
|
|
248
|
+
.option('expand', {
|
|
249
|
+
type: 'boolean',
|
|
250
|
+
default: true,
|
|
251
|
+
description:
|
|
252
|
+
'Enumerate glob patterns in the package.json "exports"/"imports" into concrete entries. Use --no-expand to keep them as Node runtime subpath patterns.',
|
|
231
253
|
});
|
|
232
254
|
},
|
|
233
255
|
async handler(args) {
|
|
@@ -416,6 +438,7 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
|
416
438
|
outputDir: buildDir,
|
|
417
439
|
addTypes: buildTypes,
|
|
418
440
|
isFlat: !!args.flat,
|
|
441
|
+
expand: args.expand,
|
|
419
442
|
packageType,
|
|
420
443
|
});
|
|
421
444
|
|
|
@@ -6,15 +6,14 @@
|
|
|
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
|
|
16
|
+
* @property {string[]} [filter] - Same as filtering packages with --filter in pnpm. Only include packages matching the filter. See https://pnpm.io/filtering.
|
|
18
17
|
*/
|
|
19
18
|
|
|
20
19
|
export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
@@ -29,21 +28,27 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
|
29
28
|
})
|
|
30
29
|
.option('output', {
|
|
31
30
|
type: 'string',
|
|
32
|
-
choices: ['json', 'path', 'name'
|
|
31
|
+
choices: ['json', 'path', 'name'],
|
|
33
32
|
default: 'path',
|
|
34
33
|
description:
|
|
35
|
-
'Output format: name (package names), path (package paths),
|
|
34
|
+
'Output format: name (package names), path (package paths), or json (full JSON)',
|
|
36
35
|
})
|
|
37
36
|
.option('since-ref', {
|
|
38
37
|
type: 'string',
|
|
39
38
|
description: 'Filter packages changed since git reference',
|
|
39
|
+
})
|
|
40
|
+
.option('filter', {
|
|
41
|
+
type: 'string',
|
|
42
|
+
array: true,
|
|
43
|
+
description:
|
|
44
|
+
'Same as filtering packages with --filter in pnpm. Only include packages matching the filter. See https://pnpm.io/filtering.',
|
|
40
45
|
});
|
|
41
46
|
},
|
|
42
47
|
handler: async (argv) => {
|
|
43
|
-
const { publicOnly = false, output = 'name', sinceRef } = argv;
|
|
48
|
+
const { publicOnly = false, output = 'name', sinceRef, filter = [] } = argv;
|
|
44
49
|
|
|
45
50
|
// Get packages using our helper function
|
|
46
|
-
const packages = await getWorkspacePackages({ sinceRef, publicOnly });
|
|
51
|
+
const packages = await getWorkspacePackages({ sinceRef, publicOnly, filter });
|
|
47
52
|
|
|
48
53
|
if (output === 'json') {
|
|
49
54
|
// Serialize packages to JSON
|
|
@@ -53,26 +58,6 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
|
53
58
|
packages.forEach((pkg) => {
|
|
54
59
|
console.log(pkg.path);
|
|
55
60
|
});
|
|
56
|
-
} else if (output === 'publish-dir') {
|
|
57
|
-
// TODO: Remove this option once https://github.com/stackblitz-labs/pkg.pr.new/issues/389 is resolved
|
|
58
|
-
// Print publish directories (package.json publishConfig.directory or package path)
|
|
59
|
-
const publishDirs = await Promise.all(
|
|
60
|
-
packages.map(async (pkg) => {
|
|
61
|
-
const packageJsonPath = path.join(pkg.path, 'package.json');
|
|
62
|
-
const packageJsonContent = await fs.readFile(packageJsonPath, 'utf8');
|
|
63
|
-
const packageJson = JSON.parse(packageJsonContent);
|
|
64
|
-
|
|
65
|
-
if (packageJson.publishConfig?.directory) {
|
|
66
|
-
return path.join(pkg.path, packageJson.publishConfig.directory);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return pkg.path;
|
|
70
|
-
}),
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
publishDirs.forEach((dir) => {
|
|
74
|
-
console.log(dir);
|
|
75
|
-
});
|
|
76
61
|
} else if (output === 'name') {
|
|
77
62
|
// Print package names (default)
|
|
78
63
|
packages.forEach((pkg) => {
|
|
@@ -6,111 +6,39 @@
|
|
|
6
6
|
* @typedef {Object} Args
|
|
7
7
|
* @property {string[]} workspaces - List of workspace names to process
|
|
8
8
|
* @property {boolean} [check] - Check mode - error if the generated content differs from current
|
|
9
|
+
* @property {string} [baseBranch] - Branch to compare PRs against (default: master)
|
|
9
10
|
*/
|
|
10
11
|
|
|
11
12
|
import * as fs from 'node:fs/promises';
|
|
12
13
|
import * as path from 'node:path';
|
|
13
14
|
import { findWorkspaceDir } from '@pnpm/find-workspace-dir';
|
|
14
15
|
import { toPosixPath } from '../utils/path.mjs';
|
|
15
|
-
import { getWorkspacePackages } from '../utils/pnpm.mjs';
|
|
16
|
+
import { getTransitiveDependencies, getWorkspacePackages } from '../utils/pnpm.mjs';
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
// Create the resolution promise
|
|
32
|
-
const promise = (async () => {
|
|
33
|
-
const packagePath = workspaceMap.get(packageName);
|
|
34
|
-
if (!packagePath) {
|
|
35
|
-
throw new Error(`Workspace "${packageName}" not found in the repository`);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const packageJsonPath = path.join(packagePath, 'package.json');
|
|
39
|
-
const content = await fs.readFile(packageJsonPath, 'utf8');
|
|
40
|
-
const packageJson = JSON.parse(content);
|
|
41
|
-
|
|
42
|
-
// Collect all dependency names
|
|
43
|
-
/** @type {Set<string>} */
|
|
44
|
-
const allDeps = new Set();
|
|
45
|
-
if (packageJson.dependencies) {
|
|
46
|
-
Object.keys(packageJson.dependencies).forEach((dep) => allDeps.add(dep));
|
|
47
|
-
}
|
|
48
|
-
if (packageJson.devDependencies) {
|
|
49
|
-
Object.keys(packageJson.devDependencies).forEach((dep) => allDeps.add(dep));
|
|
50
|
-
}
|
|
51
|
-
if (packageJson.peerDependencies) {
|
|
52
|
-
Object.keys(packageJson.peerDependencies).forEach((dep) => allDeps.add(dep));
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Filter to only workspace dependencies
|
|
56
|
-
const workspaceDeps = Array.from(allDeps).filter((dep) => workspaceMap.has(dep));
|
|
57
|
-
|
|
58
|
-
// Recursively process workspace dependencies in parallel
|
|
59
|
-
const recursiveResults = await Promise.all(
|
|
60
|
-
workspaceDeps.map(async (dep) => {
|
|
61
|
-
return getWorkspaceDependenciesRecursive(dep, workspaceMap, cache);
|
|
62
|
-
}),
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
// Merge all results using flatMap
|
|
66
|
-
return new Set(recursiveResults.flatMap((result) => Array.from(result)).concat(workspaceDeps));
|
|
67
|
-
})();
|
|
68
|
-
|
|
69
|
-
// Store in cache before returning
|
|
70
|
-
cache.set(packageName, promise);
|
|
71
|
-
|
|
72
|
-
return promise;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Get transitive workspace dependencies for a list of workspace names
|
|
77
|
-
* @param {string[]} workspaceNames - Array of workspace names
|
|
78
|
-
* @param {Map<string, string>} workspaceMap - Map of workspace name to path
|
|
79
|
-
* @returns {Promise<Set<string>>} Set of workspace package names (including requested packages and all their dependencies)
|
|
80
|
-
*/
|
|
81
|
-
async function getTransitiveDependencies(workspaceNames, workspaceMap) {
|
|
82
|
-
// Shared cache for all workspace dependency resolution
|
|
83
|
-
const cache = new Map();
|
|
84
|
-
|
|
85
|
-
// Validate all workspace names exist
|
|
86
|
-
for (const workspaceName of workspaceNames) {
|
|
87
|
-
if (!workspaceMap.has(workspaceName)) {
|
|
88
|
-
throw new Error(`Workspace "${workspaceName}" not found in the repository`);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Process each requested workspace in parallel
|
|
93
|
-
const workspaceResults = await Promise.all(
|
|
94
|
-
workspaceNames.map((workspaceName) =>
|
|
95
|
-
getWorkspaceDependenciesRecursive(workspaceName, workspaceMap, cache),
|
|
96
|
-
),
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
// Merge all results using flatMap and add the original package names
|
|
100
|
-
return new Set(workspaceNames.concat(workspaceResults.flatMap((result) => Array.from(result))));
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Generate the ignore command string for netlify.toml
|
|
19
|
+
* Generate the ignore command string for netlify.toml.
|
|
20
|
+
*
|
|
21
|
+
* Production and branch deploys (every Netlify $CONTEXT other than
|
|
22
|
+
* "deploy-preview") always build, so downstream plugins (e.g. e2e triggers)
|
|
23
|
+
* run on every deploy and catch regressions in external dependencies even
|
|
24
|
+
* when the commit doesn't touch the watched paths.
|
|
25
|
+
*
|
|
26
|
+
* Only deploy-previews (PR previews) are eligible to be skipped: they diff
|
|
27
|
+
* against the merge-base with origin/<baseBranch>. This way a PR rebase whose
|
|
28
|
+
* head commit doesn't touch the watched paths still rebuilds when the PR as a
|
|
29
|
+
* whole introduces changes to them ā otherwise downstream plugins silently
|
|
30
|
+
* never run.
|
|
31
|
+
*
|
|
105
32
|
* @param {string[]} paths - Array of paths to include in the ignore command
|
|
106
33
|
* @param {string} packagePath - Absolute path to the package directory
|
|
107
34
|
* @param {string} workspaceRoot - Absolute path to the workspace root
|
|
35
|
+
* @param {string} baseBranch - Branch to compare PRs against
|
|
108
36
|
* @returns {string} The ignore command string
|
|
109
37
|
*/
|
|
110
|
-
function generateIgnoreCommand(paths, packagePath, workspaceRoot) {
|
|
38
|
+
function generateIgnoreCommand(paths, packagePath, workspaceRoot, baseBranch) {
|
|
111
39
|
const relFromBase = `${toPosixPath(path.relative(packagePath, workspaceRoot))}/`;
|
|
112
40
|
const pathsStr = paths.join(' ');
|
|
113
|
-
return ` ignore = "cd ${relFromBase} && git diff --quiet
|
|
41
|
+
return ` ignore = """cd ${relFromBase} && [ "$CONTEXT" = "deploy-preview" ] && git fetch origin ${baseBranch} --depth=500 -q && git diff --quiet FETCH_HEAD...$COMMIT_REF -- ${pathsStr}"""`;
|
|
114
42
|
}
|
|
115
43
|
|
|
116
44
|
/**
|
|
@@ -180,6 +108,12 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
|
180
108
|
default: false,
|
|
181
109
|
describe: 'Check if the netlify.toml needs updating without modifying it',
|
|
182
110
|
})
|
|
111
|
+
.option('base-branch', {
|
|
112
|
+
type: 'string',
|
|
113
|
+
default: 'master',
|
|
114
|
+
describe:
|
|
115
|
+
"Branch to compare PRs against (the site's production branch on Netlify). Production and branch deploys always rebuild regardless of this value.",
|
|
116
|
+
})
|
|
183
117
|
.example('$0 netlify-ignore @mui/internal-docs-infra', 'Update netlify.toml for a workspace')
|
|
184
118
|
.example(
|
|
185
119
|
'$0 netlify-ignore @mui/internal-docs-infra @mui/internal-code-infra',
|
|
@@ -191,7 +125,7 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
|
191
125
|
);
|
|
192
126
|
},
|
|
193
127
|
handler: async (argv) => {
|
|
194
|
-
const { workspaces, check = false } = argv;
|
|
128
|
+
const { workspaces, check = false, baseBranch = 'master' } = argv;
|
|
195
129
|
|
|
196
130
|
// Get the workspace root
|
|
197
131
|
const workspaceRoot = await findWorkspaceDir(process.cwd());
|
|
@@ -220,7 +154,9 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
|
220
154
|
console.log(`Processing ${workspaceName}...`);
|
|
221
155
|
|
|
222
156
|
// Get transitive dependencies for this specific workspace
|
|
223
|
-
const dependencyNames = await getTransitiveDependencies([workspaceName],
|
|
157
|
+
const dependencyNames = await getTransitiveDependencies([workspaceName], {
|
|
158
|
+
workspacePathByName: workspaceMap,
|
|
159
|
+
});
|
|
224
160
|
|
|
225
161
|
// Convert package names to relative paths (normalize to POSIX separators for git)
|
|
226
162
|
const relativePaths = Array.from(dependencyNames)
|
|
@@ -241,7 +177,12 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
|
241
177
|
const allPaths = [...relativePaths, 'pnpm-lock.yaml'];
|
|
242
178
|
|
|
243
179
|
// Generate the ignore command for this workspace
|
|
244
|
-
const newIgnoreCommand = generateIgnoreCommand(
|
|
180
|
+
const newIgnoreCommand = generateIgnoreCommand(
|
|
181
|
+
allPaths,
|
|
182
|
+
workspacePath,
|
|
183
|
+
workspaceRoot,
|
|
184
|
+
baseBranch,
|
|
185
|
+
);
|
|
245
186
|
|
|
246
187
|
// Update or check the netlify.toml file
|
|
247
188
|
await updateNetlifyToml(tomlPath, newIgnoreCommand, check);
|
package/src/cli/cmdPublish.mjs
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
/**
|
|
6
6
|
* @typedef {import('../utils/pnpm.mjs').PublicPackage} PublicPackage
|
|
7
7
|
* @typedef {import('../utils/pnpm.mjs').PublishOptions} PublishOptions
|
|
8
|
+
* @typedef {import('../utils/pnpm.mjs').PublishSummaryEntry} PublishSummaryEntry
|
|
8
9
|
*/
|
|
9
10
|
|
|
10
11
|
import select from '@inquirer/select';
|
|
@@ -17,7 +18,11 @@ import * as fs from 'node:fs/promises';
|
|
|
17
18
|
import * as semver from 'semver';
|
|
18
19
|
|
|
19
20
|
import { persistentAuthStrategy } from '../utils/github.mjs';
|
|
20
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
getWorkspacePackages,
|
|
23
|
+
publishPackages,
|
|
24
|
+
validatePublishDependencies,
|
|
25
|
+
} from '../utils/pnpm.mjs';
|
|
21
26
|
import { getCurrentGitSha, getRepositoryInfo } from '../utils/git.mjs';
|
|
22
27
|
|
|
23
28
|
const isCI = envCI().isCi;
|
|
@@ -33,6 +38,7 @@ function getOctokit() {
|
|
|
33
38
|
* @property {string} tag NPM dist tag to publish to
|
|
34
39
|
* @property {boolean} ci Runs in CI environment
|
|
35
40
|
* @property {string} [sha] Git SHA to use for the GitHub release workflow (local only)
|
|
41
|
+
* @property {string[]} [filter] Same as filtering packages with --filter in pnpm. Only publish packages matching the filter. See https://pnpm.io/filtering.
|
|
36
42
|
*/
|
|
37
43
|
|
|
38
44
|
/**
|
|
@@ -40,7 +46,10 @@ function getOctokit() {
|
|
|
40
46
|
* @returns {Promise<string | null>} Version string
|
|
41
47
|
*/
|
|
42
48
|
async function getReleaseVersion() {
|
|
43
|
-
|
|
49
|
+
// `--json` is required: pnpm 11 returns the raw value (e.g. `9.4.0`) for a
|
|
50
|
+
// single field without it, which is not valid JSON. The flag forces quoted
|
|
51
|
+
// output (`"9.4.0"`) across pnpm 9/10/11.
|
|
52
|
+
const result = await $`pnpm pkg get version --json`;
|
|
44
53
|
const version = JSON.parse(result.stdout.trim());
|
|
45
54
|
return semver.valid(version);
|
|
46
55
|
}
|
|
@@ -189,18 +198,11 @@ async function validateGitHubRelease(version) {
|
|
|
189
198
|
* Publish packages to npm
|
|
190
199
|
* @param {PublicPackage[]} packages - Packages to publish
|
|
191
200
|
* @param {PublishOptions} options - Publishing options
|
|
192
|
-
* @returns {Promise<
|
|
201
|
+
* @returns {Promise<PublishSummaryEntry[]>}
|
|
193
202
|
*/
|
|
194
203
|
async function publishToNpm(packages, options) {
|
|
195
|
-
console.log('\nš¦ Publishing packages to npm...');
|
|
196
|
-
console.log(`š Found ${packages.length} packages:`);
|
|
197
|
-
packages.forEach((pkg) => {
|
|
198
|
-
console.log(` ⢠${pkg.name}@${pkg.version}`);
|
|
199
|
-
});
|
|
200
|
-
|
|
201
204
|
// Use pnpm's built-in duplicate checking - no need to check versions ourselves
|
|
202
|
-
|
|
203
|
-
console.log('ā
Successfully published to npm');
|
|
205
|
+
return publishPackages(packages, options);
|
|
204
206
|
}
|
|
205
207
|
|
|
206
208
|
/**
|
|
@@ -260,10 +262,16 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
|
260
262
|
.option('sha', {
|
|
261
263
|
type: 'string',
|
|
262
264
|
description: 'Git SHA to use for the GitHub release workflow (local only)',
|
|
265
|
+
})
|
|
266
|
+
.option('filter', {
|
|
267
|
+
type: 'string',
|
|
268
|
+
array: true,
|
|
269
|
+
description:
|
|
270
|
+
'Same as filtering packages with --filter in pnpm. Only publish packages matching the filter. See https://pnpm.io/filtering.',
|
|
263
271
|
});
|
|
264
272
|
},
|
|
265
273
|
handler: async (argv) => {
|
|
266
|
-
const { dryRun = false, githubRelease = false, tag = 'latest', sha } = argv;
|
|
274
|
+
const { dryRun = false, githubRelease = false, tag = 'latest', sha, filter = [] } = argv;
|
|
267
275
|
|
|
268
276
|
if (isCI && !argv.ci) {
|
|
269
277
|
console.error(
|
|
@@ -290,13 +298,34 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
|
290
298
|
// Get all packages
|
|
291
299
|
console.log('š Discovering all workspace packages...');
|
|
292
300
|
|
|
293
|
-
const allPackages = await getWorkspacePackages({ publicOnly: true });
|
|
301
|
+
const allPackages = await getWorkspacePackages({ publicOnly: true, filter });
|
|
294
302
|
|
|
295
303
|
if (allPackages.length === 0) {
|
|
296
|
-
console.log(
|
|
304
|
+
console.log(
|
|
305
|
+
`ā ļø No publishable packages found in workspace${filter.length > 0 ? ` matching filter "${filter.join(', ')}"` : ''}`,
|
|
306
|
+
);
|
|
297
307
|
return;
|
|
298
308
|
}
|
|
299
309
|
|
|
310
|
+
if (filter.length > 0) {
|
|
311
|
+
console.log('š Validating workspace dependencies for filtered packages...');
|
|
312
|
+
|
|
313
|
+
const { issues } = await validatePublishDependencies(allPackages);
|
|
314
|
+
|
|
315
|
+
if (issues.length > 0) {
|
|
316
|
+
throw new Error(
|
|
317
|
+
`Invalid dependencies structure of packages to be published -
|
|
318
|
+
${issues.join('\n ')}
|
|
319
|
+
`,
|
|
320
|
+
{
|
|
321
|
+
cause: issues,
|
|
322
|
+
},
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
console.log('ā
All workspace dependency requirements satisfied');
|
|
327
|
+
}
|
|
328
|
+
|
|
300
329
|
// Get version from root package.json
|
|
301
330
|
const version = await getReleaseVersion();
|
|
302
331
|
|
|
@@ -323,7 +352,18 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
|
|
|
323
352
|
|
|
324
353
|
// Publish to npm (pnpm handles duplicate checking automatically)
|
|
325
354
|
// No git checks, we'll do our own
|
|
326
|
-
|
|
355
|
+
console.log('\nš¦ Publishing packages to npm...');
|
|
356
|
+
const publishedPackages = await publishToNpm(allPackages, { dryRun, noGitChecks: true, tag });
|
|
357
|
+
|
|
358
|
+
if (publishedPackages.length === 0) {
|
|
359
|
+
console.log('ā¹ļø No packages were published (all may already be up to date on npm)');
|
|
360
|
+
console.log('\nš Nothing to publish, skipping git tag and GitHub release.');
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
publishedPackages.forEach((pkg) => {
|
|
365
|
+
console.log(`ā
Published ${pkg.name}@${pkg.version}`);
|
|
366
|
+
});
|
|
327
367
|
|
|
328
368
|
await createGitTag(version, dryRun);
|
|
329
369
|
|