Files
vue3/bin/dts.ts
2023-06-21 12:04:22 +08:00

120 lines
3.4 KiB
TypeScript

/*
* @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()