/* * @Author: zhaojinfeng 121016171@qq.com * @Date: 2023-06-19 16:41:12 * @LastEditors: zhaojinfeng 121016171@qq.com * @LastEditTime: 2023-06-21 10:23:39 * @FilePath: \tianheng-design\bin\dts.ts * @Description: * */ /* eslint-env node */ import { dirname, resolve } from 'node:path' // eslint-disable-next-line @typescript-eslint/no-require-imports import glob = require('fast-glob') import consola from 'consola' import { mkdir, readFile, writeFile } from 'fs-extra' import { Project } from 'ts-morph' import { compileScript, parse } from '@vue/compiler-sfc' import type { SourceFile } from 'ts-morph' let index = 1 const packageRoot = resolve(process.cwd(), 'es/packages') const esRoot = resolve(process.cwd(), 'es') async function writeDTS(sourceFiles: SourceFile[]) { // 随后将解析完的文件写道打包路径 for (const sourceFile of sourceFiles) { const emitOutput = sourceFile.getEmitOutput() for (const outputFile of emitOutput.getOutputFiles()) { const filePath = resolve(outputFile.getFilePath()) if (!filePath.endsWith('.d.ts') && !filePath.endsWith('index.js')) { // 过滤非ts文件 continue } const newPath = filePath.replace(packageRoot, esRoot) await mkdir(dirname(newPath), { recursive: true }) await writeFile(newPath, outputFile.getText(), 'utf8') consola.success(newPath) } } } async function main() { // 这部份内容具体能够查阅 ts-morph 的文档 // 这里仅须要知道这是用来处理 ts 文件并生成类型声明文件便可 const project = new Project({ compilerOptions: { // composite: true, // declaration: false, // emitDeclarationOnly: true, // noEmitOnError: true, allowJs: true, // 若是想兼容 js 语法须要加上 outDir: 'es', // 能够设置自定义的打包文件夹,如 'types' }, tsConfigFilePath: resolve(process.cwd(), './tsconfig.app.json'), skipAddingFilesFromTsConfig: true, }) // 获取 src 下的 .vue 和 .ts 文件 const files = await glob(['packages/**/*.ts', 'packages/**/*.vue']) const sourceFiles: SourceFile[] = [] await Promise.all( files.map(async (file) => { if (!file.endsWith('.vue')) { // 若是是 ts 文件则直接添加便可 sourceFiles.push(project.addSourceFileAtPath(file)) return } // 对于 vue 文件,借助 @vue/compiler-sfc 的 parse 进行解析 const sfc = parse(await readFile(file, 'utf-8')) // 提取出 script 中的内容 const { script, scriptSetup } = sfc.descriptor if (script || scriptSetup) { let content = '' let isTs = false if (script?.content) { content += script.content if (script.lang === 'ts') isTs = true } if (scriptSetup) { const compiled = compileScript(sfc.descriptor, { id: `${index++}`, }) content += compiled.content if (scriptSetup.lang === 'ts') isTs = true } sourceFiles.push( // 建立一个同路径的同名 ts/js 的映射文件 project.createSourceFile(file + (isTs ? '.ts' : '.js'), content), ) } }), ) const diagnostics = project.getPreEmitDiagnostics() // 输出解析过程当中的错误信息 consola.error(project.formatDiagnosticsWithColorAndContext(diagnostics)) project.emitToMemory() await writeDTS(sourceFiles) } main()