Skip to content

Commit 87d315b

Browse files
fix: TypeScript ESLint unbound-method errors in Auth0 context interface (#1368)
1 parent fb7c44d commit 87d315b

File tree

5 files changed

+239
-42
lines changed

5 files changed

+239
-42
lines changed

eslint.config.mjs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { fixupConfigRules } from '@eslint/compat';
22
import { FlatCompat } from '@eslint/eslintrc';
33
import js from '@eslint/js';
44
import prettier from 'eslint-plugin-prettier';
5+
import tseslint from 'typescript-eslint';
56
import { defineConfig } from 'eslint/config';
67
import path from 'node:path';
78
import { fileURLToPath } from 'node:url';
@@ -32,6 +33,23 @@ export default defineConfig([
3233
],
3334
},
3435
},
36+
// TypeScript-specific configuration for type-checked rules
37+
{
38+
files: ['**/*.ts', '**/*.tsx'],
39+
ignores: ['**/__tests__/**', '**/__mocks__/**', '**/*.spec.ts', '**/*.spec.tsx', '**/*.test.ts', '**/*.test.tsx'],
40+
languageOptions: {
41+
parserOptions: {
42+
project: true,
43+
tsconfigRootDir: import.meta.dirname,
44+
},
45+
},
46+
rules: {
47+
// Enable unbound-method rule to catch interface typing issues
48+
// This helps ensure methods in interfaces use arrow function syntax
49+
// instead of method syntax when they don't use 'this'
50+
'@typescript-eslint/unbound-method': 'error',
51+
},
52+
},
3553
{
3654
ignores: ['node_modules/', 'lib/', 'docs'],
3755
},

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,8 @@
132132
"typedoc": "^0.28.2",
133133
"typedoc-plugin-missing-exports": "^4.0.0",
134134
"typedoc-plugin-replace-text": "^4.2.0",
135-
"typescript": "5.2.2"
135+
"typescript": "5.2.2",
136+
"typescript-eslint": "^8.46.2"
136137
},
137138
"dependencies": {
138139
"@auth0/auth0-spa-js": "2.7.0",

src/hooks/Auth0Context.ts

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ export interface Auth0ContextInterface extends AuthState {
3939
* @returns A promise that resolves with the user's credentials upon successful authentication.
4040
* @throws {AuthError} If the authentication fails.
4141
*/
42-
authorize(
42+
authorize: (
4343
parameters?: WebAuthorizeParameters,
4444
options?: NativeAuthorizeOptions
45-
): Promise<Credentials>;
45+
) => Promise<Credentials>;
4646

4747
/**
4848
* Clears the user's session and logs them out.
@@ -51,18 +51,18 @@ export interface Auth0ContextInterface extends AuthState {
5151
* @returns A promise that resolves when the session has been cleared.
5252
* @throws {AuthError} If the logout fails.
5353
*/
54-
clearSession(
54+
clearSession: (
5555
parameters?: ClearSessionParameters,
5656
options?: NativeClearSessionOptions
57-
): Promise<void>;
57+
) => Promise<void>;
5858

5959
/**
6060
* Saves the user's credentials.
6161
* @param credentials The credentials to save.
6262
* @returns A promise that resolves when the credentials have been saved.
6363
* @throws {AuthError} If the save fails.
6464
*/
65-
saveCredentials(credentials: Credentials): Promise<void>;
65+
saveCredentials: (credentials: Credentials) => Promise<void>;
6666

6767
/**
6868
* Retrieves the stored credentials, refreshing them if necessary.
@@ -73,12 +73,12 @@ export interface Auth0ContextInterface extends AuthState {
7373
* @returns A promise that resolves with the user's credentials.
7474
* @throws {AuthError} If credentials cannot be retrieved or refreshed.
7575
*/
76-
getCredentials(
76+
getCredentials: (
7777
scope?: string,
7878
minTtl?: number,
7979
parameters?: Record<string, unknown>,
8080
forceRefresh?: boolean
81-
): Promise<Credentials>;
81+
) => Promise<Credentials>;
8282

8383
/**
8484
* Clears the user's credentials without clearing their web session and logs them out.
@@ -96,13 +96,13 @@ export interface Auth0ContextInterface extends AuthState {
9696
* @param minTtl The minimum time-to-live (in seconds) required for the access token to be considered valid. Defaults to 0.
9797
* @returns A promise that resolves with `true` if valid credentials exist, `false` otherwise.
9898
*/
99-
hasValidCredentials(minTtl?: number): Promise<boolean>;
99+
hasValidCredentials: (minTtl?: number) => Promise<boolean>;
100100

101101
/**
102102
* Cancels the ongoing web authentication process.
103103
* This works only on iOS. On other platforms, it will resolve without performing an action.
104104
*/
105-
cancelWebAuth(): Promise<void>;
105+
cancelWebAuth: () => Promise<void>;
106106

107107
/**
108108
* Authenticates a user with their username and password.
@@ -111,25 +111,25 @@ export interface Auth0ContextInterface extends AuthState {
111111
* @returns A promise that resolves with the user's credentials.
112112
* @throws {AuthError} If the authentication fails.
113113
*/
114-
loginWithPasswordRealm(
114+
loginWithPasswordRealm: (
115115
parameters: PasswordRealmParameters
116-
): Promise<Credentials>;
116+
) => Promise<Credentials>;
117117

118118
/**
119119
* Creates a new user in a database connection.
120120
* @param parameters The parameters for creating the new user.
121121
* @returns A promise that resolves with the new user's profile information.
122122
* @throws {AuthError} If the user creation fails.
123123
*/
124-
createUser(parameters: CreateUserParameters): Promise<Partial<User>>;
124+
createUser: (parameters: CreateUserParameters) => Promise<Partial<User>>;
125125

126126
/**
127127
* Resets the user's password.
128128
* @param parameters The parameters for resetting the password.
129129
* @returns A promise that resolves when the password has been reset.
130130
* @throws {AuthError} If the reset fails.
131131
*/
132-
resetPassword(parameters: ResetPasswordParameters): Promise<void>;
132+
resetPassword: (parameters: ResetPasswordParameters) => Promise<void>;
133133

134134
/**
135135
* Exchanges an authorization code for tokens.
@@ -138,87 +138,91 @@ export interface Auth0ContextInterface extends AuthState {
138138
* @returns A promise that resolves with the user's credentials.
139139
* @throws {AuthError} If the exchange fails.
140140
*/
141-
authorizeWithExchange(parameters: ExchangeParameters): Promise<Credentials>;
141+
authorizeWithExchange: (
142+
parameters: ExchangeParameters
143+
) => Promise<Credentials>;
142144

143145
/**
144146
* Exchanges an authorization code for native social tokens.
145147
* @param parameters The parameters containing the authorization code and verifier.
146148
* @returns A promise that resolves with the user's credentials.
147149
* @throws {AuthError} If the exchange fails.
148150
*/
149-
authorizeWithExchangeNativeSocial(
151+
authorizeWithExchangeNativeSocial: (
150152
parameters: ExchangeNativeSocialParameters
151-
): Promise<Credentials>;
153+
) => Promise<Credentials>;
152154

153155
/**
154156
* Sends a verification code to the user's email.
155157
* @param parameters The parameters for sending the email code.
156158
* @throws {AuthError} If sending the email code fails.
157159
*/
158-
sendEmailCode(parameters: PasswordlessEmailParameters): Promise<void>;
160+
sendEmailCode: (parameters: PasswordlessEmailParameters) => Promise<void>;
159161

160162
/**
161163
* Authorizes a user with their email.
162164
* @param parameters The parameters for email authorization.
163165
* @returns A promise that resolves with the user's credentials.
164166
* @throws {AuthError} If the authorization fails.
165167
*/
166-
authorizeWithEmail(parameters: LoginEmailParameters): Promise<Credentials>;
168+
authorizeWithEmail: (
169+
parameters: LoginEmailParameters
170+
) => Promise<Credentials>;
167171

168172
/**
169173
/**
170174
* Sends a verification code to the user's SMS.
171175
* @param parameters The parameters for sending the SMS code.
172176
* @throws {AuthError} If sending the SMS code fails.
173177
*/
174-
sendSMSCode(parameters: PasswordlessSmsParameters): Promise<void>;
178+
sendSMSCode: (parameters: PasswordlessSmsParameters) => Promise<void>;
175179

176180
/**
177181
* Authorizes a user with their SMS.
178182
* @param parameters The parameters for SMS authorization.
179183
* @returns A promise that resolves with the user's credentials.
180184
* @throws {AuthError} If the authorization fails.
181185
*/
182-
authorizeWithSMS(parameters: LoginSmsParameters): Promise<Credentials>;
186+
authorizeWithSMS: (parameters: LoginSmsParameters) => Promise<Credentials>;
183187

184188
/**
185189
* Sends a multifactor challenge to the user.
186190
* @param parameters The parameters for the multifactor challenge.
187191
* @returns A promise that resolves when the challenge has been sent.
188192
* @throws {AuthError} If sending the challenge fails.
189193
*/
190-
sendMultifactorChallenge(
194+
sendMultifactorChallenge: (
191195
parameters: MfaChallengeParameters
192-
): Promise<MfaChallengeResponse>;
196+
) => Promise<MfaChallengeResponse>;
193197

194198
/**
195199
* Authorizes a user with out-of-band (OOB) authentication.
196200
* @param parameters The parameters for OOB authorization.
197201
* @returns A promise that resolves with the user's credentials.
198202
* @throws {AuthError} If the authorization fails.
199203
*/
200-
authorizeWithOOB(parameters: LoginOobParameters): Promise<Credentials>;
204+
authorizeWithOOB: (parameters: LoginOobParameters) => Promise<Credentials>;
201205

202206
/**
203207
* Authorizes a user with a one-time password (OTP).
204208
* @param parameters The parameters for OTP authorization.
205209
* @returns A promise that resolves with the user's credentials.
206210
* @throws {AuthError} If the authorization fails.
207211
*/
208-
authorizeWithOTP(parameters: LoginOtpParameters): Promise<Credentials>;
212+
authorizeWithOTP: (parameters: LoginOtpParameters) => Promise<Credentials>;
209213

210214
/**
211215
* Authorizes a user with a recovery code.
212216
* @param parameters The parameters for recovery code authorization.
213217
* @returns A promise that resolves with the user's credentials.
214218
* @throws {AuthError} If the authorization fails.
215219
*/
216-
authorizeWithRecoveryCode(
220+
authorizeWithRecoveryCode: (
217221
parameters: LoginRecoveryCodeParameters
218-
): Promise<Credentials>;
222+
) => Promise<Credentials>;
219223

220224
// Token Management
221-
revokeRefreshToken(parameters: RevokeOptions): Promise<void>;
225+
revokeRefreshToken: (parameters: RevokeOptions) => Promise<void>;
222226

223227
/**
224228
* Generates DPoP headers for making authenticated requests to custom APIs.
@@ -244,7 +248,9 @@ export interface Auth0ContextInterface extends AuthState {
244248
* }
245249
* ```
246250
*/
247-
getDPoPHeaders(params: DPoPHeadersParams): Promise<Record<string, string>>;
251+
getDPoPHeaders: (
252+
params: DPoPHeadersParams
253+
) => Promise<Record<string, string>>;
248254
}
249255

250256
const stub = (): any => {

src/platforms/native/bridge/NativeBridgeManager.ts

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ export class NativeBridgeManager implements INativeBridge {
4040

4141
async hasValidInstance(clientId: string, domain: string): Promise<boolean> {
4242
return this.a0_call(
43-
Auth0NativeModule.hasValidAuth0InstanceWithConfiguration,
43+
Auth0NativeModule.hasValidAuth0InstanceWithConfiguration.bind(
44+
Auth0NativeModule
45+
),
4446
clientId,
4547
domain
4648
);
@@ -55,7 +57,9 @@ export class NativeBridgeManager implements INativeBridge {
5557
// This is a new method we'd add to the native side to ensure the
5658
// underlying Auth0.swift/Auth0.android SDKs are configured.
5759
return this.a0_call(
58-
Auth0NativeModule.initializeAuth0WithConfiguration,
60+
Auth0NativeModule.initializeAuth0WithConfiguration.bind(
61+
Auth0NativeModule
62+
),
5963
clientId,
6064
domain,
6165
localAuthenticationOptions,
@@ -64,7 +68,9 @@ export class NativeBridgeManager implements INativeBridge {
6468
}
6569

6670
getBundleIdentifier(): Promise<string> {
67-
return this.a0_call(Auth0NativeModule.getBundleIdentifier);
71+
return this.a0_call(
72+
Auth0NativeModule.getBundleIdentifier.bind(Auth0NativeModule)
73+
);
6874
}
6975

7076
async authorize(
@@ -79,7 +85,7 @@ export class NativeBridgeManager implements INativeBridge {
7985
const scheme =
8086
parameters.redirectUrl?.split('://')[0] ?? options.customScheme;
8187
const credential = await this.a0_call(
82-
Auth0NativeModule.webAuth,
88+
Auth0NativeModule.webAuth.bind(Auth0NativeModule),
8389
scheme,
8490
parameters.redirectUrl,
8591
parameters.state,
@@ -104,19 +110,24 @@ export class NativeBridgeManager implements INativeBridge {
104110
options: NativeClearSessionOptions
105111
): Promise<void> {
106112
return this.a0_call(
107-
Auth0NativeModule.webAuthLogout,
113+
Auth0NativeModule.webAuthLogout.bind(Auth0NativeModule),
108114
options.customScheme,
109115
parameters.federated ?? false,
110116
parameters.returnToUrl
111117
);
112118
}
113119

114120
async cancelWebAuth(): Promise<void> {
115-
return this.a0_call(Auth0NativeModule.cancelWebAuth);
121+
return this.a0_call(
122+
Auth0NativeModule.cancelWebAuth.bind(Auth0NativeModule)
123+
);
116124
}
117125

118126
async saveCredentials(credentials: Credentials): Promise<void> {
119-
return this.a0_call(Auth0NativeModule.saveCredentials, credentials);
127+
return this.a0_call(
128+
Auth0NativeModule.saveCredentials.bind(Auth0NativeModule),
129+
credentials
130+
);
120131
}
121132

122133
async getCredentials(
@@ -128,7 +139,7 @@ export class NativeBridgeManager implements INativeBridge {
128139
// Assuming the native side can take an empty object for parameters.
129140
const params = parameters ?? {};
130141
return this.a0_call(
131-
Auth0NativeModule.getCredentials,
142+
Auth0NativeModule.getCredentials.bind(Auth0NativeModule),
132143
scope,
133144
minTtl ?? 0,
134145
params,
@@ -137,22 +148,30 @@ export class NativeBridgeManager implements INativeBridge {
137148
}
138149

139150
async hasValidCredentials(minTtl?: number): Promise<boolean> {
140-
return this.a0_call(Auth0NativeModule.hasValidCredentials, minTtl ?? 0);
151+
return this.a0_call(
152+
Auth0NativeModule.hasValidCredentials.bind(Auth0NativeModule),
153+
minTtl ?? 0
154+
);
141155
}
142156

143157
async clearCredentials(): Promise<void> {
144-
return this.a0_call(Auth0NativeModule.clearCredentials);
158+
return this.a0_call(
159+
Auth0NativeModule.clearCredentials.bind(Auth0NativeModule)
160+
);
145161
}
146162

147163
async resumeWebAuth(url: string): Promise<void> {
148-
return this.a0_call(Auth0NativeModule.resumeWebAuth, url);
164+
return this.a0_call(
165+
Auth0NativeModule.resumeWebAuth.bind(Auth0NativeModule),
166+
url
167+
);
149168
}
150169

151170
async getDPoPHeaders(
152171
params: DPoPHeadersParams
153172
): Promise<Record<string, string>> {
154173
return this.a0_call(
155-
Auth0NativeModule.getDPoPHeaders,
174+
Auth0NativeModule.getDPoPHeaders.bind(Auth0NativeModule),
156175
params.url,
157176
params.method,
158177
params.accessToken,
@@ -162,6 +181,6 @@ export class NativeBridgeManager implements INativeBridge {
162181
}
163182

164183
async clearDPoPKey(): Promise<void> {
165-
return this.a0_call(Auth0NativeModule.clearDPoPKey);
184+
return this.a0_call(Auth0NativeModule.clearDPoPKey.bind(Auth0NativeModule));
166185
}
167186
}

0 commit comments

Comments
 (0)