Skip to content

Commit 04367cc

Browse files
authored
feat(mkdist): emit .d.vue.ts as type declaration of .vue files (#83)
1 parent 14eb7b0 commit 04367cc

File tree

2 files changed

+57
-2
lines changed

2 files changed

+57
-2
lines changed

src/plugins/mkdist.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import type { LoaderFile } from '../block-loader/types'
22
import type { VueSFCTransformerFileLoader } from '../sfc-transformer'
33
import type { Loader } from '../types/mkdist'
4-
import { resolve } from 'node:path'
4+
import { readFileSync } from 'node:fs'
5+
import { createRequire } from 'node:module'
6+
import { join, resolve } from 'node:path'
57
import { scriptLoader } from '../block-loader/script'
68
import { styleLoader } from '../block-loader/style'
79
import { templateLoader } from '../block-loader/template'
@@ -19,6 +21,29 @@ function importEsbuild(): Promise<typeof import('esbuild')> | typeof import('esb
1921
})()
2022
}
2123

24+
let _isMkdistSupportDualVueDts: boolean | undefined
25+
function isMkdistSupportDualVueDts(): boolean {
26+
if (typeof _isMkdistSupportDualVueDts === 'boolean') {
27+
return _isMkdistSupportDualVueDts
28+
}
29+
try {
30+
const require = createRequire(import.meta.url)
31+
const mkdistPath = require.resolve('mkdist').replace(/\\/g, '/')
32+
const lastNodeModules = mkdistPath.lastIndexOf('/mkdist/')
33+
const withoutDist = lastNodeModules !== -1 ? mkdistPath.slice(0, lastNodeModules) : mkdistPath
34+
const packageJson = readFileSync(join(withoutDist, 'mkdist/package.json'), 'utf-8')
35+
const { version = '0.0.0' } = JSON.parse(packageJson) as { version: string }
36+
const [major = 0, minor = 0, patch = 0] = version.split('.').map(n => Number.parseInt(n))
37+
const normalizedVersion = major * 1_000_000 + minor * 1_000 + patch
38+
39+
return !Number.isNaN(normalizedVersion) && normalizedVersion > 2_003_000
40+
}
41+
catch (error) {
42+
console.error(`Error checking mkdist version: ${error}`)
43+
return false
44+
}
45+
}
46+
2247
const vueSFCTransformer = defineVueSFCTransformer({
2348
blockLoaders: {
2449
template: templateLoader,
@@ -77,6 +102,15 @@ export const vueLoader: Loader = async (input, mkdistContext) => {
77102
extension: '.js',
78103
getContents: () => 'export default {}',
79104
}))?.filter(f => f.declaration) || []
105+
if (dts.length && isMkdistSupportDualVueDts()) {
106+
dts.push({
107+
contents: await input.getContents(),
108+
path: input.path,
109+
srcPath: input.srcPath,
110+
extension: '.d.vue.ts',
111+
declaration: true,
112+
})
113+
}
80114

81115
return [
82116
{

test/mkdist.test.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,15 @@ describe('transform typescript script setup', () => {
234234
const msg = 1
235235
</script>`
236236

237+
expect(await legacyDeclaration(src)).toMatchInlineSnapshot(`
238+
"declare const _default: import("vue").DefineComponent<{
239+
msg: string;
240+
}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{
241+
msg: string;
242+
}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
243+
export default _default;
244+
"
245+
`)
237246
expect(await declaration(src)).toMatchInlineSnapshot(`
238247
"declare const _default: import("vue").DefineComponent<{
239248
msg: string;
@@ -245,6 +254,11 @@ describe('transform typescript script setup', () => {
245254
`)
246255

247256
expect(await fixture(`<template><div /></template>`)).toMatchInlineSnapshot(`"<template><div /></template>"`)
257+
expect(await legacyDeclaration(`<template><div /></template>`)).toMatchInlineSnapshot(`
258+
"declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
259+
export default _default;
260+
"
261+
`)
248262
expect(await declaration(`<template><div /></template>`)).toMatchInlineSnapshot(`
249263
"declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
250264
export default _default;
@@ -424,11 +438,18 @@ describe('transform typescript script setup', () => {
424438
return await readFile(join(tmpDir, 'dist/index.vue'), 'utf-8')
425439
}
426440

427-
async function declaration(src: string): Promise<string | undefined> {
441+
async function legacyDeclaration(src: string): Promise<string | undefined> {
428442
await rm(tmpDir, { force: true, recursive: true })
429443
await mkdir(join(tmpDir, 'src'), { recursive: true })
430444
await writeFile(join(tmpDir, 'src/index.vue'), src)
431445
await mkdist({ declaration: true, loaders: ['js', vueLoader], rootDir: tmpDir })
432446
return await readFile(join(tmpDir, 'dist/index.vue.d.ts'), 'utf-8').catch(() => undefined)
433447
}
448+
async function declaration(src: string): Promise<string | undefined> {
449+
await rm(tmpDir, { force: true, recursive: true })
450+
await mkdir(join(tmpDir, 'src'), { recursive: true })
451+
await writeFile(join(tmpDir, 'src/index.vue'), src)
452+
await mkdist({ declaration: true, loaders: ['js', vueLoader], rootDir: tmpDir })
453+
return await readFile(join(tmpDir, 'dist/index.d.vue.ts'), 'utf-8').catch(() => undefined)
454+
}
434455
})

0 commit comments

Comments
 (0)