Last active
April 18, 2024 21:04
-
-
Save maksimr/dc80652c63abfa287e0f8d98f2a094ef to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
async function main() { | |
const fs = require('fs/promises'); | |
const os = require('os'); | |
const path = require('path'); | |
const promisify = require('util').promisify; | |
const babelParentDir = path.resolve(__dirname, '..', 'packages'); | |
const babelParserDir = path.join(babelParentDir, 'babel-parser') | |
const babelPackageName = '@packages/babel-parser'; | |
const babelOutDir = 'lib'; | |
const babelVersion = process.argv[2] || 'v7.24.4'; | |
const babelCloneDir = path.join(os.tmpdir(), `babel-${babelVersion}`); | |
await cloneBabelParser(babelCloneDir, babelVersion); | |
await copyBabelParser(babelCloneDir); | |
await Promise.all([ | |
await removeTsExtensionFromImportAndTsExpectError(), | |
await patchPackageJson(babelCloneDir), | |
await patchTsConfig() | |
]); | |
async function cloneBabelParser(babelCloneDir, version = 'main') { | |
await fs.mkdir(babelCloneDir, { recursive: true }); | |
const isNotEmpty = (await fs.readdir(babelCloneDir)).length > 0; | |
if (isNotEmpty) { | |
console.log(`babel@${version} is already cloned to ${babelCloneDir}`); | |
return; | |
}; | |
console.log(`cloning babel@${version}`); | |
const exec = promisify(require('child_process').exec); | |
await exec(`git clone --depth=1 --branch=${version} https://github.com/babel/babel ${babelCloneDir}`) | |
console.log(`cloned babel@${version} to ${babelCloneDir}`); | |
} | |
async function copyBabelParser(babelCloneDir) { | |
console.log('copying babel-parser to the project'); | |
await fs.mkdir(babelParserDir, { recursive: true }); | |
await fs.cp(path.join(babelCloneDir, 'packages', 'babel-parser'), babelParserDir, { recursive: true }) | |
await fs.copyFile( | |
path.join(babelCloneDir, 'tsconfig.base.json'), | |
path.join(babelParserDir, 'tsconfig.json') | |
); | |
console.log('copied babel-parser') | |
} | |
async function getBabelPackagesVersion(babelCloneDir) { | |
const babelPackages = await fs.readdir(path.join(babelCloneDir, 'packages')); | |
const babelPackagesVersion = new Map(); | |
for (const package of babelPackages) { | |
try { | |
const pkg = require(path.join(babelCloneDir, 'packages', package, 'package.json')); | |
babelPackagesVersion.set(pkg.name, pkg.version); | |
} catch (error) { | |
continue; | |
} | |
} | |
return babelPackagesVersion; | |
} | |
async function patchPackageJson(babelCloneDir) { | |
console.log('patching package.json'); | |
const babelPackagesVersion = await getBabelPackagesVersion(babelCloneDir); | |
const pkg = require(path.join(babelParserDir, 'package.json')); | |
pkg.name = babelPackageName; | |
// patch workspace: dependencies | |
if (pkg.devDependencies) { | |
pkg.devDependencies = Object.fromEntries( | |
Object.entries(pkg.devDependencies).map(([name, version]) => { | |
if (/^workspace:/.test(version)) { | |
return [name, babelPackagesVersion.get(name)]; | |
} | |
return [name, version]; | |
}) | |
); | |
// add typescript and @types/node to build babel-parser | |
pkg.devDependencies["typescript"] = "5.4.5"; | |
pkg.devDependencies["@types/node"] = "20.12.7"; | |
// add @types/charcodes for charcodes | |
if (pkg.devDependencies['charcodes']) { | |
pkg.devDependencies['@types/charcodes'] = pkg.devDependencies['charcodes']; | |
} | |
// convert devDependencies to dependencies | |
// because we will build the package without inline dependencies | |
// how it is done in the babel project | |
pkg.dependencies = pkg.devDependencies; | |
pkg.devDependencies = undefined; | |
} | |
pkg.types = undefined; | |
pkg.conditions = undefined; | |
// add preapre and build script | |
pkg.scripts = pkg.scripts || {}; | |
pkg.scripts['prepare'] = 'npm run build'; | |
pkg.scripts['build'] = 'tsc'; | |
pkg.exports = pkg.exports || {}; | |
pkg.exports["./src/*"] = `./${babelOutDir}/*.js`; | |
await fs.writeFile(path.join(babelParserDir, 'package.json'), JSON.stringify(pkg, null, 2)); | |
console.log('patched package.json'); | |
} | |
async function removeTsExtensionFromImportAndTsExpectError() { | |
console.log('processing .ts files'); | |
const src = path.join(babelParserDir, 'src'); | |
processTsFiles(src, async (filePath) => { | |
const content = await fs.readFile(filePath, 'utf-8'); | |
let newContent = content.replace(/from (['"])(.+)\.ts['"];/g, 'from $1$2$1;'); | |
newContent = newContent.replace(/@ts-expect-error/g, '@ts-ignore'); | |
await fs.writeFile(filePath, newContent); | |
}); | |
console.log('processed .ts files'); | |
} | |
async function processTsFiles(dir, cb) { | |
const files = await fs.readdir(dir, { withFileTypes: true }); | |
for (const file of files) { | |
const filePath = path.join(dir, file.name); | |
if (file.isFile() && file.name.endsWith('.ts')) { | |
cb(filePath); | |
continue; | |
} | |
if (file.isDirectory()) { | |
processTsFiles(filePath, cb); | |
} | |
} | |
} | |
async function patchTsConfig() { | |
console.log('patching tsconfig.json'); | |
const tsConfigPath = path.resolve(babelParserDir, 'tsconfig.json'); | |
const babelBaseTsConfig = require(tsConfigPath); | |
const babelTsConfig = { | |
...babelBaseTsConfig, | |
/**@type {import('typescript').CompilerOptions} */ | |
compilerOptions: { | |
...babelBaseTsConfig.compilerOptions, | |
declarationDir: undefined, | |
emitDeclarationOnly: false, | |
skipLibCheck: false, | |
allowImportingTsExtensions: false, | |
outDir: babelOutDir, | |
noImplicitAny: false, | |
sourceMap: true, | |
module: 'commonjs', | |
moduleResolution: 'node', | |
incremental: true | |
}, | |
include: ["src"] | |
}; | |
await fs.writeFile(tsConfigPath, JSON.stringify(babelTsConfig, null, 2)); | |
console.log('patched tsconfig.json'); | |
} | |
} | |
main(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment