@factiii/auth 0.5.3 → 0.5.4

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/index.d.mts CHANGED
@@ -1,13 +1,11 @@
1
1
  import * as http from 'http';
2
2
  import * as SuperJSON from 'superjson';
3
3
  import SuperJSON__default from 'superjson';
4
- import * as _prisma_client from '@prisma/client';
5
- import { PrismaClient } from '@prisma/client';
6
4
  import * as _trpc_server from '@trpc/server';
7
5
  import * as zod from 'zod';
8
6
  import { CreateHTTPContextOptions } from '@trpc/server/adapters/standalone';
9
- import { S as SchemaExtensions, A as AuthHooks } from './hooks-BXNxNK4S.mjs';
10
- export { C as ChangePasswordInput, L as LoginInput, O as OAuthLoginInput, R as ResetPasswordInput, a as SignupInput, T as TwoFaVerifyInput, V as VerifyEmailInput, b as biometricVerifySchema, c as changePasswordSchema, e as endAllSessionsSchema, l as loginSchema, o as oAuthLoginSchema, r as requestPasswordResetSchema, d as resetPasswordSchema, s as signupSchema, t as twoFaResetSchema, f as twoFaVerifySchema, v as verifyEmailSchema } from './hooks-BXNxNK4S.mjs';
7
+ import { S as SchemaExtensions, A as AuthHooks } from './hooks-yHGJ7C6_.mjs';
8
+ export { C as ChangePasswordInput, L as LoginInput, O as OAuthLoginInput, R as ResetPasswordInput, a as SignupInput, T as TwoFaVerifyInput, V as VerifyEmailInput, b as biometricVerifySchema, c as changePasswordSchema, e as endAllSessionsSchema, l as loginSchema, o as oAuthLoginSchema, r as requestPasswordResetSchema, d as resetPasswordSchema, s as signupSchema, t as twoFaResetSchema, f as twoFaVerifySchema, v as verifyEmailSchema } from './hooks-yHGJ7C6_.mjs';
11
9
 
12
10
  //# sourceMappingURL=TRPCError.d.ts.map
13
11
  //#endregion
@@ -149,6 +147,208 @@ declare function createNoopEmailAdapter(): EmailAdapter;
149
147
  */
150
148
  declare function createConsoleEmailAdapter(): EmailAdapter;
151
149
 
