@factiii/auth 0.5.3 → 0.5.5

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.ts CHANGED
@@ -1,13 +1,12 @@
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';
9
+ import { AnyPgTable, PgColumn, PgDatabase, PgQueryResultHKT } from 'drizzle-orm/pg-core';
11
10
 
12
11
  //# sourceMappingURL=TRPCError.d.ts.map
13
12
  //#endregion
@@ -149,6 +148,215 @@ declare function createNoopEmailAdapter(): EmailAdapter;
149
148
  */
150
149
  declare function createConsoleEmailAdapter(): EmailAdapter;
151
150
 
151
+ /**
152
+ * ORM-agnostic database adapter interface for @factiii/auth.
153
+ * Implement this interface to use any database/ORM with the auth library.
154
+ */
155
+ interface AuthUser {
156
+ id: number;
157
+ status: string;
158
+ email: string;
159
+ username: string;
160
+ password: string | null;
161
+ twoFaEnabled: boolean;
162
+ oauthProvider: string | null;
163
+ oauthId: string | null;
164
+ tag: string;
165
+ verifiedHumanAt: Date | null;
166
+ emailVerificationStatus: string;
167
+ otpForEmailVerification: string | null;
168
+ isActive: boolean;
169
+ }
170
+ interface AuthSession {
171
+ id: number;
172
+ userId: number;
173
+ socketId: string | null;
174
+ twoFaSecret: string | null;
175
+ browserName: string;
176
+ issuedAt: Date;
177
+ lastUsed: Date;
178
+ revokedAt: Date | null;
179
+ deviceId: number | null;
180
+ }
181
+ interface AuthOTP {
182
+ id: number;
183
+ code: number;
184
+ expiresAt: Date;
185
+ userId: number;
186
+ }
187
+ interface AuthPasswordReset {
188
+ id: string;
189
+ createdAt: Date;
190
+ userId: number;
191
+ }
192
+ interface CreateUserData {
193
+ username: string;
194
+ email: string;
195
+ password: string | null;
196
+ status: string;
197
+ tag: string;
198
+ twoFaEnabled: boolean;
199
+ emailVerificationStatus: string;
200
+ verifiedHumanAt: Date | null;
201
+ oauthProvider?: string;
202
+ oauthId?: string;
203
+ }
204
+ interface CreateSessionData {
205
+ userId: number;
206
+ browserName: string;
207
+ socketId: string | null;
208
+ [key: string]: unknown;
209
+ }
210
+ type SessionWithUser = AuthSession & {
211
+ user: {
212
+ status: string;
213
+ verifiedHumanAt: Date | null;
214
+ };
215
+ };
216
+ type SessionWithDevice = {
217
+ twoFaSecret: string | null;
218
+ deviceId: number | null;
219
+ device: {
220
+ pushToken: string;
221
+ } | null;
222
+ };
223
+ interface DatabaseAdapter {
224
+ user: {
225
+ findByEmailInsensitive(email: string): Promise<AuthUser | null>;
226
+ findByUsernameInsensitive(username: string): Promise<AuthUser | null>;
227
+ findByEmailOrUsernameInsensitive(identifier: string): Promise<AuthUser | null>;
228
+ findByEmailOrOAuthId(email: string, oauthId: string): Promise<AuthUser | null>;
229
+ findById(id: number): Promise<AuthUser | null>;
230
+ findActiveById(id: number): Promise<AuthUser | null>;
231
+ create(data: CreateUserData): Promise<AuthUser>;
232
+ update(id: number, data: Partial<Omit<AuthUser, 'id'>>): Promise<AuthUser>;
233
+ };
234
+ session: {
235
+ /** Find session by ID with user status and verifiedHumanAt joined. */
236
+ findById(id: number): Promise<SessionWithUser | null>;
237
+ create(data: CreateSessionData): Promise<AuthSession>;
238
+ update(id: number, data: Partial<Pick<AuthSession, 'revokedAt' | 'lastUsed' | 'twoFaSecret' | 'deviceId'>>): Promise<AuthSession>;
239
+ /** Update lastUsed and return session with user's verifiedHumanAt. */
240
+ updateLastUsed(id: number): Promise<AuthSession & {
241
+ user: {
242
+ verifiedHumanAt: Date | null;
243
+ };
244
+ }>;
245
+ /** Set revokedAt on a single session. */
246
+ revoke(id: number): Promise<void>;
247
+ /** Find active (non-revoked) sessions for a user, optionally excluding one. */
248
+ findActiveByUserId(userId: number, excludeSessionId?: number): Promise<Pick<AuthSession, 'id' | 'socketId' | 'userId'>[]>;
249
+ /** Revoke all active sessions for a user, optionally excluding one. */
250
+ revokeAllByUserId(userId: number, excludeSessionId?: number): Promise<void>;
251
+ /** Get twoFaSecret from all sessions that have one for a user. */
252
+ findTwoFaSecretsByUserId(userId: number): Promise<{
253
+ twoFaSecret: string | null;
254
+ }[]>;
255
+ /** Clear twoFaSecret on sessions for a user, optionally excluding one. */
256
+ clearTwoFaSecrets(userId: number, excludeSessionId?: number): Promise<void>;
257
+ /** Find session with device relation for TOTP verification. */
258
+ findByIdWithDevice(id: number, userId: number): Promise<SessionWithDevice | null>;
259
+ /** Revoke other sessions that share a device push token. */
260
+ revokeByDevicePushToken(userId: number, pushToken: string, excludeSessionId: number): Promise<void>;
261
+ /** Clear deviceId on all sessions for a user+device pair. */
262
+ clearDeviceId(userId: number, deviceId: number): Promise<void>;
263
+ };
264
+ otp: {
265
+ findValidByUserAndCode(userId: number, code: number): Promise<AuthOTP | null>;
266
+ create(data: {
267
+ userId: number;
268
+ code: number;
269
+ expiresAt: Date;
270
+ }): Promise<AuthOTP>;
271
+ delete(id: number): Promise<void>;
272
+ };
273
+ passwordReset: {
274
+ findById(id: string): Promise<AuthPasswordReset | null>;
275
+ create(userId: number): Promise<AuthPasswordReset>;
276
+ delete(id: string): Promise<void>;
277
+ deleteAllByUserId(userId: number): Promise<void>;
278
+ };
279
+ device: {
280
+ findByTokenSessionAndUser(pushToken: string, sessionId: number, userId: number): Promise<{
281
+ id: number;
282
+ } | null>;
283
+ upsertByPushToken(pushToken: string, sessionId: number, userId: number): Promise<void>;
284
+ findByUserAndToken(userId: number, pushToken: string): Promise<{
285
+ id: number;
286
+ } | null>;
287
+ disconnectUser(deviceId: number, userId: number): Promise<void>;
288
+ hasRemainingUsers(deviceId: number): Promise<boolean>;
289
+ delete(id: number): Promise<void>;
290
+ };
291
+ admin: {
292
+ findByUserId(userId: number): Promise<{
293
+ ip: string;
294
+ } | null>;
295
+ };
296
+ }
297
+
298
+ /**
299
+ * Creates a DatabaseAdapter backed by Prisma.
300
+ * Pass your generated PrismaClient instance — its full types are preserved at the call site.
301
+ */
302
+ declare function createPrismaAdapter(prisma: unknown): DatabaseAdapter;
303
+
304
+ /**
305
+ * A Postgres Drizzle table with column properties accessible by name.
306
+ * `AnyPgTable` is Drizzle's base Postgres table type; intersecting with
307
+ * `Record<string, Column>` exposes the column descriptors for index access.
308
+ */
309
+ type DrizzleTable = AnyPgTable & Record<string, PgColumn>;
310
+ /**
311
+ * Drizzle table references required by the adapter.
312
+ * Consumers pass their Drizzle Postgres table objects so the adapter
313
+ * can build queries without knowing the schema file location.
314
+ *
315
+ * **Note:** This adapter only supports PostgreSQL via `drizzle-orm/pg-core`.
316
+ */
317
+ interface DrizzleAdapterTables {
318
+ users: DrizzleTable;
319
+ sessions: DrizzleTable;
320
+ otps: DrizzleTable;
321
+ passwordResets: DrizzleTable;
322
+ devices: DrizzleTable;
323
+ admins: DrizzleTable;
324
+ /** Join table for many-to-many device↔user relation (if applicable). */
325
+ devicesToUsers?: DrizzleTable;
326
+ /** Join table for many-to-many device↔session relation (if applicable). */
327
+ devicesToSessions?: DrizzleTable;
328
+ }
329
+ /**
330
+ * Any `PgDatabase` instance, regardless of the underlying driver
331
+ * (node-postgres, postgres.js, Neon, PGLite, etc.).
332
+ */
333
+ type AnyPgDatabase = PgDatabase<PgQueryResultHKT, Record<string, unknown>>;
334
+ /**
335
+ * Creates a DatabaseAdapter backed by Drizzle ORM.
336
+ *
337
+ * Usage:
338
+ * ```ts
339
+ * import { drizzle } from 'drizzle-orm/node-postgres';
340
+ * import { createDrizzleAdapter } from '@factiii/auth';
341
+ * import * as schema from './schema';
342
+ *
343
+ * const db = drizzle(pool, { schema });
344
+ * const adapter = createDrizzleAdapter(db, {
345
+ * users: schema.users,
346
+ * sessions: schema.sessions,
347
+ * otps: schema.otps,
348
+ * passwordResets: schema.passwordResets,
349
+ * devices: schema.devices,
350
+ * admins: schema.admins,
351
+ * });
352
+ * ```
353
+ *
354
+ * **Important:** This adapter uses Drizzle's relational query API (`db.query.*`)
355
+ * for joins and `db.insert/update/delete` for mutations. Make sure your Drizzle
356
+ * instance is created with `{ schema }` so relational queries work.
357
+ */
358
+ declare function createDrizzleAdapter(db: AnyPgDatabase, tables: DrizzleAdapterTables): DatabaseAdapter;
359
+
152
360
  /**
153
361
  * JWT payload structure
154
362
  */
