@gauts/auth 0.8.2 → 0.9.0

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.
Files changed (75) hide show
  1. package/README.md +292 -66
  2. package/dist/adapters/drizzle/config.d.ts +11 -0
  3. package/dist/adapters/drizzle/config.d.ts.map +1 -0
  4. package/dist/adapters/drizzle/config.js +147 -0
  5. package/dist/adapters/drizzle/config.js.map +1 -0
  6. package/dist/adapters/drizzle/index.d.ts +4 -0
  7. package/dist/adapters/drizzle/index.d.ts.map +1 -0
  8. package/dist/adapters/drizzle/index.js +156 -0
  9. package/dist/adapters/drizzle/index.js.map +1 -0
  10. package/dist/adapters/drizzle/model.d.ts +21 -0
  11. package/dist/adapters/drizzle/model.d.ts.map +1 -0
  12. package/dist/adapters/drizzle/model.js +61 -0
  13. package/dist/adapters/drizzle/model.js.map +1 -0
  14. package/dist/adapters/drizzle/schema.d.ts +311 -0
  15. package/dist/adapters/drizzle/schema.d.ts.map +1 -0
  16. package/dist/adapters/drizzle/schema.js +37 -0
  17. package/dist/adapters/drizzle/schema.js.map +1 -0
  18. package/dist/adapters/drizzle/types.d.ts +109 -0
  19. package/dist/adapters/drizzle/types.d.ts.map +1 -0
  20. package/dist/adapters/drizzle/types.js +2 -0
  21. package/dist/adapters/drizzle/types.js.map +1 -0
  22. package/dist/adapters/express/index.d.ts +83 -0
  23. package/dist/adapters/express/index.d.ts.map +1 -0
  24. package/dist/adapters/express/index.js +72 -0
  25. package/dist/adapters/express/index.js.map +1 -0
  26. package/dist/adapters/express/social.d.ts +29 -0
  27. package/dist/adapters/express/social.d.ts.map +1 -0
  28. package/dist/adapters/express/social.js +44 -0
  29. package/dist/adapters/express/social.js.map +1 -0
  30. package/dist/adapters/fastify/index.d.ts +85 -0
  31. package/dist/adapters/fastify/index.d.ts.map +1 -0
  32. package/dist/adapters/fastify/index.js +100 -0
  33. package/dist/adapters/fastify/index.js.map +1 -0
  34. package/dist/adapters/fastify/social.d.ts +27 -0
  35. package/dist/adapters/fastify/social.d.ts.map +1 -0
  36. package/dist/adapters/fastify/social.js +48 -0
  37. package/dist/adapters/fastify/social.js.map +1 -0
  38. package/dist/adapters/hono/index.d.ts +4 -11
  39. package/dist/adapters/hono/index.d.ts.map +1 -1
  40. package/dist/adapters/hono/index.js +31 -223
  41. package/dist/adapters/hono/index.js.map +1 -1
  42. package/dist/adapters/hono/social.d.ts +4 -10
  43. package/dist/adapters/hono/social.d.ts.map +1 -1
  44. package/dist/adapters/hono/social.js +25 -221
  45. package/dist/adapters/hono/social.js.map +1 -1
  46. package/dist/adapters/model.d.ts +33 -0
  47. package/dist/adapters/model.d.ts.map +1 -0
  48. package/dist/adapters/model.js +87 -0
  49. package/dist/adapters/model.js.map +1 -0
  50. package/dist/adapters/prisma/config.d.ts.map +1 -1
  51. package/dist/adapters/prisma/config.js +1 -4
  52. package/dist/adapters/prisma/config.js.map +1 -1
  53. package/dist/adapters/prisma/model.d.ts +7 -8
  54. package/dist/adapters/prisma/model.d.ts.map +1 -1
  55. package/dist/adapters/prisma/model.js +11 -79
  56. package/dist/adapters/prisma/model.js.map +1 -1
  57. package/dist/adapters/utils/cookie.d.ts +17 -0
  58. package/dist/adapters/utils/cookie.d.ts.map +1 -0
  59. package/dist/adapters/utils/cookie.js +59 -0
  60. package/dist/adapters/utils/cookie.js.map +1 -0
  61. package/dist/adapters/utils/session.d.ts +4 -0
  62. package/dist/adapters/utils/session.d.ts.map +1 -0
  63. package/dist/adapters/utils/session.js +216 -0
  64. package/dist/adapters/utils/session.js.map +1 -0
  65. package/dist/adapters/utils/social.d.ts +51 -0
  66. package/dist/adapters/utils/social.d.ts.map +1 -0
  67. package/dist/adapters/utils/social.js +278 -0
  68. package/dist/adapters/utils/social.js.map +1 -0
  69. package/dist/adapters/utils/types.d.ts +67 -0
  70. package/dist/adapters/utils/types.d.ts.map +1 -0
  71. package/dist/adapters/utils/types.js +2 -0
  72. package/dist/adapters/utils/types.js.map +1 -0
  73. package/package.json +40 -3
  74. package/src/adapters/drizzle/schema.ts +47 -0
  75. package/src/adapters/prisma/schema.prisma +38 -0
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Database-backed password authentication, opaque browser sessions, and optional social authentication for Node.js applications.
4
4
 
