Skip to content

Commit e7eaa28

Browse files
authored
chore: fix types (#393)
1 parent acf94d9 commit e7eaa28

27 files changed

+253
-117
lines changed

.github/workflows/ci.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ jobs:
6565
- name: Run test suite
6666
run: pnpm test
6767

68-
# - name: Test types
69-
# run: pnpm test:types
68+
- name: Test types
69+
run: pnpm test:types
7070

7171
# - name: Test playground types
7272
# run: pnpm test:types:playground

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"lint:fix": "eslint . --fix",
3232
"test": "vitest run",
3333
"test:types": "vue-tsc --noEmit",
34-
"test:types:playground": "cd playground && vue-tsc --noEmit",
34+
"test:types:playground": "nuxt typecheck playground",
3535
"test:watch": "vitest watch"
3636
},
3737
"dependencies": {

playground/components/AuthLogin.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const isOpen = ref(false)
44
const { fetch, user } = useUserSession()
55
const toast = useToast()
66
7-
async function login(event: SubmitEvent) {
7+
async function login(event: Event) {
88
const target = event.target as HTMLFormElement
99
1010
await $fetch('/api/login', {

playground/components/AuthRegister.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const isOpen = ref(false)
44
const { fetch, user } = useUserSession()
55
const toast = useToast()
66
7-
async function register(event: SubmitEvent) {
7+
async function register(event: Event) {
88
const target = event.target as HTMLFormElement
99
1010
await $fetch('/api/register', {

playground/package.json

-3
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,5 @@
2020
},
2121
"devDependencies": {
2222
"better-sqlite3": "^11.8.1"
23-
},
24-
"resolutions": {
25-
"h3": "^1.14.0"
2623
}
2724
}

playground/server/api/webauthn/authenticate.post.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export default defineWebAuthnAuthenticateEventHandler({
3737
},
3838
async onSuccess(event, { credential, authenticationInfo }) {
3939
const db = useDatabase()
40-
const { rows } = await db.sql<{ rows: string[] }>`
40+
const { rows } = await db.sql<{ rows: { email: string }[] }>`
4141
SELECT users.email
4242
FROM credentials
4343
INNER JOIN users ON users.id = credentials.userId

playground/server/api/webauthn/register.post.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export default defineWebAuthnRegisterEventHandler({
1717
const db = useDatabase()
1818
try {
1919
await db.sql`BEGIN TRANSACTION`
20+
// @ts-expect-error - dbUser is not defined in the type
2021
let { rows: [dbUser] } = await db.sql`SELECT * FROM users WHERE email = ${user.userName}`
2122
if (!dbUser) {
2223
await db.sql`INSERT INTO users (email) VALUES (${user.userName})`
@@ -50,7 +51,7 @@ export default defineWebAuthnRegisterEventHandler({
5051
await db.sql`ROLLBACK`
5152
throw createError({
5253
statusCode: 500,
53-
message: err.message.includes('UNIQUE constraint failed') ? 'User already registered' : 'Failed to store credential',
54+
message: err instanceof Error && err.message.includes('UNIQUE constraint failed') ? 'User already registered' : 'Failed to store credential',
5455
})
5556
}
5657
},

pnpm-lock.yaml

+166-75
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pnpm-workspace.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
packages:
22
- "playground"
3+
- "./"

src/runtime/app/composables/session.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import type { UserSession, UserSessionComposable } from '#auth-utils'
88
*/
99
export function useUserSession(): UserSessionComposable {
1010
const serverEvent = import.meta.server ? useRequestEvent() : null
11-
const sessionState = useState<UserSession>('nuxt-session', () => ({}))
11+
const sessionState = useState<UserSession | null>('nuxt-session', () => null)
1212
const authReadyState = useState('nuxt-auth-ready', () => false)
1313

1414
const clear = async () => {
@@ -23,16 +23,16 @@ export function useUserSession(): UserSessionComposable {
2323
}
2424
},
2525
})
26-
sessionState.value = {}
26+
sessionState.value = null
2727
}
2828

2929
const fetch = async () => {
30-
sessionState.value = await useRequestFetch()('/api/_auth/session', {
30+
sessionState.value = await useRequestFetch()<UserSession>('/api/_auth/session', {
3131
headers: {
3232
accept: 'application/json',
3333
},
3434
retry: false,
35-
}).catch(() => ({}))
35+
}).catch(() => null)
3636
if (!authReadyState.value) {
3737
authReadyState.value = true
3838
}
@@ -68,8 +68,8 @@ export function useUserSession(): UserSessionComposable {
6868

6969
return {
7070
ready: computed(() => authReadyState.value),
71-
loggedIn: computed(() => Boolean(sessionState.value.user)),
72-
user: computed(() => sessionState.value.user || null),
71+
loggedIn: computed(() => Boolean(sessionState.value?.user)),
72+
user: computed(() => sessionState.value?.user || null),
7373
session: sessionState,
7474
fetch,
7575
openInPopup,

src/runtime/server/lib/atproto/bluesky.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export interface OAuthBlueskyConfig {
3131
type BlueSkyUser = AppBskyActorDefs.ProfileViewDetailed | Pick<AppBskyActorDefs.ProfileView, 'did'>
3232
type BlueSkyTokens = NodeSavedSession['tokenSet']
3333

34-
export function defineOAuthBlueskyEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthBlueskyConfig, BlueSkyUser, BlueSkyTokens>) {
34+
export function defineOAuthBlueskyEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthBlueskyConfig, { user: BlueSkyUser, tokens: BlueSkyTokens }>) {
3535
return eventHandler(async (event: H3Event) => {
3636
const clientMetadata = getAtprotoClientMetadata(event, 'bluesky', config)
3737
const scopes = clientMetadata.scope?.split(' ') ?? []

src/runtime/server/lib/oauth/apple.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ export function defineOAuthAppleEventHandler({
9292
config,
9393
onSuccess,
9494
onError,
95-
}: OAuthConfig<OAuthAppleConfig>) {
95+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
96+
}: OAuthConfig<OAuthAppleConfig, { user: OAuthAppleUser, payload: OAuthAppleTokens, tokens: any }>) {
9697
return eventHandler(async (event: H3Event) => {
9798
config = defu(config, useRuntimeConfig(event).oauth?.apple, {
9899
authorizationURL: config?.authorizationURL || 'https://appleid.apple.com/auth/authorize',
@@ -172,7 +173,7 @@ export function defineOAuthAppleEventHandler({
172173
return handleAccessTokenErrorResponse(event, 'apple', payload, onError)
173174
}
174175

175-
return onSuccess(event, { user, payload, tokens: accessTokenResult })
176+
return onSuccess(event, { user: user!, payload, tokens: accessTokenResult })
176177
}
177178
catch (error) {
178179
return handleAccessTokenErrorResponse(event, 'apple', error, onError)

src/runtime/server/lib/oauth/atlassian.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ export function defineOAuthAtlassianEventHandler({
9999
config,
100100
onSuccess,
101101
onError,
102-
}: OAuthConfig<OAuthAtlassianConfig>) {
102+
}: OAuthConfig<OAuthAtlassianConfig, { user: AtlassianUser, tokens: AtlassianTokens }>) {
103103
return eventHandler(async (event: H3Event) => {
104104
config = defu(config, useRuntimeConfig().oauth?.atlassian, {
105105
authorizationURL: 'https://auth.atlassian.com/authorize',

src/runtime/server/lib/oauth/facebook.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ export function defineOAuthFacebookEventHandler({
6969
authorizationParams: {},
7070
}) as OAuthFacebookConfig
7171

72-
const query = getQuery<{ code?: string, error?: string }>(event)
72+
const query = getQuery<{ code?: string, error?: string, state?: string }>(event)
7373

7474
if (query.error) {
7575
const error = createError({

src/runtime/server/lib/oauth/github.ts

+43-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,49 @@ export interface OAuthGitHubConfig {
6363
redirectURL?: string
6464
}
6565

66-
export function defineOAuthGitHubEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthGitHubConfig>) {
66+
interface GitHubUser {
67+
login: string
68+
id: number
69+
node_id: string
70+
avatar_url: string
71+
gravatar_id: string
72+
url: string
73+
html_url: string
74+
followers_url: string
75+
following_url: string
76+
gists_url: string
77+
starred_url: string
78+
subscriptions_url: string
79+
organizations_url: string
80+
repos_url: string
81+
events_url: string
82+
received_events_url: string
83+
type: string
84+
site_admin: boolean
85+
name: string
86+
company: string
87+
blog: string
88+
location: string
89+
email: string | null
90+
hireable: boolean | null
91+
bio: string | null
92+
twitter_username: string | null
93+
public_repos: number
94+
public_gists: number
95+
followers: number
96+
following: number
97+
created_at: string
98+
updated_at: string
99+
email_verified?: boolean
100+
}
101+
102+
interface GitHubTokens {
103+
access_token: string
104+
scope: string
105+
token_type: string
106+
}
107+
108+
export function defineOAuthGitHubEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthGitHubConfig, { user: GitHubUser, tokens: GitHubTokens }>) {
67109
return eventHandler(async (event: H3Event) => {
68110
config = defu(config, useRuntimeConfig(event).oauth?.github, {
69111
authorizationURL: 'https://github.com/login/oauth/authorize',

src/runtime/server/lib/oauth/line.ts

+7-4
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,13 @@ export function defineOAuthLineEventHandler({
7373
const query = getQuery<{ code?: string, error?: string, state?: string }>(event)
7474

7575
if (query.error) {
76-
return onError(
77-
event,
78-
new Error(`Line login failed: ${query.error || 'Unknown error'}`),
79-
)
76+
const error = createError({
77+
statusCode: 401,
78+
message: `Line login failed: ${query.error || 'Unknown error'}`,
79+
data: query,
80+
})
81+
if (!onError) throw error
82+
return onError(event, error)
8083
}
8184

8285
if (!config.clientId || !config.clientSecret) {

src/runtime/server/lib/oauth/microsoft.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export function defineOAuthMicrosoftEventHandler({ config, onSuccess, onError }:
6565
authorizationParams: {},
6666
}) as OAuthMicrosoftConfig
6767

68-
const query = getQuery<{ code?: string }>(event)
68+
const query = getQuery<{ code?: string, state?: string }>(event)
6969

7070
if (!config.clientId || !config.clientSecret || !config.tenant) {
7171
return handleMissingConfiguration(event, 'microsoft', ['clientId', 'clientSecret', 'tenant'], onError)

src/runtime/server/lib/oauth/seznam.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ export interface OAuthSeznamUser {
116116
gender?: string | null
117117
}
118118

119-
export function defineOAuthSeznamEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthSeznamConfig, OAuthSeznamUser>) {
119+
export function defineOAuthSeznamEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthSeznamConfig, { user: OAuthSeznamUser, tokens: unknown }>) {
120120
return eventHandler(async (event: H3Event) => {
121121
config = defu(config, useRuntimeConfig(event).oauth?.seznam, {
122122
authorizationURL: 'https://login.szn.cz/api/v1/oauth/auth',

src/runtime/server/lib/oauth/steam.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ export function defineOAuthSteamEventHandler({ config, onSuccess, onError }: OAu
101101
const idRegex = /^https?:\/\/steamcommunity\.com\/openid\/id\/(\d+)$/
102102
const steamIdCheck = idRegex.exec(query['openid.claimed_id'])
103103

104-
const steamId = steamIdCheck[1]
104+
const steamId = steamIdCheck?.[1]
105105

106106
// TODO: improve typing
107107
// eslint-disable-next-line @typescript-eslint/no-explicit-any

src/runtime/server/lib/oauth/strava.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ export function defineOAuthStravaEventHandler({
152152
config,
153153
onSuccess,
154154
onError,
155-
}: OAuthConfig<OAuthStravaConfig, OAuthStravaUser>) {
155+
}: OAuthConfig<OAuthStravaConfig, { user: OAuthStravaUser, tokens: OAuthStravaTokens }>) {
156156
return eventHandler(async (event: H3Event) => {
157157
config = defu(config, useRuntimeConfig(event).oauth?.strava) as OAuthStravaConfig
158158

src/runtime/server/lib/oauth/workos.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export interface OAuthWorkOSTokens {
7272
refresh_token: string
7373
}
7474

75-
export function defineOAuthWorkOSEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthWorkOSConfig, OAuthWorkOSUser, OAuthWorkOSTokens>) {
75+
export function defineOAuthWorkOSEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthWorkOSConfig, { user: OAuthWorkOSUser, tokens: OAuthWorkOSTokens }>) {
7676
return eventHandler(async (event: H3Event) => {
7777
config = defu(config, useRuntimeConfig(event).oauth?.workos, { screen_hint: 'sign-in' }) as OAuthWorkOSConfig
7878

src/runtime/server/lib/webauthn/authenticate.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import { generateAuthenticationOptions, verifyAuthenticationResponse } from '@si
44
import defu from 'defu'
55
import { getRandomValues } from 'uncrypto'
66
import { base64URLStringToBuffer, bufferToBase64URLString } from '@simplewebauthn/browser'
7+
import type { AuthenticationBody } from '../../../types/webauthn'
78
import { useRuntimeConfig } from '#imports'
89
import type { WebAuthnAuthenticateEventHandlerOptions, WebAuthnCredential } from '#auth-utils'
9-
import type { AuthenticationBody } from '~/src/runtime/types/webauthn'
1010

1111
export function defineWebAuthnAuthenticateEventHandler<T extends WebAuthnCredential>({
1212
storeChallenge,

src/runtime/server/lib/webauthn/register.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import { generateRegistrationOptions, verifyRegistrationResponse } from '@simple
55
import defu from 'defu'
66
import { bufferToBase64URLString } from '@simplewebauthn/browser'
77
import { getRandomValues } from 'uncrypto'
8+
import type { RegistrationBody, ValidateUserFunction } from '../../../types/webauthn'
89
import { useRuntimeConfig } from '#imports'
910
import type { WebAuthnUser, WebAuthnRegisterEventHandlerOptions } from '#auth-utils'
10-
import type { RegistrationBody, ValidateUserFunction } from '~/src/runtime/types/webauthn'
1111

1212
export function defineWebAuthnRegisterEventHandler<T extends WebAuthnUser>({
1313
storeChallenge,

src/runtime/server/utils/atproto.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import type { H3Event } from 'h3'
22
import type { OAuthClientMetadataInput, OAuthGrantType } from '@atproto/oauth-client-node'
3+
import { getRequestURL } from 'h3'
34
import type { AtprotoProviderClientMetadata } from '../../types/atproto'
45
import type { OAuthBlueskyConfig } from '../lib/atproto/bluesky'
56
import { getOAuthRedirectURL } from '../lib/utils'
67
import { getClientMetadataFilename } from '../../utils/atproto'
78
import type { ATProtoProvider, OAuthConfig } from '#auth-utils'
8-
import { getRequestURL, useRuntimeConfig } from '#imports'
9+
import { useRuntimeConfig } from '#imports'
910

1011
export function getAtprotoClientMetadata(
1112
event: H3Event,

src/runtime/server/utils/session.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ export const sessionHooks = createHooks<SessionHooks>()
3030
export async function getUserSession(event: UseSessionEvent): Promise<UserSession> {
3131
const session = await _useSession(event)
3232
return {
33-
id: session.id,
3433
...session.data,
34+
id: session.id,
3535
}
3636
}
3737
/**
@@ -40,7 +40,7 @@ export async function getUserSession(event: UseSessionEvent): Promise<UserSessio
4040
* @param data User session data, please only store public information since it can be decoded with API calls
4141
* @see https://github.com/atinux/nuxt-auth-utils
4242
*/
43-
export async function setUserSession(event: H3Event, data: UserSession, config?: Partial<SessionConfig>): Promise<UserSession> {
43+
export async function setUserSession(event: H3Event, data: Omit<UserSession, 'id'>, config?: Partial<SessionConfig>): Promise<UserSession> {
4444
const session = await _useSession(event, config)
4545

4646
await session.update(defu(data, session.data))
@@ -53,7 +53,7 @@ export async function setUserSession(event: H3Event, data: UserSession, config?:
5353
* @param event The Request (h3) event
5454
* @param data User session data, please only store public information since it can be decoded with API calls
5555
*/
56-
export async function replaceUserSession(event: H3Event, data: UserSession, config?: Partial<SessionConfig>): Promise<UserSession> {
56+
export async function replaceUserSession(event: H3Event, data: Omit<UserSession, 'id'>, config?: Partial<SessionConfig>): Promise<UserSession> {
5757
const session = await _useSession(event, config)
5858

5959
await session.clear()

src/runtime/types/oauth-config.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ export type OAuthProvider = ATProtoProvider | 'atlassian' | 'auth0' | 'authentik
77
export type OnError = (event: H3Event, error: H3Error) => Promise<void> | void
88

99
// eslint-disable-next-line @typescript-eslint/no-explicit-any
10-
export interface OAuthConfig<TConfig, TUser = any, TTokens = any> {
10+
export interface OAuthConfig<TConfig, TResult = { user: any, tokens: any }> {
1111
config?: TConfig
1212
onSuccess: (
1313
event: H3Event,
14-
result: { user: TUser, tokens: TTokens }
14+
result: TResult
1515
) => Promise<void> | void
1616
onError?: OnError
1717
}

src/runtime/types/session.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export interface UserSession {
1010
/**
1111
* Session ID
1212
*/
13-
id?: string
13+
id: string
1414
/**
1515
* User session data, available on client and server
1616
*/
@@ -26,7 +26,6 @@ export interface UserSession {
2626
}
2727

2828
export interface UserSessionRequired extends UserSession {
29-
id: string
3029
user: User
3130
}
3231

@@ -46,7 +45,7 @@ export interface UserSessionComposable {
4645
/**
4746
* The session object.
4847
*/
49-
session: Ref<UserSession>
48+
session: Ref<UserSession | null>
5049
/**
5150
* Fetch the user session from the server.
5251
*/

0 commit comments

Comments
 (0)