expect(deps && [...deps]).toStrictEqual(['/user.ts'])
})
+ test('ts module resolve w/ path aliased vue file', () => {
+ const files = {
+ '/tsconfig.json': JSON.stringify({
+ compilerOptions: {
+ include: ['**/*.ts', '**/*.vue'],
+ paths: {
+ '@/*': ['./src/*']
+ }
+ }
+ }),
+ '/src/Foo.vue':
+ '<script lang="ts">export type P = { bar: string }</script>'
+ }
+
+ const { props, deps } = resolve(
+ `
+ import { P } from '@/Foo.vue'
+ defineProps<P>()
+ `,
+ files
+ )
+
+ expect(props).toStrictEqual({
+ bar: ['String']
+ })
+ expect(deps && [...deps]).toStrictEqual(['/src/Foo.vue'])
+ })
+
test('global types', () => {
const files = {
// ambient
// required
'source' | 'filename' | 'error' | 'options'
> &
- Partial<Pick<ScriptCompileContext, 'scope' | 'globalScopes' | 'deps'>> & {
+ Partial<
+ Pick<ScriptCompileContext, 'scope' | 'globalScopes' | 'deps' | 'fs'>
+ > & {
ast: Statement[]
}
function resolveGlobalScope(ctx: TypeResolveContext): TypeScope[] | undefined {
if (ctx.options.globalTypeFiles) {
- const fs: FS = ctx.options.fs || ts?.sys
+ const fs = resolveFS(ctx)
if (!fs) {
throw new Error('[vue/compiler-sfc] globalTypeFiles requires fs access.')
}
type FS = NonNullable<SFCScriptCompileOptions['fs']>
+function resolveFS(ctx: TypeResolveContext): FS | undefined {
+ if (ctx.fs) {
+ return ctx.fs
+ }
+ const fs = ctx.options.fs || ts.sys
+ if (!fs) {
+ return
+ }
+ return (ctx.fs = {
+ fileExists(file) {
+ if (file.endsWith('.vue.ts')) {
+ file = file.replace(/\.ts$/, '')
+ }
+ return fs.fileExists(file)
+ },
+ readFile(file) {
+ if (file.endsWith('.vue.ts')) {
+ file = file.replace(/\.ts$/, '')
+ }
+ return fs.readFile(file)
+ }
+ })
+}
+
function resolveTypeFromImport(
ctx: TypeResolveContext,
node: ReferenceTypes,
scope: TypeScope,
source: string
): TypeScope {
- const fs: FS = ctx.options.fs || ts?.sys
+ const fs = resolveFS(ctx)
if (!fs) {
- ctx.error(
+ return ctx.error(
`No fs option provided to \`compileScript\` in non-Node environment. ` +
`File system access is required for resolving imported types.`,
node,
)
if (res.resolvedModule) {
- return res.resolvedModule.resolvedFileName
+ let filename = res.resolvedModule.resolvedFileName
+ if (filename.endsWith('.vue.ts')) {
+ filename = filename.replace(/\.ts$/, '')
+ }
+ return filename
}
}
return cached
}
// fs should be guaranteed to exist here
- const fs = ctx.options.fs || ts?.sys
+ const fs = resolveFS(ctx)!
const source = fs.readFile(filename) || ''
const body = parseFile(filename, source, ctx.options.babelParserPlugins)
const scope = new TypeScope(filename, source, 0, recordImports(body))