@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.
Files changed (111) 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-guarded-throw.d.mts +31 -0
  25. package/build/eslint/mui/rules/no-presentation-role.d.mts +5 -0
  26. package/build/eslint/mui/rules/no-restricted-resolved-imports.d.mts +2 -2
  27. package/build/eslint/mui/rules/nodeEnvUtils.d.mts +18 -0
  28. package/build/markdownlint/duplicate-h1.d.mts +1 -1
  29. package/build/markdownlint/git-diff.d.mts +1 -1
  30. package/build/markdownlint/index.d.mts +1 -1
  31. package/build/markdownlint/straight-quotes.d.mts +1 -1
  32. package/build/markdownlint/table-alignment.d.mts +1 -1
  33. package/build/markdownlint/terminal-language.d.mts +1 -1
  34. package/build/remark/config.d.mts +43 -0
  35. package/build/remark/createLintTester.d.mts +10 -0
  36. package/build/remark/firstBlockHeading.d.mts +4 -0
  37. package/build/remark/gitDiff.d.mts +2 -0
  38. package/build/remark/noSpaceInLinks.d.mts +2 -0
  39. package/build/remark/straightQuotes.d.mts +2 -0
  40. package/build/remark/tableAlignment.d.mts +2 -0
  41. package/build/remark/terminalLanguage.d.mts +2 -0
  42. package/build/utils/babel.d.mts +1 -1
  43. package/build/utils/build.d.mts +61 -25
  44. package/build/utils/github.d.mts +1 -1
  45. package/build/utils/pnpm.d.mts +68 -2
  46. package/build/utils/testUtils.d.mts +7 -0
  47. package/build/utils/typescript.d.mts +2 -2
  48. package/package.json +61 -34
  49. package/src/babel-config.mjs +9 -3
  50. package/src/brokenLinksChecker/__fixtures__/static-site/index.html +1 -0
  51. package/src/brokenLinksChecker/__fixtures__/static-site/invalid-html.html +15 -0
  52. package/src/brokenLinksChecker/crawlWorker.mjs +217 -0
  53. package/src/brokenLinksChecker/index.mjs +217 -164
  54. package/src/brokenLinksChecker/index.test.ts +50 -13
  55. package/src/changelog/categorizeCommits.test.ts +5 -5
  56. package/src/changelog/fetchChangelogs.mjs +6 -2
  57. package/src/changelog/parseCommitLabels.test.ts +5 -5
  58. package/src/changelog/renderChangelog.mjs +1 -1
  59. package/src/changelog/types.ts +1 -1
  60. package/src/cli/cmdBuild.mjs +39 -16
  61. package/src/cli/cmdListWorkspaces.mjs +12 -27
  62. package/src/cli/cmdNetlifyIgnore.mjs +34 -93
  63. package/src/cli/cmdPublish.mjs +55 -15
  64. package/src/cli/cmdPublishCanary.mjs +128 -132
  65. package/src/cli/cmdPublishNewPackage.mjs +27 -6
  66. package/src/cli/cmdVale.mjs +513 -0
  67. package/src/cli/cmdVale.test.mjs +644 -0
  68. package/src/cli/index.mjs +2 -0
  69. package/src/cli/packageJson.d.ts +1 -1
  70. package/src/eslint/baseConfig.mjs +45 -20
  71. package/src/eslint/docsConfig.mjs +4 -2
  72. package/src/eslint/jsonConfig.mjs +2 -1
  73. package/src/eslint/mui/config.mjs +24 -4
  74. package/src/eslint/mui/index.mjs +4 -0
  75. package/src/eslint/mui/rules/no-guarded-throw.mjs +115 -0
  76. package/src/eslint/mui/rules/no-guarded-throw.test.mjs +206 -0
  77. package/src/eslint/mui/rules/no-presentation-role.mjs +60 -0
  78. package/src/eslint/mui/rules/no-presentation-role.test.mjs +33 -0
  79. package/src/eslint/mui/rules/nodeEnvUtils.mjs +52 -0
  80. package/src/eslint/mui/rules/require-dev-wrapper.mjs +25 -40
  81. package/src/eslint/testConfig.mjs +2 -1
  82. package/src/estree-typescript.d.ts +1 -1
  83. package/src/remark/config.mjs +157 -0
  84. package/src/remark/createLintTester.mjs +19 -0
  85. package/src/remark/firstBlockHeading.mjs +87 -0
  86. package/src/remark/firstBlockHeading.test.mjs +107 -0
  87. package/src/remark/gitDiff.mjs +43 -0
  88. package/src/remark/gitDiff.test.mjs +45 -0
  89. package/src/remark/noSpaceInLinks.mjs +42 -0
  90. package/src/remark/noSpaceInLinks.test.mjs +22 -0
  91. package/src/remark/straightQuotes.mjs +31 -0
  92. package/src/remark/straightQuotes.test.mjs +25 -0
  93. package/src/remark/tableAlignment.mjs +23 -0
  94. package/src/remark/tableAlignment.test.mjs +28 -0
  95. package/src/remark/terminalLanguage.mjs +19 -0
  96. package/src/remark/terminalLanguage.test.mjs +17 -0
  97. package/src/untyped-plugins.d.ts +11 -11
  98. package/src/utils/build.mjs +621 -256
  99. package/src/utils/build.test.mjs +1064 -485
  100. package/src/utils/git.mjs +16 -7
  101. package/src/utils/pnpm.mjs +192 -3
  102. package/src/utils/pnpm.test.mjs +580 -0
  103. package/src/utils/testUtils.mjs +18 -0
  104. package/src/utils/typescript.test.mjs +249 -272
  105. package/vale/.vale.ini +1 -0
  106. package/vale/styles/MUI/CorrectReferenceAllCases.yml +43 -0
  107. package/vale/styles/MUI/CorrectRererenceCased.yml +14 -0
  108. package/vale/styles/MUI/GoogleLatin.yml +11 -0
  109. package/vale/styles/MUI/MuiBrandName.yml +22 -0
  110. package/vale/styles/MUI/NoBritish.yml +112 -0
  111. package/vale/styles/MUI/NoCompanyName.yml +17 -0
