forge/tools/gen-ts-glue.ts

84 строки
3.1 KiB
TypeScript

/**
* 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 yarn 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 baseTypedocJson = path.resolve(__dirname, '../typedoc.base.json');
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');
const typedocJsonPath = path.resolve(pkg.path, 'typedoc.json');
await fs.writeFile(
typedocJsonPath,
JSON.stringify(
{
$schema: 'https://typedoc.org/schema.json',
extends: [baseTypedocJson],
entryPoints: [srcMain],
},
null,
2
)
);
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);