@mui/internal-code-infra 0.0.4-canary.61 → 0.0.4-canary.63
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/build/utils/pnpm.d.mts +13 -0
- package/package.json +3 -2
- package/src/cli/cmdSetVersionOverrides.mjs +8 -9
- package/src/utils/build.test.mjs +73 -0
- package/src/utils/pnpm.mjs +63 -0
- package/src/utils/pnpm.test.mjs +152 -1
package/build/utils/pnpm.d.mts
CHANGED
|
@@ -135,6 +135,19 @@ export declare function readPackageJson(packagePath: string): Promise<import('..
|
|
|
135
135
|
* @returns {Promise<void>}
|
|
136
136
|
*/
|
|
137
137
|
export declare function writePackageJson(packagePath: string, packageJson: Object): Promise<void>;
|
|
138
|
+
/**
|
|
139
|
+
* Write the computed overrides into whichever manifest already defines
|
|
140
|
+
* overrides — preferring pnpm-workspace.yaml, falling back to package.json
|
|
141
|
+
* `pnpm.overrides`, defaulting to pnpm-workspace.yaml — and persist the result.
|
|
142
|
+
* A missing pnpm-workspace.yaml is treated as empty, so a fresh file is created
|
|
143
|
+
* with just the `overrides:` block. Rejects a `resolutions` field in
|
|
144
|
+
* package.json because pnpm 11 silently ignores it.
|
|
145
|
+
*
|
|
146
|
+
* @param {string} workspaceDir - Workspace root directory
|
|
147
|
+
* @param {Record<string, string>} overrides - Overrides to apply
|
|
148
|
+
* @returns {Promise<void>}
|
|
149
|
+
*/
|
|
150
|
+
export declare function writeOverridesToWorkspace(workspaceDir: string, overrides: Record<string, string>): Promise<void>;
|
|
138
151
|
/**
|
|
139
152
|
* Resolve a package@version specifier to an exact version
|
|
140
153
|
* @param {string} packageSpec - Package specifier in format "package@version"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mui/internal-code-infra",
|
|
3
|
-
"version": "0.0.4-canary.
|
|
3
|
+
"version": "0.0.4-canary.63",
|
|
4
4
|
"author": "MUI Team",
|
|
5
5
|
"description": "Infra scripts and configs to be used across MUI repos.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -138,6 +138,7 @@
|
|
|
138
138
|
"unified": "^11.0.5",
|
|
139
139
|
"unified-lint-rule": "^3.0.1",
|
|
140
140
|
"unist-util-visit": "^5.1.0",
|
|
141
|
+
"yaml": "^2.9.0",
|
|
141
142
|
"yargs": "^18.0.0",
|
|
142
143
|
"@mui/internal-babel-plugin-display-name": "1.0.4-canary.20",
|
|
143
144
|
"@mui/internal-babel-plugin-minify-errors": "2.0.8-canary.27",
|
|
@@ -191,7 +192,7 @@
|
|
|
191
192
|
"publishConfig": {
|
|
192
193
|
"access": "public"
|
|
193
194
|
},
|
|
194
|
-
"gitSha": "
|
|
195
|
+
"gitSha": "e08081fbb9ce12311a1acb555f69108dc1231951",
|
|
195
196
|
"scripts": {
|
|
196
197
|
"build": "tsgo -p tsconfig.build.json",
|
|
197
198
|
"typescript": "tsgo -noEmit",
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import fs from 'node:fs/promises';
|
|
4
|
-
import os from 'node:os';
|
|
5
|
-
import path from 'node:path';
|
|
6
3
|
import * as semver from 'semver';
|
|
7
4
|
import { $ } from 'execa';
|
|
8
|
-
import {
|
|
5
|
+
import { findWorkspaceDir } from '@pnpm/find-workspace-dir';
|
|
6
|
+
import {
|
|
7
|
+
resolveVersion,
|
|
8
|
+
findDependencyVersionFromSpec,
|
|
9
|
+
writeOverridesToWorkspace,
|
|
10
|
+
} from '../utils/pnpm.mjs';
|
|
9
11
|
|
|
10
12
|
/**
|
|
11
13
|
* @typedef {Object} Args
|
|
@@ -103,11 +105,8 @@ async function handler(args) {
|
|
|
103
105
|
// eslint-disable-next-line no-console
|
|
104
106
|
console.log(`Using overrides: ${JSON.stringify(overrides, null, 2)}`);
|
|
105
107
|
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
packageJson.resolutions ??= {};
|
|
109
|
-
Object.assign(packageJson.resolutions, overrides);
|
|
110
|
-
await fs.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}${os.EOL}`);
|
|
108
|
+
const workspaceDir = (await findWorkspaceDir(process.cwd())) ?? process.cwd();
|
|
109
|
+
await writeOverridesToWorkspace(workspaceDir, overrides);
|
|
111
110
|
|
|
112
111
|
await $({ stdio: 'inherit' })`pnpm dedupe`;
|
|
113
112
|
}
|
package/src/utils/build.test.mjs
CHANGED
|
@@ -1281,4 +1281,77 @@ describe('createPackageImports', () => {
|
|
|
1281
1281
|
},
|
|
1282
1282
|
});
|
|
1283
1283
|
});
|
|
1284
|
+
|
|
1285
|
+
it('passes a conditions object of bare specifiers through unchanged, preserving condition order', async () => {
|
|
1286
|
+
const cwd = await makeTempDir();
|
|
1287
|
+
|
|
1288
|
+
const imports = await createPackageImports(
|
|
1289
|
+
{
|
|
1290
|
+
'#mui/TransitionGroupContext': {
|
|
1291
|
+
node: 'react-transition-group/cjs/TransitionGroupContext.js',
|
|
1292
|
+
browser: 'react-transition-group/esm/TransitionGroupContext.js',
|
|
1293
|
+
default: 'react-transition-group/esm/TransitionGroupContext.js',
|
|
1294
|
+
},
|
|
1295
|
+
},
|
|
1296
|
+
{
|
|
1297
|
+
bundles: [
|
|
1298
|
+
{ type: 'esm', dir: '.' },
|
|
1299
|
+
{ type: 'cjs', dir: '.' },
|
|
1300
|
+
],
|
|
1301
|
+
cwd,
|
|
1302
|
+
isFlat: true,
|
|
1303
|
+
packageType: 'module',
|
|
1304
|
+
},
|
|
1305
|
+
);
|
|
1306
|
+
|
|
1307
|
+
expect(imports).toEqual({
|
|
1308
|
+
'#mui/TransitionGroupContext': {
|
|
1309
|
+
node: 'react-transition-group/cjs/TransitionGroupContext.js',
|
|
1310
|
+
browser: 'react-transition-group/esm/TransitionGroupContext.js',
|
|
1311
|
+
default: 'react-transition-group/esm/TransitionGroupContext.js',
|
|
1312
|
+
},
|
|
1313
|
+
});
|
|
1314
|
+
expect(
|
|
1315
|
+
Object.keys(
|
|
1316
|
+
/** @type {Record<string, unknown>} */ (imports?.['#mui/TransitionGroupContext']),
|
|
1317
|
+
),
|
|
1318
|
+
).toEqual(['node', 'browser', 'default']);
|
|
1319
|
+
});
|
|
1320
|
+
|
|
1321
|
+
it('passes a nested import/require/default object of bare specifiers through unchanged', async () => {
|
|
1322
|
+
const cwd = await makeTempDir();
|
|
1323
|
+
|
|
1324
|
+
const imports = await createPackageImports(
|
|
1325
|
+
{
|
|
1326
|
+
'#mui/TransitionGroupContext': {
|
|
1327
|
+
node: 'react-transition-group/cjs/TransitionGroupContext.js',
|
|
1328
|
+
default: {
|
|
1329
|
+
import: 'react-transition-group/esm/TransitionGroupContext.js',
|
|
1330
|
+
require: 'react-transition-group/cjs/TransitionGroupContext.js',
|
|
1331
|
+
default: 'react-transition-group/esm/TransitionGroupContext.js',
|
|
1332
|
+
},
|
|
1333
|
+
},
|
|
1334
|
+
},
|
|
1335
|
+
{
|
|
1336
|
+
bundles: [
|
|
1337
|
+
{ type: 'esm', dir: '.' },
|
|
1338
|
+
{ type: 'cjs', dir: '.' },
|
|
1339
|
+
],
|
|
1340
|
+
cwd,
|
|
1341
|
+
isFlat: true,
|
|
1342
|
+
packageType: 'module',
|
|
1343
|
+
},
|
|
1344
|
+
);
|
|
1345
|
+
|
|
1346
|
+
expect(imports).toEqual({
|
|
1347
|
+
'#mui/TransitionGroupContext': {
|
|
1348
|
+
node: 'react-transition-group/cjs/TransitionGroupContext.js',
|
|
1349
|
+
default: {
|
|
1350
|
+
import: 'react-transition-group/esm/TransitionGroupContext.js',
|
|
1351
|
+
require: 'react-transition-group/cjs/TransitionGroupContext.js',
|
|
1352
|
+
default: 'react-transition-group/esm/TransitionGroupContext.js',
|
|
1353
|
+
},
|
|
1354
|
+
},
|
|
1355
|
+
});
|
|
1356
|
+
});
|
|
1284
1357
|
});
|
package/src/utils/pnpm.mjs
CHANGED
|
@@ -5,6 +5,7 @@ import { $ } from 'execa';
|
|
|
5
5
|
import * as fs from 'node:fs/promises';
|
|
6
6
|
import * as path from 'node:path';
|
|
7
7
|
import * as semver from 'semver';
|
|
8
|
+
import { parseDocument, isMap } from 'yaml';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* @typedef {Object} PrivatePackage
|
|
@@ -385,6 +386,68 @@ export async function writePackageJson(packagePath, packageJson) {
|
|
|
385
386
|
await fs.writeFile(path.join(packagePath, 'package.json'), content);
|
|
386
387
|
}
|
|
387
388
|
|
|
389
|
+
/**
|
|
390
|
+
* Write the computed overrides into whichever manifest already defines
|
|
391
|
+
* overrides — preferring pnpm-workspace.yaml, falling back to package.json
|
|
392
|
+
* `pnpm.overrides`, defaulting to pnpm-workspace.yaml — and persist the result.
|
|
393
|
+
* A missing pnpm-workspace.yaml is treated as empty, so a fresh file is created
|
|
394
|
+
* with just the `overrides:` block. Rejects a `resolutions` field in
|
|
395
|
+
* package.json because pnpm 11 silently ignores it.
|
|
396
|
+
*
|
|
397
|
+
* @param {string} workspaceDir - Workspace root directory
|
|
398
|
+
* @param {Record<string, string>} overrides - Overrides to apply
|
|
399
|
+
* @returns {Promise<void>}
|
|
400
|
+
*/
|
|
401
|
+
export async function writeOverridesToWorkspace(workspaceDir, overrides) {
|
|
402
|
+
const workspaceYamlPath = path.join(workspaceDir, 'pnpm-workspace.yaml');
|
|
403
|
+
const yamlPromise = fs.readFile(workspaceYamlPath, { encoding: 'utf8' }).catch((error) => {
|
|
404
|
+
if (/** @type {NodeJS.ErrnoException} */ (error).code !== 'ENOENT') {
|
|
405
|
+
throw error;
|
|
406
|
+
}
|
|
407
|
+
return '';
|
|
408
|
+
});
|
|
409
|
+
const [rootPackageJson, yamlSource] = await Promise.all([
|
|
410
|
+
readPackageJson(workspaceDir),
|
|
411
|
+
yamlPromise,
|
|
412
|
+
]);
|
|
413
|
+
|
|
414
|
+
const { resolutions } = rootPackageJson;
|
|
415
|
+
if (resolutions && Object.keys(resolutions).length > 0) {
|
|
416
|
+
throw new Error(
|
|
417
|
+
'Found a "resolutions" field in package.json. pnpm 11 ignores it silently. ' +
|
|
418
|
+
'Move those entries into the "overrides:" key of pnpm-workspace.yaml.',
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// Parsed once, reused for both the read (does it have overrides?) and the write.
|
|
423
|
+
const doc = parseDocument(yamlSource);
|
|
424
|
+
const existing = doc.get('overrides');
|
|
425
|
+
const workspaceHasOverrides = isMap(existing) && existing.items.length > 0;
|
|
426
|
+
|
|
427
|
+
const pnpm = /** @type {{ overrides?: Record<string, string> } | undefined} */ (
|
|
428
|
+
rootPackageJson.pnpm
|
|
429
|
+
);
|
|
430
|
+
const packageJsonOverrides = pnpm?.overrides;
|
|
431
|
+
|
|
432
|
+
// Write where overrides already live; default to the workspace file.
|
|
433
|
+
if (
|
|
434
|
+
!workspaceHasOverrides &&
|
|
435
|
+
packageJsonOverrides &&
|
|
436
|
+
Object.keys(packageJsonOverrides).length > 0
|
|
437
|
+
) {
|
|
438
|
+
await writePackageJson(workspaceDir, {
|
|
439
|
+
...rootPackageJson,
|
|
440
|
+
pnpm: { ...pnpm, overrides: { ...packageJsonOverrides, ...overrides } },
|
|
441
|
+
});
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
for (const [name, version] of Object.entries(overrides)) {
|
|
446
|
+
doc.setIn(['overrides', name], version);
|
|
447
|
+
}
|
|
448
|
+
await fs.writeFile(workspaceYamlPath, doc.toString());
|
|
449
|
+
}
|
|
450
|
+
|
|
388
451
|
/**
|
|
389
452
|
* Resolve a package@version specifier to an exact version
|
|
390
453
|
* @param {string} packageSpec - Package specifier in format "package@version"
|
package/src/utils/pnpm.test.mjs
CHANGED
|
@@ -3,7 +3,12 @@ import * as path from 'node:path';
|
|
|
3
3
|
import { describe, it, expect } from 'vitest';
|
|
4
4
|
|
|
5
5
|
import { makeTempDir } from './testUtils.mjs';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
checkPublishDependencies,
|
|
8
|
+
readPackageJson,
|
|
9
|
+
writePackageJson,
|
|
10
|
+
writeOverridesToWorkspace,
|
|
11
|
+
} from './pnpm.mjs';
|
|
7
12
|
|
|
8
13
|
/**
|
|
9
14
|
* Write a package.json file to a temp subdirectory and return the directory path.
|
|
@@ -578,3 +583,149 @@ describe('checkPublishDependencies', () => {
|
|
|
578
583
|
});
|
|
579
584
|
});
|
|
580
585
|
});
|
|
586
|
+
|
|
587
|
+
/**
|
|
588
|
+
* Set up a temp workspace with a package.json and optional pnpm-workspace.yaml.
|
|
589
|
+
* @param {object} packageJson - package.json contents
|
|
590
|
+
* @param {string} [workspaceYaml] - pnpm-workspace.yaml contents, omitted to skip the file
|
|
591
|
+
* @returns {Promise<string>} The workspace directory
|
|
592
|
+
*/
|
|
593
|
+
async function makeWorkspace(packageJson, workspaceYaml) {
|
|
594
|
+
const cwd = await makeTempDir();
|
|
595
|
+
const writes = [writePackageJson(cwd, packageJson)];
|
|
596
|
+
if (workspaceYaml !== undefined) {
|
|
597
|
+
writes.push(fs.writeFile(path.join(cwd, 'pnpm-workspace.yaml'), workspaceYaml));
|
|
598
|
+
}
|
|
599
|
+
await Promise.all(writes);
|
|
600
|
+
return cwd;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
/**
|
|
604
|
+
* @param {string} cwd
|
|
605
|
+
* @returns {Promise<string>}
|
|
606
|
+
*/
|
|
607
|
+
function readWorkspaceYaml(cwd) {
|
|
608
|
+
return fs.readFile(path.join(cwd, 'pnpm-workspace.yaml'), 'utf8');
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
describe('writeOverridesToWorkspace', () => {
|
|
612
|
+
describe('writing to pnpm-workspace.yaml', () => {
|
|
613
|
+
it('creates the file with an overrides block when none exists', async () => {
|
|
614
|
+
const cwd = await makeWorkspace({ name: 'root' });
|
|
615
|
+
|
|
616
|
+
await writeOverridesToWorkspace(cwd, { foo: '1.2.3' });
|
|
617
|
+
|
|
618
|
+
expect(await readWorkspaceYaml(cwd)).toMatchInlineSnapshot(`
|
|
619
|
+
"overrides:
|
|
620
|
+
foo: 1.2.3
|
|
621
|
+
"
|
|
622
|
+
`);
|
|
623
|
+
});
|
|
624
|
+
|
|
625
|
+
it('merges into an existing block, preserving comments and quoting scoped names', async () => {
|
|
626
|
+
const cwd = await makeWorkspace(
|
|
627
|
+
{ name: 'root' },
|
|
628
|
+
[
|
|
629
|
+
'packages:',
|
|
630
|
+
" - 'packages/*'",
|
|
631
|
+
'overrides:',
|
|
632
|
+
' # keep this pin',
|
|
633
|
+
" bar: '2.0.0'",
|
|
634
|
+
'',
|
|
635
|
+
].join('\n'),
|
|
636
|
+
);
|
|
637
|
+
|
|
638
|
+
await writeOverridesToWorkspace(cwd, { playwright: '1.49.1', '@playwright/test': '1.49.1' });
|
|
639
|
+
|
|
640
|
+
expect(await readWorkspaceYaml(cwd)).toMatchInlineSnapshot(`
|
|
641
|
+
"packages:
|
|
642
|
+
- 'packages/*'
|
|
643
|
+
overrides:
|
|
644
|
+
# keep this pin
|
|
645
|
+
bar: '2.0.0'
|
|
646
|
+
playwright: 1.49.1
|
|
647
|
+
"@playwright/test": 1.49.1
|
|
648
|
+
"
|
|
649
|
+
`);
|
|
650
|
+
// The package.json is left untouched.
|
|
651
|
+
expect(await readPackageJson(cwd)).toEqual({ name: 'root' });
|
|
652
|
+
});
|
|
653
|
+
|
|
654
|
+
it('overwrites a same-named override, keeping its quote style', async () => {
|
|
655
|
+
const cwd = await makeWorkspace(
|
|
656
|
+
{ name: 'root' },
|
|
657
|
+
['overrides:', " foo: '1.0.0'", ''].join('\n'),
|
|
658
|
+
);
|
|
659
|
+
|
|
660
|
+
await writeOverridesToWorkspace(cwd, { foo: '2.0.0' });
|
|
661
|
+
|
|
662
|
+
expect(await readWorkspaceYaml(cwd)).toMatchInlineSnapshot(`
|
|
663
|
+
"overrides:
|
|
664
|
+
foo: '2.0.0'
|
|
665
|
+
"
|
|
666
|
+
`);
|
|
667
|
+
});
|
|
668
|
+
|
|
669
|
+
it('prefers the workspace file when both manifests define overrides', async () => {
|
|
670
|
+
const cwd = await makeWorkspace(
|
|
671
|
+
{ name: 'root', pnpm: { overrides: { baz: '3.0.0' } } },
|
|
672
|
+
['overrides:', " bar: '2.0.0'", ''].join('\n'),
|
|
673
|
+
);
|
|
674
|
+
|
|
675
|
+
await writeOverridesToWorkspace(cwd, { foo: '1.2.3' });
|
|
676
|
+
|
|
677
|
+
expect(await readWorkspaceYaml(cwd)).toContain('foo: 1.2.3');
|
|
678
|
+
// package.json overrides are left where they were.
|
|
679
|
+
expect(await readPackageJson(cwd)).toEqual({
|
|
680
|
+
name: 'root',
|
|
681
|
+
pnpm: { overrides: { baz: '3.0.0' } },
|
|
682
|
+
});
|
|
683
|
+
});
|
|
684
|
+
});
|
|
685
|
+
|
|
686
|
+
describe('writing to package.json', () => {
|
|
687
|
+
it('honors the package.json location when no workspace overrides exist', async () => {
|
|
688
|
+
const cwd = await makeWorkspace({
|
|
689
|
+
name: 'root',
|
|
690
|
+
pnpm: { overrides: { foo: '1.0.0' }, packageExtensions: { thing: {} } },
|
|
691
|
+
});
|
|
692
|
+
|
|
693
|
+
await writeOverridesToWorkspace(cwd, { bar: '2.0.0' });
|
|
694
|
+
|
|
695
|
+
expect(await readPackageJson(cwd)).toEqual({
|
|
696
|
+
name: 'root',
|
|
697
|
+
pnpm: { overrides: { foo: '1.0.0', bar: '2.0.0' }, packageExtensions: { thing: {} } },
|
|
698
|
+
});
|
|
699
|
+
// No workspace file is created.
|
|
700
|
+
await expect(fs.access(path.join(cwd, 'pnpm-workspace.yaml'))).rejects.toThrow();
|
|
701
|
+
});
|
|
702
|
+
|
|
703
|
+
it('lets computed overrides win over an existing package.json override', async () => {
|
|
704
|
+
const cwd = await makeWorkspace({ name: 'root', pnpm: { overrides: { foo: '1.0.0' } } });
|
|
705
|
+
|
|
706
|
+
await writeOverridesToWorkspace(cwd, { foo: '2.0.0' });
|
|
707
|
+
|
|
708
|
+
expect(await readPackageJson(cwd)).toEqual({
|
|
709
|
+
name: 'root',
|
|
710
|
+
pnpm: { overrides: { foo: '2.0.0' } },
|
|
711
|
+
});
|
|
712
|
+
});
|
|
713
|
+
});
|
|
714
|
+
|
|
715
|
+
describe('rejecting resolutions', () => {
|
|
716
|
+
it('throws and writes nothing when package.json has a resolutions field', async () => {
|
|
717
|
+
const cwd = await makeWorkspace({ name: 'root', resolutions: { foo: '1.0.0' } });
|
|
718
|
+
|
|
719
|
+
await expect(writeOverridesToWorkspace(cwd, { bar: '2.0.0' })).rejects.toThrow(/resolutions/);
|
|
720
|
+
await expect(fs.access(path.join(cwd, 'pnpm-workspace.yaml'))).rejects.toThrow();
|
|
721
|
+
});
|
|
722
|
+
|
|
723
|
+
it('ignores an empty resolutions field', async () => {
|
|
724
|
+
const cwd = await makeWorkspace({ name: 'root', resolutions: {} });
|
|
725
|
+
|
|
726
|
+
await writeOverridesToWorkspace(cwd, { foo: '1.2.3' });
|
|
727
|
+
|
|
728
|
+
expect(await readWorkspaceYaml(cwd)).toContain('foo: 1.2.3');
|
|
729
|
+
});
|
|
730
|
+
});
|
|
731
|
+
});
|