fix(nuxt,schema): prefer unknown rather than any for signatures (#21700)

This commit is contained in:
Daniel Roe 2023-06-22 14:14:21 +01:00 committed by GitHub
parent f380be910e
commit dd5dff37d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 56 additions and 41 deletions

View File

@ -32,7 +32,7 @@ interface PageMeta {
keepalive?: boolean | KeepAliveProps
layout?: false | LayoutKey | Ref<LayoutKey> | ComputedRef<LayoutKey>
middleware?: MiddlewareKey | NavigationGuard | Array<MiddlewareKey | NavigationGuard>
[key: string]: any
[key: string]: unknown
}
```

View File

@ -1,4 +1,5 @@
import { useNuxtApp } from '../nuxt'
import type { NuxtPayload } from '#app'
/**
* Allows full control of the hydration cycle to set and receive data from the server.
@ -7,7 +8,7 @@ import { useNuxtApp } from '../nuxt'
* @param get a function that returns the value to set the initial data
* @param set a function that will receive the data on the client-side
*/
export const useHydration = <T> (key: string, get: () => T, set: (value: T) => void) => {
export const useHydration = <K extends keyof NuxtPayload, T = NuxtPayload[K]> (key: K, get: () => T, set: (value: T) => void) => {
const nuxt = useNuxtApp()
if (process.server) {
@ -18,7 +19,7 @@ export const useHydration = <T> (key: string, get: () => T, set: (value: T) => v
if (process.client) {
nuxt.hooks.hook('app:created', () => {
set(nuxt.payload[key])
set(nuxt.payload[key] as T)
})
}
}

View File

@ -5,9 +5,8 @@ import { useRuntimeConfig } from '#app'
export function useRequestURL () {
if (process.server) {
const { baseURL } = useRuntimeConfig().app
const url = getRequestURL(useRequestEvent())
url.pathname = joinURL(baseURL, url.pathname)
url.pathname = joinURL(useRuntimeConfig().app.baseURL, url.pathname)
return url
}
return new URL(window.location.href)

View File

@ -58,7 +58,9 @@ export interface NuxtSSRContext extends SSRContext {
/** whether we are rendering an SSR error */
error?: boolean
nuxt: _NuxtApp
payload: _NuxtApp['payload']
payload: NuxtPayload
/** This is used solely to render runtime config with SPA renderer. */
config?: Pick<RuntimeConfig, 'public' | 'app'>
teleports?: Record<string, string>
renderMeta?: () => Promise<NuxtMeta> | NuxtMeta
islandContext?: NuxtIslandContext
@ -68,6 +70,25 @@ export interface NuxtSSRContext extends SSRContext {
_payloadReducers: Record<string, (data: any) => any>
}
export interface NuxtPayload {
path?: string
serverRendered?: boolean
prerenderedAt?: number
data: Record<string, any>
state: Record<string, any>
config?: Pick<RuntimeConfig, 'public' | 'app'>
error?: Error | {
url: string
statusCode: number
statusMessage: string
message: string
description: string
data?: any
} | null
_errors: Record<string, NuxtError | undefined>
[key: string]: unknown
}
interface _NuxtApp {
vueApp: App<Element>
globalName: string
@ -120,23 +141,7 @@ interface _NuxtApp {
deferHydration: () => () => void | Promise<void>
ssrContext?: NuxtSSRContext
payload: {
path?: string
serverRendered?: boolean
prerenderedAt?: number
data: Record<string, any>
state: Record<string, any>
error?: Error | {
url: string
statusCode: number
statusMessage: string
message: string
description: string
data?: any
} | null
_errors: Record<string, NuxtError | undefined>
[key: string]: any
}
payload: NuxtPayload
static: {
data: Record<string, any>
}
@ -297,7 +302,7 @@ export function createNuxtApp (options: CreateOptions) {
}
// Expose runtime config
const runtimeConfig = process.server ? options.ssrContext!.runtimeConfig : reactive(nuxtApp.payload.config)
const runtimeConfig = process.server ? options.ssrContext!.runtimeConfig : reactive(nuxtApp.payload.config!)
nuxtApp.provide('config', runtimeConfig)
return nuxtApp

View File

@ -101,6 +101,7 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
runtimeConfig: {
...nuxt.options.runtimeConfig,
nitro: {
// @ts-expect-error TODO: https://github.com/unjs/nitro/pull/1336
envPrefix: 'NUXT_',
...nuxt.options.runtimeConfig.nitro
}

View File

@ -14,7 +14,7 @@ import { defineRenderHandler, getRouteRules, useRuntimeConfig } from '#internal/
import { useNitroApp } from '#internal/nitro/app'
// eslint-disable-next-line import/no-restricted-paths
import type { NuxtApp, NuxtSSRContext } from '#app/nuxt'
import type { NuxtPayload, NuxtSSRContext } from '#app/nuxt'
// @ts-expect-error virtual file
import { appRootId, appRootTag } from '#internal/nuxt.config.mjs'
// @ts-expect-error virtual file
@ -179,7 +179,7 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
// Whether we're rendering an error page
const ssrError = event.node.req.url?.startsWith('/__nuxt_error')
? getQuery(event) as unknown as Exclude<NuxtApp['payload']['error'], Error>
? getQuery(event) as unknown as Exclude<NuxtPayload['error'], Error>
: null
if (ssrError && ssrError.statusCode) {
@ -230,7 +230,7 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
(process.env.prerender ? PRERENDER_NO_SSR_ROUTES.has(url) : false),
error: !!ssrError,
nuxt: undefined!, /* NuxtApp */
payload: (ssrError ? { error: ssrError } : {}) as NuxtSSRContext['payload'],
payload: (ssrError ? { error: ssrError } : {}) as NuxtPayload,
_payloadReducers: {},
islandContext
}

View File

@ -5,7 +5,7 @@ import { useRoute } from 'vue-router'
import type { NuxtError } from '#app'
export interface PageMeta {
[key: string]: any
[key: string]: unknown
/**
* Validate whether a given route can validly be rendered with this page.
*

View File

@ -10,7 +10,10 @@ declare global {
}
declare module 'nitropack' {
interface NitroRuntimeConfigApp extends RuntimeConfig['app'] {}
interface NitroRuntimeConfigApp {
buildAssetsDir: string
cdnURL: string
}
interface NitroRuntimeConfig extends RuntimeConfig {}
interface NitroRouteConfig {
ssr?: boolean

View File

@ -6,6 +6,7 @@ import type { Options as VueJsxPluginOptions } from '@vitejs/plugin-vue-jsx'
import type { AppHeadMetaObject } from './head'
import type { Nuxt } from './nuxt'
import type { SchemaDefinition } from 'untyped'
import type { NitroRuntimeConfig, NitroRuntimeConfigApp } from 'nitropack'
export type { SchemaDefinition } from 'untyped'
type DeepPartial<T> = T extends Function ? T : T extends Record<string, any> ? { [P in keyof T]?: DeepPartial<T[P]> } : T
@ -52,12 +53,14 @@ const message = Symbol('message')
export type RuntimeValue<T, B extends string> = T & { [message]?: B }
type Overrideable<T extends Record<string, any>, Path extends string = ''> = {
[K in keyof T]?: K extends string
? T[K] extends Record<string, any>
? RuntimeValue<Overrideable<T[K], `${Path}_${UpperSnakeCase<K>}`>, `You can override this value at runtime with NUXT${Path}_${UpperSnakeCase<K>}`>
: RuntimeValue<T[K], `You can override this value at runtime with NUXT${Path}_${UpperSnakeCase<K>}`>
: K extends number
? T[K]
: never
? unknown extends T[K]
? unknown
: T[K] extends Record<string, unknown>
? RuntimeValue<Overrideable<T[K], `${Path}_${UpperSnakeCase<K>}`>, `You can override this value at runtime with NUXT${Path}_${UpperSnakeCase<K>}`>
: RuntimeValue<T[K], `You can override this value at runtime with NUXT${Path}_${UpperSnakeCase<K>}`>
: K extends number
? T[K]
: never
}
/** User configuration in `nuxt.config` file */
@ -128,11 +131,14 @@ export interface ViteConfig extends ViteUserConfig {
// -- Runtime Config --
type RuntimeConfigNamespace = Record<string, any>
type RuntimeConfigNamespace = Record<string, unknown>
export interface PublicRuntimeConfig extends RuntimeConfigNamespace { }
export interface RuntimeConfig extends RuntimeConfigNamespace {
app: NitroRuntimeConfigApp
/** Only available on the server. */
nitro?: NitroRuntimeConfig['nitro']
public: PublicRuntimeConfig
}

View File

@ -20,7 +20,7 @@ export interface ModuleMeta {
*/
compatibility?: NuxtCompatibility
[key: string]: any
[key: string]: unknown
}
/** The options received. */

View File

@ -218,14 +218,14 @@ describe('runtimeConfig', () => {
expectTypeOf(runtimeConfig.public.needsFallback).toEqualTypeOf<string>()
expectTypeOf(runtimeConfig.privateConfig).toEqualTypeOf<string>()
expectTypeOf(runtimeConfig.public.ids).toEqualTypeOf<number[]>()
expectTypeOf(runtimeConfig.unknown).toEqualTypeOf<any>()
expectTypeOf(runtimeConfig.unknown).toEqualTypeOf<unknown>()
const injectedConfig = useNuxtApp().$config
expectTypeOf(injectedConfig.public.testConfig).toEqualTypeOf<number>()
expectTypeOf(injectedConfig.public.needsFallback).toEqualTypeOf<string>()
expectTypeOf(injectedConfig.privateConfig).toEqualTypeOf<string>()
expectTypeOf(injectedConfig.public.ids).toEqualTypeOf<number[]>()
expectTypeOf(injectedConfig.unknown).toEqualTypeOf<any>()
expectTypeOf(injectedConfig.unknown).toEqualTypeOf<unknown>()
})
it('provides hints on overriding these values', () => {
const val = defineNuxtConfig({
@ -241,8 +241,8 @@ describe('runtimeConfig', () => {
expectTypeOf(val.runtimeConfig!.privateConfig).toEqualTypeOf<undefined | RuntimeValue<string, 'You can override this value at runtime with NUXT_PRIVATE_CONFIG'>>()
expectTypeOf(val.runtimeConfig!.baseURL).toEqualTypeOf<undefined | RuntimeValue<string, 'You can override this value at runtime with NUXT_BASE_URL'>>()
expectTypeOf(val.runtimeConfig!.baseAPIToken).toEqualTypeOf<undefined | RuntimeValue<string, 'You can override this value at runtime with NUXT_BASE_API_TOKEN'>>()
expectTypeOf(val.runtimeConfig!.public!.ids).toEqualTypeOf<undefined | RuntimeValue<Array<number | undefined>, 'You can override this value at runtime with NUXT_PUBLIC_IDS'>>()
expectTypeOf(val.runtimeConfig!.unknown).toEqualTypeOf<any>()
expectTypeOf(val.runtimeConfig!.public!.ids).toEqualTypeOf<undefined | RuntimeValue<Array<number>, 'You can override this value at runtime with NUXT_PUBLIC_IDS'>>()
expectTypeOf(val.runtimeConfig!.unknown).toEqualTypeOf<unknown>()
})
})