@@ -1,13 +1,41 @@
1
1
  import * as fs from 'node:fs/promises';
2
2
  import * as path from 'node:path';
3
3
  import { globby } from 'globby';
4
- import { minimatch } from 'minimatch';
5
4
  import * as semver from 'semver';
6
5
 
7
6
  /**
8
7
  * @typedef {'esm' | 'cjs'} BundleType
9
8
  */
10
9
 
10
+ /**
11
+ * @typedef {Object} BundleMeta
12
+ * @property {BundleType} type
13
+ * @property {string} dir
14
+ * @property {'import' | 'require'} condition - The package.json condition this bundle maps to.
15
+ * @property {string} outExtension
16
+ * @property {string} typeOutExtension
17
+ */
18
+
19
+ /**
20
+ * Source files in JS/TS-like languages that the build compiles. These are the
21
+ * only leaves that get an extension swap + `import`/`require`/`types` conditions.
22
+ * Other files under `src/` (e.g. `.css`, `.json`) are copied verbatim and only
23
+ * get their `./src/` prefix rewritten.
24
+ */
25
+ const JS_TS_EXTENSIONS = new Set(['.ts', '.tsx', '.mts', '.cts', '.js', '.jsx', '.mjs', '.cjs']);
26
+
27
+ export const BASE_IGNORES = [
28
+ '**/*.test.js',
29
+ '**/*.test.ts',
30
+ '**/*.test.tsx',
31
+ '**/*.spec.js',
32
+ '**/*.spec.ts',
33
+ '**/*.spec.tsx',
34
+ '**/*.d.ts',
35
+ '**/*.test/*.*',
36
+ '**/test-cases/*.*',
37
+ ];
38
+
11
39
  /**
12
40
  * @param {BundleType} bundle
13
41
  * @param {Object} [options]
@@ -35,215 +63,524 @@ export function getOutExtension(bundle, options = {}) {
35
63
  }
36
64
 
37
65
  /**
38
- * @param {Object} param0
39
- * @param {NonNullable<import('../cli/packageJson').PackageJson.Exports>} param0.importPath
40
- * @param {string} param0.key
41
- * @param {string} param0.cwd
42
- * @param {string} param0.dir
43
- * @param {string} param0.type
44
- * @param {import('../cli/packageJson').PackageJson.ExportConditions} param0.newExports
45
- * @param {string} param0.typeOutExtension
46
- * @param {string} param0.outExtension
47
- * @param {boolean} param0.addTypes
48
- * @returns {Promise<void>}
66
+ * Returns a new object with `import` first, `require` second, `default` last,
67
+ * and any other condition keys preserved in their original relative order in between.
68
+ * @param {Record<string, any>} conditions
69
+ * @returns {Record<string, any>}
70
+ */
71
+ function sortExportConditions(conditions) {
72
+ /** @type {Record<string, number | undefined>} */
73
+ const order = { import: 0, require: 1, default: 3 };
74
+ return Object.fromEntries(
75
+ Object.entries(conditions).sort(([a], [b]) => (order[a] ?? 2) - (order[b] ?? 2)),
76
+ );
77
+ }
78
+
79
+ /**
80
+ * Recursively fills in the `default` condition and stabilizes key order for a
81
+ * single condition value. Bundles run in parallel, so `import`/`require`
82
+ * insertion order would otherwise depend on Promise timing. Nested condition
83
+ * objects (e.g. `{ node: {...}, default: {...} }`) are handled at every level
84
+ * that carries `import`/`require`. Non-condition values (plain strings, bare
85
+ * specifiers, `null`) are returned untouched.
86
+ * @param {any} value
87
+ * @param {boolean} addTypes
88
+ * @param {string} kind - Used for error messages, e.g. `export` or `import`.
89
+ * @param {string} key - Used for error messages.
90
+ * @returns {any}
49
91
  */