150
+ /**
151
+ * ORM-agnostic database adapter interface for @factiii/auth.
152
+ * Implement this interface to use any database/ORM with the auth library.
153
+ */
154
+ interface AuthUser {
155
+ id: number;
156
+ status: string;
157
+ email: string;
158
+ username: string;
159
+ password: string | null;
160
+ twoFaEnabled: boolean;
161
+ oauthProvider: string | null;
162
+ oauthId: string | null;
163
+ tag: string;
164
+ verifiedHumanAt: Date | null;
165
+ emailVerificationStatus: string;
166
+ otpForEmailVerification: string | null;
167
+ isActive: boolean;
168
+ }
169
+ interface AuthSession {
170
+ id: number;
171
+ userId: number;
172
+ socketId: string | null;
173
+ twoFaSecret: string | null;
174
+ browserName: string;
175
+ issuedAt: Date;
176
+ lastUsed: Date;
177
+ revokedAt: Date | null;
178
+ deviceId: number | null;
179
+ }
180
+ interface AuthOTP {
181
+ id: number;
182
+ code: number;
183
+ expiresAt: Date;
184
+ userId: number;
185
+ }
186
+ interface AuthPasswordReset {
187
+ id: string;
188
+ createdAt: Date;
189
+ userId: number;
190
+ }
191
+ interface CreateUserData {
192
+ username: string;
193
+ email: string;
194
+ password: string | null;
195
+ status: string;
196
+ tag: string;
197
+ twoFaEnabled: boolean;
198
+ emailVerificationStatus: string;
199
+ verifiedHumanAt: Date | null;
200
+ oauthProvider?: string;
201
+ oauthId?: string;
202
+ }
203
+ interface CreateSessionData {
204
+ userId: number;
205
+ browserName: string;
206
+ socketId: string | null;
207
+ [key: string]: unknown;
208
+ }
209
+ type SessionWithUser = AuthSession & {
210
+ user: {
211
+ status: string;
212
+ verifiedHumanAt: Date | null;
213
+ };
214
+ };
215
+ type SessionWithDevice = {
216
+ twoFaSecret: string | null;
217
+ deviceId: number | null;
218
+ device: {
219
+ pushToken: string;
220
+ } | null;
221
+ };
222
+ interface DatabaseAdapter {
223
+ user: {
224
+ findByEmailInsensitive(email: string): Promise<AuthUser | null>;
225
+ findByUsernameInsensitive(username: string): Promise<AuthUser | null>;
226
+ findByEmailOrUsernameInsensitive(identifier: string): Promise<AuthUser | null>;
227
+ findByEmailOrOAuthId(email: string, oauthId: string): Promise<AuthUser | null>;
228
+ findById(id: number): Promise<AuthUser | null>;
229
+ findActiveById(id: number): Promise<AuthUser | null>;
230
+ create(data: CreateUserData): Promise<AuthUser>;
231
+ update(id: number, data: Partial<Omit<AuthUser, 'id'>>): Promise<AuthUser>;
232
+ };
233
+ session: {
234
+ /** Find session by ID with user status and verifiedHumanAt joined. */
235
+ findById(id: number): Promise<SessionWithUser | null>;
236
+ create(data: CreateSessionData): Promise<AuthSession>;
237
+ update(id: number, data: Partial<Pick<AuthSession, 'revokedAt' | 'lastUsed' | 'twoFaSecret' | 'deviceId'>>): Promise<AuthSession>;
238
+ /** Update lastUsed and return session with user's verifiedHumanAt. */
239
+ updateLastUsed(id: number): Promise<AuthSession & {
240
+ user: {
241
+ verifiedHumanAt: Date | null;
242
+ };
243
+ }>;
244
+ /** Set revokedAt on a single session. */
245
+ revoke(id: number): Promise<void>;
246
+ /** Find active (non-revoked) sessions for a user, optionally excluding one. */
247
+ findActiveByUserId(userId: number, excludeSessionId?: number): Promise<Pick<AuthSession, 'id' | 'socketId' | 'userId'>[]>;
248
+ /** Revoke all active sessions for a user, optionally excluding one. */
249
+ revokeAllByUserId(userId: number, excludeSessionId?: number): Promise<void>;
250
+ /** Get twoFaSecret from all sessions that have one for a user. */
251
+ findTwoFaSecretsByUserId(userId: number): Promise<{
252
+ twoFaSecret: string | null;
253
+ }[]>;
254
+ /** Clear twoFaSecret on sessions for a user, optionally excluding one. */
255
+ clearTwoFaSecrets(userId: number, excludeSessionId?: number): Promise<void>;
256
+ /** Find session with device relation for TOTP verification. */
257
+ findByIdWithDevice(id: number, userId: number): Promise<SessionWithDevice | null>;
258
+ /** Revoke other sessions that share a device push token. */
259
+ revokeByDevicePushToken(userId: number, pushToken: string, excludeSessionId: number): Promise<void>;
260
+ /** Clear deviceId on all sessions for a user+device pair. */
261
+ clearDeviceId(userId: number, deviceId: number): Promise<void>;
262
+ };
263
+ otp: {
264
+ findValidByUserAndCode(userId: number, code: number): Promise<AuthOTP | null>;
265
+ create(data: {
266
+ userId: number;
267
+ code: number;
268
+ expiresAt: Date;
269
+ }): Promise<AuthOTP>;
270
+ delete(id: number): Promise<void>;
271
+ };
272
+ passwordReset: {
273
+ findById(id: string): Promise<AuthPasswordReset | null>;
274
+ create(userId: number): Promise<AuthPasswordReset>;
275
+ delete(id: string): Promise<void>;
276
+ deleteAllByUserId(userId: number): Promise<void>;
277
+ };
278
+ device: {
279
+ findByTokenSessionAndUser(pushToken: string, sessionId: number, userId: number): Promise<{
280
+ id: number;
281
+ } | null>;
282
+ upsertByPushToken(pushToken: string, sessionId: number, userId: number): Promise<void>;
283
+ findByUserAndToken(userId: number, pushToken: string): Promise<{
284
+ id: number;
285
+ } | null>;
286
+ disconnectUser(deviceId: number, userId: number): Promise<void>;
287
+ hasRemainingUsers(deviceId: number): Promise<boolean>;
288
+ delete(id: number): Promise<void>;
289
+ };
290
+ admin: {
291
+ findByUserId(userId: number): Promise<{
292
+ ip: string;
293
+ } | null>;
294
+ };
295
+ }
296
+
297
+ type PrismaClient = any;
298
+ /**
299
+ * Creates a DatabaseAdapter backed by Prisma.
300
+ * Each method is a direct extraction of existing Prisma calls from the procedures.
301
+ */
302
+ declare function createPrismaAdapter(prisma: PrismaClient): DatabaseAdapter;
303
+
304
+ /**
305
+ * Drizzle table references required by the adapter.
306
+ * Consumers pass their Drizzle table objects so the adapter
307
+ * can build queries without knowing the schema file location.
308
+ */
309
+ interface DrizzleAdapterTables {
310
+ users: any;
311
+ sessions: any;
312
+ otps: any;
313
+ passwordResets: any;
314
+ devices: any;
315
+ admins: any;
316
+ /** Join table for many-to-many device↔user relation (if applicable). */
317
+ devicesToUsers?: any;
318
+ /** Join table for many-to-many device↔session relation (if applicable). */
319
+ devicesToSessions?: any;
320
+ }
321
+ /**
322
+ * Any Drizzle database instance (pg, mysql, better-sqlite3, etc.).
323
+ * We keep this generic so consumers aren't locked into a specific driver.
324
+ */
325
+ type DrizzleDB = any;
326
+ /**
327
+ * Creates a DatabaseAdapter backed by Drizzle ORM.
328
+ *
329
+ * Usage:
330
+ * ```ts
331
+ * import { drizzle } from 'drizzle-orm/node-postgres';
332
+ * import { createDrizzleAdapter } from '@factiii/auth';
333
+ * import * as schema from './schema';
334
+ *
335
+ * const db = drizzle(pool, { schema });
336
+ * const adapter = createDrizzleAdapter(db, {
337
+ * users: schema.users,
338
+ * sessions: schema.sessions,
339
+ * otps: schema.otps,
340
+ * passwordResets: schema.passwordResets,
341
+ * devices: schema.devices,
342
+ * admins: schema.admins,
343
+ * });
344
+ * ```
345
+ *
346
+ * **Important:** This adapter uses Drizzle's relational query API (`db.query.*`)
347
+ * for joins and `db.insert/update/delete` for mutations. Make sure your Drizzle
348
+ * instance is created with `{ schema }` so relational queries work.
349
+ */
350
+ declare function createDrizzleAdapter(db: DrizzleDB, tables: DrizzleAdapterTables): DatabaseAdapter;
351
+
152
352
  /**
153
353
  * JWT payload structure
154
354
  */
