Skip to content

Commit

Permalink
[core] Export functions from copyFiles script to reuse in MUI X repo (
Browse files Browse the repository at this point in the history
  • Loading branch information
cherniavskii committed Feb 8, 2024
1 parent 7c9ba66 commit 97bd4c7
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 117 deletions.
124 changes: 7 additions & 117 deletions scripts/copyFiles.mjs
Original file line number Diff line number Diff line change
@@ -1,127 +1,17 @@
/* eslint-disable no-console */
import path from 'path';
import fse from 'fs-extra';
import glob from 'fast-glob';
import {
createModulePackages,
createPackageFile,
includeFileInBuild,
prepend,
typescriptCopy,
} from './copyFilesUtils.mjs';

const packagePath = process.cwd();
const buildPath = path.join(packagePath, './build');
const srcPath = path.join(packagePath, './src');

async function includeFileInBuild(file) {
const sourcePath = path.resolve(packagePath, file);
const targetPath = path.resolve(buildPath, path.basename(file));
await fse.copy(sourcePath, targetPath);
console.log(`Copied ${sourcePath} to ${targetPath}`);
}

/**
* Puts a package.json into every immediate child directory of rootDir.
* That package.json contains information about esm for bundlers so that imports
* like import Typography from '@mui/material/Typography' are tree-shakeable.
*
* It also tests that an this import can be used in TypeScript by checking
* if an index.d.ts is present at that path.
* @param {object} param0
* @param {string} param0.from
* @param {string} param0.to
*/
async function createModulePackages({ from, to }) {
const directoryPackages = glob.sync('*/index.{js,ts,tsx}', { cwd: from }).map(path.dirname);

await Promise.all(
directoryPackages.map(async (directoryPackage) => {
const packageJsonPath = path.join(to, directoryPackage, 'package.json');
const topLevelPathImportsAreCommonJSModules = await fse.pathExists(
path.resolve(path.dirname(packageJsonPath), '../esm'),
);

const packageJson = {
sideEffects: false,
module: topLevelPathImportsAreCommonJSModules
? path.posix.join('../esm', directoryPackage, 'index.js')
: './index.js',
main: topLevelPathImportsAreCommonJSModules
? './index.js'
: path.posix.join('../node', directoryPackage, 'index.js'),
types: './index.d.ts',
};

const [typingsEntryExist, moduleEntryExists, mainEntryExists] = await Promise.all([
fse.pathExists(path.resolve(path.dirname(packageJsonPath), packageJson.types)),
fse.pathExists(path.resolve(path.dirname(packageJsonPath), packageJson.module)),
fse.pathExists(path.resolve(path.dirname(packageJsonPath), packageJson.main)),
fse.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2)),
]);

const manifestErrorMessages = [];
if (!typingsEntryExist) {
manifestErrorMessages.push(`'types' entry '${packageJson.types}' does not exist`);
}
if (!moduleEntryExists) {
manifestErrorMessages.push(`'module' entry '${packageJson.module}' does not exist`);
}
if (!mainEntryExists) {
manifestErrorMessages.push(`'main' entry '${packageJson.main}' does not exist`);
}
if (manifestErrorMessages.length > 0) {
// TODO: AggregateError
throw new Error(`${packageJsonPath}:\n${manifestErrorMessages.join('\n')}`);
}

return packageJsonPath;
}),
);
}

async function typescriptCopy({ from, to }) {
if (!(await fse.pathExists(to))) {
console.warn(`path ${to} does not exists`);
return [];
}

const files = await glob('**/*.d.ts', { cwd: from });
const cmds = files.map((file) => fse.copy(path.resolve(from, file), path.resolve(to, file)));
return Promise.all(cmds);
}

async function createPackageFile() {
const packageData = await fse.readFile(path.resolve(packagePath, './package.json'), 'utf8');
const { nyc, scripts, devDependencies, workspaces, ...packageDataOther } =
JSON.parse(packageData);

const newPackageData = {
...packageDataOther,
private: false,
...(packageDataOther.main
? {
main: fse.existsSync(path.resolve(buildPath, './node/index.js'))
? './node/index.js'
: './index.js',
module: fse.existsSync(path.resolve(buildPath, './esm/index.js'))
? './esm/index.js'
: './index.js',
}
: {}),
};

const typeDefinitionsFilePath = path.resolve(buildPath, './index.d.ts');
if (await fse.pathExists(typeDefinitionsFilePath)) {
newPackageData.types = './index.d.ts';
}

const targetPath = path.resolve(buildPath, './package.json');

await fse.writeFile(targetPath, JSON.stringify(newPackageData, null, 2), 'utf8');
console.log(`Created package.json in ${targetPath}`);

return newPackageData;
}

