/** * Mixing glue with lint is probably something you never want to do in real * life, but in this project it helps the linter do its job. And sometimes the * test suite too. * * This script creates `index.ts` files in each package directory that simply * re-export the exports of the real main file. This is necessary for when all * the packages are run under a common context (instead of each individually). * This is because the symlinks bolt makes for each package are descendants of * the context node is running in and therefore aren't treated as modules, only * as directories. Therefore package.json isn't considered and we need an index * file (like index.ts) to redirect to the right file. */ import { promises as fs } from 'fs'; import path from 'path'; import { getPackageInfo } from './utils'; // NOTE: this interface only defines the fields in the package.json that are // used in this script interface PartialPackageManifest { main?: string; } /** * A heuristic to convert the `main` value from the package.json from its output * location to the source location (e.g. dist/ to src/ & .js to .ts). */ function convertMainToSrc(main: string): string { return main.replace(/^dist\//, 'src/').replace(/\.js$/, '.ts'); } (async () => { const pkgs = await getPackageInfo(); // Run each package in parallel await Promise.all( pkgs.map(async (pkg) => { // Extract the `main` field from the package.json const { main } = pkg.manifest as PartialPackageManifest; // Skip packages that have no main (e.g. the cli as of writing) if (main === undefined) { return; } // Read the main file const srcMain = convertMainToSrc(main); const srcMainFull = path.resolve(pkg.path, srcMain); const srcMainContents = await fs.readFile(srcMainFull, { encoding: 'utf8' }); // Detect if the package has a default export const hasDefault = /export\s+default/i.test(srcMainContents); // Write the facade entry-point file const importTarget = './' + srcMain.replace(/\.ts$/, ''); const facadeFilePath = path.resolve(pkg.path, 'index.ts'); let facadeFileContents = '// ⚠️ AUTOGENERATED ⚠️ AUTOGENERATED ⚠️ AUTOGENERATED ⚠️\n' + '// This file was automatically generated by `tools/gen-ts-glue.ts`. Do not modify directly if you want to keep your changes.\n' + `export * from "${importTarget}";\n`; if (hasDefault) { facadeFileContents += `import defaultExport from "${importTarget}";\n` + `export default defaultExport;\n`; } await fs.writeFile(facadeFilePath, facadeFileContents); }) ); })().catch(console.error);