@aranzatech/aranza-auth 0.1.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.
@@ -0,0 +1,226 @@
1
+ import { __decorateClass, resolveRegisterIdentifier, normalizeIdentifier, AUTH_REPOSITORY, AUTH_MODULE_OPTIONS } from '../chunk-DKYNHXY2.js';
2
+ import { Injectable, Module } from '@nestjs/common';
3
+ import { Prop, Schema, SchemaFactory, MongooseModule, getModelToken } from '@nestjs/mongoose';
4
+ import { Types } from 'mongoose';
5
+
6
+ function toAccount(doc) {
7
+ return {
8
+ id: doc._id.toString(),
9
+ ...doc.email != null ? { email: doc.email } : {},
10
+ ...doc.username != null ? { username: doc.username } : {},
11
+ emailVerified: doc.emailVerified,
12
+ disabled: doc.disabled,
13
+ createdAt: doc.createdAt,
14
+ updatedAt: doc.updatedAt
15
+ };
16
+ }
17
+ function toAccountWithSecrets(doc) {
18
+ return {
19
+ ...toAccount(doc),
20
+ passwordHash: doc.passwordHash,
21
+ refreshTokenHash: doc.refreshTokenHash ?? null
22
+ };
23
+ }
24
+ var MongoAuthRepository = class {
25
+ constructor(authModel, identifierField = "email") {
26
+ this.authModel = authModel;
27
+ this.identifierField = identifierField;
28
+ }
29
+ async create(data) {
30
+ const identifier = resolveRegisterIdentifier(
31
+ data,
32
+ this.identifierField
33
+ );
34
+ const created = new this.authModel({
35
+ email: this.identifierField === "email" ? identifier : data.email != null ? normalizeIdentifier(data.email) : void 0,
36
+ username: this.identifierField === "username" ? identifier : data.username != null ? normalizeIdentifier(data.username) : void 0,
37
+ passwordHash: data.passwordHash,
38
+ emailVerified: data.emailVerified ?? false,
39
+ disabled: false
40
+ });
41
+ const saved = await created.save();
42
+ return toAccount(saved);
43
+ }
44
+ async findByEmail(email) {
45
+ const doc = await this.authModel.findOne({ email: normalizeIdentifier(email) }).exec();
46
+ return doc != null ? toAccount(doc) : null;
47
+ }
48
+ async findByIdentifier(identifier) {
49
+ const doc = await this.authModel.findOne(this.identifierQuery(identifier)).exec();
50
+ return doc != null ? toAccount(doc) : null;
51
+ }
52
+ async findByIdentifierWithSecrets(identifier) {
53
+ const doc = await this.authModel.findOne(this.identifierQuery(identifier)).select("+passwordHash +refreshTokenHash").exec();
54
+ return doc != null ? toAccountWithSecrets(doc) : null;
55
+ }
56
+ async findById(id) {
57
+ if (!Types.ObjectId.isValid(id)) return null;
58
+ const doc = await this.authModel.findById(id).exec();
59
+ return doc != null ? toAccount(doc) : null;
60
+ }
61
+ async findByIdWithSecrets(id) {
62
+ if (!Types.ObjectId.isValid(id)) return null;
63
+ const doc = await this.authModel.findById(id).select("+passwordHash +refreshTokenHash").exec();
64
+ return doc != null ? toAccountWithSecrets(doc) : null;
65
+ }
66
+ async updateRefreshTokenHash(id, hash) {
67
+ if (!Types.ObjectId.isValid(id)) return;
68
+ await this.authModel.updateOne({ _id: id }, { $set: { refreshTokenHash: hash } }).exec();
69
+ }
70
+ async updatePasswordHash(id, passwordHash) {
71
+ if (!Types.ObjectId.isValid(id)) return;
72
+ await this.authModel.updateOne({ _id: id }, { $set: { passwordHash } }).exec();
73
+ }
74
+ async setEmailVerificationToken(id, tokenHash, expiresAt) {
75
+ if (!Types.ObjectId.isValid(id)) return;
76
+ await this.authModel.updateOne(
77
+ { _id: id },
78
+ {
79
+ $set: {
80
+ emailVerificationTokenHash: tokenHash,
81
+ emailVerificationExpiresAt: expiresAt
82
+ }
83
+ }
84
+ ).exec();
85
+ }
86
+ async findByEmailVerificationTokenHash(tokenHash) {
87
+ const doc = await this.authModel.findOne({
88
+ emailVerificationTokenHash: tokenHash,
89
+ emailVerificationExpiresAt: { $gt: /* @__PURE__ */ new Date() }
90
+ }).select("+emailVerificationTokenHash").exec();
91
+ return doc != null ? toAccount(doc) : null;
92
+ }
93
+ async markEmailVerified(id) {
94
+ if (!Types.ObjectId.isValid(id)) return;
95
+ await this.authModel.updateOne(
96
+ { _id: id },
97
+ {
98
+ $set: { emailVerified: true },
99
+ $unset: {
100
+ emailVerificationTokenHash: "",
101
+ emailVerificationExpiresAt: ""
102
+ }
103
+ }
104
+ ).exec();
105
+ }
106
+ async setResetToken(id, tokenHash, expiresAt) {
107
+ if (!Types.ObjectId.isValid(id)) return;
108
+ await this.authModel.updateOne(
109
+ { _id: id },
110
+ { $set: { resetTokenHash: tokenHash, resetTokenExpiresAt: expiresAt } }
111
+ ).exec();
112
+ }
113
+ async findByResetTokenHash(tokenHash) {
114
+ const doc = await this.authModel.findOne({
115
+ resetTokenHash: tokenHash,
116
+ resetTokenExpiresAt: { $gt: /* @__PURE__ */ new Date() }
117
+ }).select("+passwordHash +resetTokenHash").exec();
118
+ return doc != null ? toAccountWithSecrets(doc) : null;
119
+ }
120
+ async clearResetToken(id) {
121
+ if (!Types.ObjectId.isValid(id)) return;
122
+ await this.authModel.updateOne(
123
+ { _id: id },
124
+ { $unset: { resetTokenHash: "", resetTokenExpiresAt: "" } }
125
+ ).exec();
126
+ }
127
+ identifierQuery(identifier) {
128
+ const normalized = normalizeIdentifier(identifier);
129
+ return this.identifierField === "email" ? { email: normalized } : { username: normalized };
130
+ }
131
+ };
132
+ MongoAuthRepository = __decorateClass([
133
+ Injectable()
134
+ ], MongoAuthRepository);
135
+ var BASE_AUTH_ACCOUNT_MODEL = "AuthAccount";
136
+ var BaseAuthAccountSchema = class {
137
+ };
138
+ __decorateClass([
139
+ Prop({ required: false, trim: true, lowercase: true, index: true })
140
+ ], BaseAuthAccountSchema.prototype, "email", 2);
141
+ __decorateClass([
142
+ Prop({ required: false, trim: true, lowercase: true, index: true })
143
+ ], BaseAuthAccountSchema.prototype, "username", 2);
144
+ __decorateClass([
145
+ Prop({ required: true, select: false })
146
+ ], BaseAuthAccountSchema.prototype, "passwordHash", 2);
147
+ __decorateClass([
148
+ Prop({ required: false, select: false })
149
+ ], BaseAuthAccountSchema.prototype, "refreshTokenHash", 2);
150
+ __decorateClass([
151
+ Prop({ type: Boolean, default: false })
152
+ ], BaseAuthAccountSchema.prototype, "emailVerified", 2);
153
+ __decorateClass([
154
+ Prop({ type: Boolean, default: false })
155
+ ], BaseAuthAccountSchema.prototype, "disabled", 2);
156
+ __decorateClass([
157
+ Prop({ required: false, select: false })
158
+ ], BaseAuthAccountSchema.prototype, "emailVerificationTokenHash", 2);
159
+ __decorateClass([
160
+ Prop({ required: false })
161
+ ], BaseAuthAccountSchema.prototype, "emailVerificationExpiresAt", 2);
162
+ __decorateClass([
163
+ Prop({ required: false, select: false })
164
+ ], BaseAuthAccountSchema.prototype, "resetTokenHash", 2);
165
+ __decorateClass([
166
+ Prop({ required: false })
167
+ ], BaseAuthAccountSchema.prototype, "resetTokenExpiresAt", 2);
168
+ BaseAuthAccountSchema = __decorateClass([
169
+ Schema({
170
+ timestamps: true,
171
+ collection: "auth_accounts"
172
+ })
173
+ ], BaseAuthAccountSchema);
174
+ var baseAuthAccountSchema = SchemaFactory.createForClass(BaseAuthAccountSchema);
175
+ baseAuthAccountSchema.index(
176
+ { email: 1 },
177
+ {
178
+ unique: true,
179
+ partialFilterExpression: { email: { $type: "string" } }
180
+ }
181
+ );
182
+ baseAuthAccountSchema.index(
183
+ { username: 1 },
184
+ {
185
+ unique: true,
186
+ partialFilterExpression: { username: { $type: "string" } }
187
+ }
188
+ );
189
+
190
+ // src/mongo/mongo-auth.module.ts
191
+ var MongoAuthModule = class {
192
+ static forFeature(options) {
193
+ const name = options?.name ?? BASE_AUTH_ACCOUNT_MODEL;
194
+ const schema = options?.schema ?? baseAuthAccountSchema;
195
+ const identifierField = options?.identifierField ?? "email";
196
+ return {
197
+ module: MongoAuthModule,
198
+ imports: [MongooseModule.forFeature([{ name, schema }])],
199
+ providers: [
200
+ {
201
+ provide: MongoAuthRepository,
202
+ useFactory: (model, authOptions) => new MongoAuthRepository(
203
+ model,
204
+ authOptions?.identifierField ?? identifierField
205
+ ),
206
+ inject: [
207
+ getModelToken(name),
208
+ { token: AUTH_MODULE_OPTIONS, optional: true }
209
+ ]
210
+ },
211
+ {
212
+ provide: AUTH_REPOSITORY,
213
+ useExisting: MongoAuthRepository
214
+ }
215
+ ],
216
+ exports: [AUTH_REPOSITORY, MongooseModule]
217
+ };
218
+ }
219
+ };
220
+ MongoAuthModule = __decorateClass([
221
+ Module({})
222
+ ], MongoAuthModule);
223
+
224
+ export { BASE_AUTH_ACCOUNT_MODEL, BaseAuthAccountSchema, MongoAuthModule, MongoAuthRepository, baseAuthAccountSchema };
225
+ //# sourceMappingURL=index.js.map
226
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/mongo/mongo-auth.repository.ts","../../src/mongo/schemas/base-auth-account.schema.ts","../../src/mongo/mongo-auth.module.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { Injectable } from \"@nestjs/common\";\nimport { Types, type Model } from \"mongoose\";\n\nimport type { AuthIdentifierField } from \"../interfaces/auth-config.interface\";\nimport type {\n AuthAccountWithSecrets,\n BaseAuthAccount,\n} from \"../interfaces/auth-hooks.interface\";\nimport type {\n CreateAccountData,\n IAuthRepository,\n} from \"../interfaces/auth-repository.interface\";\nimport {\n normalizeIdentifier,\n resolveRegisterIdentifier,\n} from \"../utils/identifier.util\";\nimport type { BaseAuthAccountDocument } from \"./schemas/base-auth-account.schema\";\n\nfunction toAccount(doc: BaseAuthAccountDocument): BaseAuthAccount {\n return {\n id: doc._id.toString(),\n ...(doc.email != null ? { email: doc.email } : {}),\n ...(doc.username != null ? { username: doc.username } : {}),\n emailVerified: doc.emailVerified,\n disabled: doc.disabled,\n createdAt: doc.createdAt,\n updatedAt: doc.updatedAt,\n };\n}\n\nfunction toAccountWithSecrets(\n doc: BaseAuthAccountDocument,\n): AuthAccountWithSecrets {\n return {\n ...toAccount(doc),\n passwordHash: doc.passwordHash,\n refreshTokenHash: doc.refreshTokenHash ?? null,\n };\n}\n\n@Injectable()\nexport class MongoAuthRepository implements IAuthRepository {\n constructor(\n private readonly authModel: Model<BaseAuthAccountDocument>,\n private readonly identifierField: AuthIdentifierField = \"email\",\n ) {}\n\n async create(data: CreateAccountData): Promise<BaseAuthAccount> {\n const identifier = resolveRegisterIdentifier(\n data,\n this.identifierField,\n );\n\n const created = new this.authModel({\n email:\n this.identifierField === \"email\"\n ? identifier\n : data.email != null\n ? normalizeIdentifier(data.email)\n : undefined,\n username:\n this.identifierField === \"username\"\n ? identifier\n : data.username != null\n ? normalizeIdentifier(data.username)\n : undefined,\n passwordHash: data.passwordHash,\n emailVerified: data.emailVerified ?? false,\n disabled: false,\n });\n\n const saved = await created.save();\n return toAccount(saved);\n }\n\n async findByEmail(email: string): Promise<BaseAuthAccount | null> {\n const doc = await this.authModel\n .findOne({ email: normalizeIdentifier(email) })\n .exec();\n return doc != null ? toAccount(doc) : null;\n }\n\n async findByIdentifier(identifier: string): Promise<BaseAuthAccount | null> {\n const doc = await this.authModel\n .findOne(this.identifierQuery(identifier))\n .exec();\n return doc != null ? toAccount(doc) : null;\n }\n\n async findByIdentifierWithSecrets(\n identifier: string,\n ): Promise<AuthAccountWithSecrets | null> {\n const doc = await this.authModel\n .findOne(this.identifierQuery(identifier))\n .select(\"+passwordHash +refreshTokenHash\")\n .exec();\n return doc != null ? toAccountWithSecrets(doc) : null;\n }\n\n async findById(id: string): Promise<BaseAuthAccount | null> {\n if (!Types.ObjectId.isValid(id)) return null;\n const doc = await this.authModel.findById(id).exec();\n return doc != null ? toAccount(doc) : null;\n }\n\n async findByIdWithSecrets(id: string): Promise<AuthAccountWithSecrets | null> {\n if (!Types.ObjectId.isValid(id)) return null;\n const doc = await this.authModel\n .findById(id)\n .select(\"+passwordHash +refreshTokenHash\")\n .exec();\n return doc != null ? toAccountWithSecrets(doc) : null;\n }\n\n async updateRefreshTokenHash(\n id: string,\n hash: string | null,\n ): Promise<void> {\n if (!Types.ObjectId.isValid(id)) return;\n await this.authModel\n .updateOne({ _id: id }, { $set: { refreshTokenHash: hash } })\n .exec();\n }\n\n async updatePasswordHash(id: string, passwordHash: string): Promise<void> {\n if (!Types.ObjectId.isValid(id)) return;\n await this.authModel\n .updateOne({ _id: id }, { $set: { passwordHash } })\n .exec();\n }\n\n async setEmailVerificationToken(\n id: string,\n tokenHash: string,\n expiresAt: Date,\n ): Promise<void> {\n if (!Types.ObjectId.isValid(id)) return;\n await this.authModel\n .updateOne(\n { _id: id },\n {\n $set: {\n emailVerificationTokenHash: tokenHash,\n emailVerificationExpiresAt: expiresAt,\n },\n },\n )\n .exec();\n }\n\n async findByEmailVerificationTokenHash(\n tokenHash: string,\n ): Promise<BaseAuthAccount | null> {\n const doc = await this.authModel\n .findOne({\n emailVerificationTokenHash: tokenHash,\n emailVerificationExpiresAt: { $gt: new Date() },\n })\n .select(\"+emailVerificationTokenHash\")\n .exec();\n return doc != null ? toAccount(doc) : null;\n }\n\n async markEmailVerified(id: string): Promise<void> {\n if (!Types.ObjectId.isValid(id)) return;\n await this.authModel\n .updateOne(\n { _id: id },\n {\n $set: { emailVerified: true },\n $unset: {\n emailVerificationTokenHash: \"\",\n emailVerificationExpiresAt: \"\",\n },\n },\n )\n .exec();\n }\n\n async setResetToken(\n id: string,\n tokenHash: string,\n expiresAt: Date,\n ): Promise<void> {\n if (!Types.ObjectId.isValid(id)) return;\n await this.authModel\n .updateOne(\n { _id: id },\n { $set: { resetTokenHash: tokenHash, resetTokenExpiresAt: expiresAt } },\n )\n .exec();\n }\n\n async findByResetTokenHash(\n tokenHash: string,\n ): Promise<AuthAccountWithSecrets | null> {\n const doc = await this.authModel\n .findOne({\n resetTokenHash: tokenHash,\n resetTokenExpiresAt: { $gt: new Date() },\n })\n .select(\"+passwordHash +resetTokenHash\")\n .exec();\n return doc != null ? toAccountWithSecrets(doc) : null;\n }\n\n async clearResetToken(id: string): Promise<void> {\n if (!Types.ObjectId.isValid(id)) return;\n await this.authModel\n .updateOne(\n { _id: id },\n { $unset: { resetTokenHash: \"\", resetTokenExpiresAt: \"\" } },\n )\n .exec();\n }\n\n private identifierQuery(identifier: string) {\n const normalized = normalizeIdentifier(identifier);\n return this.identifierField === \"email\"\n ? { email: normalized }\n : { username: normalized };\n }\n}\n","import { Prop, Schema, SchemaFactory } from \"@nestjs/mongoose\";\nimport type { HydratedDocument } from \"mongoose\";\n\nexport const BASE_AUTH_ACCOUNT_MODEL = \"AuthAccount\";\n\n@Schema({\n timestamps: true,\n collection: \"auth_accounts\",\n})\nexport class BaseAuthAccountSchema {\n @Prop({ required: false, trim: true, lowercase: true, index: true })\n email?: string;\n\n @Prop({ required: false, trim: true, lowercase: true, index: true })\n username?: string;\n\n @Prop({ required: true, select: false })\n passwordHash!: string;\n\n @Prop({ required: false, select: false })\n refreshTokenHash?: string | null;\n\n @Prop({ type: Boolean, default: false })\n emailVerified!: boolean;\n\n @Prop({ type: Boolean, default: false })\n disabled!: boolean;\n\n @Prop({ required: false, select: false })\n emailVerificationTokenHash?: string;\n\n @Prop({ required: false })\n emailVerificationExpiresAt?: Date;\n\n @Prop({ required: false, select: false })\n resetTokenHash?: string;\n\n @Prop({ required: false })\n resetTokenExpiresAt?: Date;\n\n createdAt!: Date;\n updatedAt!: Date;\n}\n\nexport type BaseAuthAccountDocument = HydratedDocument<BaseAuthAccountSchema>;\n\nexport const baseAuthAccountSchema =\n SchemaFactory.createForClass(BaseAuthAccountSchema);\n\nbaseAuthAccountSchema.index(\n { email: 1 },\n {\n unique: true,\n partialFilterExpression: { email: { $type: \"string\" } },\n },\n);\n\nbaseAuthAccountSchema.index(\n { username: 1 },\n {\n unique: true,\n partialFilterExpression: { username: { $type: \"string\" } },\n },\n);\n","import { DynamicModule, Module } from \"@nestjs/common\";\nimport { getModelToken } from \"@nestjs/mongoose\";\nimport { MongooseModule } from \"@nestjs/mongoose\";\nimport type { Model, Schema } from \"mongoose\";\n\nimport { AUTH_MODULE_OPTIONS, AUTH_REPOSITORY } from \"../constants/tokens\";\nimport type { AuthIdentifierField } from \"../interfaces/auth-config.interface\";\nimport type { AuthModuleOptions } from \"../interfaces/auth-config.interface\";\nimport { MongoAuthRepository } from \"./mongo-auth.repository\";\nimport {\n BASE_AUTH_ACCOUNT_MODEL,\n baseAuthAccountSchema,\n type BaseAuthAccountDocument,\n} from \"./schemas/base-auth-account.schema\";\n\nexport interface MongoAuthFeatureOptions {\n /** Mongoose model name. Default: `AuthAccount`. */\n name?: string;\n /** Custom schema (e.g. extended with orgId, roleId). Default: base auth schema. */\n schema?: Schema;\n /** Identifier field when AuthModule options are not yet available. Default: `email`. */\n identifierField?: AuthIdentifierField;\n}\n\n@Module({})\nexport class MongoAuthModule {\n static forFeature(options?: MongoAuthFeatureOptions): DynamicModule {\n const name = options?.name ?? BASE_AUTH_ACCOUNT_MODEL;\n const schema = options?.schema ?? baseAuthAccountSchema;\n const identifierField = options?.identifierField ?? \"email\";\n\n return {\n module: MongoAuthModule,\n imports: [MongooseModule.forFeature([{ name, schema }])],\n providers: [\n {\n provide: MongoAuthRepository,\n useFactory: (\n model: Model<BaseAuthAccountDocument>,\n authOptions?: AuthModuleOptions,\n ) =>\n new MongoAuthRepository(\n model,\n authOptions?.identifierField ?? identifierField,\n ),\n inject: [\n getModelToken(name),\n { token: AUTH_MODULE_OPTIONS, optional: true },\n ],\n },\n {\n provide: AUTH_REPOSITORY,\n useExisting: MongoAuthRepository,\n },\n ],\n exports: [AUTH_REPOSITORY, MongooseModule],\n };\n }\n}"]}
package/package.json ADDED
@@ -0,0 +1,102 @@
1
+ {
2
+ "name": "@aranzatech/aranza-auth",
3
+ "version": "0.1.0",
4
+ "description": "Módulo de autenticación extensible para NestJS — JWT, refresh tokens, register/login y adapter MongoDB",
5
+ "license": "MIT",
6
+ "author": "AranzaTech",
7
+ "keywords": [
8
+ "nestjs",
9
+ "auth",
10
+ "authentication",
11
+ "jwt",
12
+ "refresh-token",
13
+ "passport",
14
+ "mongodb",
15
+ "mongoose",
16
+ "aranzatech"
17
+ ],
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/aapa96/aranza-auth.git"
21
+ },
22
+ "bugs": {
23
+ "url": "https://github.com/aapa96/aranza-auth/issues"
24
+ },
25
+ "homepage": "https://github.com/aapa96/aranza-auth#readme",
26
+ "publishConfig": {
27
+ "access": "public"
28
+ },
29
+ "type": "module",
30
+ "main": "./dist/index.cjs",
31
+ "module": "./dist/index.js",
32
+ "types": "./dist/index.d.ts",
33
+ "exports": {
34
+ ".": {
35
+ "types": "./dist/index.d.ts",
36
+ "import": "./dist/index.js",
37
+ "require": "./dist/index.cjs"
38
+ },
39
+ "./mongo": {
40
+ "types": "./dist/mongo/index.d.ts",
41
+ "import": "./dist/mongo/index.js",
42
+ "require": "./dist/mongo/index.cjs"
43
+ }
44
+ },
45
+ "files": [
46
+ "dist",
47
+ "README.md",
48
+ "CHANGELOG.md"
49
+ ],
50
+ "scripts": {
51
+ "build": "tsup",
52
+ "dev": "tsup --watch",
53
+ "lint": "tsc --noEmit",
54
+ "test": "vitest run",
55
+ "test:watch": "vitest",
56
+ "test:coverage": "vitest run --coverage",
57
+ "deploy:npm": "npm install && npm run build && npm publish --access public"
58
+ },
59
+ "peerDependencies": {
60
+ "@nestjs/common": ">=11",
61
+ "@nestjs/core": ">=11",
62
+ "@nestjs/jwt": ">=11",
63
+ "@nestjs/mongoose": ">=11",
64
+ "@nestjs/passport": ">=11",
65
+ "bcryptjs": ">=2",
66
+ "class-transformer": ">=0.5",
67
+ "class-validator": ">=0.14",
68
+ "mongoose": ">=8",
69
+ "passport": ">=0.7",
70
+ "passport-jwt": ">=4",
71
+ "reflect-metadata": ">=0.2"
72
+ },
73
+ "peerDependenciesMeta": {
74
+ "@nestjs/mongoose": {
75
+ "optional": true
76
+ },
77
+ "mongoose": {
78
+ "optional": true
79
+ }
80
+ },
81
+ "devDependencies": {
82
+ "@nestjs/common": "^11.0.1",
83
+ "@nestjs/core": "^11.0.1",
84
+ "@nestjs/jwt": "^11.0.2",
85
+ "@nestjs/mongoose": "^11.0.4",
86
+ "@nestjs/passport": "^11.0.5",
87
+ "@types/bcryptjs": "^2.4.6",
88
+ "@types/passport-jwt": "^4.0.1",
89
+ "@vitest/coverage-v8": "^4.1.7",
90
+ "bcryptjs": "^3.0.3",
91
+ "class-transformer": "^0.5.1",
92
+ "class-validator": "^0.14.4",
93
+ "mongoose": "^8.19.1",
94
+ "passport": "^0.7.0",
95
+ "passport-jwt": "^4.0.1",
96
+ "reflect-metadata": "^0.2.2",
97
+ "rxjs": "^7.8.2",
98
+ "tsup": "^8.1.0",
99
+ "typescript": "^5.4.5",
100
+ "vitest": "^4.1.5"
101
+ }
102
+ }