From 904ef05cc51f16d6ba615e490c4b50c6230b0823 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Mon, 22 May 2023 12:11:20 +0100 Subject: [PATCH 1/5] test: refactor type tests into a separate fixture --- package.json | 2 +- pnpm-lock.yaml | 22 ++++++ test/fixtures/basic-types/.gitignore | 1 + test/fixtures/basic-types/app.config.ts | 6 ++ .../basic-types/extends/bar/app.config.ts | 3 + .../basic-types/extends/bar/index.d.ts | 5 ++ .../extends/bar/layouts/override.vue | 6 ++ .../extends/bar/middleware/override.ts | 3 + .../basic-types/extends/bar/nuxt.config.ts | 1 + .../extends/bar/pages/override.vue | 14 ++++ .../node_modules/foo/layouts/default.vue | 6 ++ .../node_modules/foo/layouts/override.vue | 3 + .../node_modules/foo/middleware/foo.ts | 3 + .../node_modules/foo/middleware/override.ts | 3 + .../extends/node_modules/foo/nuxt.config.ts | 3 + .../extends/node_modules/foo/pages/foo.vue | 19 +++++ .../node_modules/foo/pages/override.vue | 3 + .../extends/node_modules/foo/plugins/foo.ts | 7 ++ .../node_modules/foo/server/api/foo.ts | 3 + .../basic-types/layouts/PascalCase.ts | 0 test/fixtures/basic-types/layouts/custom.vue | 6 ++ .../basic-types/middleware/global.global.ts | 7 ++ test/fixtures/basic-types/middleware/named.ts | 3 + .../modules/auto-registered/index.ts | 15 ++++ .../auto-registered/runtime/handler.ts | 1 + test/fixtures/basic-types/modules/example.ts | 23 ++++++ .../basic-types/modules/page-extend.ts | 19 +++++ .../basic-types/modules/runtime/middleware.ts | 4 + .../basic-types/modules/runtime/page.vue | 17 ++++ .../basic-types/modules/runtime/plugin.ts | 4 + .../basic-types/modules/test/index.ts | 7 ++ test/fixtures/basic-types/nuxt.config.ts | 79 +++++++++++++++++++ .../{basic => basic-types}/nuxt.schema.ts | 0 test/fixtures/basic-types/package.json | 17 ++++ test/fixtures/basic-types/pages/page.vue | 5 ++ .../fixtures/basic-types/pages/param/[id].vue | 5 ++ .../fixtures/basic-types/plugins/injection.ts | 7 ++ test/fixtures/basic-types/server/api/hello.ts | 1 + .../basic-types/server/api/hey/index.get.ts | 4 + .../basic-types/server/api/hey/index.post.ts | 3 + test/fixtures/basic-types/server/api/union.ts | 4 + .../fixtures/basic-types/server/tsconfig.json | 3 + test/fixtures/basic-types/tsconfig.json | 3 + test/fixtures/{basic => basic-types}/types.ts | 43 ++++++---- test/fixtures/basic/modules/example.ts | 4 - test/fixtures/basic/nuxt.config.ts | 40 +--------- 46 files changed, 378 insertions(+), 59 deletions(-) create mode 100644 test/fixtures/basic-types/.gitignore create mode 100644 test/fixtures/basic-types/app.config.ts create mode 100644 test/fixtures/basic-types/extends/bar/app.config.ts create mode 100644 test/fixtures/basic-types/extends/bar/index.d.ts create mode 100644 test/fixtures/basic-types/extends/bar/layouts/override.vue create mode 100644 test/fixtures/basic-types/extends/bar/middleware/override.ts create mode 100644 test/fixtures/basic-types/extends/bar/nuxt.config.ts create mode 100644 test/fixtures/basic-types/extends/bar/pages/override.vue create mode 100644 test/fixtures/basic-types/extends/node_modules/foo/layouts/default.vue create mode 100644 test/fixtures/basic-types/extends/node_modules/foo/layouts/override.vue create mode 100644 test/fixtures/basic-types/extends/node_modules/foo/middleware/foo.ts create mode 100644 test/fixtures/basic-types/extends/node_modules/foo/middleware/override.ts create mode 100644 test/fixtures/basic-types/extends/node_modules/foo/nuxt.config.ts create mode 100644 test/fixtures/basic-types/extends/node_modules/foo/pages/foo.vue create mode 100644 test/fixtures/basic-types/extends/node_modules/foo/pages/override.vue create mode 100644 test/fixtures/basic-types/extends/node_modules/foo/plugins/foo.ts create mode 100644 test/fixtures/basic-types/extends/node_modules/foo/server/api/foo.ts create mode 100644 test/fixtures/basic-types/layouts/PascalCase.ts create mode 100644 test/fixtures/basic-types/layouts/custom.vue create mode 100644 test/fixtures/basic-types/middleware/global.global.ts create mode 100644 test/fixtures/basic-types/middleware/named.ts create mode 100644 test/fixtures/basic-types/modules/auto-registered/index.ts create mode 100644 test/fixtures/basic-types/modules/auto-registered/runtime/handler.ts create mode 100644 test/fixtures/basic-types/modules/example.ts create mode 100644 test/fixtures/basic-types/modules/page-extend.ts create mode 100644 test/fixtures/basic-types/modules/runtime/middleware.ts create mode 100644 test/fixtures/basic-types/modules/runtime/page.vue create mode 100644 test/fixtures/basic-types/modules/runtime/plugin.ts create mode 100644 test/fixtures/basic-types/modules/test/index.ts create mode 100644 test/fixtures/basic-types/nuxt.config.ts rename test/fixtures/{basic => basic-types}/nuxt.schema.ts (100%) create mode 100644 test/fixtures/basic-types/package.json create mode 100644 test/fixtures/basic-types/pages/page.vue create mode 100644 test/fixtures/basic-types/pages/param/[id].vue create mode 100644 test/fixtures/basic-types/plugins/injection.ts create mode 100644 test/fixtures/basic-types/server/api/hello.ts create mode 100644 test/fixtures/basic-types/server/api/hey/index.get.ts create mode 100644 test/fixtures/basic-types/server/api/hey/index.post.ts create mode 100644 test/fixtures/basic-types/server/api/union.ts create mode 100644 test/fixtures/basic-types/server/tsconfig.json create mode 100644 test/fixtures/basic-types/tsconfig.json rename test/fixtures/{basic => basic-types}/types.ts (93%) diff --git a/package.json b/package.json index ebfbf5efabcc..0487824242ec 100644 --- a/package.json +++ b/package.json @@ -21,7 +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": "nuxi prepare test/fixtures/basic && cd test/fixtures/basic && npx vue-tsc --noEmit", + "test:types": "nuxi prepare test/fixtures/basic-types && cd test/fixtures/basic-types && npx vue-tsc --noEmit", "test:unit": "vitest run --dir packages", "typecheck": "tsc --noEmit" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fa09eef0c3d1..0ff077e3e285 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -913,6 +913,28 @@ importers: specifier: latest version: 4.2.1(vue@3.3.4) + test/fixtures/basic-types: + dependencies: + nuxt: + specifier: workspace:* + version: link:../../../packages/nuxt + devDependencies: + ofetch: + specifier: latest + version: 1.0.1 + ufo: + specifier: latest + version: 1.1.2 + unplugin: + specifier: latest + version: 1.3.1 + vitest: + specifier: latest + version: 0.31.1(playwright@1.34.0) + vue-router: + specifier: latest + version: 4.2.1(vue@3.3.4) + test/fixtures/minimal: dependencies: nuxt: diff --git a/test/fixtures/basic-types/.gitignore b/test/fixtures/basic-types/.gitignore new file mode 100644 index 000000000000..2a0469def7c5 --- /dev/null +++ b/test/fixtures/basic-types/.gitignore @@ -0,0 +1 @@ +!extends/node_modules diff --git a/test/fixtures/basic-types/app.config.ts b/test/fixtures/basic-types/app.config.ts new file mode 100644 index 000000000000..2bb6b31bd5c8 --- /dev/null +++ b/test/fixtures/basic-types/app.config.ts @@ -0,0 +1,6 @@ +export default defineAppConfig({ + userConfig: 123, + nested: { + val: 2 + } +}) diff --git a/test/fixtures/basic-types/extends/bar/app.config.ts b/test/fixtures/basic-types/extends/bar/app.config.ts new file mode 100644 index 000000000000..92e47a3736d1 --- /dev/null +++ b/test/fixtures/basic-types/extends/bar/app.config.ts @@ -0,0 +1,3 @@ +export default { + fromLayer: true +} diff --git a/test/fixtures/basic-types/extends/bar/index.d.ts b/test/fixtures/basic-types/extends/bar/index.d.ts new file mode 100644 index 000000000000..3d1121c5447b --- /dev/null +++ b/test/fixtures/basic-types/extends/bar/index.d.ts @@ -0,0 +1,5 @@ +declare module 'bing' { + interface BingInterface { + foo: 'bar' + } +} diff --git a/test/fixtures/basic-types/extends/bar/layouts/override.vue b/test/fixtures/basic-types/extends/bar/layouts/override.vue new file mode 100644 index 000000000000..7397c7ad6326 --- /dev/null +++ b/test/fixtures/basic-types/extends/bar/layouts/override.vue @@ -0,0 +1,6 @@ + diff --git a/test/fixtures/basic-types/extends/bar/middleware/override.ts b/test/fixtures/basic-types/extends/bar/middleware/override.ts new file mode 100644 index 000000000000..00edf7812469 --- /dev/null +++ b/test/fixtures/basic-types/extends/bar/middleware/override.ts @@ -0,0 +1,3 @@ +export default defineNuxtRouteMiddleware((to) => { + to.meta.override = 'Injected by extended middleware from bar' +}) diff --git a/test/fixtures/basic-types/extends/bar/nuxt.config.ts b/test/fixtures/basic-types/extends/bar/nuxt.config.ts new file mode 100644 index 000000000000..268da7f8c110 --- /dev/null +++ b/test/fixtures/basic-types/extends/bar/nuxt.config.ts @@ -0,0 +1 @@ +export default defineNuxtConfig({}) diff --git a/test/fixtures/basic-types/extends/bar/pages/override.vue b/test/fixtures/basic-types/extends/bar/pages/override.vue new file mode 100644 index 000000000000..d104ece7bf04 --- /dev/null +++ b/test/fixtures/basic-types/extends/bar/pages/override.vue @@ -0,0 +1,14 @@ + + + diff --git a/test/fixtures/basic-types/extends/node_modules/foo/layouts/default.vue b/test/fixtures/basic-types/extends/node_modules/foo/layouts/default.vue new file mode 100644 index 000000000000..16278621894d --- /dev/null +++ b/test/fixtures/basic-types/extends/node_modules/foo/layouts/default.vue @@ -0,0 +1,6 @@ + diff --git a/test/fixtures/basic-types/extends/node_modules/foo/layouts/override.vue b/test/fixtures/basic-types/extends/node_modules/foo/layouts/override.vue new file mode 100644 index 000000000000..b10cfadd9a97 --- /dev/null +++ b/test/fixtures/basic-types/extends/node_modules/foo/layouts/override.vue @@ -0,0 +1,3 @@ + diff --git a/test/fixtures/basic-types/extends/node_modules/foo/middleware/foo.ts b/test/fixtures/basic-types/extends/node_modules/foo/middleware/foo.ts new file mode 100644 index 000000000000..53963c77032a --- /dev/null +++ b/test/fixtures/basic-types/extends/node_modules/foo/middleware/foo.ts @@ -0,0 +1,3 @@ +export default defineNuxtRouteMiddleware((to) => { + to.meta.foo = 'Injected by extended middleware from foo' +}) diff --git a/test/fixtures/basic-types/extends/node_modules/foo/middleware/override.ts b/test/fixtures/basic-types/extends/node_modules/foo/middleware/override.ts new file mode 100644 index 000000000000..fbbfd73091ef --- /dev/null +++ b/test/fixtures/basic-types/extends/node_modules/foo/middleware/override.ts @@ -0,0 +1,3 @@ +export default defineNuxtRouteMiddleware((to) => { + to.meta.override = 'This middleware should be overriden by bar' +}) diff --git a/test/fixtures/basic-types/extends/node_modules/foo/nuxt.config.ts b/test/fixtures/basic-types/extends/node_modules/foo/nuxt.config.ts new file mode 100644 index 000000000000..f716d9f9da91 --- /dev/null +++ b/test/fixtures/basic-types/extends/node_modules/foo/nuxt.config.ts @@ -0,0 +1,3 @@ +import { defineNuxtConfig } from 'nuxt/config' + +export default defineNuxtConfig({}) diff --git a/test/fixtures/basic-types/extends/node_modules/foo/pages/foo.vue b/test/fixtures/basic-types/extends/node_modules/foo/pages/foo.vue new file mode 100644 index 000000000000..9599ea6eac9e --- /dev/null +++ b/test/fixtures/basic-types/extends/node_modules/foo/pages/foo.vue @@ -0,0 +1,19 @@ + + + diff --git a/test/fixtures/basic-types/extends/node_modules/foo/pages/override.vue b/test/fixtures/basic-types/extends/node_modules/foo/pages/override.vue new file mode 100644 index 000000000000..81a97ed0f2ca --- /dev/null +++ b/test/fixtures/basic-types/extends/node_modules/foo/pages/override.vue @@ -0,0 +1,3 @@ + diff --git a/test/fixtures/basic-types/extends/node_modules/foo/plugins/foo.ts b/test/fixtures/basic-types/extends/node_modules/foo/plugins/foo.ts new file mode 100644 index 000000000000..23534da003c6 --- /dev/null +++ b/test/fixtures/basic-types/extends/node_modules/foo/plugins/foo.ts @@ -0,0 +1,7 @@ +export default defineNuxtPlugin(() => { + return { + provide: { + foo: () => 'String generated from foo plugin!' + } + } +}) diff --git a/test/fixtures/basic-types/extends/node_modules/foo/server/api/foo.ts b/test/fixtures/basic-types/extends/node_modules/foo/server/api/foo.ts new file mode 100644 index 000000000000..4529f026397b --- /dev/null +++ b/test/fixtures/basic-types/extends/node_modules/foo/server/api/foo.ts @@ -0,0 +1,3 @@ +import { eventHandler } from 'h3' + +export default eventHandler(() => 'foo') diff --git a/test/fixtures/basic-types/layouts/PascalCase.ts b/test/fixtures/basic-types/layouts/PascalCase.ts new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/fixtures/basic-types/layouts/custom.vue b/test/fixtures/basic-types/layouts/custom.vue new file mode 100644 index 000000000000..e7938d8f69d6 --- /dev/null +++ b/test/fixtures/basic-types/layouts/custom.vue @@ -0,0 +1,6 @@ + diff --git a/test/fixtures/basic-types/middleware/global.global.ts b/test/fixtures/basic-types/middleware/global.global.ts new file mode 100644 index 000000000000..efc4f51753de --- /dev/null +++ b/test/fixtures/basic-types/middleware/global.global.ts @@ -0,0 +1,7 @@ +export default defineNuxtRouteMiddleware((to) => { + if ('abort' in to.query) { + return abortNavigation({ + statusCode: 401 + }) + } +}) diff --git a/test/fixtures/basic-types/middleware/named.ts b/test/fixtures/basic-types/middleware/named.ts new file mode 100644 index 000000000000..30801347aefc --- /dev/null +++ b/test/fixtures/basic-types/middleware/named.ts @@ -0,0 +1,3 @@ +export default defineNuxtRouteMiddleware((to) => { + to.meta.auth = 'Injected by injectAuth middleware' +}) diff --git a/test/fixtures/basic-types/modules/auto-registered/index.ts b/test/fixtures/basic-types/modules/auto-registered/index.ts new file mode 100644 index 000000000000..60406e1126bf --- /dev/null +++ b/test/fixtures/basic-types/modules/auto-registered/index.ts @@ -0,0 +1,15 @@ +import { addServerHandler, createResolver, defineNuxtModule } from 'nuxt/kit' + +export default defineNuxtModule({ + meta: { + name: 'auto-registered-module' + }, + setup () { + const resolver = createResolver(import.meta.url) + + addServerHandler({ + handler: resolver.resolve('./runtime/handler'), + route: '/auto-registered-module' + }) + } +}) diff --git a/test/fixtures/basic-types/modules/auto-registered/runtime/handler.ts b/test/fixtures/basic-types/modules/auto-registered/runtime/handler.ts new file mode 100644 index 000000000000..563d40e0b9c4 --- /dev/null +++ b/test/fixtures/basic-types/modules/auto-registered/runtime/handler.ts @@ -0,0 +1 @@ +export default defineEventHandler(() => 'handler added by auto-registered module') diff --git a/test/fixtures/basic-types/modules/example.ts b/test/fixtures/basic-types/modules/example.ts new file mode 100644 index 000000000000..94365f629f51 --- /dev/null +++ b/test/fixtures/basic-types/modules/example.ts @@ -0,0 +1,23 @@ +import { addPlugin, createResolver, defineNuxtModule, useNuxt } from 'nuxt/kit' + +export default defineNuxtModule({ + defaults: { + enabled: true, + typeTest: (value: boolean) => typeof value === 'boolean' + }, + meta: { + name: 'my-module', + configKey: 'sampleModule' + }, + setup () { + const resolver = createResolver(import.meta.url) + + addPlugin(resolver.resolve('./runtime/plugin')) + useNuxt().hook('app:resolve', (app) => { + app.middleware.push({ + name: 'unctx-test', + path: resolver.resolve('./runtime/middleware') + }) + }) + } +}) diff --git a/test/fixtures/basic-types/modules/page-extend.ts b/test/fixtures/basic-types/modules/page-extend.ts new file mode 100644 index 000000000000..1f794eeee60a --- /dev/null +++ b/test/fixtures/basic-types/modules/page-extend.ts @@ -0,0 +1,19 @@ +import { createResolver, defineNuxtModule, useNuxt } from 'nuxt/kit' + +export default defineNuxtModule({ + meta: { + name: 'page-extend' + }, + setup () { + const nuxt = useNuxt() + const resolver = createResolver(import.meta.url) + + nuxt.hook('pages:extend', (pages) => { + pages.push({ + name: 'page-extend', + path: '/page-extend', + file: resolver.resolve('./runtime/page.vue') + }) + }) + } +}) diff --git a/test/fixtures/basic-types/modules/runtime/middleware.ts b/test/fixtures/basic-types/modules/runtime/middleware.ts new file mode 100644 index 000000000000..7ddcb23d820a --- /dev/null +++ b/test/fixtures/basic-types/modules/runtime/middleware.ts @@ -0,0 +1,4 @@ +export default defineNuxtRouteMiddleware(async () => { + await new Promise(resolve => setTimeout(resolve, 1)) + useNuxtApp() +}) diff --git a/test/fixtures/basic-types/modules/runtime/page.vue b/test/fixtures/basic-types/modules/runtime/page.vue new file mode 100644 index 000000000000..5174b019cb65 --- /dev/null +++ b/test/fixtures/basic-types/modules/runtime/page.vue @@ -0,0 +1,17 @@ + + + diff --git a/test/fixtures/basic-types/modules/runtime/plugin.ts b/test/fixtures/basic-types/modules/runtime/plugin.ts new file mode 100644 index 000000000000..61a24ed6d201 --- /dev/null +++ b/test/fixtures/basic-types/modules/runtime/plugin.ts @@ -0,0 +1,4 @@ +export default defineNuxtPlugin(async () => { + await new Promise(resolve => setTimeout(resolve, 1)) + useNuxtApp() +}) diff --git a/test/fixtures/basic-types/modules/test/index.ts b/test/fixtures/basic-types/modules/test/index.ts new file mode 100644 index 000000000000..b3c385cda4d9 --- /dev/null +++ b/test/fixtures/basic-types/modules/test/index.ts @@ -0,0 +1,7 @@ +import { defineNuxtModule } from 'nuxt/kit' + +export default defineNuxtModule({ + meta: { + name: 'test' + } +}) diff --git a/test/fixtures/basic-types/nuxt.config.ts b/test/fixtures/basic-types/nuxt.config.ts new file mode 100644 index 000000000000..26d8253dc092 --- /dev/null +++ b/test/fixtures/basic-types/nuxt.config.ts @@ -0,0 +1,79 @@ +import type { NuxtPage } from 'nuxt/schema' +import { withoutLeadingSlash } from 'ufo' + +export default defineNuxtConfig({ + experimental: { + typedPages: true + }, + typescript: { + strict: true, + tsConfig: { + compilerOptions: { + moduleResolution: process.env.MODULE_RESOLUTION + } + } + }, + buildDir: process.env.NITRO_BUILD_DIR, + builder: process.env.TEST_BUILDER as 'webpack' | 'vite' ?? 'vite', + theme: './extends/bar', + extends: [ + './extends/node_modules/foo' + ], + runtimeConfig: { + baseURL: '', + baseAPIToken: '', + privateConfig: 'secret_key', + public: { + ids: [1, 2, 3], + needsFallback: undefined, + testConfig: 123 + } + }, + appConfig: { + fromNuxtConfig: true, + nested: { + val: 1 + } + }, + modules: [ + './modules/test', + [ + '~/modules/example', + { + typeTest (val) { + // @ts-expect-error module type defines val as boolean + const b: string = val + return !!b + } + } + ], + function (_options, nuxt) { + nuxt.hook('pages:extend', (pages) => { + pages.push({ + name: 'internal-async-parent', + path: '/internal-async-parent' + }) + }) + } + ], + telemetry: false, // for testing telemetry types - it is auto-disabled in tests + hooks: { + 'schema:extend' (schemas) { + schemas.push({ + appConfig: { + someThing: { + value: { + $default: 'default', + $schema: { + tsType: 'string | false' + } + } + } + } + }) + }, + 'prepare:types' ({ tsConfig }) { + tsConfig.include = tsConfig.include!.filter(i => i !== '../../../../**/*') + } + } +}) diff --git a/test/fixtures/basic/nuxt.schema.ts b/test/fixtures/basic-types/nuxt.schema.ts similarity index 100% rename from test/fixtures/basic/nuxt.schema.ts rename to test/fixtures/basic-types/nuxt.schema.ts diff --git a/test/fixtures/basic-types/package.json b/test/fixtures/basic-types/package.json new file mode 100644 index 000000000000..fdbd8f31d956 --- /dev/null +++ b/test/fixtures/basic-types/package.json @@ -0,0 +1,17 @@ +{ + "private": true, + "name": "fixture-basic-types", + "scripts": { + "build": "nuxi build" + }, + "dependencies": { + "nuxt": "workspace:*" + }, + "devDependencies": { + "ofetch": "latest", + "ufo": "latest", + "unplugin": "latest", + "vitest": "latest", + "vue-router": "latest" + } +} diff --git a/test/fixtures/basic-types/pages/page.vue b/test/fixtures/basic-types/pages/page.vue new file mode 100644 index 000000000000..41b642051a2c --- /dev/null +++ b/test/fixtures/basic-types/pages/page.vue @@ -0,0 +1,5 @@ + diff --git a/test/fixtures/basic-types/pages/param/[id].vue b/test/fixtures/basic-types/pages/param/[id].vue new file mode 100644 index 000000000000..41b642051a2c --- /dev/null +++ b/test/fixtures/basic-types/pages/param/[id].vue @@ -0,0 +1,5 @@ + diff --git a/test/fixtures/basic-types/plugins/injection.ts b/test/fixtures/basic-types/plugins/injection.ts new file mode 100644 index 000000000000..70726e2ade97 --- /dev/null +++ b/test/fixtures/basic-types/plugins/injection.ts @@ -0,0 +1,7 @@ +export default defineNuxtPlugin(() => { + return { + provide: { + pluginInjection: () => '' + } + } +}) diff --git a/test/fixtures/basic-types/server/api/hello.ts b/test/fixtures/basic-types/server/api/hello.ts new file mode 100644 index 000000000000..569613d6f79e --- /dev/null +++ b/test/fixtures/basic-types/server/api/hello.ts @@ -0,0 +1 @@ +export default defineEventHandler(() => 'Hello API') diff --git a/test/fixtures/basic-types/server/api/hey/index.get.ts b/test/fixtures/basic-types/server/api/hey/index.get.ts new file mode 100644 index 000000000000..7ae4e47bf963 --- /dev/null +++ b/test/fixtures/basic-types/server/api/hey/index.get.ts @@ -0,0 +1,4 @@ +export default defineEventHandler(() => ({ + foo: 'bar', + baz: 'qux' +})) diff --git a/test/fixtures/basic-types/server/api/hey/index.post.ts b/test/fixtures/basic-types/server/api/hey/index.post.ts new file mode 100644 index 000000000000..b09599aed336 --- /dev/null +++ b/test/fixtures/basic-types/server/api/hey/index.post.ts @@ -0,0 +1,3 @@ +export default defineEventHandler(() => ({ + method: 'post' as const +})) diff --git a/test/fixtures/basic-types/server/api/union.ts b/test/fixtures/basic-types/server/api/union.ts new file mode 100644 index 000000000000..9358a00ecc29 --- /dev/null +++ b/test/fixtures/basic-types/server/api/union.ts @@ -0,0 +1,4 @@ +export default defineEventHandler(() => ({ + type: 'a', + foo: 'bar' +}) as { type: 'a', foo: string } | { type: 'b', baz: string }) diff --git a/test/fixtures/basic-types/server/tsconfig.json b/test/fixtures/basic-types/server/tsconfig.json new file mode 100644 index 000000000000..b9ed69c19eaf --- /dev/null +++ b/test/fixtures/basic-types/server/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "../.nuxt/tsconfig.server.json" +} diff --git a/test/fixtures/basic-types/tsconfig.json b/test/fixtures/basic-types/tsconfig.json new file mode 100644 index 000000000000..4b34df1571f7 --- /dev/null +++ b/test/fixtures/basic-types/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "./.nuxt/tsconfig.json" +} diff --git a/test/fixtures/basic/types.ts b/test/fixtures/basic-types/types.ts similarity index 93% rename from test/fixtures/basic/types.ts rename to test/fixtures/basic-types/types.ts index cd3b1386dd82..c5c3ad3670e1 100644 --- a/test/fixtures/basic/types.ts +++ b/test/fixtures/basic-types/types.ts @@ -15,6 +15,10 @@ interface TestResponse { message: string } describe('API routes', () => { it('generates types for routes', () => { expectTypeOf($fetch('/api/hello')).toEqualTypeOf>() + // registered in extends + expectTypeOf($fetch('/api/foo')).toEqualTypeOf>() + // registered in module + expectTypeOf($fetch('/auto-registered-module')).toEqualTypeOf>() expectTypeOf($fetch('/api/hey')).toEqualTypeOf>() expectTypeOf($fetch('/api/hey', { method: 'get' })).toEqualTypeOf>() expectTypeOf($fetch('/api/hey', { method: 'post' })).toEqualTypeOf>() @@ -90,11 +94,14 @@ describe('aliases', () => { describe('middleware', () => { it('recognizes named middleware', () => { - definePageMeta({ middleware: 'inject-auth' }) + definePageMeta({ middleware: 'named' }) + // provided by layer + definePageMeta({ middleware: 'override' }) + definePageMeta({ middleware: 'foo' }) // @ts-expect-error ignore global middleware - definePageMeta({ middleware: 'redirect' }) + definePageMeta({ middleware: 'global' }) // @ts-expect-error Invalid middleware - definePageMeta({ middleware: 'invalid-middleware' }) + definePageMeta({ middleware: 'nonexistent' }) }) it('handles adding middleware', () => { addRouteMiddleware('example', (to, from) => { @@ -117,14 +124,14 @@ describe('typed router integration', () => { // @ts-expect-error this named route does not exist router.push({ name: 'some-thing' }) // this one does - router.push({ name: 'fixed-keyed-child-parent' }) + router.push({ name: 'page' }) // @ts-expect-error this is an invalid param - router.push({ name: 'random-id', params: { bob: 23 } }) - router.push({ name: 'random-id', params: { id: 4 } }) + router.push({ name: 'param-id', params: { bob: 23 } }) + router.push({ name: 'param-id', params: { id: 4 } }) }) it('allows typing useRoute', () => { - const route = useRoute('random-id') + const route = useRoute('param-id') // @ts-expect-error this param does not exist const _invalid = route.params.something // this param does @@ -135,10 +142,10 @@ describe('typed router integration', () => { // @ts-expect-error this named route does not exist navigateTo({ name: 'some-thing' }) // this one does - navigateTo({ name: 'fixed-keyed-child-parent' }) + navigateTo({ name: 'page' }) // @ts-expect-error this is an invalid param - navigateTo({ name: 'random-id', params: { bob: 23 } }) - navigateTo({ name: 'random-id', params: { id: 4 } }) + navigateTo({ name: 'param-id', params: { bob: 23 } }) + navigateTo({ name: 'param-id', params: { id: 4 } }) }) it('allows typing middleware', () => { @@ -146,7 +153,7 @@ describe('typed router integration', () => { expectTypeOf(to.name).not.toBeAny() // @ts-expect-error this route does not exist expectTypeOf(to.name === 'bob').toMatchTypeOf() - expectTypeOf(to.name === 'assets').toMatchTypeOf() + expectTypeOf(to.name === 'page').toMatchTypeOf() }) }) @@ -157,14 +164,18 @@ describe('typed router integration', () => { expectTypeOf(useRoute().name === 'invalid').toMatchTypeOf() }) + it('respects pages added via layer', () => { + expectTypeOf(useRoute().name === 'override').toMatchTypeOf() + }) + it('allows typing NuxtLink', () => { // @ts-expect-error this named route does not exist h(NuxtLink, { to: { name: 'some-thing' } }) // this one does - h(NuxtLink, { to: { name: 'fixed-keyed-child-parent' } }) + h(NuxtLink, { to: { name: 'page' } }) // @ts-expect-error this is an invalid param - h(NuxtLink, { to: { name: 'random-id', params: { bob: 23 } } }) - h(NuxtLink, { to: { name: 'random-id', params: { id: 4 } } }) + h(NuxtLink, { to: { name: 'param-id', params: { bob: 23 } } }) + h(NuxtLink, { to: { name: 'param-id', params: { id: 4 } } }) }) }) @@ -172,6 +183,7 @@ describe('layouts', () => { it('recognizes named layouts', () => { definePageMeta({ layout: 'custom' }) definePageMeta({ layout: 'pascal-case' }) + definePageMeta({ layout: 'override' }) // @ts-expect-error Invalid layout definePageMeta({ layout: 'invalid-layout' }) }) @@ -189,7 +201,8 @@ describe('modules', () => { describe('nuxtApp', () => { it('types injections provided by plugins', () => { - expectTypeOf(useNuxtApp().$asyncPlugin).toEqualTypeOf<() => string>() + expectTypeOf(useNuxtApp().$pluginInjection).toEqualTypeOf<() => ''>() + expectTypeOf(useNuxtApp().$foo).toEqualTypeOf<() => 'String generated from foo plugin!'>() expectTypeOf(useNuxtApp().$router).toEqualTypeOf() }) it('marks unknown injections as unknown', () => { diff --git a/test/fixtures/basic/modules/example.ts b/test/fixtures/basic/modules/example.ts index 7b770f65f008..861b7726c5fd 100644 --- a/test/fixtures/basic/modules/example.ts +++ b/test/fixtures/basic/modules/example.ts @@ -1,10 +1,6 @@ import { addPlugin, createResolver, defineNuxtModule, useNuxt } from 'nuxt/kit' export default defineNuxtModule({ - defaults: { - enabled: true, - typeTest: (value: boolean) => typeof value === 'boolean' - }, meta: { name: 'my-module', configKey: 'sampleModule' diff --git a/test/fixtures/basic/nuxt.config.ts b/test/fixtures/basic/nuxt.config.ts index c4b074af6123..a00baee16b5c 100644 --- a/test/fixtures/basic/nuxt.config.ts +++ b/test/fixtures/basic/nuxt.config.ts @@ -11,14 +11,6 @@ declare module 'nitropack' { } export default defineNuxtConfig({ - typescript: { - strict: true, - tsConfig: { - compilerOptions: { - moduleResolution: process.env.MODULE_RESOLUTION - } - } - }, app: { pageTransition: true, layoutTransition: true, @@ -70,27 +62,14 @@ export default defineNuxtConfig({ ] }, runtimeConfig: { - baseURL: '', - baseAPIToken: '', - privateConfig: 'secret_key', public: { - ids: [1, 2, 3], needsFallback: undefined, testConfig: 123 } }, modules: [ './modules/test', - [ - '~/modules/example', - { - typeTest (val) { - // @ts-expect-error module type defines val as boolean - const b: string = val - return !!b - } - } - ], + '~/modules/example', function (_, nuxt) { if (typeof nuxt.options.builder === 'string' && nuxt.options.builder.includes('webpack')) { return } @@ -143,23 +122,6 @@ export default defineNuxtConfig({ }, telemetry: false, // for testing telemetry types - it is auto-disabled in tests hooks: { - 'schema:extend' (schemas) { - schemas.push({ - appConfig: { - someThing: { - value: { - $default: 'default', - $schema: { - tsType: 'string | false' - } - } - } - } - }) - }, - 'prepare:types' ({ tsConfig }) { - tsConfig.include = tsConfig.include!.filter(i => i !== '../../../../**/*') - }, 'modules:done' () { addComponent({ name: 'CustomComponent', From 732b71c080797742079e74da4882ad3a88249220 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Mon, 22 May 2023 14:48:08 +0100 Subject: [PATCH 2/5] fix(nuxt): add type support for router composables without `pages/` integration --- packages/nuxt/src/pages/module.ts | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/packages/nuxt/src/pages/module.ts b/packages/nuxt/src/pages/module.ts index 46bbdab5ecfd..c3de3ab0ef90 100644 --- a/packages/nuxt/src/pages/module.ts +++ b/packages/nuxt/src/pages/module.ts @@ -64,6 +64,14 @@ export default defineNuxtModule({ } }) + // adds support for #vue-router alias (used for types) with and without pages integration + addTemplate({ + filename: 'vue-router.d.ts', + getContents: () => `export * from '${useExperimentalTypedPages ? 'vue-router/auto' : 'vue-router'}'` + }) + + nuxt.options.alias['#vue-router'] = join(nuxt.options.buildDir, 'vue-router') + if (!nuxt.options.pages) { addPlugin(resolve(distDir, 'app/plugins/router')) addTemplate({ @@ -78,6 +86,12 @@ export default defineNuxtModule({ return } + addTemplate({ + filename: 'vue-router.mjs', + // TODO: use `vue-router/auto` when we have support for page metadata + getContents: () => 'export * from \'vue-router\';' + }) + if (useExperimentalTypedPages) { const declarationFile = './types/typed-router.d.ts' @@ -261,17 +275,6 @@ export default defineNuxtModule({ } }) - // adds support for #vue-router alias - addTemplate({ - filename: 'vue-router.mjs', - // TODO: use `vue-router/auto` when we have support for page metadata - getContents: () => 'export * from \'vue-router\';' - }) - addTemplate({ - filename: 'vue-router.d.ts', - getContents: () => `export * from '${useExperimentalTypedPages ? 'vue-router/auto' : 'vue-router'}'` - }) - // Add routes template addTemplate({ filename: 'routes.mjs', @@ -365,8 +368,6 @@ export default defineNuxtModule({ filePath: resolve(distDir, 'pages/runtime/page') }) - nuxt.options.alias['#vue-router'] = join(nuxt.options.buildDir, 'vue-router') - // Add declarations for middleware keys nuxt.hook('prepare:types', ({ references }) => { references.push({ path: resolve(nuxt.options.buildDir, 'types/middleware.d.ts') }) From cbe5f12712af822c2d64af00017a2e052f3fb07f Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Mon, 22 May 2023 14:50:45 +0100 Subject: [PATCH 3/5] test: add minimal type test --- package.json | 4 +- pnpm-lock.yaml | 6 +++ test/fixtures/basic-types/types.ts | 10 ++--- test/fixtures/minimal-types/app.vue | 3 ++ test/fixtures/minimal-types/nuxt.config.ts | 1 + test/fixtures/minimal-types/package.json | 10 +++++ test/fixtures/minimal-types/tsconfig.json | 3 ++ test/fixtures/minimal-types/types.ts | 48 ++++++++++++++++++++++ 8 files changed, 79 insertions(+), 6 deletions(-) create mode 100644 test/fixtures/minimal-types/app.vue create mode 100644 test/fixtures/minimal-types/nuxt.config.ts create mode 100644 test/fixtures/minimal-types/package.json create mode 100644 test/fixtures/minimal-types/tsconfig.json create mode 100644 test/fixtures/minimal-types/types.ts diff --git a/package.json b/package.json index 0487824242ec..74d42c6599f7 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,9 @@ "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": "nuxi prepare test/fixtures/basic-types && cd test/fixtures/basic-types && npx vue-tsc --noEmit", + "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:unit": "vitest run --dir packages", "typecheck": "tsc --noEmit" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0ff077e3e285..f3d877f3aafd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -941,6 +941,12 @@ importers: specifier: workspace:* version: link:../../../packages/nuxt + test/fixtures/minimal-types: + dependencies: + nuxt: + specifier: workspace:* + version: link:../../../packages/nuxt + test/fixtures/runtime-compiler: dependencies: nuxt: diff --git a/test/fixtures/basic-types/types.ts b/test/fixtures/basic-types/types.ts index c5c3ad3670e1..bf48fb0f5d17 100644 --- a/test/fixtures/basic-types/types.ts +++ b/test/fixtures/basic-types/types.ts @@ -152,20 +152,20 @@ describe('typed router integration', () => { defineNuxtRouteMiddleware((to) => { expectTypeOf(to.name).not.toBeAny() // @ts-expect-error this route does not exist - expectTypeOf(to.name === 'bob').toMatchTypeOf() - expectTypeOf(to.name === 'page').toMatchTypeOf() + expectTypeOf(to.name === 'bob').toEqualTypeOf() + expectTypeOf(to.name === 'page').toEqualTypeOf() }) }) it('respects pages:extend augmentation', () => { // added via pages:extend - expectTypeOf(useRoute().name === 'internal-async-parent').toMatchTypeOf() + expectTypeOf(useRoute().name === 'internal-async-parent').toEqualTypeOf() // @ts-expect-error this route does not exist - expectTypeOf(useRoute().name === 'invalid').toMatchTypeOf() + expectTypeOf(useRoute().name === 'invalid').toEqualTypeOf() }) it('respects pages added via layer', () => { - expectTypeOf(useRoute().name === 'override').toMatchTypeOf() + expectTypeOf(useRoute().name === 'override').toEqualTypeOf() }) it('allows typing NuxtLink', () => { diff --git a/test/fixtures/minimal-types/app.vue b/test/fixtures/minimal-types/app.vue new file mode 100644 index 000000000000..585f495151c9 --- /dev/null +++ b/test/fixtures/minimal-types/app.vue @@ -0,0 +1,3 @@ + diff --git a/test/fixtures/minimal-types/nuxt.config.ts b/test/fixtures/minimal-types/nuxt.config.ts new file mode 100644 index 000000000000..268da7f8c110 --- /dev/null +++ b/test/fixtures/minimal-types/nuxt.config.ts @@ -0,0 +1 @@ +export default defineNuxtConfig({}) diff --git a/test/fixtures/minimal-types/package.json b/test/fixtures/minimal-types/package.json new file mode 100644 index 000000000000..bcba9c9e149d --- /dev/null +++ b/test/fixtures/minimal-types/package.json @@ -0,0 +1,10 @@ +{ + "private": true, + "name": "fixture-minimal-types", + "scripts": { + "build": "nuxi build" + }, + "dependencies": { + "nuxt": "workspace:*" + } +} diff --git a/test/fixtures/minimal-types/tsconfig.json b/test/fixtures/minimal-types/tsconfig.json new file mode 100644 index 000000000000..4b34df1571f7 --- /dev/null +++ b/test/fixtures/minimal-types/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "./.nuxt/tsconfig.json" +} diff --git a/test/fixtures/minimal-types/types.ts b/test/fixtures/minimal-types/types.ts new file mode 100644 index 000000000000..fd39ed7c5ae0 --- /dev/null +++ b/test/fixtures/minimal-types/types.ts @@ -0,0 +1,48 @@ +import { describe, expectTypeOf, it } from 'vitest' + +describe('routing utilities', () => { + it('allows using route composables', () => { + const router = useRouter() + router.push('/test') + + expectTypeOf(useRouter()).not.toBeAny() + expectTypeOf(useRoute()).not.toBeAny() + + navigateTo('/thing') + }) +}) + +describe('auto-imports', () => { + it('defineNuxtConfig', () => { + defineNuxtConfig({ + modules: [], + // @ts-expect-error Should show error on unknown properties + unknownProp: '' + }) + }) + it('core composables', () => { + ref() + useHead({ + script: [], + // @ts-expect-error Should show error on unknown properties + unknown: [] + }) + }) +}) + +describe('config typings', () => { + it('runtimeConfig', () => { + expectTypeOf(useRuntimeConfig()).toMatchTypeOf<{ + app: { + baseURL: string + buildAssetsDir: string + cdnURL: string + } + public: Record + }>() + }) + + it('appConfig', () => { + expectTypeOf(useAppConfig()).toEqualTypeOf<{ [key: string]: unknown }>() + }) +}) From e22f884be61330a46c215e7f05cf0e20c50e8a99 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Mon, 22 May 2023 15:12:28 +0100 Subject: [PATCH 4/5] test: add prop test --- .../basic-types/components/WithTypes.vue | 28 +++++++++++++++++++ test/fixtures/basic-types/types.ts | 9 +++++- 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 test/fixtures/basic-types/components/WithTypes.vue diff --git a/test/fixtures/basic-types/components/WithTypes.vue b/test/fixtures/basic-types/components/WithTypes.vue new file mode 100644 index 000000000000..c3f4b271fca9 --- /dev/null +++ b/test/fixtures/basic-types/components/WithTypes.vue @@ -0,0 +1,28 @@ + + + diff --git a/test/fixtures/basic-types/types.ts b/test/fixtures/basic-types/types.ts index bf48fb0f5d17..8714207a83b5 100644 --- a/test/fixtures/basic-types/types.ts +++ b/test/fixtures/basic-types/types.ts @@ -7,7 +7,7 @@ import type { AppConfig, RuntimeValue } from 'nuxt/schema' import { defineNuxtConfig } from 'nuxt/config' import { callWithNuxt, isVue3 } from '#app' import type { NavigateToOptions } from '#app/composables/router' -import { NuxtLink, NuxtPage } from '#components' +import { NuxtLink, NuxtPage, WithTypes } from '#components' import { useRouter } from '#imports' interface TestResponse { message: string } @@ -277,6 +277,13 @@ describe('components', () => { it('includes types for NuxtPage', () => { expectTypeOf(NuxtPage).not.toBeAny() }) + it('includes types for other components', () => { + h(WithTypes) + // @ts-expect-error wrong prop type for this component + h(WithTypes, { aProp: '40' }) + + // TODO: assert typed slots, exposed, generics, etc. + }) }) describe('composables', () => { From a562c6007ab83b436650f2f5ec2bdf261716b20d Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Mon, 22 May 2023 16:09:22 +0100 Subject: [PATCH 5/5] chore: lint --- pnpm-lock.yaml | 3 --- test/fixtures/basic-types/nuxt.config.ts | 3 --- test/fixtures/basic-types/package.json | 1 - 3 files changed, 7 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f3d877f3aafd..4df0c06b22dc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -922,9 +922,6 @@ importers: ofetch: specifier: latest version: 1.0.1 - ufo: - specifier: latest - version: 1.1.2 unplugin: specifier: latest version: 1.3.1 diff --git a/test/fixtures/basic-types/nuxt.config.ts b/test/fixtures/basic-types/nuxt.config.ts index 26d8253dc092..164fdd0fcc77 100644 --- a/test/fixtures/basic-types/nuxt.config.ts +++ b/test/fixtures/basic-types/nuxt.config.ts @@ -1,6 +1,3 @@ -import type { NuxtPage } from 'nuxt/schema' -import { withoutLeadingSlash } from 'ufo' - export default defineNuxtConfig({ experimental: { typedPages: true diff --git a/test/fixtures/basic-types/package.json b/test/fixtures/basic-types/package.json index fdbd8f31d956..aa52bcae27f8 100644 --- a/test/fixtures/basic-types/package.json +++ b/test/fixtures/basic-types/package.json @@ -9,7 +9,6 @@ }, "devDependencies": { "ofetch": "latest", - "ufo": "latest", "unplugin": "latest", "vitest": "latest", "vue-router": "latest"