@mui/internal-code-infra 0.0.4-canary.7 → 0.0.4-canary.71

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.
Files changed (120) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +19 -8
  3. package/build/babel-config.d.mts +11 -3
  4. package/build/brokenLinksChecker/crawlWorker.d.mts +1 -0
  5. package/build/brokenLinksChecker/index.d.mts +45 -2
  6. package/build/changelog/types.d.ts +1 -1
  7. package/build/cli/cmdArgosPush.d.mts +2 -2
  8. package/build/cli/cmdBuild.d.mts +3 -2
  9. package/build/cli/cmdCopyFiles.d.mts +2 -2
  10. package/build/cli/cmdExtractErrorCodes.d.mts +2 -2
  11. package/build/cli/cmdGenerateChangelog.d.mts +2 -2
  12. package/build/cli/cmdGithubAuth.d.mts +2 -2
  13. package/build/cli/cmdListWorkspaces.d.mts +6 -4
  14. package/build/cli/cmdNetlifyIgnore.d.mts +3 -2
  15. package/build/cli/cmdPublish.d.mts +4 -2
  16. package/build/cli/cmdPublishCanary.d.mts +3 -3
  17. package/build/cli/cmdPublishNewPackage.d.mts +4 -2
  18. package/build/cli/cmdSetVersionOverrides.d.mts +2 -2
  19. package/build/cli/cmdVale.d.mts +46 -0
  20. package/build/cli/cmdValidateBuiltTypes.d.mts +2 -2
  21. package/build/eslint/baseConfig.d.mts +3 -1
  22. package/build/eslint/mui/rules/disallow-react-api-in-server-components.d.mts +2 -2
  23. package/build/eslint/mui/rules/docgen-ignore-before-comment.d.mts +2 -2
  24. package/build/eslint/mui/rules/no-floating-cleanup.d.mts +5 -0
  25. package/build/eslint/mui/rules/no-guarded-throw.d.mts +31 -0
  26. package/build/eslint/mui/rules/no-presentation-role.d.mts +5 -0
  27. package/build/eslint/mui/rules/no-restricted-resolved-imports.d.mts +2 -2
  28. package/build/eslint/mui/rules/nodeEnvUtils.d.mts +18 -0
  29. package/build/remark/config.d.mts +43 -0
  30. package/build/remark/createLintTester.d.mts +10 -0
  31. package/build/remark/firstBlockHeading.d.mts +4 -0
  32. package/build/remark/gitDiff.d.mts +2 -0
  33. package/build/remark/noSpaceInLinks.d.mts +2 -0
  34. package/build/remark/straightQuotes.d.mts +2 -0
  35. package/build/remark/tableAlignment.d.mts +2 -0
  36. package/build/remark/terminalLanguage.d.mts +2 -0
  37. package/build/utils/babel.d.mts +1 -1
  38. package/build/utils/build.d.mts +56 -37
  39. package/build/utils/github.d.mts +1 -1
  40. package/build/utils/pnpm.d.mts +81 -2
  41. package/build/utils/testUtils.d.mts +7 -0
  42. package/build/utils/typescript.d.mts +6 -16
  43. package/package.json +60 -38
  44. package/src/babel-config.mjs +9 -3
  45. package/src/brokenLinksChecker/__fixtures__/static-site/index.html +1 -0
  46. package/src/brokenLinksChecker/__fixtures__/static-site/invalid-html.html +15 -0
  47. package/src/brokenLinksChecker/crawlWorker.mjs +217 -0
  48. package/src/brokenLinksChecker/index.mjs +263 -188
  49. package/src/brokenLinksChecker/index.test.ts +53 -13
  50. package/src/changelog/categorizeCommits.test.ts +5 -5
  51. package/src/changelog/fetchChangelogs.mjs +6 -2
  52. package/src/changelog/parseCommitLabels.test.ts +5 -5
  53. package/src/changelog/renderChangelog.mjs +1 -1
  54. package/src/changelog/types.ts +1 -1
  55. package/src/cli/cmdBuild.mjs +51 -85
  56. package/src/cli/cmdListWorkspaces.mjs +12 -27
  57. package/src/cli/cmdNetlifyIgnore.mjs +34 -93
  58. package/src/cli/cmdPublish.mjs +55 -15
  59. package/src/cli/cmdPublishCanary.mjs +128 -132
  60. package/src/cli/cmdPublishNewPackage.mjs +27 -6
  61. package/src/cli/cmdSetVersionOverrides.mjs +8 -9
  62. package/src/cli/cmdVale.mjs +513 -0
  63. package/src/cli/cmdVale.test.mjs +644 -0
  64. package/src/cli/index.mjs +2 -0
  65. package/src/cli/packageJson.d.ts +1 -1
  66. package/src/eslint/baseConfig.mjs +51 -19
  67. package/src/eslint/docsConfig.mjs +2 -1
  68. package/src/eslint/mui/config.mjs +24 -4
  69. package/src/eslint/mui/index.mjs +6 -0
  70. package/src/eslint/mui/rules/no-floating-cleanup.mjs +187 -0
  71. package/src/eslint/mui/rules/no-floating-cleanup.test.mjs +141 -0
  72. package/src/eslint/mui/rules/no-guarded-throw.mjs +115 -0
  73. package/src/eslint/mui/rules/no-guarded-throw.test.mjs +206 -0
  74. package/src/eslint/mui/rules/no-presentation-role.mjs +60 -0
  75. package/src/eslint/mui/rules/no-presentation-role.test.mjs +33 -0
  76. package/src/eslint/mui/rules/nodeEnvUtils.mjs +52 -0
  77. package/src/eslint/mui/rules/require-dev-wrapper.mjs +25 -40
  78. package/src/estree-typescript.d.ts +1 -1
  79. package/src/remark/config.mjs +157 -0
  80. package/src/remark/createLintTester.mjs +19 -0
  81. package/src/remark/firstBlockHeading.mjs +87 -0
  82. package/src/remark/firstBlockHeading.test.mjs +107 -0
  83. package/src/remark/gitDiff.mjs +43 -0
  84. package/src/remark/gitDiff.test.mjs +45 -0
  85. package/src/remark/noSpaceInLinks.mjs +42 -0
  86. package/src/remark/noSpaceInLinks.test.mjs +22 -0
  87. package/src/remark/straightQuotes.mjs +31 -0
  88. package/src/remark/straightQuotes.test.mjs +25 -0
  89. package/src/remark/tableAlignment.mjs +23 -0
  90. package/src/remark/tableAlignment.test.mjs +28 -0
  91. package/src/remark/terminalLanguage.mjs +19 -0
  92. package/src/remark/terminalLanguage.test.mjs +17 -0
  93. package/src/untyped-plugins.d.ts +11 -11
  94. package/src/utils/build.mjs +604 -270
  95. package/src/utils/build.test.mjs +1079 -521
  96. package/src/utils/git.mjs +16 -7
  97. package/src/utils/pnpm.mjs +255 -3
  98. package/src/utils/pnpm.test.mjs +731 -0
  99. package/src/utils/testUtils.mjs +18 -0
  100. package/src/utils/typescript.mjs +23 -42
  101. package/src/utils/typescript.test.mjs +234 -273
  102. package/vale/.vale.ini +1 -0
  103. package/vale/styles/MUI/CorrectReferenceAllCases.yml +43 -0
  104. package/vale/styles/MUI/CorrectRererenceCased.yml +14 -0
  105. package/vale/styles/MUI/GoogleLatin.yml +11 -0
  106. package/vale/styles/MUI/MuiBrandName.yml +22 -0
  107. package/vale/styles/MUI/NoBritish.yml +112 -0
  108. package/vale/styles/MUI/NoCompanyName.yml +17 -0
  109. package/build/markdownlint/duplicate-h1.d.mts +0 -56
  110. package/build/markdownlint/git-diff.d.mts +0 -11
  111. package/build/markdownlint/index.d.mts +0 -52
  112. package/build/markdownlint/straight-quotes.d.mts +0 -11
  113. package/build/markdownlint/table-alignment.d.mts +0 -11
  114. package/build/markdownlint/terminal-language.d.mts +0 -11
  115. package/src/markdownlint/duplicate-h1.mjs +0 -69
  116. package/src/markdownlint/git-diff.mjs +0 -31
  117. package/src/markdownlint/index.mjs +0 -62
  118. package/src/markdownlint/straight-quotes.mjs +0 -26
  119. package/src/markdownlint/table-alignment.mjs +0 -42
  120. package/src/markdownlint/terminal-language.mjs +0 -19
