UNPKG

dtsc

Version:

Generate bundled TypeScript declaration files

74 lines (65 loc) 2.48 kB
import fs from 'fs/promises' import { compile, load, TsConfig } from 'tsconfig-utils' import { createRequire } from 'module' import { join, resolve } from 'path' import { bundle } from './bundle.js' declare module 'tsconfig-utils' { interface TsConfig { dtsc: Config } } export interface Config { inline?: string[] exclude?: string[] } async function compileToFile(filename: string, config: TsConfig) { filename = filename.replace(/\.d\.ts$/, '') + '.tmp.d.ts' config.set('project', '.', false) config.set('outFile', filename) config.set('composite', 'false') config.set('incremental', 'false') const code = await compile(config.args, { cwd: config.cwd }) if (code) process.exit(code) const content = await fs.readFile(filename, 'utf8') await fs.rm(filename) return content } async function getModules(path: string, prefix = ''): Promise<string[]> { const files = await fs.readdir(path, { withFileTypes: true }) return ([] as string[]).concat(...await Promise.all(files.map(async (file) => { if (file.isDirectory()) { return getModules(join(path, file.name), `${prefix}${file.name}/`) } else if (file.name.endsWith('.ts')) { return [prefix + file.name.slice(0, -3)] } else { return [] } }))) } export async function build(cwd: string, args: string[] = []) { const require = createRequire(cwd + '/') const config = await load(cwd, args) const outFile = config.get('outFile') if (!outFile) throw new Error('outFile is required') const rootDir = config.get('rootDir') if (!rootDir) throw new Error('rootDir is required') const srcpath = `${cwd.replace(/\\/g, '/')}/${rootDir}` const destpath = resolve(cwd, outFile) const [files, input] = await Promise.all([ getModules(srcpath), compileToFile(destpath, config), ]) let source = input const { inline = [], exclude = [] } = config.dtsc || {} files.push(...inline) for (const extra of inline) { const manifest = require(extra + '/package.json') const filename = join(extra, manifest.typings || manifest.types) const content = await fs.readFile(require.resolve(filename), 'utf8') source += [`declare module "${extra}" {`, ...content.split('\n')].join('\n ') + '\n}\n' } const manifest = require(cwd + '/package.json') const dependencies = Object.keys(manifest.dependencies || {}) const output = await bundle({ files, source, exclude, dependencies }) await fs.writeFile(destpath, output) }