@korajs/auth 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/server.d.cts CHANGED
@@ -296,15 +296,70 @@ interface AuthDevice {
296
296
  declare class DuplicateEmailError extends KoraError {
297
297
  constructor();
298
298
  }
299
+ /**
300
+ * Generic interface for user and device persistence.
301
+ *
302
+ * Implement this interface to provide database-backed user storage for
303
+ * the built-in auth provider. All methods are async to support both
304
+ * synchronous (in-memory, SQLite) and asynchronous (PostgreSQL) backends.
305
+ *
306
+ * Built-in implementations:
307
+ * - {@link InMemoryUserStore} — development and testing (no persistence)
308
+ * - `SqliteUserStore` — SQLite via better-sqlite3 (from `@korajs/auth/server`)
309
+ * - `PostgresUserStore` — PostgreSQL via postgres-js (from `@korajs/auth/server`)
310
+ *
311
+ * @example
312
+ * ```typescript
313
+ * import { BuiltInAuthRoutes, SqliteUserStore } from '@korajs/auth/server'
314
+ *
315
+ * const userStore = await createSqliteUserStore({ filename: './auth.db' })
316
+ * const routes = new BuiltInAuthRoutes({ userStore, tokenManager })
317
+ * ```
318
+ */
319
+ interface UserStore {
320
+ /** Create a new user account. Throws DuplicateEmailError if email exists. */
321
+ createUser(params: {
322
+ email: string;
323
+ passwordHash: string;
324
+ salt: string;
325
+ name: string;
326
+ }): Promise<AuthUser>;
327
+ /** Find a user by email address (case-insensitive). */
328
+ findByEmail(email: string): Promise<StoredUser | null>;
329
+ /** Find a user by ID. */
330
+ findById(id: string): Promise<StoredUser | null>;
331
+ /** Register a device for a user. Idempotent if device already exists and is not revoked. */
332
+ registerDevice(params: {
333
+ id: string;
334
+ userId: string;
335
+ publicKey: string;
336
+ name: string;
337
+ }): Promise<AuthDevice>;
338
+ /** Find a device by its ID. */
339
+ findDevice(deviceId: string): Promise<AuthDevice | null>;
340
+ /** List all devices registered for a user (includes revoked). */
341
+ listDevices(userId: string): Promise<AuthDevice[]>;
342
+ /** Soft-revoke a device. No-op if device does not exist. */
343
+ revokeDevice(deviceId: string): Promise<void>;
344
+ /** Set a user's email verification status. */
345
+ setEmailVerified(userId: string, verified: boolean): Promise<void>;
346
+ /** Update a user's password hash and salt. */
347
+ updatePassword(userId: string, passwordHash: string, salt: string): Promise<void>;
348
+ /** List all users. For admin/development use. */
349
+ listAll(): Promise<StoredUser[]>;
350
+ /** Update a stored user record. */
351
+ update(user: StoredUser): Promise<void>;
352
+ /** Delete a user and all associated devices. */
353
+ delete(userId: string): Promise<void>;
354
+ /** Update the last-seen timestamp for a device. No-op if device does not exist. */
355
+ touchDevice(deviceId: string): Promise<void>;
356
+ }
299
357
  /**
300
358
  * In-memory user and device store for the built-in auth provider.
301
359
  *
302
360
  * This is a simple implementation suitable for development and testing.
303
- * Production applications should replace this with a database-backed store
304
- * implementing the same interface.
305
- *
306
- * All methods are async to match the interface that a real database store
307
- * would expose, even though the in-memory operations are synchronous.
361
+ * Production applications should use {@link SqliteUserStore} or
362
+ * {@link PostgresUserStore} for persistent storage.
308
363
  *
309
364
  * @example
310
365
  * ```typescript
@@ -317,7 +372,7 @@ declare class DuplicateEmailError extends KoraError {
317
372
  * })
318
373
  * ```
319
374
  */
320
- declare class InMemoryUserStore {
375
+ declare class InMemoryUserStore implements UserStore {
321
376
  /** Users indexed by ID */
322
377
  private readonly usersById;
323
378
  /** Users indexed by email (lowercase) for fast lookup */
@@ -522,7 +577,7 @@ declare class InMemoryRateLimiter implements RateLimiter {
522
577
  */
523
578
  interface AuthRoutesConfig {
524
579
  /** The user/device store backing the auth routes */
525
- userStore: InMemoryUserStore;
580
+ userStore: UserStore;
526
581
  /** The token manager for issuing and validating JWTs */
527
582
  tokenManager: TokenManager;
528
583
  /**
@@ -973,7 +1028,7 @@ interface PasswordResetStore {
973
1028
  */
974
1029
  interface PasswordResetConfig {
975
1030
  /** User store for looking up users and updating passwords */
976
- userStore: InMemoryUserStore;
1031
+ userStore: UserStore;
977
1032
  /** Store for reset tokens. Defaults to InMemoryPasswordResetStore. */
978
1033
  resetStore?: PasswordResetStore;
979
1034
  /** Token TTL in milliseconds. Defaults to 1 hour. */
@@ -1116,7 +1171,7 @@ interface EmailVerificationStore {
1116
1171
  */
1117
1172
  interface EmailVerificationConfig {
1118
1173
  /** User store for looking up users */
1119
- userStore: InMemoryUserStore;
1174
+ userStore: UserStore;
1120
1175
  /** Store for verification tokens. Defaults to InMemoryEmailVerificationStore. */
1121
1176
  verificationStore?: EmailVerificationStore;
1122
1177
  /** Token TTL in milliseconds. Defaults to 24 hours. */
@@ -1220,6 +1275,148 @@ declare class EmailVerificationManager {
1220
1275
  }>;
1221
1276
  }
1222
1277
 
1278
+ /**
1279
+ * Minimal better-sqlite3 subset to avoid a hard dependency on the package.
1280
+ * The real Database instance satisfies this at runtime.
1281
+ */
1282
+ interface SqliteDatabase {
1283
+ pragma(source: string): unknown;
1284
+ exec(source: string): void;
1285
+ prepare(source: string): {
1286
+ run(...params: unknown[]): unknown;
1287
+ get(...params: unknown[]): unknown;
1288
+ all(...params: unknown[]): unknown[];
1289
+ };
1290
+ transaction<T>(fn: () => T): () => T;
1291
+ }
1292
+ /**
1293
+ * SQLite-backed user and device store using better-sqlite3.
1294
+ *
1295
+ * Provides persistent user storage suitable for single-server deployments,
1296
+ * Electron apps, and development environments. Uses WAL mode for concurrent
1297
+ * read/write performance.
1298
+ *
1299
+ * This implementation uses dynamic imports for better-sqlite3 so projects
1300
+ * that do not use SQLite server-side do not need to install it.
1301
+ *
1302
+ * @example
1303
+ * ```typescript
1304
+ * import { createSqliteUserStore } from '@korajs/auth/server'
1305
+ *
1306
+ * const userStore = await createSqliteUserStore({ filename: './auth.db' })
1307
+ * const routes = new BuiltInAuthRoutes({ userStore, tokenManager })
1308
+ * ```
1309
+ */
1310
+ declare class SqliteUserStore implements UserStore {
1311
+ private readonly db;
1312
+ constructor(db: SqliteDatabase);
1313
+ private ensureTables;
1314
+ createUser(params: {
1315
+ email: string;
1316
+ passwordHash: string;
1317
+ salt: string;
1318
+ name: string;
1319
+ }): Promise<AuthUser>;
1320
+ findByEmail(email: string): Promise<StoredUser | null>;
1321
+ findById(id: string): Promise<StoredUser | null>;
1322
+ registerDevice(params: {
1323
+ id: string;
1324
+ userId: string;
1325
+ publicKey: string;
1326
+ name: string;
1327
+ }): Promise<AuthDevice>;
1328
+ findDevice(deviceId: string): Promise<AuthDevice | null>;
1329
+ listDevices(userId: string): Promise<AuthDevice[]>;
1330
+ revokeDevice(deviceId: string): Promise<void>;
1331
+ setEmailVerified(userId: string, verified: boolean): Promise<void>;
1332
+ updatePassword(userId: string, passwordHash: string, salt: string): Promise<void>;
1333
+ listAll(): Promise<StoredUser[]>;
1334
+ update(user: StoredUser): Promise<void>;
1335
+ delete(userId: string): Promise<void>;
1336
+ touchDevice(deviceId: string): Promise<void>;
1337
+ }
1338
+ /**
1339
+ * Creates a SqliteUserStore from a file path.
1340
+ *
1341
+ * Uses runtime dynamic imports so projects that do not use SQLite server-side
1342
+ * do not need to install `better-sqlite3`.
1343
+ *
1344
+ * @param options.filename - Path to the SQLite database file, or `:memory:` for in-memory
1345
+ */
1346
+ declare function createSqliteUserStore(options: {
1347
+ filename: string;
1348
+ }): Promise<SqliteUserStore>;
1349
+
1350
+ /**
1351
+ * Minimal typed subset of a postgres-js SQL tag for our queries.
1352
+ * Avoids a hard dependency on the postgres package.
1353
+ * Uses Record<string, unknown>[] for result type to match postgres-js return shape.
1354
+ */
1355
+ interface PostgresClient {
1356
+ begin<T>(fn: (sql: PostgresClient) => Promise<T>): Promise<T>;
1357
+ (template: TemplateStringsArray, ...args: unknown[]): Promise<Record<string, unknown>[]>;
1358
+ }
1359
+ /**
1360
+ * PostgreSQL-backed user and device store using postgres-js.
1361
+ *
1362
+ * Provides persistent user storage suitable for production multi-server
1363
+ * deployments. Uses parameterized queries for SQL injection safety and
1364
+ * transactions for atomic operations.
1365
+ *
1366
+ * This implementation uses dynamic imports for postgres so projects
1367
+ * that do not use PostgreSQL do not need to install it.
1368
+ *
1369
+ * @example
1370
+ * ```typescript
1371
+ * import { createPostgresUserStore } from '@korajs/auth/server'
1372
+ *
1373
+ * const userStore = await createPostgresUserStore({
1374
+ * connectionString: 'postgres://user:pass@localhost:5432/mydb',
1375
+ * })
1376
+ * const routes = new BuiltInAuthRoutes({ userStore, tokenManager })
1377
+ * ```
1378
+ */
1379
+ declare class PostgresUserStore implements UserStore {
1380
+ private readonly sql;
1381
+ private readonly ready;
1382
+ constructor(sql: PostgresClient);
1383
+ private ensureTables;
1384
+ createUser(params: {
1385
+ email: string;
1386
+ passwordHash: string;
1387
+ salt: string;
1388
+ name: string;
1389
+ }): Promise<AuthUser>;
1390
+ findByEmail(email: string): Promise<StoredUser | null>;
1391
+ findById(id: string): Promise<StoredUser | null>;
1392
+ registerDevice(params: {
1393
+ id: string;
1394
+ userId: string;
1395
+ publicKey: string;
1396
+ name: string;
1397
+ }): Promise<AuthDevice>;
1398
+ findDevice(deviceId: string): Promise<AuthDevice | null>;
1399
+ listDevices(userId: string): Promise<AuthDevice[]>;
1400
+ revokeDevice(deviceId: string): Promise<void>;
1401
+ setEmailVerified(userId: string, verified: boolean): Promise<void>;
1402
+ updatePassword(userId: string, passwordHash: string, salt: string): Promise<void>;
1403
+ listAll(): Promise<StoredUser[]>;
1404
+ update(user: StoredUser): Promise<void>;
1405
+ delete(userId: string): Promise<void>;
1406
+ touchDevice(deviceId: string): Promise<void>;
1407
+ }
1408
+ /**
1409
+ * Creates a PostgresUserStore from a connection string.
1410
+ *
1411
+ * Uses runtime dynamic imports so projects that do not use PostgreSQL
1412
+ * do not need to install `postgres`.
1413
+ *
1414
+ * @param options.connectionString - PostgreSQL connection URL (e.g., `postgres://user:pass@host:5432/db`)
1415
+ */
1416
+ declare function createPostgresUserStore(options: {
1417
+ connectionString: string;
1418
+ }): Promise<PostgresUserStore>;
1419
+
1223
1420
  /**
1224
1421
  * Parameters for signing up a new user.
1225
1422
  */
@@ -3505,7 +3702,7 @@ declare class AuditLogger {
3505
3702
  */
3506
3703
  interface AdminApiConfig {
3507
3704
  /** User store for managing users */
3508
- userStore: InMemoryUserStore;
3705
+ userStore: UserStore;
3509
3706
  /** Session store for managing sessions (optional) */
3510
3707
  sessionStore?: SessionStore;
3511
3708
  /** Audit logger (optional) */
@@ -3787,4 +3984,4 @@ declare class WebhookManager {
3787
3984
  */
3788
3985
  declare function verifyWebhookSignature(payload: string, signature: string, secret: string): Promise<boolean>;
3789
3986
 
3790
- export { AdminApi, type AdminApiConfig, AdminApiError, AdminUnauthorizedError, AdminUserNotFoundError, type AdminUserUpdate, type AuditAction, type AuditEntry, AuditLogError, type AuditLogQuery, type AuditLogStore, AuditLogger, type AuthDevice, type AuthProviderAdapter, AuthProviderError, type AuthRouteResponse, type AuthRoutesConfig, type AuthUser, type AuthenticationOptions, type AuthenticationVerificationResult, BUILT_IN_ROLES, BuiltInAuthRoutes, BuiltInProvider, CannotRemoveOwnerError, type ChallengeStore, CircularInheritanceError, type ClerkAdapterConfig, type CollectionScopeResolver, type CreateInvitationParams, type CreateOrgParams, type CreateSessionParams, DuplicateEmailError, type EmailVerificationConfig, EmailVerificationError, EmailVerificationManager, type EmailVerificationStore, type EmailVerificationToken, ExternalAuthOperationNotSupportedError, ExternalJwtProvider, type ExternalJwtProviderConfig, ExternalTokenValidationError, type ExternalUserInfo, INVITATION_STATUSES, InMemoryAuditLogStore, InMemoryChallengeStore, InMemoryEmailVerificationStore, InMemoryOAuthStateStore, InMemoryOrgStore, InMemoryPasswordResetStore, InMemoryRateLimiter, InMemorySessionStore, InMemoryTokenRevocationStore, InMemoryTotpStore, InMemoryUserStore, InMemoryWebhookStore, InsufficientRoleError, InvalidPermissionError, InvitationExpiredError, InvitationNotFoundError, type InvitationStatus, type LinkedIdentity, MemberAlreadyExistsError, type Membership, MembershipNotFoundError, OAuthCodeExchangeError, OAuthError, OAuthManager, type OAuthManagerConfig, type OAuthProviderConfig, OAuthProviderNotFoundError, type OAuthState, OAuthStateMismatchError, type OAuthStateStore, type OAuthTokens, type OAuthUserInfo, OAuthUserInfoError, ORG_ROLES, OrgError, type OrgInvitation, OrgNotFoundError, type OrgRole, type OrgRouteResponse, OrgRoutes, type OrgRoutesConfig, OrgScopeResolver, OrgSlugTakenError, type OrgStore, type Organization, type PaginatedResult, PasskeyVerificationError, type PasswordResetConfig, PasswordResetError, PasswordResetManager, type PasswordResetStore, type PasswordResetToken, type Permission, ROLE_HIERARCHY, type RateLimiter, type RbacConfig, RbacEngine, RbacError, type RegistrationOptions, type RegistrationVerificationResult, ResetRateLimitedError, ResetTokenExpiredError, ResetTokenNotFoundError, type RoleDefinition, RoleNotFoundError, type ScopeContext, type ScopeFilter, type Session, SessionError, SessionExpiredError, SessionLimitExceededError, SessionManager, type SessionManagerConfig, SessionMfaRequiredError, SessionNotFoundError, type SessionStore, type SignInParams, type SignUpParams, type StoredUser, type SupabaseAdapterConfig, type SyncScopes, TokenManager, type TokenManagerConfig, type TokenRevocationStore, TotpAlreadyEnabledError, type TotpConfig, TotpError, TotpInvalidCodeError, TotpManager, TotpNotEnabledError, TotpNotVerifiedError, TotpRecoveryExhaustedError, type TotpSecret, type TotpSetupResult, type TotpStore, type UpdateOrgParams, type UserListQuery, VerificationTokenExpiredError, VerificationTokenNotFoundError, type WebhookDelivery, type WebhookEndpoint, WebhookEndpointNotFoundError, WebhookError, type WebhookEvent, WebhookManager, type WebhookPayload, type WebhookStore, base32Decode, base32Encode, createClerkAdapter, createSupabaseAdapter, decodeJwt, defineRoles, encodeJwt, generateAuthenticationOptions, generateRegistrationOptions, githubProvider, googleProvider, hasRoleLevel, hashPassword, isExpired, microsoftProvider, parsePermission, permissionCovers, verifyAuthenticationResponse, verifyJwt, verifyPassword, verifyRegistrationResponse, verifyWebhookSignature };
3987
+ export { AdminApi, type AdminApiConfig, AdminApiError, AdminUnauthorizedError, AdminUserNotFoundError, type AdminUserUpdate, type AuditAction, type AuditEntry, AuditLogError, type AuditLogQuery, type AuditLogStore, AuditLogger, type AuthDevice, type AuthProviderAdapter, AuthProviderError, type AuthRouteResponse, type AuthRoutesConfig, type AuthUser, type AuthenticationOptions, type AuthenticationVerificationResult, BUILT_IN_ROLES, BuiltInAuthRoutes, BuiltInProvider, CannotRemoveOwnerError, type ChallengeStore, CircularInheritanceError, type ClerkAdapterConfig, type CollectionScopeResolver, type CreateInvitationParams, type CreateOrgParams, type CreateSessionParams, DuplicateEmailError, type EmailVerificationConfig, EmailVerificationError, EmailVerificationManager, type EmailVerificationStore, type EmailVerificationToken, ExternalAuthOperationNotSupportedError, ExternalJwtProvider, type ExternalJwtProviderConfig, ExternalTokenValidationError, type ExternalUserInfo, INVITATION_STATUSES, InMemoryAuditLogStore, InMemoryChallengeStore, InMemoryEmailVerificationStore, InMemoryOAuthStateStore, InMemoryOrgStore, InMemoryPasswordResetStore, InMemoryRateLimiter, InMemorySessionStore, InMemoryTokenRevocationStore, InMemoryTotpStore, InMemoryUserStore, InMemoryWebhookStore, InsufficientRoleError, InvalidPermissionError, InvitationExpiredError, InvitationNotFoundError, type InvitationStatus, type LinkedIdentity, MemberAlreadyExistsError, type Membership, MembershipNotFoundError, OAuthCodeExchangeError, OAuthError, OAuthManager, type OAuthManagerConfig, type OAuthProviderConfig, OAuthProviderNotFoundError, type OAuthState, OAuthStateMismatchError, type OAuthStateStore, type OAuthTokens, type OAuthUserInfo, OAuthUserInfoError, ORG_ROLES, OrgError, type OrgInvitation, OrgNotFoundError, type OrgRole, type OrgRouteResponse, OrgRoutes, type OrgRoutesConfig, OrgScopeResolver, OrgSlugTakenError, type OrgStore, type Organization, type PaginatedResult, PasskeyVerificationError, type PasswordResetConfig, PasswordResetError, PasswordResetManager, type PasswordResetStore, type PasswordResetToken, type Permission, PostgresUserStore, ROLE_HIERARCHY, type RateLimiter, type RbacConfig, RbacEngine, RbacError, type RegistrationOptions, type RegistrationVerificationResult, ResetRateLimitedError, ResetTokenExpiredError, ResetTokenNotFoundError, type RoleDefinition, RoleNotFoundError, type ScopeContext, type ScopeFilter, type Session, SessionError, SessionExpiredError, SessionLimitExceededError, SessionManager, type SessionManagerConfig, SessionMfaRequiredError, SessionNotFoundError, type SessionStore, type SignInParams, type SignUpParams, SqliteUserStore, type StoredUser, type SupabaseAdapterConfig, type SyncScopes, TokenManager, type TokenManagerConfig, type TokenRevocationStore, TotpAlreadyEnabledError, type TotpConfig, TotpError, TotpInvalidCodeError, TotpManager, TotpNotEnabledError, TotpNotVerifiedError, TotpRecoveryExhaustedError, type TotpSecret, type TotpSetupResult, type TotpStore, type UpdateOrgParams, type UserListQuery, type UserStore, VerificationTokenExpiredError, VerificationTokenNotFoundError, type WebhookDelivery, type WebhookEndpoint, WebhookEndpointNotFoundError, WebhookError, type WebhookEvent, WebhookManager, type WebhookPayload, type WebhookStore, base32Decode, base32Encode, createClerkAdapter, createPostgresUserStore, createSqliteUserStore, createSupabaseAdapter, decodeJwt, defineRoles, encodeJwt, generateAuthenticationOptions, generateRegistrationOptions, githubProvider, googleProvider, hasRoleLevel, hashPassword, isExpired, microsoftProvider, parsePermission, permissionCovers, verifyAuthenticationResponse, verifyJwt, verifyPassword, verifyRegistrationResponse, verifyWebhookSignature };
package/dist/server.d.ts CHANGED
@@ -296,15 +296,70 @@ interface AuthDevice {
296
296
  declare class DuplicateEmailError extends KoraError {
297
297
  constructor();
298
298
  }
299
+ /**
300
+ * Generic interface for user and device persistence.
301
+ *
302
+ * Implement this interface to provide database-backed user storage for
303
+ * the built-in auth provider. All methods are async to support both
304
+ * synchronous (in-memory, SQLite) and asynchronous (PostgreSQL) backends.
305
+ *
306
+ * Built-in implementations:
307
+ * - {@link InMemoryUserStore} — development and testing (no persistence)
308
+ * - `SqliteUserStore` — SQLite via better-sqlite3 (from `@korajs/auth/server`)
309
+ * - `PostgresUserStore` — PostgreSQL via postgres-js (from `@korajs/auth/server`)
310
+ *
311
+ * @example
312
+ * ```typescript
313
+ * import { BuiltInAuthRoutes, SqliteUserStore } from '@korajs/auth/server'
314
+ *
315
+ * const userStore = await createSqliteUserStore({ filename: './auth.db' })
316
+ * const routes = new BuiltInAuthRoutes({ userStore, tokenManager })
317
+ * ```
318
+ */
319
+ interface UserStore {
320
+ /** Create a new user account. Throws DuplicateEmailError if email exists. */
321
+ createUser(params: {
322
+ email: string;
323
+ passwordHash: string;
324
+ salt: string;
325
+ name: string;
326
+ }): Promise<AuthUser>;
327
+ /** Find a user by email address (case-insensitive). */
328
+ findByEmail(email: string): Promise<StoredUser | null>;
329
+ /** Find a user by ID. */
330
+ findById(id: string): Promise<StoredUser | null>;
331
+ /** Register a device for a user. Idempotent if device already exists and is not revoked. */
332
+ registerDevice(params: {
333
+ id: string;
334
+ userId: string;
335
+ publicKey: string;
336
+ name: string;
337
+ }): Promise<AuthDevice>;
338
+ /** Find a device by its ID. */
339
+ findDevice(deviceId: string): Promise<AuthDevice | null>;
340
+ /** List all devices registered for a user (includes revoked). */
341
+ listDevices(userId: string): Promise<AuthDevice[]>;
342
+ /** Soft-revoke a device. No-op if device does not exist. */
343
+ revokeDevice(deviceId: string): Promise<void>;
344
+ /** Set a user's email verification status. */
345
+ setEmailVerified(userId: string, verified: boolean): Promise<void>;
346
+ /** Update a user's password hash and salt. */
347
+ updatePassword(userId: string, passwordHash: string, salt: string): Promise<void>;
348
+ /** List all users. For admin/development use. */
349
+ listAll(): Promise<StoredUser[]>;
350
+ /** Update a stored user record. */
351
+ update(user: StoredUser): Promise<void>;
352
+ /** Delete a user and all associated devices. */
353
+ delete(userId: string): Promise<void>;
354
+ /** Update the last-seen timestamp for a device. No-op if device does not exist. */
355
+ touchDevice(deviceId: string): Promise<void>;
356
+ }
299
357
  /**
300
358
  * In-memory user and device store for the built-in auth provider.
301
359
  *
302
360
  * This is a simple implementation suitable for development and testing.
303
- * Production applications should replace this with a database-backed store
304
- * implementing the same interface.
305
- *
306
- * All methods are async to match the interface that a real database store
307
- * would expose, even though the in-memory operations are synchronous.
361
+ * Production applications should use {@link SqliteUserStore} or
362
+ * {@link PostgresUserStore} for persistent storage.
308
363
  *
309
364
  * @example
310
365
  * ```typescript
@@ -317,7 +372,7 @@ declare class DuplicateEmailError extends KoraError {
317
372
  * })
318
373
  * ```
319
374
  */
320
- declare class InMemoryUserStore {
375
+ declare class InMemoryUserStore implements UserStore {
321
376
  /** Users indexed by ID */
322
377
  private readonly usersById;
323
378
  /** Users indexed by email (lowercase) for fast lookup */
@@ -522,7 +577,7 @@ declare class InMemoryRateLimiter implements RateLimiter {
522
577
  */
523
578
  interface AuthRoutesConfig {
524
579
  /** The user/device store backing the auth routes */
525
- userStore: InMemoryUserStore;
580
+ userStore: UserStore;
526
581
  /** The token manager for issuing and validating JWTs */
527
582
  tokenManager: TokenManager;
528
583
  /**
@@ -973,7 +1028,7 @@ interface PasswordResetStore {
973
1028
  */
974
1029
  interface PasswordResetConfig {
975
1030
  /** User store for looking up users and updating passwords */
976
- userStore: InMemoryUserStore;
1031
+ userStore: UserStore;
977
1032
  /** Store for reset tokens. Defaults to InMemoryPasswordResetStore. */
978
1033
  resetStore?: PasswordResetStore;
979
1034
  /** Token TTL in milliseconds. Defaults to 1 hour. */
@@ -1116,7 +1171,7 @@ interface EmailVerificationStore {
1116
1171
  */
1117
1172
  interface EmailVerificationConfig {
1118
1173
  /** User store for looking up users */
1119
- userStore: InMemoryUserStore;
1174
+ userStore: UserStore;
1120
1175
  /** Store for verification tokens. Defaults to InMemoryEmailVerificationStore. */
1121
1176
  verificationStore?: EmailVerificationStore;
1122
1177
  /** Token TTL in milliseconds. Defaults to 24 hours. */
@@ -1220,6 +1275,148 @@ declare class EmailVerificationManager {
1220
1275
  }>;
1221
1276
  }
1222
1277
 
1278
+ /**
1279
+ * Minimal better-sqlite3 subset to avoid a hard dependency on the package.
1280
+ * The real Database instance satisfies this at runtime.
1281
+ */
1282
+ interface SqliteDatabase {
1283
+ pragma(source: string): unknown;
1284
+ exec(source: string): void;
1285
+ prepare(source: string): {
1286
+ run(...params: unknown[]): unknown;
1287
+ get(...params: unknown[]): unknown;
1288
+ all(...params: unknown[]): unknown[];
1289
+ };
1290
+ transaction<T>(fn: () => T): () => T;
1291
+ }
1292
+ /**
1293
+ * SQLite-backed user and device store using better-sqlite3.
1294
+ *
1295
+ * Provides persistent user storage suitable for single-server deployments,
1296
+ * Electron apps, and development environments. Uses WAL mode for concurrent
1297
+ * read/write performance.
1298
+ *
1299
+ * This implementation uses dynamic imports for better-sqlite3 so projects
1300
+ * that do not use SQLite server-side do not need to install it.
1301
+ *
1302
+ * @example
1303
+ * ```typescript
1304
+ * import { createSqliteUserStore } from '@korajs/auth/server'
1305
+ *
1306
+ * const userStore = await createSqliteUserStore({ filename: './auth.db' })
1307
+ * const routes = new BuiltInAuthRoutes({ userStore, tokenManager })
1308
+ * ```
1309
+ */
1310
+ declare class SqliteUserStore implements UserStore {
1311
+ private readonly db;
1312
+ constructor(db: SqliteDatabase);
1313
+ private ensureTables;
1314
+ createUser(params: {
1315
+ email: string;
1316
+ passwordHash: string;
1317
+ salt: string;
1318
+ name: string;
1319
+ }): Promise<AuthUser>;
1320
+ findByEmail(email: string): Promise<StoredUser | null>;
1321
+ findById(id: string): Promise<StoredUser | null>;
1322
+ registerDevice(params: {
1323
+ id: string;
1324
+ userId: string;
1325
+ publicKey: string;
1326
+ name: string;
1327
+ }): Promise<AuthDevice>;
1328
+ findDevice(deviceId: string): Promise<AuthDevice | null>;
1329
+ listDevices(userId: string): Promise<AuthDevice[]>;
1330
+ revokeDevice(deviceId: string): Promise<void>;
1331
+ setEmailVerified(userId: string, verified: boolean): Promise<void>;
1332
+ updatePassword(userId: string, passwordHash: string, salt: string): Promise<void>;
1333
+ listAll(): Promise<StoredUser[]>;
1334
+ update(user: StoredUser): Promise<void>;
1335
+ delete(userId: string): Promise<void>;
1336
+ touchDevice(deviceId: string): Promise<void>;
1337
+ }
1338
+ /**
1339
+ * Creates a SqliteUserStore from a file path.
1340
+ *
1341
+ * Uses runtime dynamic imports so projects that do not use SQLite server-side
1342
+ * do not need to install `better-sqlite3`.
1343
+ *
1344
+ * @param options.filename - Path to the SQLite database file, or `:memory:` for in-memory
1345
+ */
1346
+ declare function createSqliteUserStore(options: {
1347
+ filename: string;
1348
+ }): Promise<SqliteUserStore>;
1349
+
1350
+ /**
1351
+ * Minimal typed subset of a postgres-js SQL tag for our queries.
1352
+ * Avoids a hard dependency on the postgres package.
1353
+ * Uses Record<string, unknown>[] for result type to match postgres-js return shape.
1354
+ */
1355
+ interface PostgresClient {
1356
+ begin<T>(fn: (sql: PostgresClient) => Promise<T>): Promise<T>;
1357
+ (template: TemplateStringsArray, ...args: unknown[]): Promise<Record<string, unknown>[]>;
1358
+ }
1359
+ /**
1360
+ * PostgreSQL-backed user and device store using postgres-js.
1361
+ *
1362
+ * Provides persistent user storage suitable for production multi-server
1363
+ * deployments. Uses parameterized queries for SQL injection safety and
1364
+ * transactions for atomic operations.
1365
+ *
1366
+ * This implementation uses dynamic imports for postgres so projects
1367
+ * that do not use PostgreSQL do not need to install it.
1368
+ *
1369
+ * @example
1370
+ * ```typescript
1371
+ * import { createPostgresUserStore } from '@korajs/auth/server'
1372
+ *
1373
+ * const userStore = await createPostgresUserStore({
1374
+ * connectionString: 'postgres://user:pass@localhost:5432/mydb',
1375
+ * })
1376
+ * const routes = new BuiltInAuthRoutes({ userStore, tokenManager })
1377
+ * ```
1378
+ */
1379
+ declare class PostgresUserStore implements UserStore {
1380
+ private readonly sql;
1381
+ private readonly ready;
1382
+ constructor(sql: PostgresClient);
1383
+ private ensureTables;
1384
+ createUser(params: {
1385
+ email: string;
1386
+ passwordHash: string;
1387
+ salt: string;
1388
+ name: string;
1389
+ }): Promise<AuthUser>;
1390
+ findByEmail(email: string): Promise<StoredUser | null>;
1391
+ findById(id: string): Promise<StoredUser | null>;
1392
+ registerDevice(params: {
1393
+ id: string;
1394
+ userId: string;
1395
+ publicKey: string;
1396
+ name: string;
1397
+ }): Promise<AuthDevice>;
1398
+ findDevice(deviceId: string): Promise<AuthDevice | null>;
1399
+ listDevices(userId: string): Promise<AuthDevice[]>;
1400
+ revokeDevice(deviceId: string): Promise<void>;
1401
+ setEmailVerified(userId: string, verified: boolean): Promise<void>;
1402
+ updatePassword(userId: string, passwordHash: string, salt: string): Promise<void>;
1403
+ listAll(): Promise<StoredUser[]>;
1404
+ update(user: StoredUser): Promise<void>;
1405
+ delete(userId: string): Promise<void>;
1406
+ touchDevice(deviceId: string): Promise<void>;
1407
+ }
1408
+ /**
1409
+ * Creates a PostgresUserStore from a connection string.
1410
+ *
1411
+ * Uses runtime dynamic imports so projects that do not use PostgreSQL
1412
+ * do not need to install `postgres`.
1413
+ *
1414
+ * @param options.connectionString - PostgreSQL connection URL (e.g., `postgres://user:pass@host:5432/db`)
1415
+ */
1416
+ declare function createPostgresUserStore(options: {
1417
+ connectionString: string;
1418
+ }): Promise<PostgresUserStore>;
1419
+
1223
1420
  /**
1224
1421
  * Parameters for signing up a new user.
1225
1422
  */
@@ -3505,7 +3702,7 @@ declare class AuditLogger {
3505
3702
  */
3506
3703
  interface AdminApiConfig {
3507
3704
  /** User store for managing users */
3508
- userStore: InMemoryUserStore;
3705
+ userStore: UserStore;
3509
3706
  /** Session store for managing sessions (optional) */
3510
3707
  sessionStore?: SessionStore;
3511
3708
  /** Audit logger (optional) */
@@ -3787,4 +3984,4 @@ declare class WebhookManager {
3787
3984
  */
3788
3985
  declare function verifyWebhookSignature(payload: string, signature: string, secret: string): Promise<boolean>;
3789
3986
 
3790
- export { AdminApi, type AdminApiConfig, AdminApiError, AdminUnauthorizedError, AdminUserNotFoundError, type AdminUserUpdate, type AuditAction, type AuditEntry, AuditLogError, type AuditLogQuery, type AuditLogStore, AuditLogger, type AuthDevice, type AuthProviderAdapter, AuthProviderError, type AuthRouteResponse, type AuthRoutesConfig, type AuthUser, type AuthenticationOptions, type AuthenticationVerificationResult, BUILT_IN_ROLES, BuiltInAuthRoutes, BuiltInProvider, CannotRemoveOwnerError, type ChallengeStore, CircularInheritanceError, type ClerkAdapterConfig, type CollectionScopeResolver, type CreateInvitationParams, type CreateOrgParams, type CreateSessionParams, DuplicateEmailError, type EmailVerificationConfig, EmailVerificationError, EmailVerificationManager, type EmailVerificationStore, type EmailVerificationToken, ExternalAuthOperationNotSupportedError, ExternalJwtProvider, type ExternalJwtProviderConfig, ExternalTokenValidationError, type ExternalUserInfo, INVITATION_STATUSES, InMemoryAuditLogStore, InMemoryChallengeStore, InMemoryEmailVerificationStore, InMemoryOAuthStateStore, InMemoryOrgStore, InMemoryPasswordResetStore, InMemoryRateLimiter, InMemorySessionStore, InMemoryTokenRevocationStore, InMemoryTotpStore, InMemoryUserStore, InMemoryWebhookStore, InsufficientRoleError, InvalidPermissionError, InvitationExpiredError, InvitationNotFoundError, type InvitationStatus, type LinkedIdentity, MemberAlreadyExistsError, type Membership, MembershipNotFoundError, OAuthCodeExchangeError, OAuthError, OAuthManager, type OAuthManagerConfig, type OAuthProviderConfig, OAuthProviderNotFoundError, type OAuthState, OAuthStateMismatchError, type OAuthStateStore, type OAuthTokens, type OAuthUserInfo, OAuthUserInfoError, ORG_ROLES, OrgError, type OrgInvitation, OrgNotFoundError, type OrgRole, type OrgRouteResponse, OrgRoutes, type OrgRoutesConfig, OrgScopeResolver, OrgSlugTakenError, type OrgStore, type Organization, type PaginatedResult, PasskeyVerificationError, type PasswordResetConfig, PasswordResetError, PasswordResetManager, type PasswordResetStore, type PasswordResetToken, type Permission, ROLE_HIERARCHY, type RateLimiter, type RbacConfig, RbacEngine, RbacError, type RegistrationOptions, type RegistrationVerificationResult, ResetRateLimitedError, ResetTokenExpiredError, ResetTokenNotFoundError, type RoleDefinition, RoleNotFoundError, type ScopeContext, type ScopeFilter, type Session, SessionError, SessionExpiredError, SessionLimitExceededError, SessionManager, type SessionManagerConfig, SessionMfaRequiredError, SessionNotFoundError, type SessionStore, type SignInParams, type SignUpParams, type StoredUser, type SupabaseAdapterConfig, type SyncScopes, TokenManager, type TokenManagerConfig, type TokenRevocationStore, TotpAlreadyEnabledError, type TotpConfig, TotpError, TotpInvalidCodeError, TotpManager, TotpNotEnabledError, TotpNotVerifiedError, TotpRecoveryExhaustedError, type TotpSecret, type TotpSetupResult, type TotpStore, type UpdateOrgParams, type UserListQuery, VerificationTokenExpiredError, VerificationTokenNotFoundError, type WebhookDelivery, type WebhookEndpoint, WebhookEndpointNotFoundError, WebhookError, type WebhookEvent, WebhookManager, type WebhookPayload, type WebhookStore, base32Decode, base32Encode, createClerkAdapter, createSupabaseAdapter, decodeJwt, defineRoles, encodeJwt, generateAuthenticationOptions, generateRegistrationOptions, githubProvider, googleProvider, hasRoleLevel, hashPassword, isExpired, microsoftProvider, parsePermission, permissionCovers, verifyAuthenticationResponse, verifyJwt, verifyPassword, verifyRegistrationResponse, verifyWebhookSignature };
3987
+ export { AdminApi, type AdminApiConfig, AdminApiError, AdminUnauthorizedError, AdminUserNotFoundError, type AdminUserUpdate, type AuditAction, type AuditEntry, AuditLogError, type AuditLogQuery, type AuditLogStore, AuditLogger, type AuthDevice, type AuthProviderAdapter, AuthProviderError, type AuthRouteResponse, type AuthRoutesConfig, type AuthUser, type AuthenticationOptions, type AuthenticationVerificationResult, BUILT_IN_ROLES, BuiltInAuthRoutes, BuiltInProvider, CannotRemoveOwnerError, type ChallengeStore, CircularInheritanceError, type ClerkAdapterConfig, type CollectionScopeResolver, type CreateInvitationParams, type CreateOrgParams, type CreateSessionParams, DuplicateEmailError, type EmailVerificationConfig, EmailVerificationError, EmailVerificationManager, type EmailVerificationStore, type EmailVerificationToken, ExternalAuthOperationNotSupportedError, ExternalJwtProvider, type ExternalJwtProviderConfig, ExternalTokenValidationError, type ExternalUserInfo, INVITATION_STATUSES, InMemoryAuditLogStore, InMemoryChallengeStore, InMemoryEmailVerificationStore, InMemoryOAuthStateStore, InMemoryOrgStore, InMemoryPasswordResetStore, InMemoryRateLimiter, InMemorySessionStore, InMemoryTokenRevocationStore, InMemoryTotpStore, InMemoryUserStore, InMemoryWebhookStore, InsufficientRoleError, InvalidPermissionError, InvitationExpiredError, InvitationNotFoundError, type InvitationStatus, type LinkedIdentity, MemberAlreadyExistsError, type Membership, MembershipNotFoundError, OAuthCodeExchangeError, OAuthError, OAuthManager, type OAuthManagerConfig, type OAuthProviderConfig, OAuthProviderNotFoundError, type OAuthState, OAuthStateMismatchError, type OAuthStateStore, type OAuthTokens, type OAuthUserInfo, OAuthUserInfoError, ORG_ROLES, OrgError, type OrgInvitation, OrgNotFoundError, type OrgRole, type OrgRouteResponse, OrgRoutes, type OrgRoutesConfig, OrgScopeResolver, OrgSlugTakenError, type OrgStore, type Organization, type PaginatedResult, PasskeyVerificationError, type PasswordResetConfig, PasswordResetError, PasswordResetManager, type PasswordResetStore, type PasswordResetToken, type Permission, PostgresUserStore, ROLE_HIERARCHY, type RateLimiter, type RbacConfig, RbacEngine, RbacError, type RegistrationOptions, type RegistrationVerificationResult, ResetRateLimitedError, ResetTokenExpiredError, ResetTokenNotFoundError, type RoleDefinition, RoleNotFoundError, type ScopeContext, type ScopeFilter, type Session, SessionError, SessionExpiredError, SessionLimitExceededError, SessionManager, type SessionManagerConfig, SessionMfaRequiredError, SessionNotFoundError, type SessionStore, type SignInParams, type SignUpParams, SqliteUserStore, type StoredUser, type SupabaseAdapterConfig, type SyncScopes, TokenManager, type TokenManagerConfig, type TokenRevocationStore, TotpAlreadyEnabledError, type TotpConfig, TotpError, TotpInvalidCodeError, TotpManager, TotpNotEnabledError, TotpNotVerifiedError, TotpRecoveryExhaustedError, type TotpSecret, type TotpSetupResult, type TotpStore, type UpdateOrgParams, type UserListQuery, type UserStore, VerificationTokenExpiredError, VerificationTokenNotFoundError, type WebhookDelivery, type WebhookEndpoint, WebhookEndpointNotFoundError, WebhookError, type WebhookEvent, WebhookManager, type WebhookPayload, type WebhookStore, base32Decode, base32Encode, createClerkAdapter, createPostgresUserStore, createSqliteUserStore, createSupabaseAdapter, decodeJwt, defineRoles, encodeJwt, generateAuthenticationOptions, generateRegistrationOptions, githubProvider, googleProvider, hasRoleLevel, hashPassword, isExpired, microsoftProvider, parsePermission, permissionCovers, verifyAuthenticationResponse, verifyJwt, verifyPassword, verifyRegistrationResponse, verifyWebhookSignature };