mirror of
https://gitee.com/element-plus/element-plus.git
synced 2024-11-30 18:27:40 +08:00
4fad2a78d7
* refactor: improve build dts * chore: add comment
147 lines
4.3 KiB
TypeScript
147 lines
4.3 KiB
TypeScript
import process from 'process'
|
|
import path from 'path'
|
|
import fs from 'fs/promises'
|
|
import * as vueCompiler from 'vue/compiler-sfc'
|
|
import { Project } from 'ts-morph'
|
|
import glob from 'fast-glob'
|
|
import { bold } from 'chalk'
|
|
import { errorAndExit, green, yellow } from './utils/log'
|
|
import { buildOutput, epRoot, pkgRoot, projRoot } from './utils/paths'
|
|
import typeSafe from './type-safe.json'
|
|
|
|
import { excludeFiles, pathRewriter } from './utils/pkg'
|
|
import type { SourceFile } from 'ts-morph'
|
|
|
|
const TSCONFIG_PATH = path.resolve(projRoot, 'tsconfig.json')
|
|
const outDir = path.resolve(buildOutput, 'types')
|
|
|
|
// Type safe list. The TS errors are not all fixed yet, so we need a list of which files are fixed with TS errors to prevent accidental TS errors.
|
|
const typeSafePaths = typeSafe.map((_path) => {
|
|
let safePath = path.resolve(projRoot, _path)
|
|
if (_path.endsWith('/')) safePath += path.sep
|
|
return safePath
|
|
})
|
|
|
|
/**
|
|
* fork = require( https://github.com/egoist/vue-dts-gen/blob/main/src/index.ts
|
|
*/
|
|
export const generateTypesDefinitions = async () => {
|
|
const project = new Project({
|
|
compilerOptions: {
|
|
emitDeclarationOnly: true,
|
|
outDir,
|
|
baseUrl: projRoot,
|
|
paths: {
|
|
'@element-plus/*': ['packages/*'],
|
|
},
|
|
preserveSymlinks: true,
|
|
types: [
|
|
path.resolve(projRoot, 'typings/env'),
|
|
'unplugin-vue-define-options',
|
|
],
|
|
},
|
|
tsConfigFilePath: TSCONFIG_PATH,
|
|
skipAddingFilesFromTsConfig: true,
|
|
})
|
|
|
|
const filePaths = excludeFiles(
|
|
await glob(['**/*.{js,ts,vue}', '!element-plus/**/*'], {
|
|
cwd: pkgRoot,
|
|
absolute: true,
|
|
onlyFiles: true,
|
|
})
|
|
)
|
|
const epPaths = excludeFiles(
|
|
await glob('**/*.{js,ts,vue}', {
|
|
cwd: epRoot,
|
|
onlyFiles: true,
|
|
})
|
|
)
|
|
|
|
const sourceFiles: SourceFile[] = []
|
|
await Promise.all([
|
|
...filePaths.map(async (file) => {
|
|
if (file.endsWith('.vue')) {
|
|
const content = await fs.readFile(file, 'utf-8')
|
|
const sfc = vueCompiler.parse(content)
|
|
const { script, scriptSetup } = sfc.descriptor
|
|
if (script || scriptSetup) {
|
|
let content = ''
|
|
let isTS = false
|
|
if (script && script.content) {
|
|
content += script.content
|
|
if (script.lang === 'ts') isTS = true
|
|
}
|
|
if (scriptSetup) {
|
|
const compiled = vueCompiler.compileScript(sfc.descriptor, {
|
|
id: 'xxx',
|
|
})
|
|
content += compiled.content
|
|
if (scriptSetup.lang === 'ts') isTS = true
|
|
}
|
|
const sourceFile = project.createSourceFile(
|
|
path.relative(process.cwd(), file) + (isTS ? '.ts' : '.js'),
|
|
content
|
|
)
|
|
sourceFiles.push(sourceFile)
|
|
}
|
|
} else {
|
|
const sourceFile = project.addSourceFileAtPath(file)
|
|
sourceFiles.push(sourceFile)
|
|
}
|
|
}),
|
|
...epPaths.map(async (file) => {
|
|
const content = await fs.readFile(path.resolve(epRoot, file), 'utf-8')
|
|
sourceFiles.push(
|
|
project.createSourceFile(path.resolve(pkgRoot, file), content)
|
|
)
|
|
}),
|
|
])
|
|
|
|
const diagnostics = project.getPreEmitDiagnostics().filter((diagnostic) => {
|
|
const filePath = diagnostic.getSourceFile()?.getFilePath()
|
|
return (
|
|
filePath &&
|
|
typeSafePaths.some((safePath) => filePath.startsWith(safePath))
|
|
)
|
|
})
|
|
if (diagnostics.length > 0) {
|
|
console.log(project.formatDiagnosticsWithColorAndContext(diagnostics))
|
|
process.exit(1)
|
|
}
|
|
|
|
await project.emit({
|
|
emitOnlyDtsFiles: true,
|
|
})
|
|
|
|
const tasks = sourceFiles.map(async (sourceFile) => {
|
|
const relativePath = path.relative(pkgRoot, sourceFile.getFilePath())
|
|
yellow(`Generating definition for file: ${bold(relativePath)}`)
|
|
|
|
const emitOutput = sourceFile.getEmitOutput()
|
|
const emitFiles = emitOutput.getOutputFiles()
|
|
if (emitFiles.length === 0) {
|
|
errorAndExit(new Error(`Emit no file: ${bold(relativePath)}`))
|
|
}
|
|
|
|
const tasks = emitFiles.map(async (outputFile) => {
|
|
const filepath = outputFile.getFilePath()
|
|
await fs.mkdir(path.dirname(filepath), {
|
|
recursive: true,
|
|
})
|
|
|
|
await fs.writeFile(
|
|
filepath,
|
|
pathRewriter('esm')(outputFile.getText()),
|
|
'utf8'
|
|
)
|
|
|
|
green(`Definition for file: ${bold(relativePath)} generated`)
|
|
})
|
|
|
|
await Promise.all(tasks)
|
|
})
|
|
|
|
await Promise.all(tasks)
|
|
}
|