2023-02-03 15:48:12 +08:00
|
|
|
// @ts-check
|
2023-02-04 11:59:42 +08:00
|
|
|
import { parse } from '@babel/parser'
|
2023-02-03 15:48:12 +08:00
|
|
|
import { existsSync, readdirSync, readFileSync } from 'fs'
|
2023-02-04 11:59:42 +08:00
|
|
|
import MagicString from 'magic-string'
|
2023-02-03 15:48:12 +08:00
|
|
|
import dts from 'rollup-plugin-dts'
|
2023-02-04 11:59:42 +08:00
|
|
|
import { walk } from 'estree-walker'
|
2023-02-03 15:48:12 +08:00
|
|
|
|
|
|
|
if (!existsSync('temp/packages')) {
|
|
|
|
console.warn(
|
|
|
|
'no temp dts files found. run `tsc -p tsconfig.build.json` first.'
|
|
|
|
)
|
|
|
|
process.exit(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
export default readdirSync('temp/packages').map(pkg => {
|
|
|
|
return {
|
|
|
|
input: `./temp/packages/${pkg}/src/index.d.ts`,
|
|
|
|
output: {
|
|
|
|
file: `packages/${pkg}/dist/${pkg}.d.ts`,
|
|
|
|
format: 'es'
|
|
|
|
},
|
|
|
|
plugins: [dts(), patchTypes(pkg)],
|
|
|
|
onwarn(warning, warn) {
|
|
|
|
// during dts rollup, everything is externalized by default
|
|
|
|
if (
|
|
|
|
warning.code === 'UNRESOLVED_IMPORT' &&
|
|
|
|
!warning.exporter.startsWith('.')
|
|
|
|
) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
warn(warning)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
/**
|
2023-02-04 11:59:42 +08:00
|
|
|
* Patch the dts generated by rollup-plugin-dts
|
|
|
|
* 1. remove exports marked as @internal
|
|
|
|
* 2. Convert all types to inline exports
|
|
|
|
* and remove them from the big export {} declaration
|
|
|
|
* otherwise it gets weird in vitepress `defineComponent` call with
|
|
|
|
* "the inferred type cannot be named without a reference"
|
|
|
|
* 3. Append custom agumentations (jsx, macros)
|
2023-02-03 15:48:12 +08:00
|
|
|
* @returns {import('rollup').Plugin}
|
|
|
|
*/
|
|
|
|
function patchTypes(pkg) {
|
|
|
|
return {
|
|
|
|
name: 'patch-types',
|
|
|
|
renderChunk(code) {
|
2023-02-04 11:59:42 +08:00
|
|
|
const s = new MagicString(code)
|
|
|
|
const ast = parse(code, {
|
|
|
|
plugins: ['typescript'],
|
|
|
|
sourceType: 'module'
|
|
|
|
})
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {import('@babel/types').Node} node
|
|
|
|
* @returns {boolean}
|
|
|
|
*/
|
|
|
|
function removeInternal(node) {
|
|
|
|
if (
|
|
|
|
node.leadingComments &&
|
|
|
|
node.leadingComments.some(c => {
|
|
|
|
return c.type === 'CommentBlock' && /@internal\b/.test(c.value)
|
|
|
|
})
|
|
|
|
) {
|
|
|
|
/** @type {any} */
|
|
|
|
const n = node
|
|
|
|
let id
|
|
|
|
if (n.id && n.id.type === 'Identifier') {
|
|
|
|
id = n.id.name
|
|
|
|
} else if (n.key && n.key.type === 'Identifier') {
|
|
|
|
id = n.key.name
|
|
|
|
}
|
|
|
|
if (id) {
|
|
|
|
s.overwrite(
|
|
|
|
// @ts-ignore
|
|
|
|
node.leadingComments[0].start,
|
|
|
|
node.end,
|
|
|
|
`/* removed internal: ${id} */`
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
// @ts-ignore
|
|
|
|
s.remove(node.leadingComments[0].start, node.end)
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
const shouldRemoveExport = new Set()
|
|
|
|
// pass 1: remove internals + add exports
|
|
|
|
for (const node of ast.program.body) {
|
|
|
|
if (
|
|
|
|
(node.type === 'TSTypeAliasDeclaration' ||
|
|
|
|
node.type === 'TSInterfaceDeclaration') &&
|
|
|
|
!node.id.name.startsWith(`_`)
|
|
|
|
) {
|
|
|
|
shouldRemoveExport.add(node.id.name)
|
|
|
|
if (!removeInternal(node)) {
|
|
|
|
// @ts-ignore
|
|
|
|
s.prependLeft(node.start, `export `)
|
|
|
|
// traverse further for internal properties
|
|
|
|
if (node.type === 'TSInterfaceDeclaration') {
|
|
|
|
node.body.body.forEach(removeInternal)
|
|
|
|
} else if (node.type === 'TSTypeAliasDeclaration') {
|
|
|
|
// @ts-ignore
|
|
|
|
walk(node.typeAnnotation, {
|
|
|
|
enter(node) {
|
|
|
|
// @ts-ignore
|
|
|
|
if (removeInternal(node)) this.skip()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (removeInternal(node)) {
|
|
|
|
if (node.type === 'VariableDeclaration') {
|
|
|
|
// declare const x
|
|
|
|
for (const decl of node.declarations) {
|
|
|
|
// @ts-ignore
|
|
|
|
shouldRemoveExport.add(decl.id.name)
|
|
|
|
}
|
|
|
|
} else if (
|
|
|
|
node.type === 'TSDeclareFunction' ||
|
|
|
|
node.type === 'TSEnumDeclaration'
|
|
|
|
) {
|
|
|
|
// declare function
|
|
|
|
// @ts-ignore
|
|
|
|
shouldRemoveExport.add(node.id.name)
|
|
|
|
} else {
|
|
|
|
throw new Error(
|
|
|
|
`unhandled export type marked as @internal: ${node.type}`
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// pass 2: remove exports
|
|
|
|
for (const node of ast.program.body) {
|
|
|
|
if (node.type === 'ExportNamedDeclaration' && !node.source) {
|
|
|
|
for (let i = 0; i < node.specifiers.length; i++) {
|
|
|
|
const spec = node.specifiers[i]
|
|
|
|
if (
|
|
|
|
spec.type === 'ExportSpecifier' &&
|
|
|
|
shouldRemoveExport.has(spec.local.name)
|
|
|
|
) {
|
|
|
|
const next = node.specifiers[i + 1]
|
|
|
|
if (next) {
|
|
|
|
// @ts-ignore
|
|
|
|
s.remove(spec.start, next.start)
|
|
|
|
} else {
|
|
|
|
// last one
|
|
|
|
const prev = node.specifiers[i - 1]
|
|
|
|
// @ts-ignore
|
|
|
|
s.remove(prev ? prev.end : spec.start, spec.end)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
code = s.toString()
|
|
|
|
|
|
|
|
// append pkg specific types
|
2023-02-03 15:48:12 +08:00
|
|
|
const additionalTypeDir = `packages/${pkg}/types`
|
|
|
|
if (existsSync(additionalTypeDir)) {
|
|
|
|
code +=
|
|
|
|
'\n' +
|
|
|
|
readdirSync(additionalTypeDir)
|
|
|
|
.map(file => readFileSync(`${additionalTypeDir}/${file}`, 'utf-8'))
|
|
|
|
.join('\n')
|
|
|
|
}
|
|
|
|
return code
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|