Skip to content

Commit f998bf2

Browse files
authored
refactor: strict types (#2802)
* WIP strict types * wip types * wip strict types * More strict typing * Removing strict false Fix last types * Fix typo * Make TS happy * Fix tests * Fixes to types * Make files align with strict mode
1 parent 533ed94 commit f998bf2

29 files changed

+187
-127
lines changed

src/client/_utils.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export async function fetchData<T = any>(
4545
return Object.keys(data).length > 0 ? data : null // Return null if data empty
4646
} catch (error) {
4747
logger.error("CLIENT_FETCH_ERROR", {
48-
error,
48+
error: error as Error,
4949
path,
5050
...(req ? { header: req.headers } : {}),
5151
})
@@ -84,9 +84,9 @@ export function BroadcastChannel(name = "nextauth.message") {
8484
return {
8585
/** Get notified by other tabs/windows. */
8686
receive(onReceive: (message: BroadcastMessage) => void) {
87-
const handler = (event) => {
87+
const handler = (event: StorageEvent) => {
8888
if (event.key !== name) return
89-
const message: BroadcastMessage = JSON.parse(event.newValue)
89+
const message: BroadcastMessage = JSON.parse(event.newValue ?? "{}")
9090
if (message?.event !== "session" || !message?.data) return
9191

9292
onReceive(message)
@@ -95,7 +95,7 @@ export function BroadcastChannel(name = "nextauth.message") {
9595
return () => window.removeEventListener("storage", handler)
9696
},
9797
/** Notify other tabs/windows. */
98-
post(message) {
98+
post(message: Record<string, unknown>) {
9999
if (typeof window === "undefined") return
100100
localStorage.setItem(
101101
name,

src/core/errors.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import type { Adapter } from "../adapters"
66
* @source https://iaincollins.medium.com/error-handling-in-javascript-a6172ccdf9af
77
*/
88
export class UnknownError extends Error {
9-
constructor(error) {
9+
constructor(error: Error | string) {
1010
// Support passing error or string
11-
super(error?.message ?? error)
11+
super((error as Error)?.message ?? error)
1212
this.name = "UnknownError"
1313
if (error instanceof Error) {
1414
this.stack = error.stack
@@ -56,10 +56,10 @@ export function eventsErrorHandler(
5656
return Object.keys(methods).reduce<any>((acc, name) => {
5757
acc[name] = async (...args: any[]) => {
5858
try {
59-
const method: Method = methods[name]
59+
const method: Method = methods[name as keyof Method]
6060
return await method(...args)
6161
} catch (e) {
62-
logger.error(`${upperSnake(name)}_EVENT_ERROR`, e)
62+
logger.error(`${upperSnake(name)}_EVENT_ERROR`, e as Error)
6363
}
6464
}
6565
return acc
@@ -77,11 +77,11 @@ export function adapterErrorHandler(
7777
acc[name] = async (...args: any[]) => {
7878
try {
7979
logger.debug(`adapter_${name}`, { args })
80-
const method: Method = adapter[name as any]
80+
const method: Method = adapter[name as keyof Method]
8181
return await method(...args)
8282
} catch (error) {
83-
logger.error(`adapter_error_${name}`, error)
84-
const e = new UnknownError(error)
83+
logger.error(`adapter_error_${name}`, error as Error)
84+
const e = new UnknownError(error as Error)
8585
e.name = `${capitalize(name)}Error`
8686
throw e
8787
}

src/core/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ export async function NextAuthHandler<
195195
logger[level](code, metadata)
196196
} catch (error) {
197197
// If logging itself failed...
198-
logger.error("LOGGER_ERROR", error)
198+
logger.error("LOGGER_ERROR", error as Error)
199199
}
200200
}
201201
return {}

src/core/lib/cookie.ts

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
// REVIEW: Is there any way to defer two types of strings?
2-
2+
import { NextAuthResponse } from "../../lib/types"
33
import { CookiesOptions } from "../.."
44
import { CookieOption } from "../types"
5+
import { ServerResponse } from "http"
56

67
/** Stringified form of `JWT`. Extract the content with `jwt.decode` */
78
export type JWTString = string
89

10+
export type SetCookieOptions = Partial<CookieOption["options"]> & {
11+
expires?: Date | string
12+
encode?: (val: unknown) => string
13+
}
14+
915
/** If `options.session.jwt` is set to `true`, this is a stringified `JWT`. In case of a database persisted session, this is the `sessionToken` of the session in the database.. */
1016
export type SessionToken<T extends "jwt" | "db" = "jwt"> = T extends "jwt"
1117
? JWTString
@@ -22,13 +28,10 @@ export type SessionToken<T extends "jwt" | "db" = "jwt"> = T extends "jwt"
2228
* (with fixes for specific issues) to keep dependancy size down.
2329
*/
2430
export function set(
25-
res,
26-
name,
27-
value,
28-
options: {
29-
expires?: Date
30-
maxAge?: number
31-
} = {}
31+
res: NextAuthResponse | ServerResponse,
32+
name: string,
33+
value: unknown,
34+
options: SetCookieOptions = {}
3235
) {
3336
const stringValue =
3437
typeof value === "object" ? "j:" + JSON.stringify(value) : String(value)
@@ -39,20 +42,24 @@ export function set(
3942
}
4043

4144
// Preserve any existing cookies that have already been set in the same session
42-
let setCookieHeader = res.getHeader("Set-Cookie") || []
45+
let setCookieHeader = res.getHeader("Set-Cookie") ?? []
4346
// If not an array (i.e. a string with a single cookie) convert it into an array
4447
if (!Array.isArray(setCookieHeader)) {
45-
setCookieHeader = [setCookieHeader]
48+
setCookieHeader = [setCookieHeader.toString()]
4649
}
4750
setCookieHeader.push(_serialize(name, String(stringValue), options))
4851
res.setHeader("Set-Cookie", setCookieHeader)
4952
}
5053

51-
function _serialize(name, val, options) {
54+
function _serialize(
55+
name: string,
56+
val: unknown,
57+
options: SetCookieOptions = {}
58+
) {
5259
const fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/ // eslint-disable-line no-control-regex
5360

5461
const opt = options || {}
55-
const enc = opt.encode || encodeURIComponent
62+
const enc = opt.encode ?? encodeURIComponent
5663

5764
if (typeof enc !== "function") {
5865
throw new TypeError("option encode is invalid")
@@ -62,7 +69,7 @@ function _serialize(name, val, options) {
6269
throw new TypeError("argument name is invalid")
6370
}
6471

65-
const value = enc(val)
72+
const value = enc(val as string)
6673

6774
if (value && !fieldContentRegExp.test(value)) {
6875
throw new TypeError("argument val is invalid")
@@ -99,9 +106,9 @@ function _serialize(name, val, options) {
99106
}
100107

101108
if (opt.expires) {
102-
let expires = opt.expires
103-
if (typeof opt.expires.toUTCString === "function") {
104-
expires = opt.expires.toUTCString()
109+
let expires: Date | string = opt.expires
110+
if (typeof (opt.expires as Date).toUTCString === "function") {
111+
expires = (opt.expires as Date).toUTCString()
105112
} else {
106113
const dateExpires = new Date(opt.expires)
107114
expires = dateExpires.toUTCString()
@@ -154,7 +161,7 @@ function _serialize(name, val, options) {
154161
*
155162
* @TODO Review cookie settings (names, options)
156163
*/
157-
export function defaultCookies(useSecureCookies): CookiesOptions {
164+
export function defaultCookies(useSecureCookies: boolean): CookiesOptions {
158165
const cookiePrefix = useSecureCookies ? "__Secure-" : ""
159166
return {
160167
// default cookie options

src/core/lib/email/signin.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export default async function email(
4747
logger.error("SEND_VERIFICATION_EMAIL_ERROR", {
4848
identifier,
4949
url,
50-
error,
50+
error: error as Error,
5151
})
5252
throw new Error("SEND_VERIFICATION_EMAIL_ERROR")
5353
}

src/core/lib/oauth/authorization-url.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export default async function getAuthorizationUrl(params: {
6767
cookies,
6868
}
6969
} catch (error) {
70-
logger.error("GET_AUTHORIZATION_URL_ERROR", error)
70+
logger.error("GET_AUTHORIZATION_URL_ERROR", error as Error)
7171
throw error
7272
}
7373
}

src/core/lib/oauth/callback.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,14 @@ export default async function oAuthCallback(params: {
3838
const { oauth_token, oauth_verifier } = query ?? {}
3939
// @ts-expect-error
4040
const tokens: TokenSet = await client.getOAuthAccessToken(
41-
oauth_token,
41+
oauth_token as string,
4242
// @ts-expect-error
4343
null,
4444
oauth_verifier
4545
)
4646
// @ts-expect-error
4747
let profile: Profile = await client.get(
48-
provider.profileUrl,
48+
(provider as any).profileUrl,
4949
tokens.oauth_token,
5050
tokens.oauth_token_secret
5151
)
@@ -56,7 +56,7 @@ export default async function oAuthCallback(params: {
5656

5757
return await getProfile({ profile, tokens, provider, logger })
5858
} catch (error) {
59-
logger.error("OAUTH_V1_GET_ACCESS_TOKEN_ERROR", error)
59+
logger.error("OAUTH_V1_GET_ACCESS_TOKEN_ERROR", error as Error)
6060
throw error
6161
}
6262
}
@@ -141,8 +141,8 @@ export default async function oAuthCallback(params: {
141141
cookies: pkce?.cookie ? [pkce.cookie] : undefined,
142142
}
143143
} catch (error) {
144-
logger.error("OAUTH_CALLBACK_ERROR", { error, providerId: provider.id })
145-
throw new OAuthCallbackError(error)
144+
logger.error("OAUTH_CALLBACK_ERROR", { error: error as Error, providerId: provider.id })
145+
throw new OAuthCallbackError(error as Error)
146146
}
147147
}
148148

@@ -191,7 +191,10 @@ async function getProfile({
191191
// all providers, so we return an empty object; the user should then be
192192
// redirected back to the sign up page. We log the error to help developers
193193
// who might be trying to debug this when configuring a new provider.
194-
logger.error("OAUTH_PARSE_PROFILE_ERROR", { error, OAuthProfile })
194+
logger.error("OAUTH_PARSE_PROFILE_ERROR", {
195+
error: error as Error,
196+
OAuthProfile,
197+
})
195198
return {
196199
profile: null,
197200
account: null,

src/core/lib/oauth/client-legacy.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@ export function oAuth1Client(options: InternalOptions<"oauth">) {
4040
return await new Promise((resolve, reject) => {
4141
originalGetOAuth1AccessToken(
4242
...args,
43-
(error, oauth_token, oauth_token_secret) => {
43+
(error: any, oauth_token: any, oauth_token_secret: any) => {
4444
if (error) {
4545
return reject(error)
4646
}
47-
resolve({ oauth_token, oauth_token_secret })
47+
resolve({ oauth_token, oauth_token_secret } as any)
4848
}
4949
)
5050
})
@@ -60,7 +60,7 @@ export function oAuth1Client(options: InternalOptions<"oauth">) {
6060
if (error) {
6161
return reject(error)
6262
}
63-
resolve({ oauth_token, oauth_token_secret, params })
63+
resolve({ oauth_token, oauth_token_secret, params } as any)
6464
}
6565
)
6666
})

src/core/lib/oauth/client.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,8 @@ export async function openidClient(
3131

3232
const client = new issuer.Client(
3333
{
34-
// @ts-expect-error
35-
client_id: provider.clientId,
36-
// @ts-expect-error
37-
client_secret: provider.clientSecret,
34+
client_id: provider.clientId as string,
35+
client_secret: provider.clientSecret as string,
3836
redirect_uris: [provider.callbackUrl],
3937
...provider.client,
4038
},

src/core/lib/oauth/pkce-handler.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import * as cookie from "../cookie"
1+
import { Cookie } from "../cookie"
22
import * as jwt from "../../../jwt"
33
import { generators } from "openid-client"
44
import { InternalOptions } from "src/lib/types"
@@ -16,7 +16,17 @@ const PKCE_MAX_AGE = 60 * 15 // 15 minutes in seconds
1616
* cookie: import("../cookie").Cookie
1717
* }>
1818
*/
19-
export async function createPKCE(options) {
19+
20+
type PKCE = Promise<
21+
| undefined
22+
| {
23+
code_challenge: string
24+
code_challenge_method: "S256"
25+
cookie: Cookie
26+
}
27+
>
28+
29+
export async function createPKCE(options: InternalOptions<"oauth">): PKCE {
2030
const { cookies, logger } = options
2131
/** @type {import("src/providers").OAuthConfig} */
2232
const provider = options.provider
@@ -29,6 +39,7 @@ export async function createPKCE(options) {
2939

3040
// Encrypt code_verifier and save it to an encrypted cookie
3141
const encryptedCodeVerifier = await jwt.encode({
42+
// @ts-expect-error
3243
maxAge: PKCE_MAX_AGE,
3344
...options.jwt,
3445
token: { code_verifier: codeVerifier },
@@ -68,7 +79,7 @@ export async function usePKCECodeVerifier(params: {
6879
}): Promise<
6980
| {
7081
codeVerifier?: string
71-
cookie?: cookie.Cookie
82+
cookie?: Cookie
7283
}
7384
| undefined
7485
> {
@@ -85,7 +96,7 @@ export async function usePKCECodeVerifier(params: {
8596
})
8697

8798
// remove PKCE cookie after it has been used up
88-
const cookie: cookie.Cookie = {
99+
const cookie: Cookie = {
89100
name: cookies.pkceCodeVerifier.name,
90101
value: "",
91102
options: {

0 commit comments

Comments
 (0)