node-auth-kit 1.0.2

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 (47) hide show
  1. package/LICENSE +5 -0
  2. package/README.md +335 -0
  3. package/dist/index.d.ts +13 -0
  4. package/dist/index.js +27 -0
  5. package/dist/src/adapters/base.adapter.d.ts +21 -0
  6. package/dist/src/adapters/base.adapter.js +2 -0
  7. package/dist/src/adapters/mongoose.adapter.d.ts +53 -0
  8. package/dist/src/adapters/mongoose.adapter.js +78 -0
  9. package/dist/src/adapters/prisma.adapter.d.ts +29 -0
  10. package/dist/src/adapters/prisma.adapter.js +40 -0
  11. package/dist/src/config/default.config.d.ts +19 -0
  12. package/dist/src/config/default.config.js +17 -0
  13. package/dist/src/config/index.d.ts +4 -0
  14. package/dist/src/config/index.js +23 -0
  15. package/dist/src/controllers/registrations.controller.d.ts +3 -0
  16. package/dist/src/controllers/registrations.controller.js +25 -0
  17. package/dist/src/controllers/sessions.controller.d.ts +3 -0
  18. package/dist/src/controllers/sessions.controller.js +25 -0
  19. package/dist/src/core/auth.service.d.ts +35 -0
  20. package/dist/src/core/auth.service.js +113 -0
  21. package/dist/src/core/password.service.d.ts +9 -0
  22. package/dist/src/core/password.service.js +19 -0
  23. package/dist/src/core/token.service.d.ts +15 -0
  24. package/dist/src/core/token.service.js +26 -0
  25. package/dist/src/deviceAuth.d.ts +32 -0
  26. package/dist/src/deviceAuth.js +67 -0
  27. package/dist/src/factories/auth-service.factory.d.ts +2 -0
  28. package/dist/src/factories/auth-service.factory.js +30 -0
  29. package/dist/src/hooks/index.d.ts +5 -0
  30. package/dist/src/hooks/index.js +20 -0
  31. package/dist/src/middlewares/authenticate.middleware.d.ts +15 -0
  32. package/dist/src/middlewares/authenticate.middleware.js +46 -0
  33. package/dist/src/middlewares/authorize.middleware.d.ts +8 -0
  34. package/dist/src/middlewares/authorize.middleware.js +36 -0
  35. package/dist/src/overrides/index.d.ts +7 -0
  36. package/dist/src/overrides/index.js +13 -0
  37. package/dist/src/routes/auth.routes.d.ts +2 -0
  38. package/dist/src/routes/auth.routes.js +41 -0
  39. package/dist/src/types/index.d.ts +11 -0
  40. package/dist/src/types/index.js +2 -0
  41. package/dist/src/utils/index.d.ts +3 -0
  42. package/dist/src/utils/index.js +12 -0
  43. package/dist/src/utils/pick.d.ts +1 -0
  44. package/dist/src/utils/pick.js +13 -0
  45. package/dist/src/utils/response.d.ts +10 -0
  46. package/dist/src/utils/response.js +32 -0
  47. package/package.json +51 -0