@@ -2,12 +2,21 @@ import path from 'node:path';
2
2
  import getPort from 'get-port';
3
3
  import { describe, expect, it } from 'vitest';
4
4
 
5
- // eslint-disable-next-line import/extensions
6
- import { crawl, Issue, Link } from './index.mjs';
7
-
8
- type ExpectedIssue = Omit<Partial<Issue>, 'link'> & { link?: Partial<Link> };
9
-
10
- function objectMatchingIssue(expectedIssue: ExpectedIssue) {
5
+ import {
6
+ crawl,
7
+ // eslint-disable-next-line import/extensions
8
+ } from './index.mjs';
9
+ import type {
10
+ BrokenLinkIssue,
11
+ HtmlValidateIssue,
12
+ Issue,
13
+ Link,
14
+ // eslint-disable-next-line import/extensions
15
+ } from './index.mjs';
16
+
17
+ type ExpectedBrokenLinkIssue = Omit<Partial<BrokenLinkIssue>, 'link'> & { link?: Partial<Link> };
18
+
19
+ function objectMatchingIssue(expectedIssue: ExpectedBrokenLinkIssue) {
11
20
  return expect.objectContaining({
12
21
  ...expectedIssue,
13
22
  ...(expectedIssue.link ? { link: expect.objectContaining(expectedIssue.link) } : {}),
@@ -15,16 +24,16 @@ function objectMatchingIssue(expectedIssue: ExpectedIssue) {
15
24
  }
16
25
 
17
26
  /**
18
- * Helper to assert that an issue with matching properties exists in the issues array
27
+ * Helper to assert that a broken link issue with matching properties exists in the issues array
19
28
  */
20
- function expectIssue(issues: Issue[], expectedIssue: ExpectedIssue) {
29
+ function expectIssue(issues: Issue[], expectedIssue: ExpectedBrokenLinkIssue) {
21
30
  expect(issues).toEqual(expect.arrayContaining([objectMatchingIssue(expectedIssue)]));
22
31
  }
23
32
 
24
33
  /**
25
- * Helper to assert that no issue with matching properties exists in the issues array
34
+ * Helper to assert that no broken link issue with matching properties exists in the issues array
26
35
  */
27
- function expectNotIssue(issues: Issue[], notExpectedIssue: ExpectedIssue) {
36
+ function expectNotIssue(issues: Issue[], notExpectedIssue: ExpectedBrokenLinkIssue) {
28
37
  expect(issues).not.toEqual(expect.arrayContaining([objectMatchingIssue(notExpectedIssue)]));
29
38
  }
30
39
 
@@ -56,12 +65,30 @@ describe('Broken Links Checker', () => {
56
65
  // Test href-only rule (matches from any page) - note: matches the actual href value
57
66
  { href: 'broken-relative.html' },
58
67
  ],
68
+ // Exercise the array form with union semantics: every matching entry
69
+ // contributes to the page's config. The baseline entry (no `path`)
70
+ // turns off `no-dup-id` everywhere; the path-specific entry turns off
71
+ // `no-raw-characters` only on /invalid-html.html. Both rules are
72
+ // silenced on that page because the configs are merged, not replaced.
73
+ //
74
+ // This also guards against the path-specific entry clobbering the
75
+ // baseline: the path entry only names `no-raw-characters`, so it must
76
+ // not re-introduce the recommended ruleset and re-enable the
77
+ // `no-dup-id` that the baseline silenced (which /invalid-html.html
78
+ // violates). If it did, that page would report `no-dup-id` below.
79
+ htmlValidate: [
80
+ { config: { rules: { 'no-dup-id': 'off' } } },
81
+ { path: '/invalid-html.html', config: { rules: { 'no-raw-characters': 'off' } } },
82
+ ],
59
83
  });
60
84
 
61
- expect(result.links).toHaveLength(66);
62
- // Issue count: original 11, minus ignored ones (broken-from-markdown via contentType,
85
+ expect(result.links).toHaveLength(67);
86
+ // Broken link issue count: original 11, minus ignored ones (broken-from-markdown via contentType,
63
87
  // broken-relative via href-only rule)
64
- expect(result.issues).toHaveLength(9);
88
+ const brokenLinkIssues = result.issues.filter(
89
+ (issue) => issue.type === 'broken-link' || issue.type === 'broken-target',
90
+ );
91
+ expect(brokenLinkIssues).toHaveLength(9);
65
92
 
66
93
  // Test ignores: these broken links should be ignored (not in issues)
67
94
  expectNotIssue(result.issues, {
@@ -257,5 +284,18 @@ describe('Broken Links Checker', () => {
257
284
  // Test contentType is stored on pageData
258
285
  expect(result.pages.get('/example.md')?.contentType).toBe('text/markdown');
259
286
  expect(result.pages.get('/')?.contentType).toBe('text/html');
287
+
288
+ // Test htmlValidate union semantics: invalid-html.html has both a duplicate
289
+ // ID (no-dup-id) and a raw `&` (no-raw-characters). The baseline entry
290
+ // silences no-dup-id; the path-specific entry silences no-raw-characters.
291
+ // Under union semantics both apply, so the page reports zero issues — and
292
+ // the path-specific entry must not clobber the baseline's no-dup-id.
293
+ const htmlValidateIssues = result.issues.filter(
294
+ (issue): issue is HtmlValidateIssue => issue.type === 'html-validate',
295
+ );
296
+ const invalidHtmlIssues = htmlValidateIssues.filter(
297
+ (issue) => issue.pageUrl === '/invalid-html.html',
298
+ );
299
+ expect(invalidHtmlIssues).toEqual([]);
260
300
  }, 30000);
261
301
  });
@@ -84,15 +84,15 @@ describe('categorizeCommits', () => {
84
84
  labels: {
85
85
  ...baseLabelConfig,
86
86
  categoryOverrides: {
87
- 'all components': 'General changes',
87
+ 'scope: all components': 'General changes',
88
88
  },
89
89
  },
90
90
  };
91
91
 
92
92
  const commits = [
93
- createCommit(1, ['component: Button', 'all components']),
93
+ createCommit(1, ['component: Button', 'scope: all components']),
94
94
  createCommit(2, ['component: Checkbox']),
95
- createCommit(3, ['component: Button', 'all components']),
95
+ createCommit(3, ['component: Button', 'scope: all components']),
96
96
  ];
97
97
 
98
98
  const result = categorizeCommits(commits, configWithOverrides);
@@ -229,13 +229,13 @@ describe('categorizeCommits', () => {
229
229
  labels: {
230
230
  ...baseLabelConfig,
231
231
  categoryOverrides: {
232
- 'all packages': 'General changes',
232
+ 'scope: all components': 'General changes',
233
233
  },
234
234
  },
235
235
  };
236
236
 
237
237
  const commits = [
238
- createCommit(1, ['scope: data grid', 'all packages']),
238
+ createCommit(1, ['scope: data grid', 'scope: all components']),
239
239
  createCommit(2, ['scope: charts']),
240
240
  ];
241
241
 
@@ -93,8 +93,12 @@ async function fetchCommitsRest({ octokit, repo, lastRelease, release, org = 'mu
93
93
  }
94
94
 
95
95
  const promises = results.map(async (commit) => {
96
- const prMatch = commit.commit.message.match(/#(\d+)/);
97
- if (prMatch === null) {
96
+ const matches = [...commit.commit.message.matchAll(/#(\d+)/g)];
97
+ // The PR number is always the last match.
98
+ // Sometimes the PR titles include an issue number like this:
99
+ // [tag] PR title (#00001) (#00002)
100
+ const prMatch = matches.at(-1);
101
+ if (!prMatch) {
98
102
  return null;
99
103
  }
100
104
 
@@ -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'} : {{contributors}}`,
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),
@@ -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: "We'd like to extend a big thank you to the {{contributorCount}} contributors who made this release possible"
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
  */
@@ -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,
@@ -30,7 +31,8 @@ import {
30
31
  * @property {string[]} [copy] - Files/Directories to be copied. Can be a glob pattern.
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
- * @property {boolean} [flat] - Builds the package in a flat structure without subdirectories for each module type.
34
+ * @property {boolean} [flat] - Deprecated no-op; flat builds are always used.
35
+ * @property {boolean} expand - Whether to enumerate glob patterns in exports/imports into concrete entries.
34
36
  */
35
37
 
36
38
  const validBundles = [
@@ -45,13 +47,12 @@ const validBundles = [
45
47
  * @param {string} options.name - The name of the package.
46
48
  * @param {string} options.version - The version of the package.
47
49
  * @param {string} options.license - The license of the package.
48
- * @param {boolean} options.isFlat - Whether the build is flat structure.
49
50
  * @param {'module' | 'commonjs'} options.packageType - The package.json type field.
50
51
  * @param {import('../utils/build.mjs').BundleType} options.bundle
51
52
  * @param {string} options.outputDir
52
53
  */
53
- async function addLicense({ name, version, license, bundle, outputDir, isFlat, packageType }) {
54
- const outExtension = getOutExtension(bundle, { isFlat, packageType });
54
+ async function addLicense({ name, version, license, bundle, outputDir, packageType }) {
55
+ const outExtension = getOutExtension(bundle, { packageType });
55
56
  const file = path.join(outputDir, `index${outExtension}`);
56
57
  if (
57
58
  !(await fs.stat(file).then(
@@ -80,11 +81,11 @@ ${content}`,
80
81
  /**
81
82
  * @param {Object} param0
82
83
  * @param {import('./packageJson').PackageJson} param0.packageJson - The package.json content.
83
- * @param {{type: import('../utils/build.mjs').BundleType; dir: string}[]} param0.bundles
84
+ * @param {import('../utils/build.mjs').BundleType[]} param0.bundles
84
85
  * @param {string} param0.outputDir
85
86
  * @param {string} param0.cwd
86
87
  * @param {boolean} param0.addTypes - Whether to add type declarations for the package.
87
- * @param {boolean} param0.isFlat - Whether the build is flat structure.
88
+ * @param {boolean} [param0.expand] - Whether to enumerate glob patterns into concrete entries.
88
89
  * @param {'module' | 'commonjs'} param0.packageType - The package.json type field.
89
90
  */
90
91
  async function writePackageJson({
@@ -93,37 +94,48 @@ async function writePackageJson({
93
94
  outputDir,
94
95
  cwd,
95
96
  addTypes = false,
96
- isFlat = false,
97
+ expand = true,
97
98
  packageType,
98
99
  }) {
99
100
  delete packageJson.scripts;
100
101
  delete packageJson.publishConfig?.directory;
101
102
  delete packageJson.devDependencies;
102
- delete packageJson.imports;
103
103
 
104
104
  const resolvedPackageType = packageType || packageJson.type || 'commonjs';
105
105
  packageJson.type = resolvedPackageType;
106
106
 
107
107
  const originalExports = packageJson.exports;
108
108
  delete packageJson.exports;
109
+ const originalImports = packageJson.imports;
110
+ delete packageJson.imports;
109
111
  const originalBin = packageJson.bin;
110
112
  delete packageJson.bin;
111
113
 
112
- const {
113
- exports: packageExports,
114
- main,
115
- types,
116
- } = await createPackageExports({
117
- exports: originalExports,
118
- bundles,
119
- outputDir,
120
- cwd,
121
- addTypes,
122
- isFlat,
123
- packageType: resolvedPackageType,
124
- });
114
+ const [{ exports: packageExports, main, types }, packageImports] = await Promise.all([
115
+ createPackageExports(originalExports, {
116
+ bundles,
117
+ outputDir,
118
+ cwd,
119
+ addTypes,
120
+ expand,
121
+ packageType: resolvedPackageType,
122
+ }),
123
+ originalImports
124
+ ? createPackageImports(originalImports, {
125
+ bundles,
126
+ cwd,
127
+ outputDir,
128
+ addTypes,
129
+ expand,
130
+ packageType: resolvedPackageType,
131
+ })
132
+ : Promise.resolve(undefined),
133
+ ]);
125
134
 
126
135
  packageJson.exports = packageExports;
136
+ if (packageImports) {
137
+ packageJson.imports = packageImports;
138
+ }
127
139
  if (main) {
128
140
  packageJson.main = main;
129
141
  }
@@ -131,11 +143,9 @@ async function writePackageJson({
131
143
  packageJson.types = types;
132
144
  }
133
145
 
134
- const bin = await createPackageBin({
135
- bin: originalBin,
146
+ const bin = await createPackageBin(originalBin, {
136
147
  bundles,
137
148
  cwd,
138
- isFlat,
139
149
  packageType: resolvedPackageType,
140
150
  });
141
151
  if (bin) {
@@ -225,16 +235,23 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
225
235
  })
226
236
  .option('flat', {
227
237
  type: 'boolean',
228
- default: process.env.MUI_BUILD_FLAT === '1',
238
+ deprecated:
239
+ 'Flat builds are now always used; this flag is a no-op and will be removed in a future release.',
240
+ default: true,
241
+ description:
242
+ '@deprecated Flat builds are always used now. The package is always built in a flat structure without subdirectories for each module type.',
243
+ })
244
+ .option('expand', {
245
+ type: 'boolean',
246
+ default: true,
229
247
  description:
230
- 'Builds the package in a flat structure without subdirectories for each module type.',
248
+ 'Enumerate glob patterns in the package.json "exports"/"imports" into concrete entries. Use --no-expand to keep them as Node runtime subpath patterns.',
231
249
  });
232
250
  },
233
251
  async handler(args) {
234
252
  const {
235
253
  bundle: bundles,
236
254
  hasLargeFiles,
237
- skipBundlePackageJson,
238
255
  verbose = false,
239
256
  ignore: extraIgnores,
240
257
  buildTypes,
@@ -255,9 +272,6 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
255
272
  const packageType = packageJson.type === 'module' ? 'module' : 'commonjs';
256
273
 
257
274
  console.log(`Selected output directory: "${buildDirBase}"`);
258
- if (args.flat) {
259
- console.log('Building package in flat structure.');
260
- }
261
275
 
262
276
  await fs.rm(buildDir, { recursive: true, force: true });
263
277
 
@@ -282,15 +296,6 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
282
296
  }
283
297
 
284
298
  const { build: babelBuild, cjsCopy } = await import('../utils/babel.mjs');
285
- const relativeOutDirs = !args.flat
286
- ? {
287
- cjs: '.',
288
- esm: 'esm',
289
- }
290
- : {
291
- cjs: '.',
292
- esm: '.',
293
- };
294
299
  const sourceDir = path.join(cwd, 'src');
295
300
  const reactVersion =
296
301
  semver.minVersion(packageJson.peerDependencies?.react || '')?.version ?? 'latest';
@@ -306,13 +311,10 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
306
311
  await Promise.all(
307
312
  bundles.map(async (bundle) => {
308
313
  const outExtension = getOutExtension(bundle, {
309
- isFlat: !!args.flat,
310
314
  isType: false,
311
315
  packageType,
312
316
  });
313
- const relativeOutDir = relativeOutDirs[bundle];
314
- const outputDir = path.join(buildDir, relativeOutDir);
315
- await fs.mkdir(outputDir, { recursive: true });
317
+ await fs.mkdir(buildDir, { recursive: true });
316
318
 
317
319
  const promises = [];
318
320
 
@@ -320,7 +322,7 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
320
322
  babelBuild({
321
323
  cwd,
322
324
  sourceDir,
323
- outDir: outputDir,
325
+ outDir: buildDir,
324
326
  babelRuntimeVersion,
325
327
  hasLargeFiles,
326
328
  bundle,
@@ -340,61 +342,28 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
340
342
  }),
341
343
  );
342
344
 
343
- if (buildDir !== outputDir && !skipBundlePackageJson && !args.flat) {
344
- // @TODO - Not needed if the output extension is .mjs. Remove this before PR merge.
345
- promises.push(
346
- fs.writeFile(
347
- path.join(outputDir, 'package.json'),
348
- JSON.stringify({
349
- type: bundle === 'esm' ? 'module' : 'commonjs',
350
- sideEffects: packageJson.sideEffects ?? false,
351
- }),
352
- ),
353
- );
354
- }
355
-
356
- if (!args.flat) {
357
- // cjs for reexporting from commons only modules.
358
- // @NOTE: If we need to rely more on this we can think about setting up
359
- // a separate commonjs => commonjs build for .cjs files to .cjs
360
- // `--extensions-.cjs --out-file-extension .cjs`
361
- promises.push(cjsCopy({ from: sourceDir, to: outputDir }));
362
- }
363
-
364
345
  await Promise.all(promises);
365
346
  await addLicense({
366
347
  bundle,
367
348
  license: packageJson.license,
368
349
  name: packageJson.name,
369
350
  version: packageJson.version,
370
- outputDir,
371
- isFlat: !!args.flat,
351
+ outputDir: buildDir,
372
352
  packageType,
373
353
  });
374
354
  }),
375
355
  );
376
356
 
377
- if (args.flat) {
378
- await cjsCopy({ from: sourceDir, to: buildDir });
379
- }
357
+ await cjsCopy({ from: sourceDir, to: buildDir });
380
358
  // js build end
381
359
 
382
360
  if (buildTypes) {
383
361
  const tsMod = await import('../utils/typescript.mjs');
384
- /**
385
- * @type {{type: import('../utils/build.mjs').BundleType, dir: string}[]};
386
- */
387
- const bundleMap = bundles.map((type) => ({
388
- type,
389
- dir: relativeOutDirs[type],
390
- }));
391
-
392
362
  await tsMod.createTypes({
393
- bundles: bundleMap,
363
+ bundles,
394
364
  srcDir: sourceDir,
395
365
  cwd,
396
366
  skipTsc,
397
- isFlat: !!args.flat,
398
367
  buildDir,
399
368
  useTsgo,
400
369
  packageType,
@@ -409,13 +378,10 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
409
378
  await writePackageJson({
410
379
  cwd,
411
380
  packageJson,
412
- bundles: bundles.map((type) => ({
413
- type,
414
- dir: relativeOutDirs[type],
415
- })),
381
+ bundles,
416
382
  outputDir: buildDir,
417
383
  addTypes: buildTypes,
418
- isFlat: !!args.flat,
384
+ expand: args.expand,
419
385
  packageType,
420
386
  });
421
387
 
@@ -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'|'publish-dir'} [output] - Output format (name, path, or json)
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', 'publish-dir'],
31
+ choices: ['json', 'path', 'name'],
33
32
  default: 'path',
34
33
  description:
35
- 'Output format: name (package names), path (package paths), publish-dir (publish directories), or json (full JSON)',
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) => {