fix(shared-auth): add explicit AuthServiceInterface to fix TS inference truncation

TypeScript's ReturnType<> inference truncates large object literals,
showing only ~27 of 37 methods. This caused 5 apps to skip type-check
because verifyTwoFactor, signInWithPasskey, sendMagicLink, etc. were
invisible to consumers.

Fix: Define explicit AuthServiceInterface with all 37 methods and use
it as the return type of createAuthService(). This ensures all methods
are visible regardless of object literal size.

Verified: chat/web and presi/web now pass svelte-check for auth methods.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-03-28 03:15:29 +01:00
parent b37a451d29
commit 28bf9e5adb
2 changed files with 79 additions and 3 deletions

View file

@ -1,5 +1,6 @@
import type {
AuthServiceConfig,
AuthServiceInterface,
AuthEndpoints,
AuthResult,
TokenRefreshResult,
@ -68,7 +69,7 @@ const DEFAULT_ENDPOINTS: AuthEndpoints = {
/**
* Create an authentication service with the given configuration
*/
export function createAuthService(config: AuthServiceConfig) {
export function createAuthService(config: AuthServiceConfig): AuthServiceInterface {
const baseUrl = config.baseUrl.replace(/\/$/, ''); // Remove trailing slash
const storageKeys: StorageKeys = { ...DEFAULT_STORAGE_KEYS, ...config.storageKeys };
const endpoints: AuthEndpoints = { ...DEFAULT_ENDPOINTS, ...config.endpoints };
@ -1174,6 +1175,7 @@ export function createAuthService(config: AuthServiceConfig) {
}
/**
* Type for the auth service instance
* Type for the auth service instance.
* Uses the explicit interface instead of ReturnType<> to avoid TS inference truncation.
*/
export type AuthService = ReturnType<typeof createAuthService>;
export type AuthService = AuthServiceInterface;

View file

@ -183,3 +183,77 @@ export interface B2BInfo {
plan?: string;
role?: string;
}
/**
* Explicit interface for the auth service.
*
* TypeScript's ReturnType<> inference truncates large object literals (~27 methods shown).
* This explicit interface ensures all 37 methods are visible to consumers.
*/
export interface AuthServiceInterface {
// Core auth
signIn(email: string, password: string): Promise<AuthResult>;
signUp(email: string, password: string, sourceAppUrl?: string): Promise<AuthResult>;
signOut(): Promise<void>;
forgotPassword(email: string, redirectTo?: string): Promise<AuthResult>;
resetPassword(token: string, newPassword: string): Promise<AuthResult>;
resendVerificationEmail(email: string, sourceAppUrl?: string): Promise<AuthResult>;
refreshTokens(currentRefreshToken: string): Promise<TokenRefreshResult>;
changePassword(currentPassword: string, newPassword: string): Promise<AuthResult>;
// Magic link
sendMagicLink(email: string): Promise<AuthResult>;
// Passkeys
isPasskeyAvailable(): boolean;
registerPasskey(friendlyName?: string): Promise<AuthResult>;
signInWithPasskey(): Promise<AuthResult>;
listPasskeys(): Promise<any[]>;
deletePasskey(passkeyId: string): Promise<AuthResult>;
renamePasskey(passkeyId: string, friendlyName: string): Promise<AuthResult>;
// Two-factor auth
enableTwoFactor(
password: string
): Promise<{ success: boolean; uri?: string; backupCodes?: string[]; error?: string }>;
disableTwoFactor(password: string): Promise<AuthResult>;
verifyTwoFactor(code: string, trustDevice?: boolean): Promise<AuthResult>;
verifyBackupCode(code: string): Promise<AuthResult>;
generateBackupCodes(
password: string
): Promise<{ success: boolean; backupCodes?: string[]; error?: string }>;
// Security
getSecurityEvents(limit?: number): Promise<any[]>;
listSessions(): Promise<any[]>;
revokeSession(sessionId: string): Promise<AuthResult>;
// Token management
getAppToken(): Promise<string | null>;
getRefreshToken(): Promise<string | null>;
updateTokens(appToken: string, refreshToken: string): Promise<void>;
getUserFromToken(): Promise<UserData | null>;
clearAuthStorage(): Promise<void>;
isAuthenticated(): Promise<boolean>;
// Credits & B2B
getUserCredits(): Promise<CreditBalance | null>;
isB2BUser(): Promise<boolean>;
getB2BInfo(): Promise<B2BInfo | null>;
shouldDisableRevenueCat(): Promise<boolean>;
getAppSettings(): Promise<Record<string, unknown> | null>;
// SSO
trySSO(): Promise<AuthResult>;
// Utilities
getBaseUrl(): string;
getStorageKeys(): StorageKeys;
onTokenRefresh: ((userData: UserData) => void) | null;
// Token utilities
isTokenValidLocally(token: string): boolean;
// Internal
handleAuthError(status: number, errorData: any): AuthResult;
}