package/LICENSE ADDED
@@ -0,0 +1,5 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Yogendra Prajapati
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy...
package/README.md ADDED
@@ -0,0 +1,335 @@
1
+ ๐Ÿ” # Device Auth
2
+
3
+ Device Auth is a **Devise-inspired authentication and authorization library for Node.js**.
4
+
5
+ It gives you:
6
+
7
+ - **Config-driven auth** (email + password, roles, JWT, password rules)
8
+ - **Plug-and-play Express routes** via `createAuthRouter`
9
+ - **JWT-based security** with `authenticate` middleware
10
+ - **Role-based authorization** with `authorize`
11
+ - **Database-agnostic adapter system** (`mongooseAdapter`, future Prisma, etc.)
12
+ - **Lifecycle hooks** (before/after register/login) for side effects
13
+
14
+ You bring your framework (Express) and database (Mongo, Prisma, SQL). Device Auth handles the rest.
15
+
16
+ ---
17
+
18
+ ## โœจ Features
19
+
20
+ - **โœ… JWT Authentication (Access Tokens)**
21
+ - **๐Ÿ”‘ Role-based Authorization**
22
+ - **๐Ÿงฉ Adapter Pattern (DB-agnostic)**
23
+ - **๐Ÿš€ Ready-to-use Express routes** via `createAuthRouter`
24
+ - **๐Ÿ”’ Secure password hashing**
25
+ - **๐Ÿ“ฆ Mongoose adapter (Stable)**
26
+ - **๐Ÿงช Prisma adapter (In progress โ€“ V2)**
27
+ - **๐Ÿง  Inspired by Ruby on Rails Devise**
28
+
29
+ ---
30
+
31
+ ## ๐Ÿ“ฆ Installation
32
+
33
+ ```bash
34
+ npm install device_auth
35
+ ```
36
+
37
+ or
38
+
39
+ ```bash
40
+ yarn add device_auth
41
+ ```
42
+
43
+ `device_auth` itself is DB-agnostic. Database drivers / ORMs are **optional** and only required if you use the corresponding adapter:
44
+
45
+ - For Mongoose adapter: `mongoose`
46
+ - For Prisma adapter (V2): `@prisma/client`
47
+
48
+ ---
49
+
50
+ ## โšก Quick Start (Express + MongoDB)
51
+
52
+ ### 1๏ธโƒฃ Environment Variables
53
+
54
+ Create a `.env` file:
55
+
56
+ ```env
57
+ MONGO_URL=mongodb://localhost:27017/device-auth
58
+ DEVICE_AUTH_JWT_SECRET=your-super-secret-key
59
+ ```
60
+
61
+ ### 2๏ธโƒฃ User Model (Mongoose)
62
+
63
+ ```ts
64
+ import mongoose from 'mongoose';
65
+
66
+ const UserSchema = new mongoose.Schema({
67
+ email: {
68
+ type: String,
69
+ unique: true,
70
+ required: true,
71
+ },
72
+ password: {
73
+ type: String,
74
+ required: true,
75
+ },
76
+ role: {
77
+ type: String,
78
+ enum: ['admin', 'staff', 'user'],
79
+ default: 'user',
80
+ },
81
+ createdAt: {
82
+ type: Date,
83
+ default: Date.now,
84
+ },
85
+ });
86
+
87
+ export const User = mongoose.model('User', UserSchema);
88
+ ```
89
+
90
+ ### 3๏ธโƒฃ Express App Setup
91
+
92
+ ```ts
93
+ import 'dotenv/config';
94
+ import express from 'express';
95
+ import mongoose from 'mongoose';
96
+
97
+ import {
98
+ deviceAuth,
99
+ mongooseAdapter,
100
+ createAuthRouter,
101
+ authenticate,
102
+ authorize,
103
+ } from 'node-auth-kit';
104
+
105
+ import { User } from './models/User';
106
+
107
+ const app = express();
108
+ app.use(express.json());
109
+
110
+ // 1. Connect MongoDB
111
+ mongoose
112
+ .connect(process.env.MONGO_URL)
113
+ .then(() => console.log('MongoDB connected'))
114
+ .catch(console.error);
115
+
116
+ // 2. Initialize Device Auth
117
+ deviceAuth
118
+ .init({
119
+ authType: 'jwt',
120
+ signupFields: ['email', 'password'],
121
+ defaultRole: 'user',
122
+ password: {
123
+ minLength: 8,
124
+ requireNumbers: true,
125
+ requireSpecialChars: true,
126
+ saltRounds: 10,
127
+ },
128
+ token: {
129
+ accessTokenTtl: '15m',
130
+ },
131
+ })
132
+ .useAdapter(
133
+ mongooseAdapter({
134
+ userModel: User,
135
+ }),
136
+ );
137
+
138
+ // 3. Mount Auth Routes
139
+ app.use('/auth', createAuthRouter());
140
+
141
+ // 4. Example Protected Route
142
+ app.get(
143
+ '/admin',
144
+ authenticate,
145
+ authorize('admin'),
146
+ (req, res) => {
147
+ res.json({ message: 'Admin access granted' });
148
+ },
149
+ );
150
+
151
+ app.listen(3000, () => {
152
+ console.log('Server running on http://localhost:3000');
153
+ });
154
+ ```
155
+
156
+ ---
157
+
158
+ ## ๐Ÿ” Authentication Routes
159
+
160
+ The default router created by `createAuthRouter()` exposes:
161
+
162
+ | Method | Endpoint | Description |
163
+ | ------ | ------------- | ------------------ |
164
+ | POST | `/auth/register` | Register new user |
165
+ | POST | `/auth/login` | Login user |
166
+ | GET | `/auth/me` | Get current user |
167
+
168
+ You can mount it under any base path (e.g. `/api/auth`).
169
+
170
+ ```ts
171
+ app.use('/auth', createAuthRouter());
172
+ ```
173
+
174
+ ---
175
+
176
+ ## ๐Ÿ” Middleware
177
+
178
+ ### `authenticate`
179
+
180
+ Validates the JWT from the `Authorization: Bearer <token>` header and attaches the user to `req.user`.
181
+
182
+ ```ts
183
+ app.get('/profile', authenticate, (req, res) => {
184
+ res.json(req.user);
185
+ });
186
+ ```
187
+
188
+ ### `authorize(...roles)`
189
+
190
+ Restricts access based on user role.
191
+
192
+ ```ts
193
+ app.get('/admin', authenticate, authorize('admin', 'staff'), (req, res) => {
194
+ res.json({ message: 'Admin or staff only' });
195
+ });
196
+ ```
197
+
198
+ ---
199
+
200
+ ## ๐Ÿงฉ Adapter System
201
+
202
+ Device Auth uses a **pluggable adapter architecture**, allowing it to work with different databases without changing core logic.
203
+
204
+ Supported / planned adapters:
205
+
206
+ | Adapter | Status |
207
+ | -------- | -------------------------- |
208
+ | Mongoose | โœ… Stable |
209
+ | Prisma | ๐Ÿšง In Progress (V2) |
210
+ | TypeORM | โŒ Planned |
211
+
212
+ The public exports you can use:
213
+
214
+ - `mongooseAdapter` โ€“ helper for MongoDB via Mongoose
215
+ - `MongooseAdapter` โ€“ underlying class (advanced use)
216
+
217
+ ---
218
+
219
+ ## โš™๏ธ Configuration
220
+
221
+ The central entry point is `deviceAuth`:
222
+
223
+ ```ts
224
+ import { deviceAuth, defaultConfig } from 'device_auth';
225
+
226
+ deviceAuth.init({
227
+ ...defaultConfig,
228
+ authType: 'jwt',
229
+ defaultRole: 'user',
230
+ signupFields: ['email', 'password'],
231
+ // override anything you need
232
+ });
233
+ ```
234
+
235
+ Key options:
236
+
237
+ - **`authType`**: currently `jwt`
238
+ - **`signupFields`**: required fields on registration
239
+ - **`defaultRole`**: assigned when no role is provided
240
+ - **`password`**:
241
+ - `minLength`
242
+ - `requireNumbers`
243
+ - `requireSpecialChars`
244
+ - `saltRounds`
245
+ - **`token`**:
246
+ - `accessTokenTtl` (e.g. `15m`, `1h`)
247
+
248
+ The merged configuration is accessible via:
249
+
250
+ ```ts
251
+ const config = deviceAuth.config;
252
+ ```
253
+
254
+ ---
255
+
256
+ ## ๐Ÿง  Hooks
257
+
258
+ Hooks let you run side effects around key lifecycle events without forking core logic.
259
+
260
+ Supported hook names:
261
+
262
+ - `beforeRegister`
263
+ - `afterRegister`
264
+ - `beforeLogin`
265
+ - `afterLogin`
266
+
267
+ Register hooks on `deviceAuth`:
268
+
269
+ ```ts
270
+ import { deviceAuth } from 'device_auth';
271
+
272
+ deviceAuth
273
+ .registerHook('beforeRegister', async (createData) => {
274
+ // e.g. validate extra fields, audit, etc.
275
+ })
276
+ .registerHook('afterRegister', async (user) => {
277
+ // e.g. send welcome email
278
+ })
279
+ .registerHook('beforeLogin', async (user) => {
280
+ // e.g. check if user is blocked
281
+ })
282
+ .registerHook('afterLogin', async (user) => {
283
+ // e.g. log login event
284
+ });
285
+ ```
286
+
287
+ Hook errors are intentionally swallowed so they **never break core auth flow**.
288
+
289
+ ---
290
+
291
+ ## ๐Ÿ›ฃ๏ธ Roadmap (V2)
292
+
293
+ Planned for upcoming versions:
294
+
295
+ - ๐Ÿ” Refresh tokens
296
+ - ๐Ÿ“ฑ Multi-device sessions
297
+ - ๐Ÿšช Logout (single device / all devices)
298
+ - ๐Ÿ“ง Forgot & reset password
299
+ - โœ… Email verification
300
+ - ๐Ÿงช Stable Prisma adapter
301
+ - ๐Ÿง  Additional hooks & lifecycle events
302
+
303
+ ---
304
+
305
+ ## ๐Ÿงช Testing
306
+
307
+ ```bash
308
+ npm test
309
+ ```
310
+
311
+ Postman collection โ€“ _coming soon_.
312
+
313
+ ---
314
+
315
+ ## ๐Ÿค Contributing
316
+
317
+ Contributions are welcome!
318
+
319
+ 1. **Fork** the repository
320
+ 2. **Create** a new branch
321
+
322
+ ```bash
323
+ git checkout -b feature/my-feature
324
+ ```
325
+
326
+ 3. **Commit** your changes
327
+ 4. **Push** to your branch
328
+ 5. **Open** a Pull Request
329
+
330
+ ---
331
+
332
+ ## ๐Ÿ“„ License
333
+
334
+ MIT License ยฉ 2025
335
+
@@ -0,0 +1,13 @@
1
+ export { deviceAuth } from './src/deviceAuth';
2
+ export type { DeviceAuthConfig } from './src/config';
3
+ export { defaultConfig } from './src/config';
4
+ export { applyControllerOverrides } from './src/overrides';
5
+ export type { User, Role, Adapter, Config } from './src/types';
6
+ export { pick } from './src/utils';
7
+ export type { ResponseLike } from './src/utils';
8
+ export { sendJson, sendError, badRequest, unauthorized, forbidden, internalError, } from './src/utils';
9
+ export { MongooseAdapter, mongooseAdapter } from './src/adapters/mongoose.adapter';
10
+ export type { MongooseAdapterOptions } from './src/adapters/mongoose.adapter';
11
+ export { createAuthRouter } from './src/routes/auth.routes';
12
+ export { authenticate } from './src/middlewares/authenticate.middleware';
13
+ export { authorize } from './src/middlewares/authorize.middleware';
package/dist/index.js ADDED
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.authorize = exports.authenticate = exports.createAuthRouter = exports.mongooseAdapter = exports.MongooseAdapter = exports.internalError = exports.forbidden = exports.unauthorized = exports.badRequest = exports.sendError = exports.sendJson = exports.pick = exports.applyControllerOverrides = exports.defaultConfig = exports.deviceAuth = void 0;
4
+ var deviceAuth_1 = require("./src/deviceAuth");
5
+ Object.defineProperty(exports, "deviceAuth", { enumerable: true, get: function () { return deviceAuth_1.deviceAuth; } });
6
+ var config_1 = require("./src/config");
7
+ Object.defineProperty(exports, "defaultConfig", { enumerable: true, get: function () { return config_1.defaultConfig; } });
8
+ var overrides_1 = require("./src/overrides");
9
+ Object.defineProperty(exports, "applyControllerOverrides", { enumerable: true, get: function () { return overrides_1.applyControllerOverrides; } });
10
+ var utils_1 = require("./src/utils");
11
+ Object.defineProperty(exports, "pick", { enumerable: true, get: function () { return utils_1.pick; } });
12
+ var utils_2 = require("./src/utils");
13
+ Object.defineProperty(exports, "sendJson", { enumerable: true, get: function () { return utils_2.sendJson; } });
14
+ Object.defineProperty(exports, "sendError", { enumerable: true, get: function () { return utils_2.sendError; } });
15
+ Object.defineProperty(exports, "badRequest", { enumerable: true, get: function () { return utils_2.badRequest; } });
16
+ Object.defineProperty(exports, "unauthorized", { enumerable: true, get: function () { return utils_2.unauthorized; } });
17
+ Object.defineProperty(exports, "forbidden", { enumerable: true, get: function () { return utils_2.forbidden; } });
18
+ Object.defineProperty(exports, "internalError", { enumerable: true, get: function () { return utils_2.internalError; } });
19
+ var mongoose_adapter_1 = require("./src/adapters/mongoose.adapter");
20
+ Object.defineProperty(exports, "MongooseAdapter", { enumerable: true, get: function () { return mongoose_adapter_1.MongooseAdapter; } });
21
+ Object.defineProperty(exports, "mongooseAdapter", { enumerable: true, get: function () { return mongoose_adapter_1.mongooseAdapter; } });
22
+ var auth_routes_1 = require("./src/routes/auth.routes");
23
+ Object.defineProperty(exports, "createAuthRouter", { enumerable: true, get: function () { return auth_routes_1.createAuthRouter; } });
24
+ var authenticate_middleware_1 = require("./src/middlewares/authenticate.middleware");
25
+ Object.defineProperty(exports, "authenticate", { enumerable: true, get: function () { return authenticate_middleware_1.authenticate; } });
26
+ var authorize_middleware_1 = require("./src/middlewares/authorize.middleware");
27
+ Object.defineProperty(exports, "authorize", { enumerable: true, get: function () { return authorize_middleware_1.authorize; } });
@@ -0,0 +1,21 @@
1
+ export type AdapterUser = Record<string, unknown>;
2
+ export type CreateUserData = Record<string, unknown>;
3
+ export type UpdateUserData = Record<string, unknown>;
4
+ /**
5
+ * Base database adapter contract for device_auth.
6
+ *
7
+ * This interface is intentionally DB-agnostic and contains no ORM types
8
+ * or database-specific logic. Concrete adapters (Prisma, Mongoose, SQL, etc.)
9
+ * must implement this contract so that device_auth can talk to any backend
10
+ * in a uniform way.
11
+ */
12
+ export interface BaseAdapter {
13
+ /** Create a new user record. */
14
+ createUser(data: CreateUserData): Promise<AdapterUser>;
15
+ /** Look up a user by email, or return null if not found. */
16
+ findUserByEmail(email: string): Promise<AdapterUser | null>;
17
+ /** Look up a user by primary identifier, or return null if not found. */
18
+ findUserById(id: string | number): Promise<AdapterUser | null>;
19
+ /** Update an existing user and return the updated record. */
20
+ updateUser(id: string | number, data: UpdateUserData): Promise<AdapterUser>;
21
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,53 @@
1
+ import type { AdapterUser, BaseAdapter, CreateUserData, UpdateUserData } from './base.adapter';
2
+ interface MinimalMongooseModel<T = unknown> {
3
+ create(data: Record<string, unknown>): Promise<T>;
4
+ findOne(filter: Record<string, unknown>): {
5
+ exec(): Promise<T | null>;
6
+ };
7
+ findById(id: unknown): {
8
+ exec(): Promise<T | null>;
9
+ };
10
+ findByIdAndUpdate(id: unknown, data: Record<string, unknown>, options: {
11
+ new: boolean;
12
+ }): {
13
+ exec(): Promise<T | null>;
14
+ };
15
+ findOneAndUpdate(filter: Record<string, unknown>, data: Record<string, unknown>, options: {
16
+ new: boolean;
17
+ }): {
18
+ exec(): Promise<T | null>;
19
+ };
20
+ }
21
+ export interface MongooseAdapterOptions {
22
+ userModel: MinimalMongooseModel;
23
+ idField?: string;
24
+ emailField?: string;
25
+ }
26
+ export declare class MongooseAdapter implements BaseAdapter {
27
+ private readonly userModel;
28
+ private readonly idField;
29
+ private readonly emailField;
30
+ constructor(options: MongooseAdapterOptions);
31
+ createUser(data: CreateUserData): Promise<AdapterUser>;
32
+ findUserByEmail(email: string): Promise<AdapterUser | null>;
33
+ findUserById(id: string | number): Promise<AdapterUser | null>;
34
+ updateUser(id: string | number, data: UpdateUserData): Promise<AdapterUser>;
35
+ private normalize;
36
+ }
37
+ /**
38
+ * Mongoose adapter factory.
39
+ *
40
+ * You can use either the class-based style:
41
+ *
42
+ * ```ts
43
+ * adapter: new MongooseAdapter({ userModel: User });
44
+ * ```
45
+ *
46
+ * or the function-based style (recommended):
47
+ *
48
+ * ```ts
49
+ * adapter: mongooseAdapter({ userModel: User });
50
+ * ```
51
+ */
52
+ export declare function mongooseAdapter(options: MongooseAdapterOptions): BaseAdapter;
53
+ export {};
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MongooseAdapter = void 0;
4
+ exports.mongooseAdapter = mongooseAdapter;
5
+ class MongooseAdapter {
6
+ constructor(options) {
7
+ this.userModel = options.userModel;
8
+ this.idField = options.idField ?? '_id';
9
+ this.emailField = options.emailField ?? 'email';
10
+ }
11
+ async createUser(data) {
12
+ const doc = await this.userModel.create(data);
13
+ return this.normalize(doc);
14
+ }
15
+ async findUserByEmail(email) {
16
+ const doc = await this.userModel.findOne({ [this.emailField]: email }).exec();
17
+ if (!doc)
18
+ return null;
19
+ return this.normalize(doc);
20
+ }
21
+ async findUserById(id) {
22
+ let doc;
23
+ if (this.idField === '_id') {
24
+ doc = await this.userModel.findById(id).exec();
25
+ }
26
+ else {
27
+ doc = await this.userModel.findOne({ [this.idField]: id }).exec();
28
+ }
29
+ if (!doc)
30
+ return null;
31
+ return this.normalize(doc);
32
+ }
33
+ async updateUser(id, data) {
34
+ let doc;
35
+ if (this.idField === '_id') {
36
+ doc = await this.userModel.findByIdAndUpdate(id, data, { new: true }).exec();
37
+ }
38
+ else {
39
+ doc = await this.userModel
40
+ .findOneAndUpdate({ [this.idField]: id }, data, { new: true })
41
+ .exec();
42
+ }
43
+ if (!doc) {
44
+ throw new Error('User not found');
45
+ }
46
+ return this.normalize(doc);
47
+ }
48
+ normalize(doc) {
49
+ const obj = typeof doc.toObject === 'function' ? doc.toObject() : { ...doc };
50
+ const adapterUser = { ...obj };
51
+ const rawId = obj[this.idField];
52
+ if (rawId != null) {
53
+ // Expose a normalized id field expected by core
54
+ adapterUser['id'] =
55
+ typeof rawId === 'string' || typeof rawId === 'number' ? rawId : String(rawId);
56
+ }
57
+ return adapterUser;
58
+ }
59
+ }
60
+ exports.MongooseAdapter = MongooseAdapter;
61
+ /**
62
+ * Mongoose adapter factory.
63
+ *
64
+ * You can use either the class-based style:
65
+ *
66
+ * ```ts
67
+ * adapter: new MongooseAdapter({ userModel: User });
68
+ * ```
69
+ *
70
+ * or the function-based style (recommended):
71
+ *
72
+ * ```ts
73
+ * adapter: mongooseAdapter({ userModel: User });
74
+ * ```
75
+ */
76
+ function mongooseAdapter(options) {
77
+ return new MongooseAdapter(options);
78
+ }
@@ -0,0 +1,29 @@
1
+ import type { AdapterUser, BaseAdapter, CreateUserData, UpdateUserData } from './base.adapter';
2
+ export interface PrismaDelegate<TUser> {
3
+ create(args: {
4
+ data: Record<string, unknown>;
5
+ }): Promise<TUser>;
6
+ findUnique(args: {
7
+ where: Record<string, unknown>;
8
+ }): Promise<TUser | null>;
9
+ update(args: {
10
+ where: Record<string, unknown>;
11
+ data: Record<string, unknown>;
12
+ }): Promise<TUser>;
13
+ }
14
+ export interface PrismaAdapterOptions<TUser extends Record<string, unknown>> {
15
+ userDelegate: PrismaDelegate<TUser>;
16
+ idField?: string;
17
+ emailField?: string;
18
+ }
19
+ export declare class PrismaAdapter<TUser extends Record<string, unknown>> implements BaseAdapter {
20
+ private readonly userDelegate;
21
+ private readonly idField;
22
+ private readonly emailField;
23
+ constructor(options: PrismaAdapterOptions<TUser>);
24
+ createUser(data: CreateUserData): Promise<AdapterUser>;
25
+ findUserByEmail(email: string): Promise<AdapterUser | null>;
26
+ findUserById(id: string | number): Promise<AdapterUser | null>;
27
+ updateUser(id: string | number, data: UpdateUserData): Promise<AdapterUser>;
28
+ private normalize;
29
+ }
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PrismaAdapter = void 0;
4
+ class PrismaAdapter {
5
+ constructor(options) {
6
+ this.userDelegate = options.userDelegate;
7
+ this.idField = options.idField ?? 'id';
8
+ this.emailField = options.emailField ?? 'email';
9
+ }
10
+ async createUser(data) {
11
+ const user = await this.userDelegate.create({ data });
12
+ return this.normalize(user);
13
+ }
14
+ async findUserByEmail(email) {
15
+ const user = await this.userDelegate.findUnique({ where: { [this.emailField]: email } });
16
+ if (!user)
17
+ return null;
18
+ return this.normalize(user);
19
+ }
20
+ async findUserById(id) {
21
+ const user = await this.userDelegate.findUnique({ where: { [this.idField]: id } });
22
+ if (!user)
23
+ return null;
24
+ return this.normalize(user);
25
+ }
26
+ async updateUser(id, data) {
27
+ const user = await this.userDelegate.update({ where: { [this.idField]: id }, data });
28
+ return this.normalize(user);
29
+ }
30
+ normalize(user) {
31
+ const adapterUser = { ...user };
32
+ const rawId = user[this.idField];
33
+ if (rawId != null) {
34
+ adapterUser['id'] =
35
+ typeof rawId === 'string' || typeof rawId === 'number' ? rawId : String(rawId);
36
+ }
37
+ return adapterUser;
38
+ }
39
+ }
40
+ exports.PrismaAdapter = PrismaAdapter;
@@ -0,0 +1,19 @@
1
+ export type AuthType = 'jwt' | 'session';
2
+ export interface PasswordRulesConfig {
3
+ minLength: number;
4
+ requireNumbers: boolean;
5
+ requireSpecialChars: boolean;
6
+ saltRounds: number;
7
+ }
8
+ export interface TokenConfig {
9
+ /** e.g. '15m', '1h' */
10
+ accessTokenTtl: string;
11
+ }
12
+ export interface DeviceAuthConfig {
13
+ signupFields: string[];
14
+ defaultRole: string;
15
+ authType: AuthType;
16
+ password: PasswordRulesConfig;
17
+ token: TokenConfig;
18
+ }
19
+ export declare const defaultConfig: DeviceAuthConfig;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultConfig = void 0;
4
+ exports.defaultConfig = {
5
+ signupFields: ['email', 'password'],
6
+ defaultRole: 'user',
7
+ authType: 'jwt',
8
+ password: {
9
+ minLength: 8,
10
+ requireNumbers: true,
11
+ requireSpecialChars: false,
12
+ saltRounds: 10,
13
+ },
14
+ token: {
15
+ accessTokenTtl: '15m',
16
+ },
17
+ };
@@ -0,0 +1,4 @@
1
+ import { defaultConfig, type DeviceAuthConfig } from './default.config';
2
+ export declare const mergeConfig: (userConfig?: Partial<DeviceAuthConfig>) => DeviceAuthConfig;
3
+ export type { DeviceAuthConfig };
4
+ export { defaultConfig };
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultConfig = exports.mergeConfig = void 0;
4
+ const default_config_1 = require("./default.config");
5
+ Object.defineProperty(exports, "defaultConfig", { enumerable: true, get: function () { return default_config_1.defaultConfig; } });
6
+ // Merge user config with defaults, including nested objects we know about
7
+ const mergeConfig = (userConfig) => {
8
+ if (!userConfig)
9
+ return { ...default_config_1.defaultConfig };
10
+ return {
11
+ ...default_config_1.defaultConfig,
12
+ ...userConfig,
13
+ password: {
14
+ ...default_config_1.defaultConfig.password,
15
+ ...(userConfig.password ?? {}),
16
+ },
17
+ token: {
18
+ ...default_config_1.defaultConfig.token,
19
+ ...(userConfig.token ?? {}),
20
+ },
21
+ };
22
+ };
23
+ exports.mergeConfig = mergeConfig;
@@ -0,0 +1,3 @@
1
+ import type { SignupResult } from '../core/auth.service';
2
+ export type RegistrationsController = (data: Record<string, unknown>) => Promise<SignupResult>;
3
+ export declare const getRegistrationsController: () => RegistrationsController;