@mui/internal-code-infra 0.0.3-canary.6 → 0.0.3-canary.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mui/internal-code-infra",
3
- "version": "0.0.3-canary.6",
3
+ "version": "0.0.3-canary.8",
4
4
  "description": "Infra scripts and configs to be used across MUI repos.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -93,7 +93,7 @@
93
93
  "publishConfig": {
94
94
  "access": "public"
95
95
  },
96
- "gitSha": "b76c4e6f0a445cd70cf69bb4513802a108d24e2c",
96
+ "gitSha": "0224fd29f46991b95d9489c62cd138e10dccd65a",
97
97
  "scripts": {
98
98
  "typescript": "tsc -p tsconfig.json",
99
99
  "test": "pnpm -w test --project @mui/internal-code-infra",
@@ -13,7 +13,7 @@ import pluginRemovePropTypes from 'babel-plugin-transform-react-remove-prop-type
13
13
  * @param {boolean} [param0.debug]
14
14
  * @param {boolean} [param0.optimizeClsx]
15
15
  * @param {boolean} [param0.removePropTypes]
16
- * @param {boolean} [param0.isTest]
16
+ * @param {boolean} [param0.noResolveImports]
17
17
  * @param {'cjs' | 'esm'} param0.bundle
18
18
  * @param {string | null} param0.outExtension - Specify the output file extension.
19
19
  * @param {string} param0.runtimeVersion
@@ -23,7 +23,7 @@ export function getBaseConfig({
23
23
  debug = false,
24
24
  optimizeClsx = false,
25
25
  removePropTypes = false,
26
- isTest = false,
26
+ noResolveImports = false,
27
27
  bundle,
28
28
  runtimeVersion,
29
29
  outExtension,
@@ -81,7 +81,7 @@ export function getBaseConfig({
81
81
  plugins.push([pluginOptimizeClsx, {}, 'babel-plugin-optimize-clsx']);
82
82
  }
83
83
 
84
- if (bundle === 'esm' && !isTest) {
84
+ if (bundle === 'esm' && !noResolveImports) {
85
85
  plugins.push([
86
86
  pluginResolveImports,
87
87
  { outExtension },
@@ -119,20 +119,39 @@ export function getBaseConfig({
119
119
  }
120
120
 
121
121
  /**
122
- * @type {import('@babel/core').ConfigFunction}
122
+ * @typedef {Object} Options
123
+ * @prop {'esm' | 'cjs'} [Options.bundle]
124
+ * @prop {boolean} [Options.noResolveImports]
125
+ * @prop {undefined} [options.env]
126
+ */
127
+
128
+ /**
129
+ * @param {import('@babel/core').ConfigAPI | Options} api
130
+ * @returns {import('@babel/core').TransformOptions}
123
131
  */
124
132
  export default function getBabelConfig(api) {
125
- const isStable = api.env(['regressions', 'stable']);
126
- const isTest = api.env('test') || process.env.NODE_ENV === 'test';
133
+ /** @type {'esm' | 'cjs'} */
134
+ let bundle;
135
+ /** @type {boolean} */
136
+ let noResolveImports;
137
+
138
+ if (api.env) {
139
+ // legacy
140
+ bundle = api.env(['regressions', 'stable']) ? 'esm' : 'cjs';
141
+ noResolveImports = api.env('test') || process.env.NODE_ENV === 'test';
142
+ } else {
143
+ bundle = api.bundle || 'esm';
144
+ noResolveImports = api.noResolveImports || false;
145
+ }
127
146
 
128
147
  return getBaseConfig({
129
148
  debug: process.env.MUI_BUILD_VERBOSE === 'true',
130
- bundle: isStable ? 'esm' : 'cjs',
149
+ bundle,
131
150
  outExtension: process.env.MUI_OUT_FILE_EXTENSION || null,
132
151
  // any package needs to declare 7.25.0 as a runtime dependency. default is ^7.0.0
133
152
  runtimeVersion: process.env.MUI_BABEL_RUNTIME_VERSION || '^7.25.0',
134
153
  optimizeClsx: process.env.MUI_OPTIMIZE_CLSX === 'true',
135
154
  removePropTypes: process.env.MUI_REMOVE_PROP_TYPES === 'true',
136
- isTest,
155
+ noResolveImports,
137
156
  });
138
157
  }
@@ -1,9 +1,13 @@
1
1
  /* eslint-disable no-console */
2
+ import { findWorkspaceDir } from '@pnpm/find-workspace-dir';
2
3
  import { $ } from 'execa';
4
+ import { globby } from 'globby';
3
5
  import set from 'lodash-es/set.js';
4
6
  import * as fs from 'node:fs/promises';
5
7
  import * as path from 'node:path';
6
- import { getOutExtension, isMjsBuild, validatePkgJson } from '../utils/build.mjs';
8
+ import { sep as posixSep } from 'node:path/posix';
9
+
10
+ import { getOutExtension, isMjsBuild, mapConcurrently, validatePkgJson } from '../utils/build.mjs';
7
11
 
8
12
  /**
9
13
  * @typedef {Object} Args
@@ -18,6 +22,7 @@ import { getOutExtension, isMjsBuild, validatePkgJson } from '../utils/build.mjs
18
22
  * @property {boolean} skipPackageJson - Whether to skip generating the package.json file in the bundle output.
19
23
  * @property {boolean} skipMainCheck - Whether to skip checking for main field in package.json.
20
24
  * @property {string[]} ignore - Globs to be ignored by Babel.
25
+ * @property {string[]} [copy] - Files/Directories to be copied. Can be a glob pattern.
21
26
  */
22
27
 
23
28
  const validBundles = [
@@ -298,6 +303,13 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
298
303
  type: 'boolean',
299
304
  default: false,
300
305
  description: 'Skip checking for main field in package.json.',
306
+ })
307
+ .option('copy', {
308
+ type: 'string',
309
+ array: true,
310
+ description:
311
+ 'Files/Directories to be copied to the output directory. Can be a glob pattern.',
312
+ default: [],
301
313
  });
302
314
  },
303
315
  async handler(args) {
@@ -442,5 +454,144 @@ export default /** @type {import('yargs').CommandModule<{}, Args>} */ ({
442
454
  outputDir: buildDir,
443
455
  addTypes: buildTypes,
444
456
  });
457
+
458
+ await copyHandler({
459
+ cwd,
460
+ globs: args.copy ?? [],
461
+ buildDir,
462
+ verbose: args.verbose,
463
+ });
445
464
  },
446
465
  });
466
+
467
+ /**
468
+ * @param {Object} param0
469
+ * @param {string} param0.cwd - The current working directory.
470
+ * @param {string[]} [param0.globs=[]] - Extra files to copy, can be specified as `source:target` pairs or just `source`.
471
+ * @param {string} param0.buildDir - The build directory to copy to.
472
+ * @param {boolean} [param0.verbose=false] - Whether to suppress output.
473
+ * @returns {Promise<void>}
474
+ */
475
+ async function copyHandler({ cwd, globs = [], buildDir, verbose = false }) {
476
+ /**
477
+ * @type {(string|{targetPath: string; sourcePath: string})[]}
478
+ */
479
+ const defaultFiles = [];
480
+ const workspaceDir = await findWorkspaceDir(cwd);
481
+ if (!workspaceDir) {
482
+ throw new Error('Workspace directory not found');
483
+ }
484
+
485
+ const localOrRootFiles = [
486
+ [path.join(cwd, 'README.md'), path.join(workspaceDir, 'README.md')],
487
+ [path.join(cwd, 'LICENSE'), path.join(workspaceDir, 'LICENSE')],
488
+ [path.join(cwd, 'CHANGELOG.md'), path.join(workspaceDir, 'CHANGELOG.md')],
489
+ ];
490
+ await Promise.all(
491
+ localOrRootFiles.map(async (filesToCopy) => {
492
+ for (const file of filesToCopy) {
493
+ if (
494
+ // eslint-disable-next-line no-await-in-loop
495
+ await fs.stat(file).then(
496
+ () => true,
497
+ () => false,
498
+ )
499
+ ) {
500
+ defaultFiles.push(file);
501
+ break;
502
+ }
503
+ }
504
+ }),
505
+ );
506
+
507
+ if (globs.length) {
508
+ const res = globs.map((globPattern) => {
509
+ const [pattern, baseDir] = globPattern.split(':');
510
+ return { pattern, baseDir };
511
+ });
512
+ /**
513
+ * Avoids redundant globby calls for the same pattern.
514
+ *
515
+ * @type {Map<string, Promise<string[]>>}
516
+ */
517
+ const globToResMap = new Map();
518
+
519
+ const result = await Promise.all(
520
+ res.map(async ({ pattern, baseDir }) => {
521
+ if (!globToResMap.has(pattern)) {
522
+ const promise = globby(pattern, { cwd });
523
+ globToResMap.set(pattern, promise);
524
+ }
525
+ const files = await globToResMap.get(pattern);
526
+ return { files: files ?? [], baseDir };
527
+ }),
528
+ );
529
+ globToResMap.clear();
530
+
531
+ result.forEach(({ files, baseDir }) => {
532
+ files.forEach((file) => {
533
+ const sourcePath = path.resolve(cwd, file);
534
+ // Use posix separator for the relative paths. So devs can only specify globs with `/` even on Windows.
535
+ const pathSegments = file.split(posixSep);
536
+ const relativePath =
537
+ // Use index 2 (when required) since users can also specify paths like `./src/index.js`
538
+ pathSegments.slice(pathSegments[0] === '.' ? 2 : 1).join(posixSep) || file;
539
+ const targetPath = baseDir
540
+ ? path.resolve(buildDir, baseDir, relativePath)
541
+ : path.resolve(buildDir, relativePath);
542
+ defaultFiles.push({ sourcePath, targetPath });
543
+ });
544
+ });
545
+ }
546
+
547
+ if (!defaultFiles.length) {
548
+ if (verbose) {
549
+ console.log('⓿ No files to copy.');
550
+ }
551
+ }
552
+ await mapConcurrently(
553
+ defaultFiles,
554
+ async (file) => {
555
+ if (typeof file === 'string') {
556
+ const sourcePath = file;
557
+ const fileName = path.basename(file);
558
+ const targetPath = path.join(buildDir, fileName);
559
+ await recursiveCopy({ source: sourcePath, target: targetPath, verbose });
560
+ } else {
561
+ await fs.mkdir(path.dirname(file.targetPath), { recursive: true });
562
+ await recursiveCopy({ source: file.sourcePath, target: file.targetPath, verbose });
563
+ }
564
+ },
565
+ 20,
566
+ );
567
+ console.log(`📋 Copied ${defaultFiles.length} files.`);
568
+ }
569
+
570
+ /**
571
+ * Recursively copies files and directories from a source path to a target path.
572
+ *
573
+ * @async
574
+ * @param {Object} options - The options for copying files.
575
+ * @param {string} options.source - The source path to copy from.
576
+ * @param {string} options.target - The target path to copy to.
577
+ * @param {boolean} [options.verbose=true] - If true, suppresses console output.
578
+ * @returns {Promise<boolean>} Resolves when the copy operation is complete.
579
+ * @throws {Error} Throws if an error occurs other than the source not existing.
580
+ */
581
+ async function recursiveCopy({ source, target, verbose = true }) {
582
+ try {
583
+ await fs.cp(source, target, { recursive: true });
584
+ if (verbose) {
585
+ console.log(`Copied ${source} to ${target}`);
586
+ }
587
+ return true;
588
+ } catch (err) {
589
+ if (/** @type {{ code: string }} */ (err).code !== 'ENOENT') {
590
+ throw err;
591
+ }
592
+ if (verbose) {
593
+ console.warn(`Source does not exist: ${source}`);
594
+ }
595
+ throw err;
596
+ }
597
+ }
@@ -8,6 +8,7 @@ import { globby } from 'globby';
8
8
  import * as fs from 'node:fs/promises';
9
9
  import * as os from 'node:os';
10
10
  import * as path from 'node:path';
11
+ import { mapConcurrently } from '../utils/build.mjs';
11
12
 
12
13
  const $$ = $({ stdio: 'inherit' });
13
14
 
@@ -27,7 +28,8 @@ export async function emitDeclarations(tsconfig, outDir) {
27
28
  --emitDeclarationOnly
28
29
  --noEmit false
29
30
  --composite false
30
- --incremental false`;
31
+ --incremental false
32
+ --declarationMap false`;
31
33
  }
32
34
 
33
35
  /**
@@ -80,8 +82,9 @@ async function postProcessDeclarations({ directory }) {
80
82
  [pluginRemoveImports, { test: /\.css$/ }],
81
83
  ];
82
84
 
83
- await Promise.all(
84
- dtsFiles.map(async (dtsFile) => {
85
+ await mapConcurrently(
86
+ dtsFiles,
87
+ async (dtsFile) => {
85
88
  const result = await babel.transformFileAsync(dtsFile, {
86
89
  configFile: false,
87
90
  plugins: babelPlugins,
@@ -92,7 +95,8 @@ async function postProcessDeclarations({ directory }) {
92
95
  } else {
93
96
  console.error('failed to transform', dtsFile);
94
97
  }
95
- }),
98
+ },
99
+ 20,
96
100
  );
97
101
  }
98
102
 
@@ -107,11 +111,13 @@ async function renameDeclarations({ directory }) {
107
111
  return;
108
112
  }
109
113
  console.log(`Renaming d.ts files to d.mts in ${directory}`);
110
- await Promise.all(
111
- dtsFiles.map(async (dtsFile) => {
114
+ await mapConcurrently(
115
+ dtsFiles,
116
+ async (dtsFile) => {
112
117
  const newFileName = dtsFile.replace(/\.d\.ts$/, '.d.mts');
113
118
  await fs.rename(dtsFile, newFileName);
114
- }),
119
+ },
120
+ 20,
115
121
  );
116
122
  }
117
123