5
- `@gauts/auth` provides password hashing, session lifecycle, secure cookies, database validation, optional short caching, Prisma persistence, Hono integration, and Google/GitHub/X OAuth. The application keeps control of credential lookup, business-specific registration data, authorization, responses, and UI.
5
+ `@gauts/auth` provides password hashing, session lifecycle, secure cookies, database validation, optional short caching, Prisma or Drizzle persistence, Hono/Express/Fastify integration, and Google/GitHub/X OAuth. The application keeps control of credential lookup, business-specific registration data, authorization, responses, and UI.
6
6
 
7
7
  ## Features
8
8
 
@@ -19,7 +19,10 @@ Database-backed password authentication, opaque browser sessions, and optional s
19
19
  | IP validation | ✅ | Disabled |
20
20
  | Platform validation | ✅ | Disabled |
21
21
  | Hono adapter | ✅ | Available |
22
+ | Express adapter | ✅ | Available |
23
+ | Fastify adapter | ✅ | Available |
22
24
  | Prisma adapter | ✅ | Available |
25
+ | Drizzle MySQL/MariaDB adapter | ✅ | Available |
23
26
  | Next.js renewal adapter | ✅ | Available |
24
27
  | Google social authentication | ✅ | Opt-in |
25
28
  | GitHub social authentication | ✅ | Opt-in |
@@ -40,25 +43,38 @@ The application defines its credential login, renewal, logout, and protected end
40
43
 
41
44
  ### 1. Install the package
42
45
 
43
- Run these commands inside the Hono API project:
46
+ Install the package and the framework used by the API. Only one framework adapter is required:
44
47
 
45
48
  ```bash
46
- npm install @gauts/auth
47
- npm install hono @prisma/client
49
+ npm install @gauts/auth hono
50
+ npm install @gauts/auth express
51
+ npm install @gauts/auth fastify
48
52
  ```
49
53
 
50
- When the Next.js frontend is a separate project, run these commands inside the frontend project:
54
+ When the Next.js frontend is a separate project, run this command inside the frontend project:
51
55
 
52
56
  ```bash
53
- npm install @gauts/auth
54
- npm install next
57
+ npm install @gauts/auth next
55
58
  ```
56
59
 
57
- `hono`, `@prisma/client`, and `next` only need to be installed when the corresponding project does not already provide them. The API imports `@gauts/auth/hono` and `@gauts/auth/prisma`; the frontend imports `@gauts/auth/next`.
60
+ Run only the matching API command. `hono`, `express`, `fastify`, and `next` only need to be installed when the corresponding project does not already provide them.
58
61
 
59
- ### 2. Add the Prisma schema
62
+ Express TypeScript projects also install its type declarations:
60
63
 