@@ -241,9 +449,15 @@ interface AuthFeatures {
241
449
  }
242
450
  interface AuthConfig<TExtensions extends SchemaExtensions = {}> {
243
451
  /**
244
- * Prisma client instance with required models
452
+ * Database adapter (use createPrismaAdapter or implement your own).
453
+ * If omitted but `prisma` is provided, a PrismaAdapter is created automatically.
454
+ */
455
+ database?: DatabaseAdapter;
456
+ /**
457
+ * @deprecated Use `database` with createPrismaAdapter() instead.
458
+ * Prisma client instance — kept for backwards compatibility.
245
459
  */
246
- prisma: PrismaClient;
460
+ prisma?: unknown;
247
461
  /**
248
462
  * Secret keys for JWT signing
249
463
  */
@@ -299,9 +513,9 @@ declare function createAuthGuard(config: AuthConfig, t: TrpcBuilder): _trpc_serv
299
513
  userId: number;
300
514
  socketId: string | null;
301
515
  sessionId: number;
516
+ ip: string | undefined;
302
517
  headers: http.IncomingHttpHeaders;
303
518
  res: http.ServerResponse<http.IncomingMessage>;
304
- ip: string | undefined;
305
519
  }, unknown>;
306
520
 
307
521
  /**
@@ -318,13 +532,17 @@ declare const defaultCookieSettings: CookieSettings;
318
532
  declare const defaultStorageKeys: {
319
533
  authToken: string;
320
534
  };
535
+ /** Resolved config type with database adapter guaranteed. */
536
+ type ResolvedAuthConfig = Required<Omit<AuthConfig, 'hooks' | 'oauthKeys' | 'schemaExtensions' | 'prisma'>> & AuthConfig & {
537
+ database: DatabaseAdapter;
538
+ };
321
539
  /**
322
- * Create a fully resolved auth config with defaults applied
540
+ * Create a fully resolved auth config with defaults applied.
541
+ * Accepts either `database` (adapter) or `prisma` (auto-wrapped).
323
542
  */
