@mui/internal-code-infra 0.0.4-canary.6 → 0.0.4-canary.61
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 +53 -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
package/src/utils/build.mjs
CHANGED
|
@@ -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
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* @param {string}
|
|
41
|
-
* @
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
|
98
|
+
`Array form of package.json ${kind}s is not supported yet. Found in ${kind} "${key}".`,
|
|
64
99
|
);
|
|
65
100
|
}
|
|
66
101
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
102
|
+
for (const childKey of Object.keys(value)) {
|
|
103
|
+
value[childKey] = finalizeConditionValue(value[childKey], addTypes, kind, key);
|
|
104
|
+
}
|
|
70
105
|
|
|
71
|
-
if (
|
|
72
|
-
|
|
73
|
-
|
|
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
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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
|
-
|
|
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
|
-
`
|
|
278
|
+
`Array form of package.json ${ctx.kind}s is not supported yet. Found in ${ctx.kind} "${ctx.key}".`,
|
|
86
279
|
);
|
|
87
280
|
}
|
|
88
|
-
|
|
89
|
-
|
|
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
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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
|
-
|
|
97
|
-
|
|
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
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
-
|
|
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
|
|
119
|
-
*
|
|
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
|
-
|
|
164
|
-
|
|
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'
|
|
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
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
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 {
|
|
203
|
-
const
|
|
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
|
|
534
|
+
for (const match of globResults[i]) {
|
|
207
535
|
if (match.startsWith(srcPrefix) && match.endsWith(srcSuffix)) {
|
|
208
|
-
const stem =
|
|
209
|
-
|
|
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
|
-
|
|
221
|
-
|
|
222
|
-
|
|
544
|
+
if (stems.length === 0) {
|
|
545
|
+
console.warn(`No files matched the pattern "${srcPattern}" for "${key}".`);
|
|
546
|
+
continue;
|
|
547
|
+
}
|
|
223
548
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
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
|
-
//
|
|
236
|
-
//
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
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
|
-
*
|
|
255
|
-
*
|
|
256
|
-
* @param {{type: BundleType; dir: string}[]}
|
|
257
|
-
* @param {
|
|
258
|
-
* @param {
|
|
259
|
-
* @
|
|
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
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
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 =
|
|
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
|
-
|
|
296
|
-
const
|
|
297
|
-
|
|
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
|
|
312
|
-
|
|
313
|
-
|
|
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['.'][
|
|
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
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
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
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
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
|
-
`
|
|
747
|
+
`Invalid import "${key}": all package.json "imports" keys must start with "#".`,
|
|
376
748
|
);
|
|
377
749
|
}
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
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
|
-
|
|
768
|
+
finalizeConditions(newImports, addTypes, 'import');
|
|
769
|
+
|
|
770
|
+
return newImports;
|
|
394
771
|
}
|
|
395
772
|
|
|
396
773
|
/**
|
|
397
|
-
* @param {
|
|
398
|
-
* @param {
|
|
399
|
-
* @param {{type: BundleType; dir: string}[]}
|
|
400
|
-
* @param {string}
|
|
401
|
-
* @param {boolean} [
|
|
402
|
-
* @param {'module' | 'commonjs'} [
|
|
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(
|
|
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
|
*
|