async function prepend(file, string) {
const data = await fse.readFile(file, 'utf8');
await fse.writeFile(file, string + data, 'utf8');
}

async function addLicense(packageData) {
const license = `/**
* ${packageData.name} v${packageData.version}
Expand Down
122 changes: 122 additions & 0 deletions scripts/copyFilesUtils.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/* eslint-disable no-console */
import path from 'path';
import fse from 'fs-extra';
import glob from 'fast-glob';

const packagePath = process.cwd();
const buildPath = path.join(packagePath, './build');

export async function includeFileInBuild(file) {
const sourcePath = path.resolve(packagePath, file);
const targetPath = path.resolve(buildPath, path.basename(file));
await fse.copy(sourcePath, targetPath);
console.log(`Copied ${sourcePath} to ${targetPath}`);
}

/**
* Puts a package.json into every immediate child directory of rootDir.
* That package.json contains information about esm for bundlers so that imports
* like import Typography from '@mui/material/Typography' are tree-shakeable.
*
* It also tests that an this import can be used in TypeScript by checking
* if an index.d.ts is present at that path.
* @param {object} param0
* @param {string} param0.from
* @param {string} param0.to
*/
export async function createModulePackages({ from, to }) {
const directoryPackages = glob.sync('*/index.{js,ts,tsx}', { cwd: from }).map(path.dirname);

await Promise.all(
directoryPackages.map(async (directoryPackage) => {
const packageJsonPath = path.join(to, directoryPackage, 'package.json');
const topLevelPathImportsAreCommonJSModules = await fse.pathExists(
path.resolve(path.dirname(packageJsonPath), '../esm'),
);

const packageJson = {
sideEffects: false,
module: topLevelPathImportsAreCommonJSModules
? path.posix.join('../esm', directoryPackage, 'index.js')
: './index.js',
main: topLevelPathImportsAreCommonJSModules
? './index.js'
: path.posix.join('../node', directoryPackage, 'index.js'),
types: './index.d.ts',
};

const [typingsEntryExist, moduleEntryExists, mainEntryExists] = await Promise.all([
fse.pathExists(path.resolve(path.dirname(packageJsonPath), packageJson.types)),
fse.pathExists(path.resolve(path.dirname(packageJsonPath), packageJson.module)),
fse.pathExists(path.resolve(path.dirname(packageJsonPath), packageJson.main)),
fse.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2)),
]);

const manifestErrorMessages = [];
if (!typingsEntryExist) {
manifestErrorMessages.push(`'types' entry '${packageJson.types}' does not exist`);
}
if (!moduleEntryExists) {
manifestErrorMessages.push(`'module' entry '${packageJson.module}' does not exist`);
}
if (!mainEntryExists) {
manifestErrorMessages.push(`'main' entry '${packageJson.main}' does not exist`);
}
if (manifestErrorMessages.length > 0) {
// TODO: AggregateError
throw new Error(`${packageJsonPath}:\n${manifestErrorMessages.join('\n')}`);
}

return packageJsonPath;
}),
);
}

export async function typescriptCopy({ from, to }) {
if (!(await fse.pathExists(to))) {
console.warn(`path ${to} does not exists`);
return [];
}

const files = await glob('**/*.d.ts', { cwd: from });
const cmds = files.map((file) => fse.copy(path.resolve(from, file), path.resolve(to, file)));
return Promise.all(cmds);
}

export async function createPackageFile() {
const packageData = await fse.readFile(path.resolve(packagePath, './package.json'), 'utf8');
const { nyc, scripts, devDependencies, workspaces, ...packageDataOther } =
JSON.parse(packageData);

const newPackageData = {
...packageDataOther,
private: false,
...(packageDataOther.main
? {
main: fse.existsSync(path.resolve(buildPath, './node/index.js'))
? './node/index.js'
: './index.js',
module: fse.existsSync(path.resolve(buildPath, './esm/index.js'))
? './esm/index.js'
: './index.js',
}
: {}),
};

const typeDefinitionsFilePath = path.resolve(buildPath, './index.d.ts');
if (await fse.pathExists(typeDefinitionsFilePath)) {
newPackageData.types = './index.d.ts';
}

const targetPath = path.resolve(buildPath, './package.json');

await fse.writeFile(targetPath, JSON.stringify(newPackageData, null, 2), 'utf8');
console.log(`Created package.json in ${targetPath}`);

return newPackageData;
}

export async function prepend(file, string) {
const data = await fse.readFile(file, 'utf8');
await fse.writeFile(file, string + data, 'utf8');
}

0 comments on commit 97bd4c7

Please sign in to comment.