@@ -241,9 +441,15 @@ interface AuthFeatures {
241
441
  }
242
442
  interface AuthConfig<TExtensions extends SchemaExtensions = {}> {
243
443
  /**
244
- * Prisma client instance with required models
444
+ * Database adapter (use createPrismaAdapter or implement your own).
445
+ * If omitted but `prisma` is provided, a PrismaAdapter is created automatically.
245
446
  */
246
- prisma: PrismaClient;
447
+ database?: DatabaseAdapter;
448
+ /**
449
+ * @deprecated Use `database` with createPrismaAdapter() instead.
450
+ * Prisma client instance — kept for backwards compatibility.
451
+ */
452
+ prisma?: unknown;
247
453
  /**
248
454
  * Secret keys for JWT signing
249
455
  */
@@ -318,13 +524,17 @@ declare const defaultCookieSettings: CookieSettings;
318
524
  declare const defaultStorageKeys: {
319
525
  authToken: string;
320
526
  };
527
+ /** Resolved config type with database adapter guaranteed. */
528
+ type ResolvedAuthConfig = Required<Omit<AuthConfig, 'hooks' | 'oauthKeys' | 'schemaExtensions' | 'prisma'>> & AuthConfig & {
529
+ database: DatabaseAdapter;
530
+ };
321
531
  /**
322
- * Create a fully resolved auth config with defaults applied
532
+ * Create a fully resolved auth config with defaults applied.
533
+ * Accepts either `database` (adapter) or `prisma` (auto-wrapped).
323
534
  */
324
- declare function createAuthConfig(config: AuthConfig): Required<Omit<AuthConfig, 'hooks' | 'oauthKeys' | 'schemaExtensions'>> & AuthConfig;
325
- type ResolvedAuthConfig = ReturnType<typeof createAuthConfig>;
535
+ declare function createAuthConfig(config: AuthConfig): ResolvedAuthConfig;
326
536
  /**
327
- * Default auth config (requires prisma and secrets to be provided)
537
+ * Default auth config (requires database/prisma and secrets to be provided)
328
538
  */
329
539
  declare const defaultAuthConfig: {
330
540
  features: AuthFeatures;
@@ -438,7 +648,7 @@ declare function createAuthRouter<TExtensions extends SchemaExtensions = {}>(con
438
648
  input: void;
439
649
  output: {
440
650
  email: string;
441
- status: _prisma_client.$Enums.EmailVerificationStatus;
651
+ status: string;
442
652
  isVerified: boolean;
443
653
  };
444
654
  meta: Meta;
@@ -659,12 +869,12 @@ declare function createAuthRouter<TExtensions extends SchemaExtensions = {}>(con
659
869
  email: zod.ZodString;
660
870
  password: zod.ZodEffects<zod.ZodString, string, string>;
661
871
  }, "strip", zod.ZodTypeAny, {
662
- email: string;
663
872
  username: string;
873
+ email: string;
664
874
  password: string;
665
875
  }, {
666
- email: string;
667
876
  username: string;
877
+ email: string;
668
878
  password: string;
669
879
  }>>["in"] extends infer T_7 ? T_7 extends inferParser<[TExtensions["signup"]] extends [zod.AnyZodObject] ? zod.ZodObject<{
670
880
  username: zod.ZodString;
@@ -683,12 +893,12 @@ declare function createAuthRouter<TExtensions extends SchemaExtensions = {}>(con
683
893
  email: zod.ZodString;
684
894
  password: zod.ZodEffects<zod.ZodString, string, string>;
685
895
  }, "strip", zod.ZodTypeAny, {
686
- email: string;
687
896
  username: string;
897
+ email: string;
688
898
  password: string;
689
899
  }, {
690
- email: string;
691
900
  username: string;
901
+ email: string;
692
902
  password: string;
693
903
  }>>["in"] ? T_7 extends _trpc_server.TRPCUnsetMarker ? void : T_7 : never : never;
694
904
  output: {
@@ -1046,4 +1256,4 @@ declare function verifyTotp(code: string, secret: string): Promise<boolean>;
1046
1256
  */
1047
1257
  declare function generateOtp(min?: number, max?: number): number;
1048
1258
 
1049
- export { type AuthConfig, type AuthFeatures, AuthHooks, type AuthRouter, DEFAULT_STORAGE_KEYS, type EmailAdapter, type OAuthKeys, type OAuthProvider, type OAuthResult, OAuthVerificationError, SchemaExtensions, type TokenSettings, type TrpcContext, cleanBase32String, clearAuthCookie, comparePassword, createAuthConfig, createAuthGuard, createAuthRouter, createAuthToken, createConsoleEmailAdapter, createNoopEmailAdapter, createOAuthVerifier, decodeToken, defaultAuthConfig, defaultCookieSettings, defaultStorageKeys, defaultTokenSettings, detectBrowser, generateOtp, generateTotpCode, generateTotpSecret, hashPassword, isMobileDevice, isNativeApp, isTokenExpiredError, isTokenInvalidError, parseAuthCookie, setAuthCookie, validatePasswordStrength, verifyAuthToken, verifyTotp };
1259
+ export { type AuthConfig, type AuthFeatures, AuthHooks, type AuthOTP, type AuthPasswordReset, type AuthRouter, type AuthSession, type AuthUser, type CreateSessionData, type CreateUserData, DEFAULT_STORAGE_KEYS, type DatabaseAdapter, type DrizzleAdapterTables, type EmailAdapter, type OAuthKeys, type OAuthProvider, type OAuthResult, OAuthVerificationError, SchemaExtensions, type SessionWithDevice, type SessionWithUser, type TokenSettings, type TrpcContext, cleanBase32String, clearAuthCookie, comparePassword, createAuthConfig, createAuthGuard, createAuthRouter, createAuthToken, createConsoleEmailAdapter, createDrizzleAdapter, createNoopEmailAdapter, createOAuthVerifier, createPrismaAdapter, decodeToken, defaultAuthConfig, defaultCookieSettings, defaultStorageKeys, defaultTokenSettings, detectBrowser, generateOtp, generateTotpCode, generateTotpSecret, hashPassword, isMobileDevice, isNativeApp, isTokenExpiredError, isTokenInvalidError, parseAuthCookie, setAuthCookie, validatePasswordStrength, verifyAuthToken, verifyTotp };
package/dist/index.d.ts CHANGED
@@ -1,13 +1,11 @@
1
1
  import * as http from 'http';
2
2
  import * as SuperJSON from 'superjson';
3
3
  import SuperJSON__default from 'superjson';
4
- import * as _prisma_client from '@prisma/client';
5
- import { PrismaClient } from '@prisma/client';
6
4
  import * as _trpc_server from '@trpc/server';
7
5
  import * as zod from 'zod';
8
6
  import { CreateHTTPContextOptions } from '@trpc/server/adapters/standalone';
9
- import { S as SchemaExtensions, A as AuthHooks } from './hooks-BXNxNK4S.js';
10
- export { C as ChangePasswordInput, L as LoginInput, O as OAuthLoginInput, R as ResetPasswordInput, a as SignupInput, T as TwoFaVerifyInput, V as VerifyEmailInput, b as biometricVerifySchema, c as changePasswordSchema, e as endAllSessionsSchema, l as loginSchema, o as oAuthLoginSchema, r as requestPasswordResetSchema, d as resetPasswordSchema, s as signupSchema, t as twoFaResetSchema, f as twoFaVerifySchema, v as verifyEmailSchema } from './hooks-BXNxNK4S.js';
7
+ import { S as SchemaExtensions, A as AuthHooks } from './hooks-yHGJ7C6_.js';
8
+ export { C as ChangePasswordInput, L as LoginInput, O as OAuthLoginInput, R as ResetPasswordInput, a as SignupInput, T as TwoFaVerifyInput, V as VerifyEmailInput, b as biometricVerifySchema, c as changePasswordSchema, e as endAllSessionsSchema, l as loginSchema, o as oAuthLoginSchema, r as requestPasswordResetSchema, d as resetPasswordSchema, s as signupSchema, t as twoFaResetSchema, f as twoFaVerifySchema, v as verifyEmailSchema } from './hooks-yHGJ7C6_.js';
11
9
 
12
10
  //# sourceMappingURL=TRPCError.d.ts.map
13
11
  //#endregion
@@ -149,6 +147,208 @@ declare function createNoopEmailAdapter(): EmailAdapter;
149
147
  */
150
148
  declare function createConsoleEmailAdapter(): EmailAdapter;
151
149
 
150
+ /**
151
+ * ORM-agnostic database adapter interface for @factiii/auth.
152
+ * Implement this interface to use any database/ORM with the auth library.
153
+ */
154
+ interface AuthUser {
155
+ id: number;
156
+ status: string;
157
+ email: string;
158
+ username: string;
159
+ password: string | null;
160
+ twoFaEnabled: boolean;
161
+ oauthProvider: string | null;
162
+ oauthId: string | null;
163
+ tag: string;
164
+ verifiedHumanAt: Date | null;
165
+ emailVerificationStatus: string;
166
+ otpForEmailVerification: string | null;
167
+ isActive: boolean;
168
+ }
169
+ interface AuthSession {
170
+ id: number;
171
+ userId: number;
172
+ socketId: string | null;
173
+ twoFaSecret: string | null;
174
+ browserName: string;
175
+ issuedAt: Date;
176
+ lastUsed: Date;
177
+ revokedAt: Date | null;
178
+ deviceId: number | null;
179
+ }
180
+ interface AuthOTP {
181
+ id: number;
182
+ code: number;
183
+ expiresAt: Date;
184
+ userId: number;
185
+ }
186
+ interface AuthPasswordReset {
187
+ id: string;
188
+ createdAt: Date;
189
+ userId: number;
190
+ }
191
+ interface CreateUserData {
192
+ username: string;
193
+ email: string;
194
+ password: string | null;
195
+ status: string;
196
+ tag: string;
197
+ twoFaEnabled: boolean;
198
+ emailVerificationStatus: string;
199
+ verifiedHumanAt: Date | null;
200
+ oauthProvider?: string;
201
+ oauthId?: string;
202
+ }
203
+ interface CreateSessionData {
204
+ userId: number;
205
+ browserName: string;
206
+ socketId: string | null;
207
+ [key: string]: unknown;
208
+ }
209
+ type SessionWithUser = AuthSession & {
210
+ user: {
211
+ status: string;
212
+ verifiedHumanAt: Date | null;
213
+ };
214
+ };
215
+ type SessionWithDevice = {
216
+ twoFaSecret: string | null;
217
+ deviceId: number | null;
218
+ device: {
219
+ pushToken: string;
220
+ } | null;
221
+ };
222
+ interface DatabaseAdapter {
223
+ user: {
224
+ findByEmailInsensitive(email: string): Promise<AuthUser | null>;
225
+ findByUsernameInsensitive(username: string): Promise<AuthUser | null>;
226
+ findByEmailOrUsernameInsensitive(identifier: string): Promise<AuthUser | null>;
227
+ findByEmailOrOAuthId(email: string, oauthId: string): Promise<AuthUser | null>;
228
+ findById(id: number): Promise<AuthUser | null>;
229
+ findActiveById(id: number): Promise<AuthUser | null>;
230
+ create(data: CreateUserData): Promise<AuthUser>;
231
+ update(id: number, data: Partial<Omit<AuthUser, 'id'>>): Promise<AuthUser>;
232
+ };
233
+ session: {
234
+ /** Find session by ID with user status and verifiedHumanAt joined. */
235
+ findById(id: number): Promise<SessionWithUser | null>;
236
+ create(data: CreateSessionData): Promise<AuthSession>;
237
+ update(id: number, data: Partial<Pick<AuthSession, 'revokedAt' | 'lastUsed' | 'twoFaSecret' | 'deviceId'>>): Promise<AuthSession>;
238
+ /** Update lastUsed and return session with user's verifiedHumanAt. */
239
+ updateLastUsed(id: number): Promise<AuthSession & {
240
+ user: {
241
+ verifiedHumanAt: Date | null;
242
+ };
243
+ }>;
244
+ /** Set revokedAt on a single session. */
245
+ revoke(id: number): Promise<void>;
246
+ /** Find active (non-revoked) sessions for a user, optionally excluding one. */
247
+ findActiveByUserId(userId: number, excludeSessionId?: number): Promise<Pick<AuthSession, 'id' | 'socketId' | 'userId'>[]>;
248
+ /** Revoke all active sessions for a user, optionally excluding one. */
249
+ revokeAllByUserId(userId: number, excludeSessionId?: number): Promise<void>;
250
+ /** Get twoFaSecret from all sessions that have one for a user. */
251
+ findTwoFaSecretsByUserId(userId: number): Promise<{
252
+ twoFaSecret: string | null;
253
+ }[]>;
254
+ /** Clear twoFaSecret on sessions for a user, optionally excluding one. */
255
+ clearTwoFaSecrets(userId: number, excludeSessionId?: number): Promise<void>;
256
+ /** Find session with device relation for TOTP verification. */
257
+ findByIdWithDevice(id: number, userId: number): Promise<SessionWithDevice | null>;
258
+ /** Revoke other sessions that share a device push token. */
259
+ revokeByDevicePushToken(userId: number, pushToken: string, excludeSessionId: number): Promise<void>;
260
+ /** Clear deviceId on all sessions for a user+device pair. */
261
+ clearDeviceId(userId: number, deviceId: number): Promise<void>;
262
+ };
263
+ otp: {
264
+ findValidByUserAndCode(userId: number, code: number): Promise<AuthOTP | null>;
265
+ create(data: {
266
+ userId: number;
267
+ code: number;
268
+ expiresAt: Date;
269
+ }): Promise<AuthOTP>;
270
+ delete(id: number): Promise<void>;
271
+ };
272
+ passwordReset: {
273
+ findById(id: string): Promise<AuthPasswordReset | null>;
274
+ create(userId: number): Promise<AuthPasswordReset>;
275
+ delete(id: string): Promise<void>;
276
+ deleteAllByUserId(userId: number): Promise<void>;
277
+ };
278
+ device: {
279
+ findByTokenSessionAndUser(pushToken: string, sessionId: number, userId: number): Promise<{
280
+ id: number;
281
+ } | null>;
282
+ upsertByPushToken(pushToken: string, sessionId: number, userId: number): Promise<void>;
283
+ findByUserAndToken(userId: number, pushToken: string): Promise<{
284
+ id: number;
285
+ } | null>;
286
+ disconnectUser(deviceId: number, userId: number): Promise<void>;
287
+ hasRemainingUsers(deviceId: number): Promise<boolean>;
288
+ delete(id: number): Promise<void>;
289
+ };
290
+ admin: {
291
+ findByUserId(userId: number): Promise<{
292
+ ip: string;
293
+ } | null>;
294
+ };
295
+ }
296
+
297
+ type PrismaClient = any;
298
+ /**
299
+ * Creates a DatabaseAdapter backed by Prisma.
300
+ * Each method is a direct extraction of existing Prisma calls from the procedures.
301
+ */
302
+ declare function createPrismaAdapter(prisma: PrismaClient): DatabaseAdapter;
303
+
304
+ /**
305
+ * Drizzle table references required by the adapter.
306
+ * Consumers pass their Drizzle table objects so the adapter
307
+ * can build queries without knowing the schema file location.
308
+ */
309
+ interface DrizzleAdapterTables {
310
+ users: any;
311
+ sessions: any;
312
+ otps: any;
313
+ passwordResets: any;
314
+ devices: any;
315
+ admins: any;
316
+ /** Join table for many-to-many device↔user relation (if applicable). */
317
+ devicesToUsers?: any;
318
+ /** Join table for many-to-many device↔session relation (if applicable). */
319
+ devicesToSessions?: any;
320
+ }
321
+ /**
322
+ * Any Drizzle database instance (pg, mysql, better-sqlite3, etc.).
323
+ * We keep this generic so consumers aren't locked into a specific driver.
324
+ */
325
+ type DrizzleDB = any;
326
+ /**
327
+ * Creates a DatabaseAdapter backed by Drizzle ORM.
328
+ *
329
+ * Usage:
330
+ * ```ts
331
+ * import { drizzle } from 'drizzle-orm/node-postgres';
332
+ * import { createDrizzleAdapter } from '@factiii/auth';
333
+ * import * as schema from './schema';
334
+ *
335
+ * const db = drizzle(pool, { schema });
336
+ * const adapter = createDrizzleAdapter(db, {
337
+ * users: schema.users,
338
+ * sessions: schema.sessions,
339
+ * otps: schema.otps,
340
+ * passwordResets: schema.passwordResets,
341
+ * devices: schema.devices,
342
+ * admins: schema.admins,
343
+ * });
344
+ * ```
345
+ *
346
+ * **Important:** This adapter uses Drizzle's relational query API (`db.query.*`)
347
+ * for joins and `db.insert/update/delete` for mutations. Make sure your Drizzle
348
+ * instance is created with `{ schema }` so relational queries work.
349
+ */
350
+ declare function createDrizzleAdapter(db: DrizzleDB, tables: DrizzleAdapterTables): DatabaseAdapter;
351
+
152
352
  /**
153
353
  * JWT payload structure
154
354
  */
@@ -241,9 +441,15 @@ interface AuthFeatures {
241
441
  }
242
442
  interface AuthConfig<TExtensions extends SchemaExtensions = {}> {
243
443
  /**
244
- * Prisma client instance with required models
444
+ * Database adapter (use createPrismaAdapter or implement your own).
445
+ * If omitted but `prisma` is provided, a PrismaAdapter is created automatically.
245
446
  */
246
- prisma: PrismaClient;
447
+ database?: DatabaseAdapter;
448
+ /**
449
+ * @deprecated Use `database` with createPrismaAdapter() instead.
450
+ * Prisma client instance — kept for backwards compatibility.
451
+ */
452
+ prisma?: unknown;
247
453
  /**
248
454
  * Secret keys for JWT signing
249
455
  */
@@ -318,13 +524,17 @@ declare const defaultCookieSettings: CookieSettings;
318
524
  declare const defaultStorageKeys: {
319
525
  authToken: string;
320
526
  };
527
+ /** Resolved config type with database adapter guaranteed. */
528
+ type ResolvedAuthConfig = Required<Omit<AuthConfig, 'hooks' | 'oauthKeys' | 'schemaExtensions' | 'prisma'>> & AuthConfig & {
529
+ database: DatabaseAdapter;
530
+ };
321
531
  /**
322
- * Create a fully resolved auth config with defaults applied
532
+ * Create a fully resolved auth config with defaults applied.
533
+ * Accepts either `database` (adapter) or `prisma` (auto-wrapped).
323
534
  */
324
- declare function createAuthConfig(config: AuthConfig): Required<Omit<AuthConfig, 'hooks' | 'oauthKeys' | 'schemaExtensions'>> & AuthConfig;
325
- type ResolvedAuthConfig = ReturnType<typeof createAuthConfig>;
535
+ declare function createAuthConfig(config: AuthConfig): ResolvedAuthConfig;
326
536
  /**
327
- * Default auth config (requires prisma and secrets to be provided)
537
+ * Default auth config (requires database/prisma and secrets to be provided)
328
538
  */
329
539
  declare const defaultAuthConfig: {
330
540
  features: AuthFeatures;
@@ -438,7 +648,7 @@ declare function createAuthRouter<TExtensions extends SchemaExtensions = {}>(con
438
648
  input: void;
439
649
  output: {
440
650
  email: string;
441
- status: _prisma_client.$Enums.EmailVerificationStatus;
651
+ status: string;
442
652
  isVerified: boolean;
443
653
  };
444
654
  meta: Meta;
@@ -659,12 +869,12 @@ declare function createAuthRouter<TExtensions extends SchemaExtensions = {}>(con
659
869
  email: zod.ZodString;
660
870
  password: zod.ZodEffects<zod.ZodString, string, string>;
661
871
  }, "strip", zod.ZodTypeAny, {
662
- email: string;
663
872
  username: string;
873
+ email: string;
664
874
  password: string;
665
875
  }, {
666
- email: string;
667
876
  username: string;
877
+ email: string;
668
878
  password: string;
669
879
  }>>["in"] extends infer T_7 ? T_7 extends inferParser<[TExtensions["signup"]] extends [zod.AnyZodObject] ? zod.ZodObject<{
670
880
  username: zod.ZodString;
@@ -683,12 +893,12 @@ declare function createAuthRouter<TExtensions extends SchemaExtensions = {}>(con
683
893
  email: zod.ZodString;
684
894
  password: zod.ZodEffects<zod.ZodString, string, string>;
685
895
  }, "strip", zod.ZodTypeAny, {
686
- email: string;
687
896
  username: string;
897
+ email: string;
688
898
  password: string;
689
899
  }, {
690
- email: string;
691
900
  username: string;
901
+ email: string;
692
902
  password: string;
693
903
  }>>["in"] ? T_7 extends _trpc_server.TRPCUnsetMarker ? void : T_7 : never : never;
694
904
  output: {
@@ -1046,4 +1256,4 @@ declare function verifyTotp(code: string, secret: string): Promise<boolean>;
1046
1256
  */
1047
1257
  declare function generateOtp(min?: number, max?: number): number;
1048
1258
 
1049
- export { type AuthConfig, type AuthFeatures, AuthHooks, type AuthRouter, DEFAULT_STORAGE_KEYS, type EmailAdapter, type OAuthKeys, type OAuthProvider, type OAuthResult, OAuthVerificationError, SchemaExtensions, type TokenSettings, type TrpcContext, cleanBase32String, clearAuthCookie, comparePassword, createAuthConfig, createAuthGuard, createAuthRouter, createAuthToken, createConsoleEmailAdapter, createNoopEmailAdapter, createOAuthVerifier, decodeToken, defaultAuthConfig, defaultCookieSettings, defaultStorageKeys, defaultTokenSettings, detectBrowser, generateOtp, generateTotpCode, generateTotpSecret, hashPassword, isMobileDevice, isNativeApp, isTokenExpiredError, isTokenInvalidError, parseAuthCookie, setAuthCookie, validatePasswordStrength, verifyAuthToken, verifyTotp };
1259
+ export { type AuthConfig, type AuthFeatures, AuthHooks, type AuthOTP, type AuthPasswordReset, type AuthRouter, type AuthSession, type AuthUser, type CreateSessionData, type CreateUserData, DEFAULT_STORAGE_KEYS, type DatabaseAdapter, type DrizzleAdapterTables, type EmailAdapter, type OAuthKeys, type OAuthProvider, type OAuthResult, OAuthVerificationError, SchemaExtensions, type SessionWithDevice, type SessionWithUser, type TokenSettings, type TrpcContext, cleanBase32String, clearAuthCookie, comparePassword, createAuthConfig, createAuthGuard, createAuthRouter, createAuthToken, createConsoleEmailAdapter, createDrizzleAdapter, createNoopEmailAdapter, createOAuthVerifier, createPrismaAdapter, decodeToken, defaultAuthConfig, defaultCookieSettings, defaultStorageKeys, defaultTokenSettings, detectBrowser, generateOtp, generateTotpCode, generateTotpSecret, hashPassword, isMobileDevice, isNativeApp, isTokenExpiredError, isTokenInvalidError, parseAuthCookie, setAuthCookie, validatePasswordStrength, verifyAuthToken, verifyTotp };