61
- The default adapter uses this fixed relationship tree:
64
+ ```bash
65
+ npm install --save-dev @types/express
66
+ ```
67
+
68
+ ### 2. Choose the database adapter and schema
69
+
70
+ One database adapter is required. Prisma and Drizzle are equivalent persistence choices; install and configure only one.
71
+
72
+ | Adapter | Database support | Setup |
73
+ | ------- | -------------------------- | ---------------------------------------------- |
74
+ | Prisma | Prisma-supported databases | [Use Prisma](#option-a--prisma) |
75
+ | Drizzle | MySQL and MariaDB | [Use Drizzle](#option-b--drizzle-mysqlmariadb) |
76
+
77
+ Both schemas use the same relationship tree:
62
78
 
63
79
  ```text
64
80
  users
@@ -66,70 +82,78 @@ users
66
82
  └── account_sessions
67
83
  ```
68
84
 
69
- Add the three required models to the API schema. Social authentication is an optional addon with its own schema instructions later in this README.
85
+ Social authentication is an optional addon with separate schema instructions later in this README.
70
86
 
71
- ```prisma
72
- model users {
73
- id String @id @default(uuid()) @db.VarChar(255)
74
- name String @db.VarChar(255)
87
+ #### Option A — Prisma
75
88
 
76
- accounts user_accounts[]
77
- }
89
+ Install Prisma inside the API project:
78
90
 
79
- model user_accounts {
80
- id String @id @default(uuid()) @db.VarChar(255)
81
- user_id String @db.VarChar(255)
82
- email String @unique @db.VarChar(255)
83
- password_hash String? @db.VarChar(255)
91
+ ```bash
92
+ npm install @prisma/client
93
+ npm install --save-dev prisma
94
+ ```
84
95
 
85
- user users @relation(fields: [user_id], references: [id], onDelete: Cascade)
86
- sessions account_sessions[]
96
+ [View and copy the Prisma schema](./src/adapters/prisma/schema.prisma) into the application's Prisma schema.
87
97
 
88
- @@index([user_id])
89
- }
98
+ Create the migration through the application's Prisma workflow, then regenerate its client:
90
99
 
91
- model account_sessions {
92
- id String @id @default(uuid()) @db.VarChar(255)
93
- account_id String @db.VarChar(255)
94
- token_hash String @unique @db.VarChar(64)
95
- ip String? @db.VarChar(45)
96
- country String? @db.VarChar(2)
97
- platform String? @db.VarChar(255)
98
- agent String? @db.Text
99
- expires_at DateTime @db.Timestamp(0)
100
- revoked_at DateTime? @db.Timestamp(0)
101
- created_at DateTime @default(now()) @db.Timestamp(0)
102
- updated_at DateTime? @db.Timestamp(0)
100
+ ```bash
101
+ npx prisma migrate dev --name add_auth
102
+ npx prisma generate
103
+ ```
103
104
 
104
- account user_accounts @relation(fields: [account_id], references: [id], onDelete: Cascade)
105
+ Create the database adapter:
105
106
 
106
- @@index([account_id])
107
- @@index([expires_at])
108
- @@index([revoked_at])
109
- }
107
+ ```ts
108
+ import { createPrismaAdapter } from "@gauts/auth/prisma";
109
+
110
+ import { prisma } from "./db.js";
111
+
112
+ export const authDb = createPrismaAdapter({
113
+ client: prisma,
114
+ });
110
115
  ```
111
116
 
112
- Create the migration through the application's Prisma workflow, then regenerate its client:
117
+ #### Option B Drizzle MySQL/MariaDB
118
+
119
+ Install Drizzle and the application's MySQL driver inside the API project:
113
120
 
114
121
  ```bash
115
- npx prisma migrate dev --name add_auth
116
- npx prisma generate
122
+ npm install drizzle-orm mysql2
123
+ npm install --save-dev drizzle-kit
124
+ ```
125
+
126
+ [View and copy the Drizzle MySQL/MariaDB schema](./src/adapters/drizzle/schema.ts) into the application.
127
+
128
+ Create and apply the migration through the application's Drizzle workflow, then create the database adapter:
129
+
130
+ ```ts
131
+ import { createDrizzleAdapter } from "@gauts/auth/drizzle";
132
+
133
+ import { db } from "./db.js";
134
+ import { accountSessions, userAccounts, users } from "./schema.js";
135
+
136
+ export const authDb = createDrizzleAdapter({
137
+ client: db,
138
+ models: {
139
+ accounts: { table: userAccounts },
140
+ sessions: { table: accountSessions },
141
+ users: { table: users },
142
+ },
143
+ });
117
144
  ```
118
145
 
119
146
  ### 3. Create the auth instance and routes
120
147
 
121
- Create the API auth instance:
148
+ This Hono example is identical for Prisma and Drizzle:
122
149
 
123
150
  ```ts
124
151
  import { createHonoAuth } from "@gauts/auth/hono";
125
- import { createPrismaAdapter } from "@gauts/auth/prisma";
126
152
 
127
- import { prisma } from "./db.js";
153
+ import { authDb } from "./authDb.js";
128
154
 
129
155
  export const auth = createHonoAuth({
130
- db: createPrismaAdapter({
131
- client: prisma,
132
- }),
156
+ db: authDb,
133
157
  });
134
158
  ```
135
159
 
@@ -202,6 +226,16 @@ app.get("/account", auth.requireSession, (c) => {
202
226
  });
203
227
  ```
204
228
 
229
+ The equivalent framework examples are available here:
230
+
231
+ | Framework | Simple example | Advanced example |
232
+ | --------- | --------------------------------------------------------------- | ------------------------------------------------------------------- |
233
+ | Hono | [`examples/hono/simple`](./examples/hono/simple/index.ts) | [`examples/hono/advanced`](./examples/hono/advanced/index.ts) |
234
+ | Express | [`examples/express/simple`](./examples/express/simple/index.ts) | [`examples/express/advanced`](./examples/express/advanced/index.ts) |
235
+ | Fastify | [`examples/fastify/simple`](./examples/fastify/simple/index.ts) | [`examples/fastify/advanced`](./examples/fastify/advanced/index.ts) |
236
+
237
+ Express exposes authenticated values through `response.locals`. Fastify exposes them through request decorators and requires one `auth.decorate(app)` call before routes are registered. All routes remain application-owned.
238
+
205
239
  When `storedHash` is missing, the package performs password work with the configured algorithm and always returns `false`. Applications do not need a dummy hash. Keep the response identical for unknown accounts and incorrect passwords.
206
240
 
207
241
  ### 4. Connect the Next.js frontend
@@ -221,7 +255,6 @@ Call it from the Next.js middleware (proxy.ts) on protected routes:
221
255
  ```ts
222
256
  import type { NextRequest } from "next/server";
223
257
  import { NextResponse } from "next/server";
224
-
225
258
  import { nextAuth } from "./lib/auth.js";
226
259
 
227
260
  export const proxy = async (request: NextRequest) => {
@@ -247,16 +280,22 @@ The application owns the redirect URL. When `unauthorizedUrl` is provided, the a
247
280
 
248
281
  - Node.js 22 or newer.
249
282
  - A database adapter.
283
+ - Drizzle ORM 0.45.2 or newer when using the Drizzle adapter.
250
284
  - Hono 4 when using the Hono adapter.
285
+ - Express 5 when using the Express adapter.
286
+ - Fastify 5 when using the Fastify adapter.
251
287
  - Next.js 15 or newer when using the Next.js adapter.
252
288
 
253
- `hono` and `next` are optional peer dependencies. The Prisma adapter receives the application's generated Prisma client and does not import Prisma at runtime.
289
+ `drizzle-orm`, `hono`, `express`, `fastify`, and `next` are optional peer dependencies. Installing or importing one adapter does not load the others. The Prisma adapter receives the application's generated Prisma client and does not import Prisma at runtime. The Drizzle adapter imports `drizzle-orm`, while the application owns the MySQL/MariaDB driver.
254
290
 
255
291
  | Import | Purpose |
256
292
  | ----------------------- | --------------------------------------------------------- |
257
293
  | `@gauts/auth` | Password service, session core, errors, and public types. |
294
+ | `@gauts/auth/drizzle` | Drizzle database adapter for MySQL and MariaDB. |
258
295
  | `@gauts/auth/prisma` | Prisma database adapter. |
259
296
  | `@gauts/auth/hono` | Hono cookies, methods, and middleware. |
297
+ | `@gauts/auth/express` | Express cookies, methods, and middleware. |
298
+ | `@gauts/auth/fastify` | Fastify cookies, methods, decorators, and hooks. |
260
299
  | `@gauts/auth/next` | Next.js renewal scheduling and `Set-Cookie` forwarding. |
261
300
  | `@gauts/auth/providers` | Google, GitHub, and X OAuth providers. |
262
301
 
@@ -281,6 +320,8 @@ type HonoGetIp = (c: Context) => Promise<string | null | undefined> | string | n
281
320
 
282
321
  When `getIp` is omitted, the adapter stores `ip: null` and does not read IP headers automatically. Configuring `session.validation` with `"ip"` requires `getIp` and fails during initialization when it is missing.
283
322
 
323
+ `createExpressAuth()` and `createFastifyAuth()` accept the same configuration. Their `getIp` callback receives the native Express or Fastify request instead of a Hono context.
324
+
284
325
  ### Password
285
326
 
286
327
  #### Argon2id
@@ -453,6 +494,8 @@ users
453
494
  └── account_sessions
454
495
  ```
455
496
 
497
+ [View and copy the required Prisma schema](./src/adapters/prisma/schema.prisma).
498
+
456
499
  The required default delegate names are `prisma.users`, `prisma.user_accounts`, and `prisma.account_sessions`. The fixed Prisma relation fields are:
457
500
 
458
501
  - `user_accounts.user`;
@@ -555,6 +598,76 @@ access: {
555
598
 
556
599
  Every configured account and user condition must match. Omitting `access` applies no application-specific account restriction.
557
600
 
601
+ ### Drizzle MySQL/MariaDB adapter
602
+
603
+ The Drizzle adapter supports MySQL and MariaDB. Install it inside the API project with the driver used by the application:
604
+
605
+ ```bash
606
+ npm install @gauts/auth drizzle-orm mysql2
607
+ ```
608
+
609
+ Unlike Prisma, Drizzle does not expose model delegates that can be discovered by name. Pass the application's table objects explicitly:
610
+
611
+ ```ts
612
+ import { createDrizzleAdapter } from "@gauts/auth/drizzle";
613
+ import { createHonoAuth } from "@gauts/auth/hono";
614
+ import { db } from "./db.js";
615
+ import { accountSessions, userAccounts, users } from "./schema.js";
616
+
617
+ export const auth = createHonoAuth({
618
+ db: createDrizzleAdapter({
619
+ client: db,
620
+ models: {
621
+ accounts: { table: userAccounts },
622
+ sessions: { table: accountSessions },
623
+ users: { table: users },
624
+ },
625
+ }),
626
+ });
627
+ ```
628
+
629
+ The minimum Drizzle schema uses the same relationship tree and canonical TypeScript field names as the Prisma adapter. [View and copy the required Drizzle MySQL/MariaDB schema](./src/adapters/drizzle/schema.ts).
630
+
631
+ The adapter queries these tables through explicit SQL joins, so Drizzle `relations()` declarations are not required. Physical SQL column names may use aliases, but the TypeScript keys shown above are part of the adapter contract. Date columns must use `{ mode: "date" }`.
632
+
633
+ `select` and `access` work exactly like the Prisma adapter and are inferred from the supplied table:
634
+
635
+ ```ts
636
+ const database = createDrizzleAdapter({
637
+ client: db,
638
+ models: {
639
+ accounts: {
640
+ access: {
641
+ role: ["OWNER", "ADMIN"],
642
+ status: ["ACTIVE"],
643
+ },
644
+ select: ["role", "status", "timezone"],
645
+ table: userAccounts,
646
+ },
647
+ sessions: { table: accountSessions },
648
+ users: {
649
+ access: { status: ["ACTIVE", "PENDING"] },
650
+ select: ["status"],
651
+ table: users,
652
+ },
653
+ },
654
+ });
655
+ ```
656
+
657
+ | Property | Required | Description |
658
+ | ------------------------ | :------: | ---------------------------------------------------------------------- |
659
+ | `client` | ✅ | Drizzle MySQL client created by the application. |
660
+ | `models.users.table` | ✅ | Table with `id` and `name` columns. |
661
+ | `models.users.select` | ❌ | Additional public scalar fields; `id` and `name` are always included. |
662
+ | `models.users.access` | ❌ | Required values for the owning user/entity. |
663
+ | `models.accounts.table` | ✅ | Table with `id`, `email`, and `user_id` columns. |
664
+ | `models.accounts.select` | ❌ | Additional public scalar fields; `id` and `email` are always included. |
665
+ | `models.accounts.access` | ❌ | Required values for the authenticating account. |
666
+ | `models.sessions.table` | ✅ | Table implementing the complete documented session column contract. |
667
+ | `models.socials.table` | ❌ | Enables social persistence when the optional social table is supplied. |
668
+
669
+ Private password fields are rejected from `select` and `access` by both TypeScript and runtime validation. The adapter does not load or execute the Prisma adapter, and Prisma is not required in a Drizzle application.
670
+
558
671
  ### Next.js adapter
559
672
 
560
673
  ```ts
@@ -657,7 +770,7 @@ type Session = {
657
770
  };
658
771
  ```
659
772
 
660
- The Prisma adapter refines `account` and `user` with the exact additional scalar fields declared in their respective `select` arrays.
773
+ The Prisma and Drizzle adapters refine `account` and `user` with the exact additional scalar fields declared in their respective `select` arrays.
661
774
 
662
775
  Only `account_id` is copied into the session row. Current account/user data is loaded through the fixed database relations and is never duplicated in the session table.
663
776
 
@@ -673,7 +786,7 @@ await auth.createSession({
673
786
  });
674
787
  ```
675
788
 
676
- `country` is normalized to uppercase and is never used for authentication or client matching. It is not resolved by the package and does not trigger GeoIP work during normal requests. When supplied, the configured session model must provide a nullable `country` column. When omitted, the Prisma adapter does not send the field.
789
+ `country` is normalized to uppercase and is never used for authentication or client matching. It is not resolved by the package and does not trigger GeoIP work during normal requests. When supplied, the configured session model must provide a nullable `country` column. When omitted, the database adapter does not send the field.
677
790
 
678
791
  ### Methods
679
792
 
@@ -689,11 +802,69 @@ await auth.createSession({
689
802
 
690
803
  `requireSession` authenticates only. Application-specific route permissions remain the application's responsibility.
691
804
 
805
+ ## Express adapter
806
+
807
+ ```ts
808
+ import { createExpressAuth, type ExpressAuthLocals } from "@gauts/auth/express";
809
+
810
+ const auth = createExpressAuth({ db });
811
+
812
+ app.get("/account", auth.requireSession, (_request, response) => {
813
+ const { account, session, user } = response.locals as ExpressAuthLocals;
814
+ response.json({ account, session, user });
815
+ });
816
+ ```
817
+
818
+ | Method | Purpose |
819
+ | ----------------------------------------------------------------- | ---------------------------------------------------- |
820
+ | `auth.createSession({ account_id, request, response, country? })` | Creates the DB session and writes cookies. |
821
+ | `auth.resolveSession({ request, response })` | Resolves the selected account and session. |
822
+ | `auth.renewSession({ request, response })` | Renews when due and writes authoritative cookies. |
823
+ | `auth.revokeSession({ request, response })` | Revokes the current session and clears cookies. |
824
+ | `auth.clearSession(response)` | Clears cookies without revoking the DB session. |
825
+ | `auth.getToken(request)` | Reads and validates the opaque session token. |
826
+ | `auth.requireSession` | Express middleware that populates `response.locals`. |
827
+
828
+ Express 5 forwards rejected async middleware promises to the application's error handler. The adapter does not install routes or an error handler.
829
+
830
+ ## Fastify adapter
831
+
832
+ Register the request decorators once before declaring routes:
833
+
834
+ ```ts
835
+ import { createFastifyAuth } from "@gauts/auth/fastify";
836
+
837
+ const auth = createFastifyAuth({ db });
838
+
839
+ auth.decorate(app);
840
+
841
+ app.get("/account", { preHandler: auth.requireSession }, (request) => ({
842
+ account: request.getDecorator("account"),
843
+ session: request.getDecorator("session"),
844
+ user: request.getDecorator("user"),
845
+ }));
846
+ ```
847
+
848
+ | Method | Purpose |
849
+ | -------------------------------------------------------------- | -------------------------------------------------------------- |
850
+ | `auth.decorate(app)` | Declares the native request decorators once at startup. |
851
+ | `auth.createSession({ account_id, request, reply, country? })` | Creates the DB session and writes cookies. |
852
+ | `auth.resolveSession({ request, reply })` | Resolves the selected account and session. |
853
+ | `auth.renewSession({ request, reply })` | Renews when due and writes authoritative cookies. |
854
+ | `auth.revokeSession({ request, reply })` | Revokes the current session and clears cookies. |
855
+ | `auth.clearSession(reply)` | Clears cookies without revoking the DB session. |
856
+ | `auth.getToken(request)` | Reads and validates the opaque session token. |
857
+ | `auth.requireSession` | Fastify `preHandler` that populates native request decorators. |
858
+
859
+ When social authentication is enabled, `auth.decorate(app)` also declares `social`. The adapter does not register a Fastify plugin or create routes.
860
+
692
861
  ## Social authentication
693
862
 
694
863
  Social authentication is an optional addon and remains disabled unless `social` is configured. Complete these steps only in applications that need Google, GitHub, or X authentication.
695
864
 
696
- ### 1. Add the social Prisma schema
865
+ ### 1. Add social persistence
866
+
867
+ #### Prisma
697
868
 
698
869
  Add the social relation inside the existing `user_accounts` model in the API schema:
699
870
 
@@ -745,6 +916,49 @@ const db = createPrismaAdapter({
745
916
  });
746
917
  ```
747
918
 
919
+ #### Drizzle MySQL/MariaDB
920
+
921
+ Add the provider table to the API schema:
922
+
923
+ ```ts
924
+ export const socialAccounts = mysqlTable(
925
+ "social_accounts",
926
+ {
927
+ account_id: varchar("account_id", { length: 255 })
928
+ .notNull()
929
+ .references(() => userAccounts.id, { onDelete: "cascade" }),
930
+ created_at: timestamp("created_at", { mode: "date" }).defaultNow().notNull(),
931
+ id: varchar("id", { length: 255 }).primaryKey(),
932
+ provider: varchar("provider", { length: 32 }).notNull(),
933
+ provider_id: varchar("provider_id", { length: 255 }).notNull(),
934
+ },
935
+ (table) => [
936
+ index("social_accounts_account_id_idx").on(table.account_id),
937
+ uniqueIndex("social_accounts_provider_provider_id_key").on(
938
+ table.provider,
939
+ table.provider_id,
940
+ ),
941
+ uniqueIndex("social_accounts_account_id_provider_key").on(table.account_id, table.provider),
942
+ ],
943
+ );
944
+ ```
945
+
946
+ Then supply it to the adapter:
947
+
948
+ ```ts
949
+ const db = createDrizzleAdapter({
950
+ client,
951
+ models: {
952
+ accounts: { table: userAccounts },
953
+ sessions: { table: accountSessions },
954
+ socials: { table: socialAccounts },
955
+ users: { table: users },
956
+ },
957
+ });
958
+ ```
959
+
960
+ Omitting `models.socials` keeps the Drizzle adapter session-only. The adapter creates the owning user and account in one transaction during default social registration, so that path requires a Drizzle MySQL driver with transaction support. Additional required user/account columns must have database defaults; otherwise the application must provide `registration.createAccount`.
961
+
748
962
  ### 2. Configure the providers
749
963
 
750
964
  Import only the providers used by the API:
@@ -783,7 +997,7 @@ Register every `callbackUrl` shown above in the corresponding provider dashboard
783
997
 
784
998
  ### 3. Add the API route and frontend start
785
999
 
786
- Declare one dynamic API route covering every configured provider. `social.handle` is Hono middleware: it completes `start` and expected error responses itself, then calls the application handler only after a successful callback.
1000
+ Declare one dynamic API route covering every configured provider. `social.handle` completes `start` and expected error responses itself, then continues to the application handler only after a successful callback.
787
1001
 
788
1002
  ```ts
789
1003
  app.get("/auth/social/:provider/:action", auth.social.handle, async (c) => {
@@ -827,16 +1041,28 @@ social.registered;
827
1041
  social.returnTo;
828
1042
  ```
829
1043
 
1044
+ The native equivalents are:
1045
+
1046
+ ```ts
1047
+ // Express
1048
+ const social = (response.locals as ExpressSocialLocals).social;
1049
+
1050
+ // Fastify
1051
+ const social = request.getDecorator<SocialAuthenticated>("social");
1052
+ ```
1053
+
1054
+ See the advanced framework examples for complete social routes and custom registration.
1055
+
830
1056
  The package does not create the application route, session, notifications, logs, or final success response. Those remain explicit in the route handler.
831
1057
 
832
1058
  ### Social configuration
833
1059
 
834
- | Property | Type / allowed values | Required | Default | Description |
835
- | ---------------------------- | ------------------------------------ | :---------: | --------- | -------------------------------------------------------------------------- |
836
- | `social.providers` | `SocialProvider[]` | | — | Configured Google, GitHub, or X providers. |
837
- | `social.cookieName` | Valid cookie name | | `"__soc"` | Signed temporary OAuth/registration transaction cookie. |
838
- | `social.registration` | `SocialRegistrationConfig` | | Disabled | Enables default or application-specific social registration. |
839
- | `registration.createAccount` | Async callback returning `accountId` | | Built-in | Creates required business data when the default structure is insufficient. |
1060
+ | Property | Type / allowed values | Required | Default | Description |
1061
+ | ---------------------------- | ------------------------------------ | :------: | --------- | -------------------------------------------------------------------------- |
1062
+ | `social.providers` | `SocialProvider[]` | | — | Configured Google, GitHub, or X providers. |
1063
+ | `social.cookieName` | Valid cookie name | | `"__soc"` | Signed temporary OAuth/registration transaction cookie. |
1064
+ | `social.registration` | `SocialRegistrationConfig` | | Disabled | Enables default or application-specific social registration. |
1065
+ | `registration.createAccount` | Async callback returning `accountId` | | Built-in | Creates required business data when the default structure is insufficient. |
840
1066
 
841
1067
  Provider configuration:
842
1068
 
@@ -952,7 +1178,7 @@ app.post("/auth/register/social", async (c) => {
952
1178
 
953
1179
  ### Core and adapter composition
954
1180
 
955
- `createHonoAuth()` is the normal entry point. Use separate composition only when the same core instance is required outside Hono:
1181
+ Use the entry point matching the application framework: `createHonoAuth()`, `createExpressAuth()`, or `createFastifyAuth()`. Use separate composition only when the same core instance is required outside the framework adapter:
956
1182
 
957
1183
  ```ts
958
1184
  import { createAuth } from "@gauts/auth";
@@ -1074,7 +1300,7 @@ const socialDb = {
1074
1300
  } satisfies SocialDbAdapter;
1075
1301
  ```
1076
1302
 
1077
- The Prisma adapter already implements both `DbAdapter` and `SocialDbAdapter`.
1303
+ The Prisma and Drizzle adapters implement both `DbAdapter` and `SocialDbAdapter` when their optional social model is available.
1078
1304
 
1079
1305
  ## Performance
1080
1306
 
@@ -0,0 +1,11 @@
1
+ import type { AnyMySqlTable } from "drizzle-orm/mysql-core";
2
+ import type { ResolvedDrizzleModels } from "./types.js";
3
+ export declare const DRIZZLE_FIELDS: {
4
+ readonly accounts: readonly ["id", "email", "user_id"];
5
+ readonly sessions: readonly ["account_id", "agent", "country", "created_at", "expires_at", "id", "ip", "platform", "revoked_at", "token_hash", "updated_at"];
6
+ readonly socials: readonly ["account_id", "created_at", "id", "provider", "provider_id"];
7
+ readonly users: readonly ["id", "name"];
8
+ };
9
+ export declare const resolveDrizzleModels: (input: unknown) => ResolvedDrizzleModels;
10
+ export declare const getDrizzleSource: (table: AnyMySqlTable) => string;
11
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/adapters/drizzle/config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAK5D,OAAO,KAAK,EAA4B,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAkClF,eAAO,MAAM,cAAc;;;;;CAiBjB,CAAC;AA+HX,eAAO,MAAM,oBAAoB,GAAI,OAAO,OAAO,KAAG,qBAmCrD,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,OAAO,aAAa,KAAG,MAEvD,CAAC"}