kroxt 1.1.5 → 1.2.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.
package/README.md CHANGED
@@ -1,221 +1,177 @@
1
- # kroxt
2
-
3
- A framework-agnostic, modular authentication engine for modern TypeScript applications. Built for security, extensibility, and ease of use.
4
-
5
- ## Features
6
-
7
- - 🔐 **Secure Hashing**: Powered by `argon2` for industry-standard password security.
8
- - 🎟️ **Dual-Token Sessions**: Native support for Access and Refresh tokens via `jose`.
9
- - 🧩 **JWT Customization**: Fully extensible payload with support for custom user fields and `sub` override.
10
- - 🌍 **OAuth Ready**: Built-in support for GitHub and Google OAuth via `arctic`.
11
- - 🔌 **Built-in Adapters**: Native, one-line support for **MongoDB (Mongoose)** and **In-Memory** stores.
12
- - 🧩 **Database Agnostic**: Use Prisma, Drizzle, or any store via the generic `AuthAdapter` pattern.
13
- - 🌶️ **Password Peppering**: Server-side pepper support for enhanced hash protection.
14
- - 🛡️ **Timing Attack Protection**: Built-in safeguards against side-channel analysis during login.
15
- - **Zod Schema Support**: Perfectly preserves and types your user metadata.
16
- - 🌍 **Dual ESM/CJS Support**: Native support for both modern ESM (`import`) and CommonJS (`require`).
17
-
18
- ## Installation
19
-
20
- ```bash
21
- npm install kroxt
22
- ```
23
-
24
- ---
25
-
26
- ## Guide: Full Authentication Flow
27
-
28
- This guide walks you through setting up Kroxt from scratch in your application.
29
-
30
- ### Step 1: Define your User
31
-
32
- First, define what a User looks like in your system. Kroxt allows any additional fields (like `role`, `schoolId`, etc.) which you can later sign into your JWTs.
33
-
34
- ```typescript
35
- export interface MyUser {
36
- id: string;
37
- email: string;
38
- passwordHash: string;
39
- role: 'admin' | 'user';
40
- schoolId: string; // Custom field for enterprise/multi-tenant apps
41
- oauthProvider?: string; // Support for OAuth (e.g., 'github')
42
- oauthId?: string; // Unique ID from the provider
43
- name: string;
44
- }
45
- ```
46
-
47
- ### Step 2: Choose an Adapter
48
-
49
- Kroxt provides built-in adapters for popular databases. For MongoDB, simply pass your Mongoose model to `createMongoAdapter`.
50
-
51
- ```typescript
52
- import { createMongoAdapter } from "kroxt/adapters/mongoose";
53
- import { User } from "./models/user.model.js"; // Your Mongoose model
54
-
55
- // One line to connect your DB
56
- export const authAdapter = createMongoAdapter(User);
57
- ```
58
-
59
- > [!TIP]
60
- > Need to use Prisma, Drizzle, or a custom API? You can still build a [Custom Adapter](#custom-adapters).
61
-
62
- ### Step 3: Initialize the Auth Engine
63
-
64
- Configure Kroxt with your adapter and security settings.
65
-
66
- ```typescript
67
- import { createAuth } from "kroxt/core";
68
- import { authAdapter } from "./auth.js";
69
-
70
- export const auth = createAuth({
71
- adapter: authAdapter,
72
- secret: process.env.AUTH_SECRET, // High-entropy secret for JWT signing
73
- pepper: process.env.AUTH_PEPPER, // Optional: Server-side pepper for password hashing
74
- session: {
75
- expires: "15m", // Access token duration
76
- refreshExpires: "7d" // Refresh token duration
77
- },
78
- jwt: {
79
- /**
80
- * Optional: Fully customize the JWT payload or add extra fields.
81
- */
82
- payload: (user, type) => {
83
- // Only add extra details to 'access' tokens to keep 'refresh' tokens light.
84
- if (type === "access") {
85
- return {
86
- schoolId: user.schoolId, // Add custom user detail
87
- role: user.role, // Explicitly include role
88
- };
89
- }
90
- return {}; // Refresh tokens stay minimal
91
- }
92
- }
93
- });
94
- ```
95
-
96
- ### Step 4: Implement Controllers & Routes
97
-
98
- Use the engine in your application logic. Examples below use an Express-like structure.
99
-
100
- #### Registration
101
- ```typescript
102
- app.post("/register", async (req, res) => {
103
- const { name, email, password, ...extraFields } = req.body;
104
-
105
- // Kroxt handles argon2 hashing (with pepper) and token generation
106
- const { user, accessToken, refreshToken } = await auth.signup({
107
- name,
108
- email,
109
- ...extraFields
110
- }, password);
111
-
112
- res.json({ user, accessToken, refreshToken });
113
- });
114
- ```
115
-
116
- #### Login
117
- ```typescript
118
- app.post("/login", async (req, res) => {
119
- const { email, password } = req.body;
120
-
121
- // Kroxt verifies password (timing-attack safe) and returns tokens
122
- const { user, accessToken, refreshToken } = await auth.loginWithPassword(email, password);
123
-
124
- res.json({ user, accessToken, refreshToken });
125
- });
126
- ```
127
-
128
- #### Token Refresh
129
- Keep users logged in by rotating access tokens using a valid refresh token.
130
- ```typescript
131
- app.post("/refresh", async (req, res) => {
132
- const { refreshToken } = req.body;
133
-
134
- // Returns a fresh access token
135
- const { accessToken } = await auth.refresh(refreshToken);
136
-
137
- res.json({ accessToken });
138
- });
139
- ```
140
-
141
- #### Protecting Routes (Middleware)
142
- ```typescript
143
- app.get("/me", async (req, res) => {
144
- const token = req.headers.authorization?.split(" ")[1];
145
-
146
- // Verify the JWT and get the payload { sub: string, role: string, ... }
147
- const payload = await auth.verifyToken(token, "access");
148
-
149
- if (!payload) return res.status(401).send("Unauthorized");
150
-
151
- const user = await myAdapter.findUserById(payload.sub);
152
- res.json(user);
153
- });
154
- ```
155
-
156
- ---
157
-
158
- ## Custom Adapters
159
-
160
- Kroxt's true power lies in its database-agnostic design. If you aren't using a built-in adapter, simply implement the `AuthAdapter` interface.
161
-
162
- ```typescript
163
- import type { AuthAdapter, User } from "kroxt/adapters";
164
- import { db } from "./db.js";
165
-
166
- // Example using a generic DB client
167
- export const myCustomAdapter: AuthAdapter<MyUser> = {
168
- createUser: async (data) => {
169
- const user = await db.users.insert(data);
170
- return { ...user, id: user.id.toString() };
171
- },
172
- findUserByEmail: async (email) => {
173
- return await db.users.findFirst({ where: { email } });
174
- },
175
- findUserById: async (id) => {
176
- return await db.users.findUnique({ where: { id } });
177
- },
178
- linkOAuthAccount: async (id, provider, providerId) => {
179
- await db.users.update({
180
- where: { id },
181
- data: { oauthProvider: provider, oauthId: providerId }
182
- });
183
- }
184
- };
185
- ```
186
-
187
- Using this pattern, you can connect Kroxt to **Supabase**, **Firestore**, **PostgreSQL**, or even a 3rd-party API.
188
-
189
- ## Security Best Practices
190
-
191
- ### 1. Password Peppering
192
- Always use a `pepper` in production. It's a server-side secret added to passwords before hashing. If your database is leaked, the hashes cannot be cracked without this pepper.
193
-
194
- ### 2. CSRF Protection
195
- Kroxt provides helpers for the double-submit cookie pattern. Use these if you are storing tokens in cookies.
196
-
197
- ```typescript
198
- import { generateCsrfToken, verifyCsrf } from "kroxt/security";
199
-
200
- const token = generateCsrfToken();
201
- const isValid = verifyCsrf(tokenInRequest, tokenInCookie);
202
- ```
203
-
204
- ### 3. Secure Cookies
205
- If using cookies, always set these flags:
206
- - `httpOnly: true` (Prevents XSS)
207
- - `secure: true` (Requires HTTPS)
208
- - `sameSite: 'strict'` (Prevents CSRF)
209
-
210
- ### 4. Rate Limiting
211
- Implement rate limiting (e.g., `express-rate-limit`) on `/login` and `/register` to block brute-force attempts.
212
-
213
- ---
214
-
215
- ## Reference Project
216
-
217
- Check out the `kroxt-example` folder or the [GitHub repository](https://github.com/adepoju-oluwatobi/kroxt-example) for a complete **Express + MongoDB** implementation using this library.
218
-
219
- ## License
220
-
221
- MIT
1
+ # kroxt 🔐
2
+
3
+ A framework-agnostic, modular authentication engine for modern TypeScript applications. Built for security, extensibility, and pure developer joy.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/kroxt.svg)](https://www.npmjs.com/package/kroxt)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ ## 🚀 Why Kroxt?
9
+
10
+ Authentication is often either too complex (Passport, Auth.js) or too restrictive. Kroxt is the **"Headless" Auth Engine** that gives you the best of both worlds:
11
+
12
+ - 🏗️ **Database Agnostic**: Native adapters for **Prisma**, **Drizzle**, and **Mongoose**.
13
+ - 🛠️ **Modular**: Use only what you need. No forced session managers or UI components.
14
+ - 🔐 **Security First**: Argon2 hashing, dual-token rotation, and timing-attack protection built-in.
15
+ - 🧩 **TypeScript Native**: Perfectly preserves your user schemas and metadata.
16
+
17
+ ---
18
+
19
+ ## 🗺️ How it Works
20
+
21
+ Kroxt sits between your database and your controller logic. It handles the "heavy lifting" (hashing, JWT signing, token rotation) while you maintain full control over your API.
22
+
23
+ ```mermaid
24
+ graph LR
25
+ A[Client] -- "Credentials" --> B[Express/Fastify]
26
+ B -- "auth.signup()" --> C[Kroxt Engine]
27
+ C -- "Save User" --> D[(Database Adapter)]
28
+ D -- "Success" --> C
29
+ C -- "Tokens + User" --> B
30
+ B -- "Set Cookies/JSON" --> A
31
+
32
+ subgraph Adapters
33
+ D
34
+ E[Mongoose]
35
+ F[Drizzle]
36
+ G[Prisma]
37
+ end
38
+ ```
39
+
40
+ ---
41
+
42
+ ## 🏁 Quick Start (5 Minutes)
43
+
44
+ ### 1. Installation
45
+
46
+ ```bash
47
+ npm install kroxt
48
+ ```
49
+
50
+ ### 2. Choose Your Adapter
51
+
52
+ Kroxt provides official adapters for the most popular ORMs.
53
+
54
+ #### **Option A: Drizzle (SQLite/PG/MySQL)**
55
+ ```typescript
56
+ import { createDrizzleAdapter } from "kroxt/adapters/drizzle";
57
+ import { db } from "./db";
58
+ import { users } from "./schema";
59
+ import { eq } from "drizzle-orm";
60
+
61
+ export const adapter = createDrizzleAdapter(db, users, eq);
62
+ ```
63
+
64
+ #### **Option B: Prisma**
65
+ ```typescript
66
+ import { createPrismaAdapter } from "kroxt/adapters/prisma";
67
+ import { prisma } from "./db";
68
+
69
+ export const adapter = createPrismaAdapter(prisma.user);
70
+ ```
71
+
72
+ #### **Option C: Mongoose**
73
+ ```typescript
74
+ import { createMongoAdapter } from "kroxt/adapters/mongoose";
75
+ import { User } from "./models/user.model";
76
+
77
+ export const adapter = createMongoAdapter(User);
78
+ ```
79
+
80
+ ### 3. Initialize the Engine
81
+
82
+ ```typescript
83
+ import { createAuth } from "kroxt/core";
84
+ import { adapter } from "./auth-adapter";
85
+
86
+ export const auth = createAuth({
87
+ adapter,
88
+ secret: process.env.JWT_SECRET,
89
+ session: {
90
+ expires: "15m",
91
+ refreshExpires: "7d"
92
+ }
93
+ });
94
+ ```
95
+
96
+ ---
97
+
98
+ ## 🛡️ Core Authentication Flows
99
+
100
+ ### **Registration**
101
+ ```typescript
102
+ const { user, accessToken, refreshToken } = await auth.signup({
103
+ email,
104
+ name,
105
+ role: 'user'
106
+ }, password);
107
+ ```
108
+
109
+ ### **Login**
110
+ ```typescript
111
+ const { user, accessToken, refreshToken } = await auth.loginWithPassword(email, password);
112
+ ```
113
+
114
+ ### **Token Refresh**
115
+ ```typescript
116
+ const { accessToken } = await auth.refresh(refreshToken);
117
+ ```
118
+
119
+ ---
120
+
121
+ ## 🐣 Beginner Corner: What is "Headless"?
122
+
123
+ If you're new to backend development, "Headless" means Kroxt **doesn't provide a UI** (no login buttons or pre-made forms). Instead, it provides the **engine** (the logic).
124
+
125
+ **Why is this good?**
126
+ It means you can build your own login screen in React, Vue, or even a Mobile App, and Kroxt will handle the security part on the server exactly the same way every time.
127
+
128
+ ---
129
+
130
+ ## 🛠️ Advanced: Custom JWT Payloads
131
+
132
+ Want to share a user's `role` or `plan` with the frontend via the JWT? Use the `payload` hook:
133
+
134
+ ```typescript
135
+ export const auth = createAuth({
136
+ adapter,
137
+ jwt: {
138
+ payload: (user, type) => {
139
+ if (type === "access") {
140
+ return {
141
+ role: user.role,
142
+ tier: user.subscriptionTier
143
+ };
144
+ }
145
+ return {}; // Keep refresh tokens small
146
+ }
147
+ }
148
+ });
149
+ ```
150
+
151
+ ---
152
+
153
+ ## 🛑 Common v1.2.0 Troubleshooting
154
+
155
+ ### "Cannot find module '.prisma/client/default.js'" (ESM on Windows)
156
+ If you're using Prisma with ESM (`"type": "module"`) on Windows, you may need a robust import in your `src/db/index.ts`:
157
+
158
+ ```typescript
159
+ import { createRequire } from "module";
160
+ const require = createRequire(import.meta.url);
161
+ const { PrismaClient } = require("@prisma/client");
162
+ ```
163
+
164
+ ### Prisma "Unknown argument `name`"
165
+ Prisma is strict about schemas. If you're sending extra fields in `auth.signup()`, ensure your `schema.prisma` includes them (marked as `?` optional if needed).
166
+
167
+ ---
168
+
169
+ ## 🔗 Reference Project
170
+
171
+ Complete working implementations:
172
+ - [Express + Drizzle + SQLite](https://github.com/adepoju-oluwatobi/kroxt-example)
173
+ - [Express + Mongoose](https://github.com/adepoju-oluwatobi/kroxt-example-cjs)
174
+
175
+ ## 📄 License
176
+
177
+ MIT © [Adepoju Oluwatobi](https://github.com/adepoju-oluwatobi)
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var drizzle_exports = {};
20
+ __export(drizzle_exports, {
21
+ createDrizzleAdapter: () => createDrizzleAdapter
22
+ });
23
+ module.exports = __toCommonJS(drizzle_exports);
24
+ function createDrizzleAdapter(db, table, eq) {
25
+ return {
26
+ async createUser(data) {
27
+ const dataToSave = { id: data.id || globalThis.crypto.randomUUID(), ...data };
28
+ const results = await db.insert(table).values(dataToSave).returning();
29
+ return results[0];
30
+ },
31
+ async findUserByEmail(email) {
32
+ const results = await db.select().from(table).where(eq(table.email, email)).limit(1);
33
+ return results[0] || null;
34
+ },
35
+ async findUserById(id) {
36
+ const results = await db.select().from(table).where(eq(table.id, id)).limit(1);
37
+ return results[0] || null;
38
+ },
39
+ async linkOAuthAccount(userId, provider, providerId) {
40
+ await db.update(table).set({
41
+ oauthProvider: provider,
42
+ oauthId: providerId
43
+ }).where(eq(table.id, userId));
44
+ }
45
+ };
46
+ }
47
+ // Annotate the CommonJS export names for ESM import in node:
48
+ 0 && (module.exports = {
49
+ createDrizzleAdapter
50
+ });
51
+ //# sourceMappingURL=drizzle.cjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/auth/adapters/drizzle.ts"],
4
+ "sourcesContent": ["import type { AuthAdapter, User } from \"./index.js\";\n\n/**\n * Creates a Drizzle ORM adapter.\n * \n * Works with any Drizzle-supported database (PostgreSQL, MySQL, SQLite)\n * by using the standard drizzle-orm `db` instance and table definition.\n * \n * @param db - The Drizzle database instance.\n * @param table - The Drizzle table representing users.\n * @param eq - The Drizzle `eq` operator (imported from `drizzle-orm`).\n * @returns An AuthAdapter compliant object.\n */\nexport function createDrizzleAdapter<TUser extends User = User>(\n db: any,\n table: any,\n eq: any\n): AuthAdapter<TUser> {\n return {\n async createUser(data: any) {\n const dataToSave = { id: data.id || globalThis.crypto.randomUUID(), ...data };\n const results = await db.insert(table).values(dataToSave).returning();\n return results[0] as TUser;\n },\n\n async findUserByEmail(email: string) {\n const results = await db.select().from(table).where(eq(table.email, email)).limit(1);\n return (results[0] || null) as TUser | null;\n },\n\n async findUserById(id: string) {\n const results = await db.select().from(table).where(eq(table.id, id)).limit(1);\n return (results[0] || null) as TUser | null;\n },\n\n async linkOAuthAccount(userId: string, provider: string, providerId: string) {\n await db.update(table)\n .set({\n oauthProvider: provider,\n oauthId: providerId,\n })\n .where(eq(table.id, userId));\n },\n };\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAaO,SAAS,qBACd,IACA,OACA,IACoB;AACpB,SAAO;AAAA,IACL,MAAM,WAAW,MAAW;AAC1B,YAAM,aAAa,EAAE,IAAI,KAAK,MAAM,WAAW,OAAO,WAAW,GAAG,GAAG,KAAK;AAC5E,YAAM,UAAU,MAAM,GAAG,OAAO,KAAK,EAAE,OAAO,UAAU,EAAE,UAAU;AACpE,aAAO,QAAQ,CAAC;AAAA,IAClB;AAAA,IAEA,MAAM,gBAAgB,OAAe;AACnC,YAAM,UAAU,MAAM,GAAG,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,GAAG,MAAM,OAAO,KAAK,CAAC,EAAE,MAAM,CAAC;AACnF,aAAQ,QAAQ,CAAC,KAAK;AAAA,IACxB;AAAA,IAEA,MAAM,aAAa,IAAY;AAC7B,YAAM,UAAU,MAAM,GAAG,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,GAAG,MAAM,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC;AAC7E,aAAQ,QAAQ,CAAC,KAAK;AAAA,IACxB;AAAA,IAEA,MAAM,iBAAiB,QAAgB,UAAkB,YAAoB;AAC3E,YAAM,GAAG,OAAO,KAAK,EAClB,IAAI;AAAA,QACH,eAAe;AAAA,QACf,SAAS;AAAA,MACX,CAAC,EACA,MAAM,GAAG,MAAM,IAAI,MAAM,CAAC;AAAA,IAC/B;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,14 @@
1
+ import type { AuthAdapter, User } from "./index.js";
2
+ /**
3
+ * Creates a Drizzle ORM adapter.
4
+ *
5
+ * Works with any Drizzle-supported database (PostgreSQL, MySQL, SQLite)
6
+ * by using the standard drizzle-orm `db` instance and table definition.
7
+ *
8
+ * @param db - The Drizzle database instance.
9
+ * @param table - The Drizzle table representing users.
10
+ * @param eq - The Drizzle `eq` operator (imported from `drizzle-orm`).
11
+ * @returns An AuthAdapter compliant object.
12
+ */
13
+ export declare function createDrizzleAdapter<TUser extends User = User>(db: any, table: any, eq: any): AuthAdapter<TUser>;
14
+ //# sourceMappingURL=drizzle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drizzle.d.ts","sourceRoot":"","sources":["../../src/auth/adapters/drizzle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEpD;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,SAAS,IAAI,GAAG,IAAI,EAC5D,EAAE,EAAE,GAAG,EACP,KAAK,EAAE,GAAG,EACV,EAAE,EAAE,GAAG,GACN,WAAW,CAAC,KAAK,CAAC,CA2BpB"}
@@ -0,0 +1,27 @@
1
+ function createDrizzleAdapter(db, table, eq) {
2
+ return {
3
+ async createUser(data) {
4
+ const dataToSave = { id: data.id || globalThis.crypto.randomUUID(), ...data };
5
+ const results = await db.insert(table).values(dataToSave).returning();
6
+ return results[0];
7
+ },
8
+ async findUserByEmail(email) {
9
+ const results = await db.select().from(table).where(eq(table.email, email)).limit(1);
10
+ return results[0] || null;
11
+ },
12
+ async findUserById(id) {
13
+ const results = await db.select().from(table).where(eq(table.id, id)).limit(1);
14
+ return results[0] || null;
15
+ },
16
+ async linkOAuthAccount(userId, provider, providerId) {
17
+ await db.update(table).set({
18
+ oauthProvider: provider,
19
+ oauthId: providerId
20
+ }).where(eq(table.id, userId));
21
+ }
22
+ };
23
+ }
24
+ export {
25
+ createDrizzleAdapter
26
+ };
27
+ //# sourceMappingURL=drizzle.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/auth/adapters/drizzle.ts"],
4
+ "sourcesContent": ["import type { AuthAdapter, User } from \"./index.js\";\n\n/**\n * Creates a Drizzle ORM adapter.\n * \n * Works with any Drizzle-supported database (PostgreSQL, MySQL, SQLite)\n * by using the standard drizzle-orm `db` instance and table definition.\n * \n * @param db - The Drizzle database instance.\n * @param table - The Drizzle table representing users.\n * @param eq - The Drizzle `eq` operator (imported from `drizzle-orm`).\n * @returns An AuthAdapter compliant object.\n */\nexport function createDrizzleAdapter<TUser extends User = User>(\n db: any,\n table: any,\n eq: any\n): AuthAdapter<TUser> {\n return {\n async createUser(data: any) {\n const dataToSave = { id: data.id || globalThis.crypto.randomUUID(), ...data };\n const results = await db.insert(table).values(dataToSave).returning();\n return results[0] as TUser;\n },\n\n async findUserByEmail(email: string) {\n const results = await db.select().from(table).where(eq(table.email, email)).limit(1);\n return (results[0] || null) as TUser | null;\n },\n\n async findUserById(id: string) {\n const results = await db.select().from(table).where(eq(table.id, id)).limit(1);\n return (results[0] || null) as TUser | null;\n },\n\n async linkOAuthAccount(userId: string, provider: string, providerId: string) {\n await db.update(table)\n .set({\n oauthProvider: provider,\n oauthId: providerId,\n })\n .where(eq(table.id, userId));\n },\n };\n}\n"],
5
+ "mappings": "AAaO,SAAS,qBACd,IACA,OACA,IACoB;AACpB,SAAO;AAAA,IACL,MAAM,WAAW,MAAW;AAC1B,YAAM,aAAa,EAAE,IAAI,KAAK,MAAM,WAAW,OAAO,WAAW,GAAG,GAAG,KAAK;AAC5E,YAAM,UAAU,MAAM,GAAG,OAAO,KAAK,EAAE,OAAO,UAAU,EAAE,UAAU;AACpE,aAAO,QAAQ,CAAC;AAAA,IAClB;AAAA,IAEA,MAAM,gBAAgB,OAAe;AACnC,YAAM,UAAU,MAAM,GAAG,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,GAAG,MAAM,OAAO,KAAK,CAAC,EAAE,MAAM,CAAC;AACnF,aAAQ,QAAQ,CAAC,KAAK;AAAA,IACxB;AAAA,IAEA,MAAM,aAAa,IAAY;AAC7B,YAAM,UAAU,MAAM,GAAG,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,GAAG,MAAM,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC;AAC7E,aAAQ,QAAQ,CAAC,KAAK;AAAA,IACxB;AAAA,IAEA,MAAM,iBAAiB,QAAgB,UAAkB,YAAoB;AAC3E,YAAM,GAAG,OAAO,KAAK,EAClB,IAAI;AAAA,QACH,eAAe;AAAA,QACf,SAAS;AAAA,MACX,CAAC,EACA,MAAM,GAAG,MAAM,IAAI,MAAM,CAAC;AAAA,IAC/B;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var prisma_exports = {};
20
+ __export(prisma_exports, {
21
+ createPrismaAdapter: () => createPrismaAdapter
22
+ });
23
+ module.exports = __toCommonJS(prisma_exports);
24
+ function createPrismaAdapter(model) {
25
+ return {
26
+ async createUser(data) {
27
+ const dataToSave = { id: data.id || globalThis.crypto.randomUUID(), ...data };
28
+ const user = await model.create({ data: dataToSave });
29
+ return user;
30
+ },
31
+ async findUserByEmail(email) {
32
+ const user = await model.findUnique({
33
+ where: { email }
34
+ });
35
+ return user;
36
+ },
37
+ async findUserById(id) {
38
+ const user = await model.findUnique({
39
+ where: { id }
40
+ });
41
+ return user;
42
+ },
43
+ async linkOAuthAccount(userId, provider, providerId) {
44
+ await model.update({
45
+ where: { id: userId },
46
+ data: {
47
+ oauthProvider: provider,
48
+ oauthId: providerId
49
+ }
50
+ });
51
+ }
52
+ };
53
+ }
54
+ // Annotate the CommonJS export names for ESM import in node:
55
+ 0 && (module.exports = {
56
+ createPrismaAdapter
57
+ });
58
+ //# sourceMappingURL=prisma.cjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/auth/adapters/prisma.ts"],
4
+ "sourcesContent": ["import type { AuthAdapter, User } from \"./index.js\";\n\n/**\n * Creates a Prisma adapter using a Prisma delegate (e.g., prisma.user).\n * \n * Works with any Prisma-supported database by using the standard\n * Prisma delegate operations (findUnique, create, update).\n * \n * @param model - A Prisma delegate instance (e.g., prisma.user).\n * @returns An AuthAdapter compliant object.\n */\nexport function createPrismaAdapter<TUser extends User = User>(model: any): AuthAdapter<TUser> {\n return {\n async createUser(data: any) {\n const dataToSave = { id: data.id || globalThis.crypto.randomUUID(), ...data };\n const user = await model.create({ data: dataToSave });\n return user as TUser;\n },\n\n async findUserByEmail(email: string) {\n const user = await model.findUnique({\n where: { email },\n });\n return user as TUser | null;\n },\n\n async findUserById(id: string) {\n const user = await model.findUnique({\n where: { id },\n });\n return user as TUser | null;\n },\n\n async linkOAuthAccount(userId: string, provider: string, providerId: string) {\n await model.update({\n where: { id: userId },\n data: {\n oauthProvider: provider,\n oauthId: providerId,\n },\n });\n },\n };\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAWO,SAAS,oBAA+C,OAAgC;AAC7F,SAAO;AAAA,IACL,MAAM,WAAW,MAAW;AAC1B,YAAM,aAAa,EAAE,IAAI,KAAK,MAAM,WAAW,OAAO,WAAW,GAAG,GAAG,KAAK;AAC5E,YAAM,OAAO,MAAM,MAAM,OAAO,EAAE,MAAM,WAAW,CAAC;AACpD,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,gBAAgB,OAAe;AACnC,YAAM,OAAO,MAAM,MAAM,WAAW;AAAA,QAClC,OAAO,EAAE,MAAM;AAAA,MACjB,CAAC;AACD,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,aAAa,IAAY;AAC7B,YAAM,OAAO,MAAM,MAAM,WAAW;AAAA,QAClC,OAAO,EAAE,GAAG;AAAA,MACd,CAAC;AACD,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,iBAAiB,QAAgB,UAAkB,YAAoB;AAC3E,YAAM,MAAM,OAAO;AAAA,QACjB,OAAO,EAAE,IAAI,OAAO;AAAA,QACpB,MAAM;AAAA,UACJ,eAAe;AAAA,UACf,SAAS;AAAA,QACX;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,12 @@
1
+ import type { AuthAdapter, User } from "./index.js";
2
+ /**
3
+ * Creates a Prisma adapter using a Prisma delegate (e.g., prisma.user).
4
+ *
5
+ * Works with any Prisma-supported database by using the standard
6
+ * Prisma delegate operations (findUnique, create, update).
7
+ *
8
+ * @param model - A Prisma delegate instance (e.g., prisma.user).
9
+ * @returns An AuthAdapter compliant object.
10
+ */
11
+ export declare function createPrismaAdapter<TUser extends User = User>(model: any): AuthAdapter<TUser>;
12
+ //# sourceMappingURL=prisma.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prisma.d.ts","sourceRoot":"","sources":["../../src/auth/adapters/prisma.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEpD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,SAAS,IAAI,GAAG,IAAI,EAAE,KAAK,EAAE,GAAG,GAAG,WAAW,CAAC,KAAK,CAAC,CAgC7F"}
@@ -0,0 +1,34 @@
1
+ function createPrismaAdapter(model) {
2
+ return {
3
+ async createUser(data) {
4
+ const dataToSave = { id: data.id || globalThis.crypto.randomUUID(), ...data };
5
+ const user = await model.create({ data: dataToSave });
6
+ return user;
7
+ },
8
+ async findUserByEmail(email) {
9
+ const user = await model.findUnique({
10
+ where: { email }
11
+ });
12
+ return user;
13
+ },
14
+ async findUserById(id) {
15
+ const user = await model.findUnique({
16
+ where: { id }
17
+ });
18
+ return user;
19
+ },
20
+ async linkOAuthAccount(userId, provider, providerId) {
21
+ await model.update({
22
+ where: { id: userId },
23
+ data: {
24
+ oauthProvider: provider,
25
+ oauthId: providerId
26
+ }
27
+ });
28
+ }
29
+ };
30
+ }
31
+ export {
32
+ createPrismaAdapter
33
+ };
34
+ //# sourceMappingURL=prisma.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/auth/adapters/prisma.ts"],
4
+ "sourcesContent": ["import type { AuthAdapter, User } from \"./index.js\";\n\n/**\n * Creates a Prisma adapter using a Prisma delegate (e.g., prisma.user).\n * \n * Works with any Prisma-supported database by using the standard\n * Prisma delegate operations (findUnique, create, update).\n * \n * @param model - A Prisma delegate instance (e.g., prisma.user).\n * @returns An AuthAdapter compliant object.\n */\nexport function createPrismaAdapter<TUser extends User = User>(model: any): AuthAdapter<TUser> {\n return {\n async createUser(data: any) {\n const dataToSave = { id: data.id || globalThis.crypto.randomUUID(), ...data };\n const user = await model.create({ data: dataToSave });\n return user as TUser;\n },\n\n async findUserByEmail(email: string) {\n const user = await model.findUnique({\n where: { email },\n });\n return user as TUser | null;\n },\n\n async findUserById(id: string) {\n const user = await model.findUnique({\n where: { id },\n });\n return user as TUser | null;\n },\n\n async linkOAuthAccount(userId: string, provider: string, providerId: string) {\n await model.update({\n where: { id: userId },\n data: {\n oauthProvider: provider,\n oauthId: providerId,\n },\n });\n },\n };\n}\n"],
5
+ "mappings": "AAWO,SAAS,oBAA+C,OAAgC;AAC7F,SAAO;AAAA,IACL,MAAM,WAAW,MAAW;AAC1B,YAAM,aAAa,EAAE,IAAI,KAAK,MAAM,WAAW,OAAO,WAAW,GAAG,GAAG,KAAK;AAC5E,YAAM,OAAO,MAAM,MAAM,OAAO,EAAE,MAAM,WAAW,CAAC;AACpD,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,gBAAgB,OAAe;AACnC,YAAM,OAAO,MAAM,MAAM,WAAW;AAAA,QAClC,OAAO,EAAE,MAAM;AAAA,MACjB,CAAC;AACD,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,aAAa,IAAY;AAC7B,YAAM,OAAO,MAAM,MAAM,WAAW;AAAA,QAClC,OAAO,EAAE,GAAG;AAAA,MACd,CAAC;AACD,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,iBAAiB,QAAgB,UAAkB,YAAoB;AAC3E,YAAM,MAAM,OAAO;AAAA,QACjB,OAAO,EAAE,IAAI,OAAO;AAAA,QACpB,MAAM;AAAA,UACJ,eAAe;AAAA,UACf,SAAS;AAAA,QACX;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kroxt",
3
- "version": "1.1.5",
3
+ "version": "1.2.0",
4
4
  "keywords": [
5
5
  "auth",
6
6
  "authentication",
@@ -16,6 +16,7 @@
16
16
  "hono",
17
17
  "express",
18
18
  "prisma-adapter",
19
+ "drizzle-adapter",
19
20
  "mongoose-adapter"
20
21
  ],
21
22
  "license": "MIT",
@@ -55,6 +56,16 @@
55
56
  "import": "./dist/adapters/mongoose.js",
56
57
  "require": "./dist/adapters/mongoose.cjs"
57
58
  },
59
+ "./adapters/drizzle": {
60
+ "types": "./dist/adapters/drizzle.d.ts",
61
+ "import": "./dist/adapters/drizzle.js",
62
+ "require": "./dist/adapters/drizzle.cjs"
63
+ },
64
+ "./adapters/prisma": {
65
+ "types": "./dist/adapters/prisma.d.ts",
66
+ "import": "./dist/adapters/prisma.js",
67
+ "require": "./dist/adapters/prisma.cjs"
68
+ },
58
69
  "./security": {
59
70
  "types": "./dist/security/index.d.ts",
60
71
  "import": "./dist/security/index.js",