diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 97c7492fb8..d12ffd26dc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -101,14 +101,16 @@ jobs: category: "/language:javascript" typecheck: - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} timeout-minutes: 10 needs: - build strategy: fail-fast: false matrix: + os: [ubuntu-latest, windows-latest] module: ['bundler', 'node'] + base: ['with-base-url', 'without-base-url'] steps: - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 @@ -131,6 +133,7 @@ jobs: run: pnpm test:types env: MODULE_RESOLUTION: ${{ matrix.module }} + TS_BASE_URL: ${{ matrix.base }} lint: # autofix workflow will be triggered instead for PRs diff --git a/package.json b/package.json index 024a067546..ea2813558e 100644 --- a/package.json +++ b/package.json @@ -21,9 +21,7 @@ "test:fixtures:payload": "TEST_PAYLOAD=js pnpm test:fixtures", "test:fixtures:dev": "TEST_ENV=dev pnpm test:fixtures", "test:fixtures:webpack": "TEST_BUILDER=webpack pnpm test:fixtures", - "test:types": "pnpm test:types:basic && pnpm test:types:minimal", - "test:types:basic": "nuxi prepare test/fixtures/basic-types && cd test/fixtures/basic-types && npx vue-tsc --noEmit", - "test:types:minimal": "nuxi prepare test/fixtures/minimal-types && cd test/fixtures/minimal-types && npx vue-tsc --noEmit", + "test:types": "pnpm --filter './test/fixtures/**' test:types", "test:unit": "vitest run --dir packages", "typecheck": "tsc --noEmit" }, diff --git a/packages/nuxi/src/utils/prepare.ts b/packages/nuxi/src/utils/prepare.ts index 2e3cc9d987..d428f7782c 100644 --- a/packages/nuxi/src/utils/prepare.ts +++ b/packages/nuxi/src/utils/prepare.ts @@ -1,4 +1,4 @@ -import { existsSync, promises as fsp } from 'node:fs' +import { promises as fsp } from 'node:fs' import { isAbsolute, join, relative, resolve } from 'pathe' import type { Nuxt, TSReference } from '@nuxt/schema' import { defu } from 'defu' @@ -18,6 +18,8 @@ export const writeTypes = async (nuxt: Nuxt) => { skipLibCheck: true, strict: nuxt.options.typescript?.strict ?? false, allowJs: true, + // TODO: remove by default in 3.7 + baseUrl: nuxt.options.srcDir, noEmit: true, resolveJsonModule: true, allowSyntheticDefaultImports: true, @@ -34,7 +36,7 @@ export const writeTypes = async (nuxt: Nuxt) => { // nitro generate output: https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/core/nitro.ts#L186 relative(nuxt.options.buildDir, resolve(nuxt.options.rootDir, 'dist')) ] - }) + } satisfies TSConfig) const aliases: Record = { ...nuxt.options.alias, @@ -50,17 +52,15 @@ export const writeTypes = async (nuxt: Nuxt) => { if (excludedAlias.some(re => re.test(alias))) { continue } - const relativePath = isAbsolute(aliases[alias]) - ? relativeTo(basePath, aliases[alias]) - : aliases[alias] + const absolutePath = resolve(basePath, aliases[alias]) - const stats = await fsp.stat(resolve(basePath, relativePath)).catch(() => null /* file does not exist */) + const stats = await fsp.stat(absolutePath).catch(() => null /* file does not exist */) tsConfig.compilerOptions = tsConfig.compilerOptions || {} if (stats?.isDirectory()) { - tsConfig.compilerOptions.paths[alias] = [relativePath] - tsConfig.compilerOptions.paths[`${alias}/*`] = [`${relativePath}/*`] + tsConfig.compilerOptions.paths[alias] = [absolutePath] + tsConfig.compilerOptions.paths[`${alias}/*`] = [`${absolutePath}/*`] } else { - tsConfig.compilerOptions.paths[alias] = [relativePath.replace(/(?<=\w)\.\w+$/g, '')] /* remove extension */ + tsConfig.compilerOptions.paths[alias] = [absolutePath.replace(/(?<=\w)\.\w+$/g, '')] /* remove extension */ } } @@ -79,18 +79,6 @@ export const writeTypes = async (nuxt: Nuxt) => { await nuxt.callHook('prepare:types', { references, declarations, tsConfig }) - // Normalise aliases to be relative to buildDir for backward compatibility - for (const alias in tsConfig.compilerOptions!.paths!) { - const paths = tsConfig.compilerOptions!.paths![alias] as string[] - for (const [index, path] of paths.entries()) { - if (isAbsolute(path) || LEADING_DOT_RE.test(path)) { continue } - const resolvedPath = join(nuxt.options.rootDir, path) /* previously basePath was set to rootDir */ - if (existsSync(resolvedPath)) { - paths[index] = relativeTo(basePath, resolvedPath) - } - } - } - const declaration = [ ...references.map((ref) => { if ('path' in ref && isAbsolute(ref.path)) { @@ -123,18 +111,6 @@ export const writeTypes = async (nuxt: Nuxt) => { await writeFile() } -const LEADING_DOT_RE = /^\.{1,2}(\/|$)/ -function withLeadingDot (path: string) { - if (LEADING_DOT_RE.test(path)) { - return path - } - return `./${path}` -} - -function relativeTo (from: string, to: string) { - return withLeadingDot(relative(from, to) || '.') -} - function renderAttrs (obj: Record) { return Object.entries(obj).map(e => renderAttr(e[0], e[1])).join(' ') } diff --git a/packages/nuxt/src/components/module.ts b/packages/nuxt/src/components/module.ts index 1228e0bb70..52642c41be 100644 --- a/packages/nuxt/src/components/module.ts +++ b/packages/nuxt/src/components/module.ts @@ -178,7 +178,7 @@ export default defineNuxtModule({ }) nuxt.hook('prepare:types', ({ references, tsConfig }) => { - tsConfig.compilerOptions!.paths['#components'] = [withLeadingDot(relative(nuxt.options.buildDir, resolve(nuxt.options.buildDir, 'components')))] + tsConfig.compilerOptions!.paths['#components'] = [resolve(nuxt.options.buildDir, 'components')] references.push({ path: resolve(nuxt.options.buildDir, 'components.d.ts') }) }) @@ -255,11 +255,3 @@ export default defineNuxtModule({ }) } }) - -const LEADING_DOT_RE = /^\.{1,2}(\/|$)/ -function withLeadingDot (path: string) { - if (LEADING_DOT_RE.test(path)) { - return path - } - return `./${path}` -} diff --git a/test/fixtures/basic-types/nuxt.config.ts b/test/fixtures/basic-types/nuxt.config.ts index 19d3853d88..bde94e9aca 100644 --- a/test/fixtures/basic-types/nuxt.config.ts +++ b/test/fixtures/basic-types/nuxt.config.ts @@ -35,6 +35,14 @@ export default defineNuxtConfig({ } }, modules: [ + function (_, nuxt) { + // TODO: remove in v3.7 + if (process.env.TS_BASE_URL === 'without-base-url') { + nuxt.hook('prepare:types', ({ tsConfig }) => { + delete tsConfig.compilerOptions!.baseUrl + }) + } + }, function () { addTypeTemplate({ filename: 'test.d.ts', diff --git a/test/fixtures/basic-types/package.json b/test/fixtures/basic-types/package.json index aa52bcae27..7a9625eae1 100644 --- a/test/fixtures/basic-types/package.json +++ b/test/fixtures/basic-types/package.json @@ -2,7 +2,8 @@ "private": true, "name": "fixture-basic-types", "scripts": { - "build": "nuxi build" + "build": "nuxi build", + "test:types": "nuxi prepare && npx vue-tsc --noEmit" }, "dependencies": { "nuxt": "workspace:*" diff --git a/test/fixtures/minimal-types/package.json b/test/fixtures/minimal-types/package.json index bcba9c9e14..8cdd0337f1 100644 --- a/test/fixtures/minimal-types/package.json +++ b/test/fixtures/minimal-types/package.json @@ -2,7 +2,8 @@ "private": true, "name": "fixture-minimal-types", "scripts": { - "build": "nuxi build" + "build": "nuxi build", + "test:types": "nuxi prepare && npx vue-tsc --noEmit" }, "dependencies": { "nuxt": "workspace:*"