mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-11 08:33:53 +00:00
fix(schema): use scule types for runtimeConfig
type hints (#23696)
This commit is contained in:
parent
c069239b12
commit
6ec267be87
@ -65,6 +65,7 @@
|
|||||||
"hookable": "^5.5.3",
|
"hookable": "^5.5.3",
|
||||||
"pathe": "^1.1.1",
|
"pathe": "^1.1.1",
|
||||||
"pkg-types": "^1.0.3",
|
"pkg-types": "^1.0.3",
|
||||||
|
"scule": "^1.1.0",
|
||||||
"std-env": "^3.5.0",
|
"std-env": "^3.5.0",
|
||||||
"ufo": "^1.3.1",
|
"ufo": "^1.3.1",
|
||||||
"unimport": "^3.5.0",
|
"unimport": "^3.5.0",
|
||||||
|
@ -4,6 +4,7 @@ import type { Options as VuePluginOptions } from '@vitejs/plugin-vue'
|
|||||||
import type { Options as VueJsxPluginOptions } from '@vitejs/plugin-vue-jsx'
|
import type { Options as VueJsxPluginOptions } from '@vitejs/plugin-vue-jsx'
|
||||||
import type { SchemaDefinition } from 'untyped'
|
import type { SchemaDefinition } from 'untyped'
|
||||||
import type { NitroRuntimeConfig, NitroRuntimeConfigApp } from 'nitropack'
|
import type { NitroRuntimeConfig, NitroRuntimeConfigApp } from 'nitropack'
|
||||||
|
import type { SnakeCase } from 'scule'
|
||||||
import type { ConfigSchema } from '../../schema/config'
|
import type { ConfigSchema } from '../../schema/config'
|
||||||
import type { Nuxt } from './nuxt'
|
import type { Nuxt } from './nuxt'
|
||||||
import type { AppHeadMetaObject } from './head'
|
import type { AppHeadMetaObject } from './head'
|
||||||
@ -11,43 +12,7 @@ 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
|
type DeepPartial<T> = T extends Function ? T : T extends Record<string, any> ? { [P in keyof T]?: DeepPartial<T[P]> } : T
|
||||||
|
|
||||||
type ExtractUpperChunk<T extends string> = T extends `${infer A}${infer B}`
|
export type UpperSnakeCase<S extends string> = Uppercase<SnakeCase<S>>
|
||||||
? A extends Uppercase<A>
|
|
||||||
? B extends `${Uppercase<string>}${infer Rest}`
|
|
||||||
? B extends `${infer C}${Rest}`
|
|
||||||
? `${A}${C}${ExtractUpperChunk<Rest>}`
|
|
||||||
: never
|
|
||||||
: A
|
|
||||||
: ''
|
|
||||||
: never
|
|
||||||
|
|
||||||
type SliceLast<T extends string> = T extends `${infer A}${infer B}`
|
|
||||||
? B extends `${infer C}${infer D}`
|
|
||||||
? D extends ''
|
|
||||||
? A
|
|
||||||
: `${A}${C}${SliceLast<D>}`
|
|
||||||
: ''
|
|
||||||
: never
|
|
||||||
|
|
||||||
type UpperSnakeCase<T extends string, State extends 'start' | 'lower' | 'upper' = 'start'> = T extends `${infer A}${infer B}`
|
|
||||||
? A extends Uppercase<A>
|
|
||||||
? A extends `${1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0}`
|
|
||||||
? `${A}${UpperSnakeCase<B, 'lower'>}`
|
|
||||||
: State extends 'lower' | 'upper'
|
|
||||||
? B extends `${SliceLast<ExtractUpperChunk<B>>}${infer Rest}`
|
|
||||||
? SliceLast<ExtractUpperChunk<B>> extends ''
|
|
||||||
? `_${A}_${UpperSnakeCase<B, 'start'>}`
|
|
||||||
: `_${A}${SliceLast<ExtractUpperChunk<B>>}_${UpperSnakeCase<Rest, 'start'>}`
|
|
||||||
: B extends Uppercase<B>
|
|
||||||
? `_${A}${B}`
|
|
||||||
: `_${A}${UpperSnakeCase<B, 'lower'>}`
|
|
||||||
: State extends 'start'
|
|
||||||
? `${A}${UpperSnakeCase<B, 'lower'>}`
|
|
||||||
: never
|
|
||||||
: State extends 'start' | 'lower'
|
|
||||||
? `${Uppercase<A>}${UpperSnakeCase<B, 'lower'>}`
|
|
||||||
: `_${Uppercase<A>}${UpperSnakeCase<B, 'lower'>}`
|
|
||||||
: Uppercase<T>
|
|
||||||
|
|
||||||
const message = Symbol('message')
|
const message = Symbol('message')
|
||||||
export type RuntimeValue<T, B extends string> = T & { [message]?: B }
|
export type RuntimeValue<T, B extends string> = T & { [message]?: B }
|
||||||
|
@ -443,6 +443,9 @@ importers:
|
|||||||
pkg-types:
|
pkg-types:
|
||||||
specifier: ^1.0.3
|
specifier: ^1.0.3
|
||||||
version: 1.0.3
|
version: 1.0.3
|
||||||
|
scule:
|
||||||
|
specifier: ^1.1.0
|
||||||
|
version: 1.1.0
|
||||||
std-env:
|
std-env:
|
||||||
specifier: ^3.5.0
|
specifier: ^3.5.0
|
||||||
version: 3.5.0
|
version: 3.5.0
|
||||||
@ -3768,7 +3771,7 @@ packages:
|
|||||||
open: 9.1.0
|
open: 9.1.0
|
||||||
pathe: 1.1.1
|
pathe: 1.1.1
|
||||||
pkg-types: 1.0.3
|
pkg-types: 1.0.3
|
||||||
scule: 1.0.0
|
scule: 1.1.0
|
||||||
semver: 7.5.4
|
semver: 7.5.4
|
||||||
std-env: 3.5.0
|
std-env: 3.5.0
|
||||||
yaml: 2.3.3
|
yaml: 2.3.3
|
||||||
@ -8194,6 +8197,9 @@ packages:
|
|||||||
/scule@1.0.0:
|
/scule@1.0.0:
|
||||||
resolution: {integrity: sha512-4AsO/FrViE/iDNEPaAQlb77tf0csuq27EsVpy6ett584EcRTp6pTDLoGWVxCD77y5iU5FauOvhsI4o1APwPoSQ==}
|
resolution: {integrity: sha512-4AsO/FrViE/iDNEPaAQlb77tf0csuq27EsVpy6ett584EcRTp6pTDLoGWVxCD77y5iU5FauOvhsI4o1APwPoSQ==}
|
||||||
|
|
||||||
|
/scule@1.1.0:
|
||||||
|
resolution: {integrity: sha512-vRUjqhyM/YWYzT+jsMk6tnl3NkY4A4soJ8uyh3O6Um+JXEQL9ozUCe7pqrxn3CSKokw0hw3nFStfskzpgYwR0g==}
|
||||||
|
|
||||||
/semver@5.7.2:
|
/semver@5.7.2:
|
||||||
resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==}
|
resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
@ -8973,7 +8979,7 @@ packages:
|
|||||||
mlly: 1.4.2
|
mlly: 1.4.2
|
||||||
pathe: 1.1.1
|
pathe: 1.1.1
|
||||||
pkg-types: 1.0.3
|
pkg-types: 1.0.3
|
||||||
scule: 1.0.0
|
scule: 1.1.0
|
||||||
strip-literal: 1.3.0
|
strip-literal: 1.3.0
|
||||||
unplugin: 1.5.0
|
unplugin: 1.5.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
|
17
test/fixtures/basic-types/types.ts
vendored
17
test/fixtures/basic-types/types.ts
vendored
@ -3,7 +3,7 @@ import type { Ref } from 'vue'
|
|||||||
import type { FetchError } from 'ofetch'
|
import type { FetchError } from 'ofetch'
|
||||||
import type { NavigationFailure, RouteLocationNormalized, RouteLocationRaw, Router, useRouter as vueUseRouter } from '#vue-router'
|
import type { NavigationFailure, RouteLocationNormalized, RouteLocationRaw, Router, useRouter as vueUseRouter } from '#vue-router'
|
||||||
|
|
||||||
import type { AppConfig, RuntimeValue } from 'nuxt/schema'
|
import type { AppConfig, RuntimeValue, UpperSnakeCase } from 'nuxt/schema'
|
||||||
import { defineNuxtConfig } from 'nuxt/config'
|
import { defineNuxtConfig } from 'nuxt/config'
|
||||||
import { callWithNuxt, isVue3 } from '#app'
|
import { callWithNuxt, isVue3 } from '#app'
|
||||||
import type { NavigateToOptions } from '#app/composables/router'
|
import type { NavigateToOptions } from '#app/composables/router'
|
||||||
@ -271,6 +271,21 @@ describe('runtimeConfig', () => {
|
|||||||
expectTypeOf(val.runtimeConfig!.public!.ids).toEqualTypeOf<undefined | RuntimeValue<Array<number>, 'You can override this value at runtime with NUXT_PUBLIC_IDS'>>()
|
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>()
|
expectTypeOf(val.runtimeConfig!.unknown).toEqualTypeOf<unknown>()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('correctly converts different kinds of names to snake case', () => {
|
||||||
|
expectTypeOf<UpperSnakeCase<'testAppName'>>().toEqualTypeOf<'TEST_APP_NAME'>()
|
||||||
|
expectTypeOf<UpperSnakeCase<'TEST_APP_NAME'>>().toEqualTypeOf<'TEST_APP_NAME'>()
|
||||||
|
expectTypeOf<UpperSnakeCase<'test_APP_NAME'>>().toEqualTypeOf<'TEST_APP_NAME'>()
|
||||||
|
expectTypeOf<UpperSnakeCase<'test_app_NAME'>>().toEqualTypeOf<'TEST_APP_NAME'>()
|
||||||
|
expectTypeOf<UpperSnakeCase<'testAppNAME'>>().toEqualTypeOf<'TEST_APP_NAME'>()
|
||||||
|
expectTypeOf<UpperSnakeCase<'testApp123NAME'>>().toEqualTypeOf<'TEST_APP123NAME'>()
|
||||||
|
expectTypeOf<UpperSnakeCase<'testAPPName'>>().toEqualTypeOf<'TEST_APP_NAME'>()
|
||||||
|
expectTypeOf<UpperSnakeCase<'testAPP_Name'>>().toEqualTypeOf<'TEST_APP_NAME'>()
|
||||||
|
expectTypeOf<UpperSnakeCase<'test_APP_Name'>>().toEqualTypeOf<'TEST_APP_NAME'>()
|
||||||
|
expectTypeOf<UpperSnakeCase<'TESTAppName'>>().toEqualTypeOf<'TEST_APP_NAME'>()
|
||||||
|
expectTypeOf<UpperSnakeCase<'t'>>().toEqualTypeOf<'T'>()
|
||||||
|
expectTypeOf<UpperSnakeCase<'T'>>().toEqualTypeOf<'T'>()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('head', () => {
|
describe('head', () => {
|
||||||
|
Loading…
Reference in New Issue
Block a user