50
- async function createExportsFor({
51
- importPath,
52
- key,
53
- cwd,
54
- dir,
55
- type,
56
- newExports,
57
- typeOutExtension,
58
- outExtension,
59
- addTypes,
60
- }) {
61
- if (Array.isArray(importPath)) {
92
+ function finalizeConditionValue(value, addTypes, kind, key) {
93
+ if (value === null || typeof value !== 'object') {
94
+ return value;
95
+ }
96
+ if (Array.isArray(value)) {
62
97
  throw new Error(
63
- `Array form of package.json exports is not supported yet. Found in export "${key}".`,
98
+ `Array form of package.json ${kind}s is not supported yet. Found in ${kind} "${key}".`,
64
99
  );
65
100
  }
66
101
 
67
- let srcPath = typeof importPath === 'string' ? importPath : importPath['mui-src'];
68
- const rest = typeof importPath === 'string' ? {} : { ...importPath };
69
- delete rest['mui-src'];
102
+ for (const childKey of Object.keys(value)) {
103
+ value[childKey] = finalizeConditionValue(value[childKey], addTypes, kind, key);
104
+ }
70
105
 
71
- if (typeof srcPath !== 'string') {
72
- throw new Error(
73
- `Unsupported export for "${key}". Only a string or an object with "mui-src" field is supported for now.`,
74
- );
106
+ if (value.import || value.require) {
107
+ // Synthesize `default` from import/require (preferring ESM), but never clobber
108
+ // a user-authored `default` condition that sits alongside them.
109
+ if (value.default === undefined) {
110
+ const defaultExport = value.import || value.require;
111
+ if (addTypes) {
112
+ value.default = defaultExport;
113
+ } else {
114
+ value.default =
115
+ defaultExport && typeof defaultExport === 'object' && 'default' in defaultExport
116
+ ? defaultExport.default
117
+ : defaultExport;
118
+ }
119
+ }
120
+ return sortExportConditions(value);
75
121
  }
76
122
 
77
- const exportFileExists = srcPath.includes('*')
78
- ? true
79
- : await fs.stat(path.join(cwd, srcPath)).then(
80
- (stats) => stats.isFile() || stats.isDirectory(),
81
- () => false,
123
+ return value;
124
+ }
125
+
126
+ /**
127
+ * Applies {@link finalizeConditionValue} to every entry of a conditions map.
128
+ * @param {import('../cli/packageJson').PackageJson.ExportConditions} conditionsMap
129
+ * @param {boolean} addTypes
130
+ * @param {string} kind - Used for error messages, e.g. `export` or `import`.
131
+ * @returns {void}
132
+ */
133
+ function finalizeConditions(conditionsMap, addTypes, kind) {
134
+ for (const key of Object.keys(conditionsMap)) {
135
+ conditionsMap[key] = finalizeConditionValue(conditionsMap[key], addTypes, kind, key);
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Returns the path relative to `src/` if `leaf` points inside the source tree
141
+ * (accepting both `./src/…` and `src/…`), otherwise `null`.
142
+ * @param {string} leaf
143
+ * @returns {string | null}
144
+ */
145
+ function srcRelative(leaf) {
146
+ if (leaf.startsWith('./src/')) {
147
+ return leaf.slice('./src/'.length);
148
+ }
149
+ if (leaf.startsWith('src/')) {
150
+ return leaf.slice('src/'.length);
151
+ }
152
+ return null;
153
+ }
154
+
155
+ /**
156
+ * Maps a source-relative path to its built location, optionally swapping the
157
+ * extension. `*` wildcards are preserved verbatim (Node resolves them at runtime).
158
+ * @param {string} rel - Path relative to `src/`.
159
+ * @param {string} dir - The bundle output dir (`.` for the root).
160
+ * @param {string} ext - The current extension (from `path.extname`).
161
+ * @param {string | null} newExt - The replacement extension, or `null` to keep `ext`.
162
+ * @returns {string}
163
+ */
164
+ function buildOutPath(rel, dir, ext, newExt) {
165
+ const dirPrefix = dir === '.' ? '' : `${dir}/`;
166
+ const base = `./${dirPrefix}${rel}`;
167
+ return newExt ? `${base.slice(0, base.length - ext.length)}${newExt}` : base;
168
+ }
169
+
170
+ /**
171
+ * @param {string} target
172
+ * @returns {Promise<boolean>}
173
+ */
174
+ function fileExists(target) {
175
+ return fs.stat(target).then(
176
+ (stats) => stats.isFile(),
177
+ () => false,
178
+ );
179
+ }
180
+
181
+ /**
182
+ * @param {string} target
183
+ * @returns {Promise<boolean>}
184
+ */
185
+ function fileOrDirExists(target) {
186
+ return fs.stat(target).then(
187
+ (stats) => stats.isFile() || stats.isDirectory(),
188
+ () => false,
189
+ );
190
+ }
191
+
192
+ /**
193
+ * Rewrites a single leaf path for every bundle. A source JS/TS path becomes a
194
+ * per-bundle `{ types?, default }` (or bare out-path string when not adding
195
+ * types). A source asset (e.g. `.css`) gets only its `./src/` prefix rewritten.
196
+ * Anything else (a path already in the build output, or a bare specifier) is
197
+ * passed through verbatim — the escape hatch for `--copy`'d/custom paths.
198
+ * @param {string} leaf
199
+ * @param {Object} ctx
200
+ * @param {BundleMeta[]} ctx.bundleMetas
201
+ * @param {boolean} ctx.addTypes
202
+ * @param {string} ctx.cwd
203
+ * @param {string} [ctx.outputDir]
204
+ * @param {string} ctx.key
205
+ * @param {string} ctx.kind
206
+ * @returns {Promise<any>}
207
+ */
208
+ async function rewriteLeaf(leaf, ctx) {
209
+ const { bundleMetas, addTypes, cwd, outputDir, key, kind } = ctx;
210
+ const rel = srcRelative(leaf);
211
+
212
+ if (rel === null) {
213
+ // Not a source path: it already names a path present in the published
214
+ // output (via `--copy` or because it's there literally), or a bare
215
+ // specifier (external package). Emit verbatim.
216
+ if (outputDir && leaf.startsWith('.') && !leaf.includes('*')) {
217
+ const exists = await fileOrDirExists(path.join(outputDir, leaf));
218
+ if (!exists) {
219
+ // `--copy` runs after package.json generation, so the file may legitimately
220
+ // not be on disk yet — warn rather than fail.
221
+ console.warn(
222
+ `The ${kind} path "${leaf}" for "${key}" was not found in the build output. Ensure it is generated or copied into the output directory.`,
223
+ );
224
+ }
225
+ }
226
+ return leaf;
227
+ }
228
+
229
+ const hasGlob = leaf.includes('*');
230
+ if (!hasGlob) {
231
+ const exists = await fileOrDirExists(path.join(cwd, leaf));
232
+ if (!exists) {
233
+ throw new Error(
234
+ `The path "${leaf}" for ${kind} "${key}" does not exist in the package. Either remove the ${kind} or add the file/folder to the package.`,
82
235
  );
83
- if (!exportFileExists) {
236
+ }
237
+ }
238
+
239
+ const ext = path.extname(rel);
240
+ if (!JS_TS_EXTENSIONS.has(ext)) {
241
+ // Asset copied verbatim into the output: only rewrite the `./src/` prefix.
242
+ const meta = bundleMetas.find((bundle) => bundle.dir === '.') ?? bundleMetas[0];
243
+ return buildOutPath(rel, meta.dir, ext, null);
244
+ }
245
+
246
+ /** @type {Record<string, any>} */
247
+ const result = {};
248
+ for (const meta of bundleMetas) {
249
+ const outPath = buildOutPath(rel, meta.dir, ext, meta.outExtension);
250
+ result[meta.condition] = addTypes
251
+ ? { types: buildOutPath(rel, meta.dir, ext, meta.typeOutExtension), default: outPath }
252
+ : outPath;
253
+ }
254
+ return result;
255
+ }
256
+
257
+ /**
258
+ * Recursively rewrites an export/import entry value, rewriting every source-path
259
+ * leaf (including those nested inside standard condition objects) into its built
260
+ * equivalent. Condition keys and their order are preserved (conditions stay
261
+ * outer; the build-owned `import`/`require` split lives at the leaves).
262
+ * @param {import('../cli/packageJson').PackageJson.Exports} value
263
+ * @param {Object} ctx
264
+ * @param {BundleMeta[]} ctx.bundleMetas
265
+ * @param {boolean} ctx.addTypes
266
+ * @param {string} ctx.cwd
267
+ * @param {string} [ctx.outputDir]
268
+ * @param {string} ctx.key
269
+ * @param {string} ctx.kind
270
+ * @returns {Promise<any>}
271
+ */
272
+ async function rewriteEntryValue(value, ctx) {
273
+ if (value === null) {
274
+ return null;
275
+ }
276
+ if (Array.isArray(value)) {
84
277
  throw new Error(
85
- `The import path "${srcPath}" for export "${key}" does not exist in the package. Either remove the export or add the file/folder to the package.`,
278
+ `Array form of package.json ${ctx.kind}s is not supported yet. Found in ${ctx.kind} "${ctx.key}".`,
86
279
  );
87
280
  }
88
- srcPath = srcPath.replace(/\.\/src\//, `./${dir === '.' ? '' : `${dir}/`}`);
89
- const ext = path.extname(srcPath);
281
+ if (typeof value === 'string') {
282
+ return rewriteLeaf(value, ctx);
283
+ }
284
+ if (typeof value === 'object') {
285
+ const entries = Object.entries(value);
286
+ const results = await Promise.all(entries.map(([, child]) => rewriteEntryValue(child, ctx)));
287
+ /** @type {Record<string, any>} */
288
+ const out = {};
289
+ entries.forEach(([condition], index) => {
290
+ out[condition] = results[index];
291
+ });
292
+ return out;
293
+ }
294
+ throw new Error(`Unsupported ${ctx.kind} value for "${ctx.key}".`);
295
+ }
296
+
297
+ /**
298
+ * Rewrites every entry of a conditions map, preserving declared key order.
299
+ * @param {import('../cli/packageJson').PackageJson.ExportConditions} conditionsMap
300
+ * @param {Object} baseCtx - The {@link rewriteEntryValue} context minus `key`.
301
+ * @param {BundleMeta[]} baseCtx.bundleMetas
302
+ * @param {boolean} baseCtx.addTypes
303
+ * @param {string} baseCtx.cwd
304
+ * @param {string} [baseCtx.outputDir]
305
+ * @param {string} baseCtx.kind
306
+ * @returns {Promise<import('../cli/packageJson').PackageJson.ExportConditions>}
307
+ */
308
+ async function rewriteConditionsMap(conditionsMap, baseCtx) {
309
+ const keys = Object.keys(conditionsMap);
310
+ const rewritten = await Promise.all(
311
+ keys.map((key) => rewriteEntryValue(conditionsMap[key], { ...baseCtx, key })),
312
+ );
313
+ /** @type {import('../cli/packageJson').PackageJson.ExportConditions} */
314
+ const result = {};
315
+ keys.forEach((key, index) => {
316
+ result[key] = rewritten[index];
317
+ });
318
+ return result;
319
+ }
90
320
 
91
- if (ext === '.css') {
92
- newExports[key] = srcPath;
93
- return;
321
+ /**
322
+ * Splits a pattern around its first `*` wildcard.
323
+ * @param {string} pattern
324
+ * @returns {{ prefix: string; suffix: string }}
325
+ */
326
+ function splitStar(pattern) {
327
+ const star = pattern.indexOf('*');
328
+ return { prefix: pattern.slice(0, star), suffix: pattern.slice(star + 1) };
329
+ }
330
+
331
+ /**
332
+ * Finds the source glob to expand inside an entry value: the plain string, else
333
+ * the `default` condition, else the first leaf that carries a `*`. The captured
334
+ * stem is applied to every sibling leaf so all conditions expand consistently.
335
+ * @param {import('../cli/packageJson').PackageJson.Exports} value
336
+ * @returns {string | undefined}
337
+ */
338
+ function primarySourcePattern(value) {
339
+ if (typeof value === 'string') {
340
+ return value.includes('*') ? value : undefined;
341
+ }
342
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
343
+ if (typeof value.default === 'string' && value.default.includes('*')) {
344
+ return value.default;
345
+ }
346
+ for (const child of Object.values(value)) {
347
+ const found = primarySourcePattern(child);
348
+ if (found) {
349
+ return found;
350
+ }
351
+ }
94
352
  }
353
+ return undefined;
354
+ }
95
355
 
96
- if (typeof newExports[key] === 'string' || Array.isArray(newExports[key])) {
97
- throw new Error(`The export "${key}" is already defined as a string or Array.`);
356
+ /**
357
+ * Substitutes the matched stem into the `*` of every leaf string in a value.
358
+ * @param {import('../cli/packageJson').PackageJson.Exports} value
359
+ * @param {string} stem
360
+ * @returns {any}
361
+ */
362
+ function substituteStem(value, stem) {
363
+ if (typeof value === 'string') {
364
+ return value.replace('*', stem);
98
365
  }
366
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
367
+ /** @type {Record<string, any>} */
368
+ const out = {};
369
+ for (const [condition, child] of Object.entries(value)) {
370
+ out[condition] = substituteStem(child, stem);
371
+ }
372
+ return out;
373
+ }
374
+ return value;
375
+ }
99
376
 
100
- newExports[key] ??= {};
101
- const exportPath = srcPath.replace(ext, outExtension);
102
- // eslint-disable-next-line no-nested-ternary
103
- newExports[key][type === 'cjs' ? 'require' : 'import'] = addTypes
104
- ? {
105
- ...rest,
106
- types: srcPath.replace(ext, typeOutExtension),
107
- default: exportPath,
108
- }
109
- : Object.keys(rest).length
110
- ? {
111
- ...rest,
112
- default: exportPath,
377
+ /**
378
+ * Drops source-path conditions whose file is missing for a glob-expanded entry,
379
+ * so a sibling glob that doesn't match every stem of the primary pattern omits
380
+ * that condition for the unmatched stems instead of failing the build. Only used
381
+ * on glob-expanded values; explicit (non-glob) entries still validate strictly.
382
+ * @param {import('../cli/packageJson').PackageJson.Exports} value
383
+ * @param {string} cwd
384
+ * @returns {Promise<any>}
385
+ */
386
+ async function pruneMissingSourceConditions(value, cwd) {
387
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
388
+ return value;
389
+ }
390
+ const entries = Object.entries(value);
391
+ const resolved = await Promise.all(
392
+ entries.map(async ([condition, child]) => {
393
+ if (typeof child === 'string') {
394
+ const rel = srcRelative(child);
395
+ if (
396
+ rel !== null &&
397
+ !child.includes('*') &&
398
+ !(await fileOrDirExists(path.join(cwd, child)))
399
+ ) {
400
+ return undefined;
113
401
  }
114
- : exportPath;
402
+ return /** @type {[string, any]} */ ([condition, child]);
403
+ }
404
+ const pruned = await pruneMissingSourceConditions(child, cwd);
405
+ if (
406
+ pruned &&
407
+ typeof pruned === 'object' &&
408
+ !Array.isArray(pruned) &&
409
+ Object.keys(pruned).length === 0
410
+ ) {
411
+ return undefined;
412
+ }
413
+ return /** @type {[string, any]} */ ([condition, pruned]);
414
+ }),
415
+ );
416
+ /** @type {Record<string, any>} */
417
+ const out = {};
418
+ for (const entry of resolved) {
419
+ if (entry) {
420
+ out[entry[0]] = entry[1];
421
+ }
422
+ }
423
+ return out;
424
+ }
425
+
426
+ /**
427
+ * Tests whether a subpath-pattern (or exact) key matches a concrete subpath.
428
+ * @param {string} key
429
+ * @param {string} subpath
430
+ * @returns {boolean}
431
+ */
432
+ function keyMatches(key, subpath) {
433
+ const star = key.indexOf('*');
434
+ if (star === -1) {
435
+ return key === subpath;
436
+ }
437
+ const base = key.slice(0, star);
438
+ const suffix = key.slice(star + 1);
439
+ return (
440
+ subpath.length >= base.length + suffix.length &&
441
+ subpath.startsWith(base) &&
442
+ subpath.endsWith(suffix)
443
+ );
444
+ }
445
+
446
+ /**
447
+ * Selects the most-specific key that matches `subpath`, mirroring Node's
448
+ * resolution: an exact key beats any pattern, and among patterns the longest
449
+ * base (substring before `*`) wins, tie-broken by the longest suffix.
450
+ * @param {string} subpath
451
+ * @param {string[]} keys
452
+ * @returns {string | null}
453
+ */
454
+ function selectMostSpecificKey(subpath, keys) {
455
+ /** @type {string | null} */
456
+ let best = null;
457
+ let bestBase = -1;
458
+ let bestSuffix = -1;
459
+ for (const key of keys) {
460
+ if (!keyMatches(key, subpath)) {
461
+ continue;
462
+ }
463
+ const star = key.indexOf('*');
464
+ const base = star === -1 ? Infinity : star;
465
+ const suffix = star === -1 ? 0 : key.length - star - 1;
466
+ if (base > bestBase || (base === bestBase && suffix > bestSuffix)) {
467
+ best = key;
468
+ bestBase = base;
469
+ bestSuffix = suffix;
470
+ }
471
+ }
472
+ return best;
115
473
  }
116
474
 
117
475
  /**
118
- * Expands glob patterns (containing `*`) in package.json export keys/values
119
- * into concrete entries by resolving them against actual files on disk.
476
+ * Expands glob patterns (containing `*`) in export/import keys into concrete
477
+ * entries resolved against files on disk. Each `*` matches a single path segment
478
+ * (use `--no-expand` to keep the pattern as a Node runtime subpath, whose `*`
479
+ * matches across `/`). Negation (`null`) keys are applied via most-specific-key
480
+ * selection rather than cascade-subtraction, so a deeper positive pattern still
481
+ * resolves under a shallower `null`, and a zero-match pattern warns instead of
482
+ * silently dropping.
120
483
  * @param {import('../cli/packageJson').PackageJson.ExportConditions} originalExports
121
484
  * @param {string} cwd
122
485
  * @returns {Promise<import('../cli/packageJson').PackageJson.ExportConditions>}
123
486
  */
124
487
  async function expandExportGlobs(originalExports, cwd) {
488
+ const allKeys = Object.keys(originalExports);
125
489
  /** @type {import('../cli/packageJson').PackageJson.ExportConditions} */
126
490
  const expandedExports = {};
127
491
 
128
- /**
129
- * @typedef {{
130
- * value: import('../cli/packageJson').PackageJson.Exports;
131
- * srcPattern: string;
132
- * srcPrefix: string;
133
- * srcSuffix: string;
134
- * keyPrefix: string;
135
- * keySuffix: string;
136
- * }} GlobEntry
137
- */
138
-
139
- // Collect entries that need glob expansion
140
- /** @type {GlobEntry[]} */
492
+ /** @type {{ key: string; value: import('../cli/packageJson').PackageJson.Exports; srcPattern: string }[]} */
141
493
  const globEntries = [];
142
494
 
143
- // Collect negation patterns (glob keys with null values)
144
- /** @type {string[]} */
145
- const negationPatterns = [];
146
-
147
495
  for (const [key, value] of Object.entries(originalExports)) {
148
- // Null value acts as a negation/exclusion
149
- if (value === null) {
150
- if (key.includes('*')) {
151
- negationPatterns.push(key);
152
- } else {
153
- delete expandedExports[key];
154
- }
155
- continue;
156
- }
157
-
158
496
  if (!key.includes('*')) {
497
+ // Exact keys (including exact `null` blocks) pass straight through.
159
498
  expandedExports[key] = value;
160
499
  continue;
161
500
  }
162
-
163
- // Extract the source pattern from the value
164
- /** @type {string | undefined} */
165
- let srcPattern;
166
- if (typeof value === 'string') {
167
- srcPattern = value;
168
- } else if (value && typeof value === 'object' && !Array.isArray(value)) {
169
- srcPattern = /** @type {string | undefined} */ (value['mui-src']);
501
+ if (value === null) {
502
+ // Negation pattern: carried through after expansion (see below).
503
+ continue;
170
504
  }
171
-
172
- if (typeof srcPattern !== 'string' || !srcPattern.includes('*')) {
505
+ const srcPattern = primarySourcePattern(value);
506
+ if (typeof srcPattern !== 'string') {
507
+ // Glob key whose value has no wildcard: pass through unchanged.
173
508
  expandedExports[key] = value;
174
509
  continue;
175
510
  }
176
-
177
- // Split patterns around the * wildcard
178
- const srcStarIndex = srcPattern.indexOf('*');
179
- const srcPrefix = srcPattern.substring(0, srcStarIndex);
180
- const srcSuffix = srcPattern.substring(srcStarIndex + 1);
181
-
182
- const keyStarIndex = key.indexOf('*');
183
- const keyPrefix = key.substring(0, keyStarIndex);
184
- const keySuffix = key.substring(keyStarIndex + 1);
185
-
186
- globEntries.push({
187
- value,
188
- srcPattern,
189
- srcPrefix,
190
- srcSuffix,
191
- keyPrefix,
192
- keySuffix,
193
- });
511
+ if (srcPattern.indexOf('*') !== srcPattern.lastIndexOf('*')) {
512
+ console.warn(
513
+ `The pattern "${srcPattern}" for "${key}" contains multiple "*" wildcards; only the first is supported.`,
514
+ );
515
+ }
516
+ globEntries.push({ key, value, srcPattern });
194
517
  }
195
518
 
196
- // Resolve all globby calls in parallel
197
519
  const globResults = await Promise.all(
198
- globEntries.map(({ srcPattern }) => globby(srcPattern, { cwd })),
520
+ globEntries.map(({ srcPattern }) => globby(srcPattern, { cwd, ignore: BASE_IGNORES })),
199
521
  );
200
522
 
523
+ /** @type {Set<string>} */
524
+ const usedNegations = new Set();
525
+ /** @type {string[]} */
526
+ const expandedObjectKeys = [];
527
+
201
528
  for (let i = 0; i < globEntries.length; i += 1) {
202
- const { value, srcPrefix, srcSuffix, keyPrefix, keySuffix } = globEntries[i];
203
- const matches = globResults[i];
529
+ const { key, value, srcPattern } = globEntries[i];
530
+ const { prefix: srcPrefix, suffix: srcSuffix } = splitStar(srcPattern);
531
+ const { prefix: keyPrefix, suffix: keySuffix } = splitStar(key);
204
532
 
205
533
  const stems = [];
206
- for (const match of matches) {
534
+ for (const match of globResults[i]) {
207
535
  if (match.startsWith(srcPrefix) && match.endsWith(srcSuffix)) {
208
- const stem =
209
- srcSuffix.length > 0
210
- ? match.substring(srcPrefix.length, match.length - srcSuffix.length)
211
- : match.substring(srcPrefix.length);
212
- if (stem.length > 0) {
536
+ const stem = match.slice(srcPrefix.length, match.length - srcSuffix.length);
537
+ if (stem) {
213
538
  stems.push(stem);
214
539
  }
215
540
  }
216
541
  }
217
-
218
542
  stems.sort();
219
543
 
220
- for (const stem of stems) {
221
- const expandedKey = `${keyPrefix}${stem}${keySuffix}`;
222
- const expandedSrcPath = `${srcPrefix}${stem}${srcSuffix}`;
544
+ if (stems.length === 0) {
545
+ console.warn(`No files matched the pattern "${srcPattern}" for "${key}".`);
546
+ continue;
547
+ }
223
548
 
224
- if (typeof value === 'string') {
225
- expandedExports[expandedKey] = expandedSrcPath;
226
- } else {
227
- expandedExports[expandedKey] = {
228
- ...value,
229
- 'mui-src': expandedSrcPath,
230
- };
549
+ for (const stem of stems) {
550
+ const concreteKey = `${keyPrefix}${stem}${keySuffix}`;
551
+ // Honour Node's most-specific-wins resolution: only emit this concrete
552
+ // entry when this positive pattern is the most-specific match. A deeper
553
+ // positive pattern emits its own entries; a `null` blocks it entirely.
554
+ const winner = selectMostSpecificKey(concreteKey, allKeys);
555
+ if (winner !== key) {
556
+ if (winner !== null && originalExports[winner] === null) {
557
+ usedNegations.add(winner);
558
+ }
559
+ continue;
560
+ }
561
+ expandedExports[concreteKey] = substituteStem(value, stem);
562
+ if (value && typeof value === 'object') {
563
+ expandedObjectKeys.push(concreteKey);
231
564
  }
232
565
  }
233
566
  }
234
567
 
235
- // Apply negation patterns: remove any expanded keys that match a null-valued glob.
236
- // If no keys matched, preserve the pattern itself with null to block that path at runtime.
237
- for (const pattern of negationPatterns) {
238
- let matched = false;
239
- for (const expandedKey of Object.keys(expandedExports)) {
240
- if (minimatch(expandedKey, pattern)) {
241
- delete expandedExports[expandedKey];
242
- matched = true;
243
- }
244
- }
245
- if (!matched) {
246
- expandedExports[pattern] = null;
568
+ // For glob-expanded condition objects, drop any condition whose source file is
569
+ // absent for this stem (a sibling glob need not match every primary stem).
570
+ await Promise.all(
571
+ expandedObjectKeys.map(async (concreteKey) => {
572
+ expandedExports[concreteKey] = await pruneMissingSourceConditions(
573
+ expandedExports[concreteKey],
574
+ cwd,
575
+ );
576
+ }),
577
+ );
578
+
579
+ // Carry through negation patterns that didn't claim any expanded entry so they
580
+ // still block their subtree at runtime.
581
+ for (const [key, value] of Object.entries(originalExports)) {
582
+ if (value === null && key.includes('*') && !usedNegations.has(key)) {
583
+ expandedExports[key] = null;
247
584
  }
248
585
  }
249
586
 
@@ -251,24 +588,46 @@ async function expandExportGlobs(originalExports, cwd) {
251
588
  }
252
589
 
253
590
  /**
254
- * @param {Object} param0
255
- * @param {import('../cli/packageJson').PackageJson['exports']} param0.exports
256
- * @param {{type: BundleType; dir: string}[]} param0.bundles
257
- * @param {string} param0.outputDir
258
- * @param {string} param0.cwd
259
- * @param {boolean} [param0.addTypes]
260
- * @param {boolean} [param0.isFlat]
261
- * @param {'module' | 'commonjs'} [param0.packageType]
591
+ * Builds the per-bundle metadata (output extensions + the `import`/`require`
592
+ * condition each bundle maps to).
593
+ * @param {{type: BundleType; dir: string}[]} bundles
594
+ * @param {boolean} isFlat
595
+ * @param {'module' | 'commonjs'} packageType
596
+ * @returns {BundleMeta[]}
262
597
  */
263
- export async function createPackageExports({
264
- exports: packageExports,
265
- bundles,
266
- outputDir,
267
- cwd,
268
- addTypes = false,
269
- isFlat = false,
270
- packageType = 'commonjs',
271
- }) {
598
+ function createBundleMetas(bundles, isFlat, packageType) {
599
+ return bundles.map(({ type, dir }) => ({
600
+ type,
601
+ dir,
602
+ condition: type === 'cjs' ? 'require' : 'import',
603
+ outExtension: getOutExtension(type, { isFlat, packageType }),
604
+ typeOutExtension: getOutExtension(type, { isFlat, isType: true, packageType }),
605
+ }));
606
+ }
607
+
608
+ /**
609
+ * @param {import('../cli/packageJson').PackageJson['exports']} packageExports
610
+ * @param {Object} options
611
+ * @param {{type: BundleType; dir: string}[]} options.bundles
612
+ * @param {string} options.outputDir
613
+ * @param {string} options.cwd
614
+ * @param {boolean} [options.addTypes]
615
+ * @param {boolean} [options.isFlat]
616
+ * @param {boolean} [options.expand] - Whether to enumerate glob patterns into concrete entries.
617
+ * @param {'module' | 'commonjs'} [options.packageType]
618
+ */
619
+ export async function createPackageExports(
620
+ packageExports,
621
+ {
622
+ bundles,
623
+ outputDir,
624
+ cwd,
625
+ addTypes = false,
626
+ isFlat = false,
627
+ expand = true,
628
+ packageType = 'commonjs',
629
+ },
630
+ ) {
272
631
  const resolvedPackageType = packageType === 'module' ? 'module' : 'commonjs';
273
632
  /**
274
633
  * @type {import('../cli/packageJson').PackageJson.ExportConditions}
@@ -277,7 +636,8 @@ export async function createPackageExports({
277
636
  typeof packageExports === 'string' || Array.isArray(packageExports)
278
637
  ? { '.': packageExports }
279
638
  : packageExports || {};
280
- const originalExports = isFlat ? await expandExportGlobs(rawExports, cwd) : rawExports;
639
+ const originalExports = expand ? await expandExportGlobs(rawExports, cwd) : rawExports;
640
+ const bundleMetas = createBundleMetas(bundles, isFlat, resolvedPackageType);
281
641
  /**
282
642
  * @type {import('../cli/packageJson').PackageJson.ExportConditions}
283
643
  */
@@ -291,73 +651,47 @@ export async function createPackageExports({
291
651
  exports: newExports,
292
652
  };
293
653
 
654
+ // Derive the `.` index entry (plus `main`/`types`) from the built index files.
294
655
  await Promise.all(
295
- bundles.map(async ({ type, dir }) => {
296
- const outExtension = getOutExtension(type, {
297
- isFlat,
298
- packageType: resolvedPackageType,
299
- });
300
- const typeOutExtension = getOutExtension(type, {
301
- isFlat,
302
- isType: true,
303
- packageType: resolvedPackageType,
304
- });
305
- const indexFileExists = await fs.stat(path.join(outputDir, dir, `index${outExtension}`)).then(
306
- (stats) => stats.isFile(),
307
- () => false,
656
+ bundleMetas.map(async (meta) => {
657
+ const indexFileExists = await fileExists(
658
+ path.join(outputDir, meta.dir, `index${meta.outExtension}`),
308
659
  );
309
660
  const typeFileExists =
310
661
  addTypes &&
311
- (await fs.stat(path.join(outputDir, dir, `index${typeOutExtension}`)).then(
312
- (stats) => stats.isFile(),
313
- () => false,
314
- ));
315
- const dirPrefix = dir === '.' ? '' : `${dir}/`;
316
- const exportDir = `./${dirPrefix}index${outExtension}`;
317
- const typeExportDir = `./${dirPrefix}index${typeOutExtension}`;
662
+ (await fileExists(path.join(outputDir, meta.dir, `index${meta.typeOutExtension}`)));
663
+ const dirPrefix = meta.dir === '.' ? '' : `${meta.dir}/`;
664
+ const exportDir = `./${dirPrefix}index${meta.outExtension}`;
665
+ const typeExportDir = `./${dirPrefix}index${meta.typeOutExtension}`;
318
666
 
319
667
  if (indexFileExists) {
320
668
  // skip `packageJson.module` to support parcel and some older bundlers
321
- if (type === 'cjs') {
669
+ if (meta.type === 'cjs') {
322
670
  result.main = exportDir;
323
671
  }
324
-
325
672
  if (typeof newExports['.'] === 'string' || Array.isArray(newExports['.'])) {
326
673
  throw new Error(`The export "." is already defined as a string or Array.`);
327
674
  }
328
-
329
675
  newExports['.'] ??= {};
330
- newExports['.'][type === 'cjs' ? 'require' : 'import'] = typeFileExists
331
- ? {
332
- types: typeExportDir,
333
- default: exportDir,
334
- }
676
+ newExports['.'][meta.condition] = typeFileExists
677
+ ? { types: typeExportDir, default: exportDir }
335
678
  : exportDir;
336
679
  }
337
- if (typeFileExists && type === 'cjs') {
680
+ if (typeFileExists && meta.type === 'cjs') {
338
681
  result.types = typeExportDir;
339
682
  }
340
- const exportKeys = Object.keys(originalExports);
341
- // need to maintain the order of exports
342
- for (const key of exportKeys) {
343
- const importPath = originalExports[key];
344
- if (!importPath) {
345
- newExports[key] = null;
346
- continue;
347
- }
348
- // eslint-disable-next-line no-await-in-loop
349
- await createExportsFor({
350
- importPath,
351
- key,
352
- cwd,
353
- dir,
354
- type,
355
- newExports,
356
- typeOutExtension,
357
- outExtension,
358
- addTypes,
359
- });
360
- }
683
+ }),
684
+ );
685
+
686
+ // Rewrite the user-configured entries, preserving their declared order.
687
+ Object.assign(
688
+ newExports,
689
+ await rewriteConditionsMap(originalExports, {
690
+ bundleMetas,
691
+ addTypes,
692
+ cwd,
693
+ outputDir,
694
+ kind: 'export',
361
695
  }),
362
696
  );
363
697
 
@@ -367,41 +701,84 @@ export async function createPackageExports({
367
701
  }
368
702
  });
369
703
 
370
- // Transform import/require to default/require pattern
371
- Object.keys(newExports).forEach((key) => {
372
- const exportVal = newExports[key];
373
- if (Array.isArray(exportVal)) {
704
+ finalizeConditions(newExports, addTypes, 'export');
705
+
706
+ return result;
707
+ }
708
+
709
+ /**
710
+ * Generates the package.json `imports` field for the built package, rewriting
711
+ * internal subpath imports (keys starting with `#`) that point at source files
712
+ * into their built equivalents with `import`/`require`/`types` conditions.
713
+ *
714
+ * Mirrors {@link createPackageExports} but without the `.` / `package.json` /
715
+ * `main` / `types` index handling that only applies to public exports. Entries
716
+ * that resolve to bare specifiers (e.g. an external package) are passed through
717
+ * unchanged, since the `imports` field commonly aliases dependencies.
718
+ * @param {import('../cli/packageJson').PackageJson['imports']} packageImports
719
+ * @param {Object} options
720
+ * @param {{type: BundleType; dir: string}[]} options.bundles
721
+ * @param {string} options.cwd
722
+ * @param {string} [options.outputDir] - Used to verify non-source passthrough paths exist in the build output.
723
+ * @param {boolean} [options.addTypes]
724
+ * @param {boolean} [options.isFlat]
725
+ * @param {boolean} [options.expand] - Whether to enumerate glob patterns into concrete entries.
726
+ * @param {'module' | 'commonjs'} [options.packageType]
727
+ * @returns {Promise<import('../cli/packageJson').PackageJson.Imports | undefined>}
728
+ */
729
+ export async function createPackageImports(
730
+ packageImports,
731
+ {
732
+ bundles,
733
+ cwd,
734
+ outputDir,
735
+ addTypes = false,
736
+ isFlat = false,
737
+ expand = true,
738
+ packageType = 'commonjs',
739
+ },
740
+ ) {
741
+ if (!packageImports || Object.keys(packageImports).length === 0) {
742
+ return undefined;
743
+ }
744
+ for (const key of Object.keys(packageImports)) {
745
+ if (!key.startsWith('#')) {
374
746
  throw new Error(
375
- `Array form of package.json exports is not supported yet. Found in export "${key}".`,
747
+ `Invalid import "${key}": all package.json "imports" keys must start with "#".`,
376
748
  );
377
749
  }
378
- if (exportVal && typeof exportVal === 'object' && (exportVal.import || exportVal.require)) {
379
- // Use ESM (import) for default if available, otherwise use require
380
- const defaultExport = exportVal.import || exportVal.require;
381
-
382
- if (addTypes) {
383
- exportVal.default = defaultExport;
384
- } else {
385
- exportVal.default =
386
- defaultExport && typeof defaultExport === 'object' && 'default' in defaultExport
387
- ? defaultExport.default
388
- : defaultExport;
389
- }
390
- }
750
+ }
751
+ const resolvedPackageType = packageType === 'module' ? 'module' : 'commonjs';
752
+ // `Imports` uses `#`-prefixed keys; treat it as a generic conditions map so the
753
+ // same glob/condition helpers used for exports can process it.
754
+ const rawImports = /** @type {import('../cli/packageJson').PackageJson.ExportConditions} */ (
755
+ packageImports
756
+ );
757
+ const originalImports = expand ? await expandExportGlobs(rawImports, cwd) : rawImports;
758
+ const bundleMetas = createBundleMetas(bundles, isFlat, resolvedPackageType);
759
+
760
+ const newImports = await rewriteConditionsMap(originalImports, {
761
+ bundleMetas,
762
+ addTypes,
763
+ cwd,
764
+ outputDir,
765
+ kind: 'import',
391
766
  });
392
767
 
393
- return result;
768
+ finalizeConditions(newImports, addTypes, 'import');
769
+
770
+ return newImports;
394
771
  }
395
772
 
396
773
  /**
397
- * @param {Object} param0
398
- * @param {import('../cli/packageJson').PackageJson['bin']} param0.bin
399
- * @param {{type: BundleType; dir: string}[]} param0.bundles
400
- * @param {string} param0.cwd
401
- * @param {boolean} [param0.isFlat]
402
- * @param {'module' | 'commonjs'} [param0.packageType]
774
+ * @param {import('../cli/packageJson').PackageJson['bin']} bin
775
+ * @param {Object} options
776
+ * @param {{type: BundleType; dir: string}[]} options.bundles
777
+ * @param {string} options.cwd
778
+ * @param {boolean} [options.isFlat]
779
+ * @param {'module' | 'commonjs'} [options.packageType]
403
780
  */
404
- export async function createPackageBin({ bin, bundles, cwd, isFlat = false, packageType }) {
781
+ export async function createPackageBin(bin, { bundles, cwd, isFlat = false, packageType }) {
405
782
  if (!bin) {
406
783
  return undefined;
407
784
  }
@@ -549,18 +926,6 @@ export function measureFn(label) {
549
926
  return performance.measure(label, startMark, endMark);
550
927
  }
551
928
 
552
- export const BASE_IGNORES = [
553
- '**/*.test.js',
554
- '**/*.test.ts',
555
- '**/*.test.tsx',
556
- '**/*.spec.js',
557
- '**/*.spec.ts',
558
- '**/*.spec.tsx',
559
- '**/*.d.ts',
560
- '**/*.test/*.*',
561
- '**/test-cases/*.*',
562
- ];
563
-
564
929
  /**
565
930
  * A utility to map a function over an array of items in a worker pool.
566
931
  *