324
- declare function createAuthConfig(config: AuthConfig): Required<Omit<AuthConfig, 'hooks' | 'oauthKeys' | 'schemaExtensions'>> & AuthConfig;
325
- type ResolvedAuthConfig = ReturnType<typeof createAuthConfig>;
543
+ declare function createAuthConfig(config: AuthConfig): ResolvedAuthConfig;
326
544
  /**
327
- * Default auth config (requires prisma and secrets to be provided)
545
+ * Default auth config (requires database/prisma and secrets to be provided)
328
546
  */
329
547
  declare const defaultAuthConfig: {
330
548
  features: AuthFeatures;
@@ -438,7 +656,7 @@ declare function createAuthRouter<TExtensions extends SchemaExtensions = {}>(con
438
656
  input: void;
439
657
  output: {
440
658
  email: string;
441
- status: _prisma_client.$Enums.EmailVerificationStatus;
659
+ status: string;
442
660
  isVerified: boolean;
443
661
  };
444
662
  meta: Meta;
@@ -659,12 +877,12 @@ declare function createAuthRouter<TExtensions extends SchemaExtensions = {}>(con
659
877
  email: zod.ZodString;
660
878
  password: zod.ZodEffects<zod.ZodString, string, string>;
661
879
  }, "strip", zod.ZodTypeAny, {
662
- email: string;
663
880
  username: string;
881
+ email: string;
664
882
  password: string;
665
883
  }, {
666
- email: string;
667
884
  username: string;
885
+ email: string;
668
886
  password: string;
669
887
  }>>["in"] extends infer T_7 ? T_7 extends inferParser<[TExtensions["signup"]] extends [zod.AnyZodObject] ? zod.ZodObject<{
670
888
  username: zod.ZodString;
@@ -683,12 +901,12 @@ declare function createAuthRouter<TExtensions extends SchemaExtensions = {}>(con
683
901
  email: zod.ZodString;
684
902
  password: zod.ZodEffects<zod.ZodString, string, string>;
685
903
  }, "strip", zod.ZodTypeAny, {
686
- email: string;
687
904
  username: string;
905
+ email: string;
688
906
  password: string;
689
907
  }, {
690
- email: string;
691
908
  username: string;
909
+ email: string;
692
910
  password: string;
693
911
  }>>["in"] ? T_7 extends _trpc_server.TRPCUnsetMarker ? void : T_7 : never : never;
694
912
  output: {
@@ -871,17 +1089,17 @@ declare function createAuthRouter<TExtensions extends SchemaExtensions = {}>(con
871
1089
  sessionId: number;
872
1090
  userId: number;
873
1091
  socketId: string | null;
1092
+ ip: string | undefined;
874
1093
  headers: http.IncomingHttpHeaders;
875
1094
  res: http.ServerResponse<http.IncomingMessage>;
876
- ip: string | undefined;
877
1095
  }, _trpc_server.TRPCUnsetMarker, _trpc_server.TRPCUnsetMarker, _trpc_server.TRPCUnsetMarker, _trpc_server.TRPCUnsetMarker, false>;
878
1096
  authProcedure: _trpc_server.TRPCProcedureBuilder<TrpcContext, Meta, {
879
1097
  sessionId: number;
880
1098
  userId: number;
881
1099
  socketId: string | null;
1100
+ ip: string | undefined;
882
1101
  headers: http.IncomingHttpHeaders;
883
1102
  res: http.ServerResponse<http.IncomingMessage>;
884
- ip: string | undefined;
885
1103
  }, _trpc_server.TRPCUnsetMarker, _trpc_server.TRPCUnsetMarker, _trpc_server.TRPCUnsetMarker, _trpc_server.TRPCUnsetMarker, false>;
886
1104
  createContext: ({ req, res }: CreateHTTPContextOptions) => TrpcContext;
887
1105
  };
@@ -1012,6 +1230,54 @@ declare function validatePasswordStrength(password: string, minLength?: number):
1012
1230
  error?: string;
1013
1231
  };
1014
1232
 
1233
+ /**
1234
+ * Parameters for creating a session with a signed JWT token.
1235
+ */
1236
+ interface CreateSessionWithTokenParams {
1237
+ /** User ID to create the session for */
1238
+ userId: number;
1239
+ /** Browser name (from user-agent) */
1240
+ browserName: string;
1241
+ /** Socket ID for real-time connections */
1242
+ socketId: string | null;
1243
+ /** Device ID for push notifications */
1244
+ deviceId?: number;
1245
+ /** Extra fields to include in the session record (e.g., instanceId) */
1246
+ extraSessionData?: Record<string, unknown>;
1247
+ }
1248
+ /**
1249
+ * Result of creating a session with a token.
1250
+ */
1251
+ interface SessionWithTokenResult {
1252
+ /** Signed JWT access token */
1253
+ accessToken: string;
1254
+ /** Created session ID */
1255
+ sessionId: number;
1256
+ }
1257
+ /**
1258
+ * Create a session and sign a JWT token.
1259
+ *
1260
+ * Use this for programmatic auth flows (magic links, auto-login, test helpers)
1261
+ * where you need a token without going through the full login procedure.
1262
+ *
1263
+ * @param config - Resolved auth config (from createAuthConfig)
1264
+ * @param params - Session creation parameters
1265
+ * @returns Signed JWT and session ID
1266
+ */
1267
+ declare function createSessionWithToken(config: ResolvedAuthConfig, params: CreateSessionWithTokenParams): Promise<SessionWithTokenResult>;
1268
+ /**
1269
+ * Create a session, sign a JWT token, and set the auth cookie on the response.
1270
+ *
1271
+ * Convenience wrapper around {@link createSessionWithToken} for HTTP handlers
1272
+ * that need to set the cookie immediately.
1273
+ *
1274
+ * @param config - Resolved auth config (from createAuthConfig)
1275
+ * @param params - Session creation parameters
1276
+ * @param res - HTTP response to set the cookie on
1277
+ * @returns Signed JWT and session ID
1278
+ */
1279
+ declare function createSessionWithTokenAndCookie(config: ResolvedAuthConfig, params: CreateSessionWithTokenParams, res: CreateHTTPContextOptions['res']): Promise<SessionWithTokenResult>;
1280
+
1015
1281
  /**
1016
1282
  * Generate a random TOTP secret
1017
1283
  * @param length - Length of the secret (default: 16)
@@ -1046,4 +1312,4 @@ declare function verifyTotp(code: string, secret: string): Promise<boolean>;
1046
1312
  */
1047
1313
  declare function generateOtp(min?: number, max?: number): number;
1048
1314
 
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 };
1315
+ export { type AuthConfig, type AuthFeatures, AuthHooks, type AuthOTP, type AuthPasswordReset, type AuthRouter, type AuthSession, type AuthUser, type CreateSessionData, type CreateSessionWithTokenParams, type CreateUserData, DEFAULT_STORAGE_KEYS, type DatabaseAdapter, type DrizzleAdapterTables, type EmailAdapter, type OAuthKeys, type OAuthProvider, type OAuthResult, OAuthVerificationError, type ResolvedAuthConfig, SchemaExtensions, type SessionWithDevice, type SessionWithTokenResult, type SessionWithUser, type TokenSettings, type TrpcContext, cleanBase32String, clearAuthCookie, comparePassword, createAuthConfig, createAuthGuard, createAuthRouter, createAuthToken, createConsoleEmailAdapter, createDrizzleAdapter, createNoopEmailAdapter, createOAuthVerifier, createPrismaAdapter, createSessionWithToken, createSessionWithTokenAndCookie, decodeToken, defaultAuthConfig, defaultCookieSettings, defaultStorageKeys, defaultTokenSettings, detectBrowser, generateOtp, generateTotpCode, generateTotpSecret, hashPassword, isMobileDevice, isNativeApp, isTokenExpiredError, isTokenInvalidError, parseAuthCookie, setAuthCookie, validatePasswordStrength, verifyAuthToken, verifyTotp };