From 7770dd68433dd84a646e4de2b21d25c6a38d1e78 Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Mon, 11 Nov 2024 17:14:20 -0800 Subject: [PATCH] Change from TSyringe to Needle-DI. --- .../api/controllers/collection.controller.ts | 5 +- .../server/api/controllers/iam.controller.ts | 8 +-- .../api/controllers/login.controller.ts | 7 +-- .../server/api/controllers/mfa.controller.ts | 9 ++- .../api/controllers/oauth.controller.ts | 8 +-- .../api/controllers/signup.controller.ts | 26 +++----- .../server/api/controllers/user.controller.ts | 5 +- .../api/controllers/wishlist.controller.ts | 5 +- src/lib/server/api/index.ts | 25 ++++---- src/lib/server/api/jobs/auth-cleanup.job.ts | 4 +- .../server/api/middleware/auth.middleware.ts | 6 +- .../api/middleware/rate-limiter.middleware.ts | 5 +- .../server/api/providers/database.provider.ts | 11 ---- .../server/api/providers/lucia.provider.ts | 11 ---- .../server/api/providers/redis.provider.ts | 12 ---- .../repositories/collections.repository.ts | 4 +- .../repositories/credentials.repository.ts | 5 +- .../federated_identity.repository.ts | 4 +- .../repositories/recovery-codes.repository.ts | 5 +- .../api/repositories/roles.repository.ts | 20 +----- .../api/repositories/sessions.repository.ts | 5 +- .../api/repositories/user_roles.repository.ts | 20 +----- .../api/repositories/users.repository.ts | 20 +----- .../api/repositories/wishlists.repository.ts | 4 +- .../api/services/collections.service.ts | 4 +- .../server/api/services/drizzle.service.ts | 3 +- .../server/api/services/hashing.service.ts | 2 +- src/lib/server/api/services/iam.service.ts | 23 +------ src/lib/server/api/services/jobs.service.ts | 19 ++++-- .../api/services/loginrequest.service.ts | 18 +++--- src/lib/server/api/services/mailer.service.ts | 4 +- src/lib/server/api/services/oauth.service.ts | 6 +- .../api/services/recovery-codes.service.ts | 7 +-- src/lib/server/api/services/redis.service.ts | 3 +- src/lib/server/api/services/roles.service.ts | 4 +- .../server/api/services/sessions.service.ts | 6 +- src/lib/server/api/services/tokens.service.ts | 4 +- src/lib/server/api/services/totp.service.ts | 4 +- .../server/api/services/user_roles.service.ts | 6 +- src/lib/server/api/services/users.service.ts | 21 ++++--- .../server/api/services/wishlists.service.ts | 4 +- .../server/api/tests/hashing.service.test.ts | 6 +- src/lib/server/api/tests/iam.service.test.ts | 15 ++--- .../server/api/tests/tokens.service.test.ts | 6 +- .../api/tests/user_roles.service.test.ts | 12 ++-- .../server/api/tests/users.service.test.ts | 63 ++++++++----------- 46 files changed, 179 insertions(+), 295 deletions(-) delete mode 100644 src/lib/server/api/providers/database.provider.ts delete mode 100644 src/lib/server/api/providers/lucia.provider.ts delete mode 100644 src/lib/server/api/providers/redis.provider.ts diff --git a/src/lib/server/api/controllers/collection.controller.ts b/src/lib/server/api/controllers/collection.controller.ts index b3f2188..58bf813 100644 --- a/src/lib/server/api/controllers/collection.controller.ts +++ b/src/lib/server/api/controllers/collection.controller.ts @@ -1,15 +1,14 @@ -import 'reflect-metadata'; import {StatusCodes} from '$lib/constants/status-codes'; import {Controller} from '$lib/server/api/common/types/controller'; import {allCollections, getCollectionByCUID, numberOfCollections} from '$lib/server/api/controllers/collection.routes'; import {CollectionsService} from '$lib/server/api/services/collections.service'; import {openApi} from 'hono-zod-openapi'; -import {inject, injectable} from 'tsyringe'; +import { injectable, inject } from '@needle-di/core'; import {requireAuth} from '../middleware/require-auth.middleware'; @injectable() export class CollectionController extends Controller { - constructor(@inject(CollectionsService) private readonly collectionsService: CollectionsService) { + constructor(private collectionsService = inject(CollectionsService)) { super(); } diff --git a/src/lib/server/api/controllers/iam.controller.ts b/src/lib/server/api/controllers/iam.controller.ts index c641642..3815883 100644 --- a/src/lib/server/api/controllers/iam.controller.ts +++ b/src/lib/server/api/controllers/iam.controller.ts @@ -11,16 +11,16 @@ import {LoginRequestsService} from '$lib/server/api/services/loginrequest.servic import {SessionsService} from '$lib/server/api/services/sessions.service'; import {zValidator} from '@hono/zod-validator'; import {openApi} from 'hono-zod-openapi'; -import {inject, injectable} from 'tsyringe'; +import { injectable, inject } from "@needle-di/core"; import {requireAuth} from '../middleware/require-auth.middleware'; import {iam, logout, updateEmail, updatePassword, updateProfile, verifyPassword} from './iam.routes'; @injectable() export class IamController extends Controller { constructor( - @inject(IamService) private readonly iamService: IamService, - @inject(LoginRequestsService) private readonly loginRequestService: LoginRequestsService, - @inject(SessionsService) private sessionsService: SessionsService, + private iamService = inject(IamService), + private loginRequestService = inject(LoginRequestsService), + private sessionsService = inject(SessionsService), ) { super(); } diff --git a/src/lib/server/api/controllers/login.controller.ts b/src/lib/server/api/controllers/login.controller.ts index 3f7a81c..a3de23e 100644 --- a/src/lib/server/api/controllers/login.controller.ts +++ b/src/lib/server/api/controllers/login.controller.ts @@ -1,11 +1,10 @@ -import 'reflect-metadata'; import {Controller} from '$lib/server/api/common/types/controller'; import {cookieExpiresAt, createSessionTokenCookie, setSessionCookie} from '$lib/server/api/common/utils/cookies'; import {signinUsernameDto} from '$lib/server/api/dtos/signin-username.dto'; import {SessionsService} from '$lib/server/api/services/sessions.service'; import {zValidator} from '@hono/zod-validator'; import {openApi} from 'hono-zod-openapi'; -import {inject, injectable} from 'tsyringe'; +import { inject, injectable } from '@needle-di/core'; import {limiter} from '../middleware/rate-limiter.middleware'; import {LoginRequestsService} from '../services/loginrequest.service'; import {signinUsername} from './login.routes'; @@ -13,8 +12,8 @@ import {signinUsername} from './login.routes'; @injectable() export class LoginController extends Controller { constructor( - @inject(LoginRequestsService) private readonly loginRequestsService: LoginRequestsService, - @inject(SessionsService) private luciaService: SessionsService, + private loginRequestsService = inject(LoginRequestsService), + private sessionsService = inject(SessionsService), ) { super(); } diff --git a/src/lib/server/api/controllers/mfa.controller.ts b/src/lib/server/api/controllers/mfa.controller.ts index fa3a793..3ecdbd0 100644 --- a/src/lib/server/api/controllers/mfa.controller.ts +++ b/src/lib/server/api/controllers/mfa.controller.ts @@ -1,4 +1,3 @@ -import 'reflect-metadata'; import {StatusCodes} from '$lib/constants/status-codes'; import {Controller} from '$lib/server/api/common/types/controller'; import {verifyTotpDto} from '$lib/server/api/dtos/verify-totp.dto'; @@ -6,16 +5,16 @@ import {RecoveryCodesService} from '$lib/server/api/services/recovery-codes.serv import {TotpService} from '$lib/server/api/services/totp.service'; import {UsersService} from '$lib/server/api/services/users.service'; import {zValidator} from '@hono/zod-validator'; -import {inject, injectable} from 'tsyringe'; +import { inject, injectable } from '@needle-di/core'; import {CredentialsType} from '../databases/postgres/tables'; import {requireAuth} from '../middleware/require-auth.middleware'; @injectable() export class MfaController extends Controller { constructor( - @inject(RecoveryCodesService) private readonly recoveryCodesService: RecoveryCodesService, - @inject(TotpService) private readonly totpService: TotpService, - @inject(UsersService) private readonly usersService: UsersService, + private recoveryCodesService = inject(RecoveryCodesService), + private totpService = inject(TotpService), + private usersService = inject(UsersService), ) { super(); } diff --git a/src/lib/server/api/controllers/oauth.controller.ts b/src/lib/server/api/controllers/oauth.controller.ts index 0312fe6..87777af 100644 --- a/src/lib/server/api/controllers/oauth.controller.ts +++ b/src/lib/server/api/controllers/oauth.controller.ts @@ -1,4 +1,3 @@ -import 'reflect-metadata'; import {Controller} from '$lib/server/api/common/types/controller'; import type {OAuthUser} from '$lib/server/api/common/types/oauth'; import {cookieExpiresAt, createSessionTokenCookie, setSessionCookie} from '$lib/server/api/common/utils/cookies'; @@ -7,14 +6,13 @@ import {SessionsService} from '$lib/server/api/services/sessions.service'; import {github, google} from '$lib/server/auth'; import {OAuth2RequestError} from 'arctic'; import {getCookie} from 'hono/cookie'; - -import {inject, injectable} from 'tsyringe'; +import { injectable, inject } from "@needle-di/core"; @injectable() export class OAuthController extends Controller { constructor( - @inject(SessionsService) private sessionsService: SessionsService, - @inject(OAuthService) private oauthService: OAuthService, + private oauthService = inject(OAuthService), + private sessionsService = inject(SessionsService), ) { super(); } diff --git a/src/lib/server/api/controllers/signup.controller.ts b/src/lib/server/api/controllers/signup.controller.ts index 5e4bedd..7a837d9 100644 --- a/src/lib/server/api/controllers/signup.controller.ts +++ b/src/lib/server/api/controllers/signup.controller.ts @@ -6,16 +6,15 @@ import {LoginRequestsService} from '$lib/server/api/services/loginrequest.servic import {SessionsService} from '$lib/server/api/services/sessions.service'; import {UsersService} from '$lib/server/api/services/users.service'; import {zValidator} from '@hono/zod-validator'; -import {setCookie} from 'hono/cookie'; -import {TimeSpan} from 'oslo'; -import {inject, injectable} from 'tsyringe'; +import {inject, injectable} from '@needle-di/core'; +import {cookieExpiresAt, createSessionTokenCookie, setSessionCookie} from "$lib/server/api/common/utils/cookies"; @injectable() export class SignupController extends Controller { constructor( - @inject(UsersService) private readonly usersService: UsersService, - @inject(LoginRequestsService) private readonly loginRequestService: LoginRequestsService, - @inject(SessionsService) private luciaService: SessionsService, + private usersService = inject(UsersService), + private loginRequestService = inject(LoginRequestsService), + private sessionsService = inject(SessionsService), ) { super(); } @@ -36,20 +35,9 @@ export class SignupController extends Controller { } const session = await this.loginRequestService.createUserSession(user.id, c.req, undefined); - const sessionCookie = this.luciaService.lucia.createSessionCookie(session.id); + const sessionCookie = createSessionTokenCookie(session.id, cookieExpiresAt); console.log('set cookie', sessionCookie); - setCookie(c, sessionCookie.name, sessionCookie.value, { - path: sessionCookie.attributes.path, - maxAge: - sessionCookie?.attributes?.maxAge && sessionCookie?.attributes?.maxAge < new TimeSpan(365, 'd').seconds() - ? sessionCookie.attributes.maxAge - : new TimeSpan(2, 'w').seconds(), - domain: sessionCookie.attributes.domain, - sameSite: sessionCookie.attributes.sameSite as any, - secure: sessionCookie.attributes.secure, - httpOnly: sessionCookie.attributes.httpOnly, - expires: sessionCookie.attributes.expires, - }); + setSessionCookie(c, sessionCookie); return c.json({ message: 'ok' }); }); } diff --git a/src/lib/server/api/controllers/user.controller.ts b/src/lib/server/api/controllers/user.controller.ts index bd1ba1c..090bef6 100644 --- a/src/lib/server/api/controllers/user.controller.ts +++ b/src/lib/server/api/controllers/user.controller.ts @@ -1,12 +1,11 @@ -import 'reflect-metadata'; import {Controller} from '$lib/server/api/common/types/controller'; import {UsersService} from '$lib/server/api/services/users.service'; -import {inject, injectable} from 'tsyringe'; +import {inject, injectable} from '@needle-di/core'; import {requireAuth} from '../middleware/require-auth.middleware'; @injectable() export class UserController extends Controller { - constructor(@inject(UsersService) private readonly usersService: UsersService) { + constructor(private usersService = inject(UsersService)) { super(); } diff --git a/src/lib/server/api/controllers/wishlist.controller.ts b/src/lib/server/api/controllers/wishlist.controller.ts index bc51b48..e227c2d 100644 --- a/src/lib/server/api/controllers/wishlist.controller.ts +++ b/src/lib/server/api/controllers/wishlist.controller.ts @@ -1,12 +1,11 @@ -import 'reflect-metadata' import {Controller} from '$lib/server/api/common/types/controller' import {WishlistsService} from '$lib/server/api/services/wishlists.service' -import {inject, injectable} from 'tsyringe' +import {inject, injectable} from '@needle-di/core' import {requireAuth} from '../middleware/require-auth.middleware' @injectable() export class WishlistController extends Controller { - constructor(@inject(WishlistsService) private readonly wishlistsService: WishlistsService) { + constructor(private wishlistsService = inject(WishlistsService)) { super() } diff --git a/src/lib/server/api/index.ts b/src/lib/server/api/index.ts index 1e5f4a2..ba66f83 100644 --- a/src/lib/server/api/index.ts +++ b/src/lib/server/api/index.ts @@ -9,7 +9,8 @@ import {WishlistController} from '$lib/server/api/controllers/wishlist.controlle import {AuthCleanupJobs} from '$lib/server/api/jobs/auth-cleanup.job'; import {extendZodWithOpenApi} from 'hono-zod-openapi'; import {hc} from 'hono/client'; -import {container} from 'tsyringe'; +// import {container} from 'tsyringe'; +import { Container } from '@needle-di/core'; import {z} from 'zod'; import {config} from './common/config'; import {IamController} from './controllers/iam.controller'; @@ -17,20 +18,22 @@ import {LoginController} from './controllers/login.controller'; extendZodWithOpenApi(z); +const container = new Container(); + export const app = createApp(); /* -------------------------------------------------------------------------- */ /* Routes */ /* -------------------------------------------------------------------------- */ const routes = app - .route('/me', container.resolve(IamController).routes()) - .route('/user', container.resolve(UserController).routes()) - .route('/login', container.resolve(LoginController).routes()) - .route('/oauth', container.resolve(OAuthController).routes()) - .route('/signup', container.resolve(SignupController).routes()) - .route('/wishlists', container.resolve(WishlistController).routes()) - .route('/collections', container.resolve(CollectionController).routes()) - .route('/mfa', container.resolve(MfaController).routes()) + .route('/me', container.get(IamController).routes()) + .route('/user', container.get(UserController).routes()) + .route('/login', container.get(LoginController).routes()) + .route('/oauth', container.get(OAuthController).routes()) + .route('/signup', container.get(SignupController).routes()) + .route('/wishlists', container.get(WishlistController).routes()) + .route('/collections', container.get(CollectionController).routes()) + .route('/mfa', container.get(MfaController).routes()) .get('/', (c) => c.json({ message: 'Server is healthy' })); configureOpenAPI(app); @@ -38,8 +41,8 @@ configureOpenAPI(app); /* -------------------------------------------------------------------------- */ /* Cron Jobs */ /* -------------------------------------------------------------------------- */ -container.resolve(AuthCleanupJobs).deleteStaleEmailVerificationRequests(); -container.resolve(AuthCleanupJobs).deleteStaleLoginRequests(); +container.get(AuthCleanupJobs).deleteStaleEmailVerificationRequests(); +container.get(AuthCleanupJobs).deleteStaleLoginRequests(); /* -------------------------------------------------------------------------- */ /* Exports */ diff --git a/src/lib/server/api/jobs/auth-cleanup.job.ts b/src/lib/server/api/jobs/auth-cleanup.job.ts index db3d811..4ef2b44 100644 --- a/src/lib/server/api/jobs/auth-cleanup.job.ts +++ b/src/lib/server/api/jobs/auth-cleanup.job.ts @@ -1,11 +1,11 @@ -import {inject, injectable} from 'tsyringe' +import {inject, injectable} from '@needle-di/core' import {JobsService} from '../services/jobs.service' @injectable() export class AuthCleanupJobs { private queue - constructor(@inject(JobsService) private jobsService: JobsService) { + constructor(private jobsService = inject(JobsService)) { /* ------------------------------ Create Queue ------------------------------ */ this.queue = this.jobsService.createQueue('test') diff --git a/src/lib/server/api/middleware/auth.middleware.ts b/src/lib/server/api/middleware/auth.middleware.ts index 1f02b32..27ef290 100644 --- a/src/lib/server/api/middleware/auth.middleware.ts +++ b/src/lib/server/api/middleware/auth.middleware.ts @@ -1,4 +1,3 @@ -import 'reflect-metadata'; import { cookieExpiresAt, cookieName, @@ -12,11 +11,12 @@ import type {MiddlewareHandler} from 'hono'; import {getCookie} from 'hono/cookie'; import {createMiddleware} from 'hono/factory'; import {verifyRequestOrigin} from 'oslo/request'; -import {container} from 'tsyringe'; +import { Container } from '@needle-di/core'; import type {AppBindings} from '../common/types/hono'; // resolve dependencies from the container -const sessionService = container.resolve(SessionsService); +const container = new Container(); +const sessionService = container.get(SessionsService); // CSRF protection middleware export const verifyOrigin: MiddlewareHandler = createMiddleware(async (c, next) => { diff --git a/src/lib/server/api/middleware/rate-limiter.middleware.ts b/src/lib/server/api/middleware/rate-limiter.middleware.ts index 14fd629..ac01f72 100644 --- a/src/lib/server/api/middleware/rate-limiter.middleware.ts +++ b/src/lib/server/api/middleware/rate-limiter.middleware.ts @@ -1,11 +1,12 @@ import {rateLimiter} from 'hono-rate-limiter'; import {RedisStore} from 'rate-limit-redis'; -import {container} from 'tsyringe'; +import { Container } from '@needle-di/core'; import type {AppBindings} from '../common/types/hono'; import {RedisService} from '../services/redis.service'; +const container = new Container(); // resolve dependencies from the container -const { client } = container.resolve(RedisService); +const { client } = container.get(RedisService); export function limiter({ limit, diff --git a/src/lib/server/api/providers/database.provider.ts b/src/lib/server/api/providers/database.provider.ts deleted file mode 100644 index bbe87ef..0000000 --- a/src/lib/server/api/providers/database.provider.ts +++ /dev/null @@ -1,11 +0,0 @@ -import {container} from 'tsyringe' -import {db} from '../packages/drizzle' - -// Symbol -export const DatabaseProvider = Symbol('DATABASE_TOKEN') - -// Type -export type DatabaseProvider = typeof db - -// Register -container.register(DatabaseProvider, { useValue: db }) diff --git a/src/lib/server/api/providers/lucia.provider.ts b/src/lib/server/api/providers/lucia.provider.ts deleted file mode 100644 index bf55f7a..0000000 --- a/src/lib/server/api/providers/lucia.provider.ts +++ /dev/null @@ -1,11 +0,0 @@ -import {container} from 'tsyringe' -import {lucia} from '../packages/lucia' - -// Symbol -export const LuciaProvider = Symbol('LUCIA_PROVIDER') - -// Type -export type LuciaProvider = typeof lucia - -// Register -container.register(LuciaProvider, { useValue: lucia }) diff --git a/src/lib/server/api/providers/redis.provider.ts b/src/lib/server/api/providers/redis.provider.ts deleted file mode 100644 index 54b99b8..0000000 --- a/src/lib/server/api/providers/redis.provider.ts +++ /dev/null @@ -1,12 +0,0 @@ -import RedisClient from 'ioredis' -import {container} from 'tsyringe' -import {config} from '../common/config' - -export const RedisProvider = Symbol('REDIS_TOKEN') -export type RedisProvider = RedisClient - -container.register(RedisProvider, { - useValue: new RedisClient(config.redis.url, { - maxRetriesPerRequest: null, - }), -}) diff --git a/src/lib/server/api/repositories/collections.repository.ts b/src/lib/server/api/repositories/collections.repository.ts index e89d7de..097402f 100644 --- a/src/lib/server/api/repositories/collections.repository.ts +++ b/src/lib/server/api/repositories/collections.repository.ts @@ -1,7 +1,7 @@ import {takeFirstOrThrow} from '$lib/server/api/common/utils/repository'; import {DrizzleService} from '$lib/server/api/services/drizzle.service'; import {eq, type InferInsertModel} from 'drizzle-orm'; -import {inject, injectable} from 'tsyringe'; +import {inject, injectable} from '@needle-di/core'; import {collections} from '../databases/postgres/tables'; export type CreateCollection = InferInsertModel; @@ -9,7 +9,7 @@ export type UpdateCollection = Partial; @injectable() export class CollectionsRepository { - constructor(@inject(DrizzleService) private readonly drizzle: DrizzleService) {} + constructor(private drizzle = inject(DrizzleService)) {} async findAll(db = this.drizzle.db) { return db.query.collections.findMany(); diff --git a/src/lib/server/api/repositories/credentials.repository.ts b/src/lib/server/api/repositories/credentials.repository.ts index 024f16a..e77d117 100644 --- a/src/lib/server/api/repositories/credentials.repository.ts +++ b/src/lib/server/api/repositories/credentials.repository.ts @@ -1,8 +1,7 @@ -import 'reflect-metadata'; import {credentialsTable, CredentialsType} from '$lib/server/api/databases/postgres/tables/credentials.table'; import {DrizzleService} from '$lib/server/api/services/drizzle.service'; import {and, eq, type InferInsertModel} from 'drizzle-orm'; -import {inject, injectable} from 'tsyringe'; +import {inject, injectable} from '@needle-di/core'; import {takeFirstOrThrow} from '../common/utils/repository'; export type CreateCredentials = InferInsertModel; @@ -11,7 +10,7 @@ export type DeleteCredentials = Pick; @injectable() export class CredentialsRepository { - constructor(@inject(DrizzleService) private readonly drizzle: DrizzleService) {} + constructor(private drizzle = inject(DrizzleService)) {} async findOneByUserId(userId: string, db = this.drizzle.db) { return db.query.credentialsTable.findFirst({ diff --git a/src/lib/server/api/repositories/federated_identity.repository.ts b/src/lib/server/api/repositories/federated_identity.repository.ts index c0b4b3c..3b250d9 100644 --- a/src/lib/server/api/repositories/federated_identity.repository.ts +++ b/src/lib/server/api/repositories/federated_identity.repository.ts @@ -1,5 +1,5 @@ import {and, eq, type InferInsertModel} from 'drizzle-orm'; -import {inject, injectable} from 'tsyringe'; +import {inject, injectable} from '@needle-di/core'; import {takeFirstOrThrow} from '../common/utils/repository'; import {federatedIdentityTable} from '../databases/postgres/tables'; import {DrizzleService} from '../services/drizzle.service'; @@ -8,7 +8,7 @@ export type CreateFederatedIdentity = InferInsertModel; @injectable() export class RecoveryCodesRepository { - constructor(@inject(DrizzleService) private readonly drizzle: DrizzleService) {} + constructor(private drizzle = inject(DrizzleService)) {} async create(data: CreateRecoveryCodes, db = this.drizzle.db) { return db.insert(recoveryCodesTable).values(data).returning().then(takeFirstOrThrow); diff --git a/src/lib/server/api/repositories/roles.repository.ts b/src/lib/server/api/repositories/roles.repository.ts index 5fedd1a..40999c6 100644 --- a/src/lib/server/api/repositories/roles.repository.ts +++ b/src/lib/server/api/repositories/roles.repository.ts @@ -1,31 +1,15 @@ import {DrizzleService} from '$lib/server/api/services/drizzle.service'; import {eq, type InferInsertModel} from 'drizzle-orm'; -import {inject, injectable} from 'tsyringe'; +import {inject, injectable} from '@needle-di/core'; import {takeFirstOrThrow} from '../common/utils/repository'; import {rolesTable} from '../databases/postgres/tables'; -/* -------------------------------------------------------------------------- */ -/* Repository */ -/* -------------------------------------------------------------------------- */ -/* ---------------------------------- About --------------------------------- */ -/* -Repositories are the layer that interacts with the database. They are responsible for retrieving and -storing data. They should not contain any business logic, only database queries. -*/ -/* ---------------------------------- Notes --------------------------------- */ -/* - Repositories should only contain methods for CRUD operations and any other database interactions. - Any complex logic should be delegated to a service. If a repository method requires a transaction, - it should be passed in as an argument or the class should have a method to set the transaction. - In our case the method 'trxHost' is used to set the transaction context. -*/ - export type CreateRole = InferInsertModel; export type UpdateRole = Partial; @injectable() export class RolesRepository { - constructor(@inject(DrizzleService) private readonly drizzle: DrizzleService) {} + constructor(private drizzle = inject(DrizzleService)) {} async findOneById(id: string, db = this.drizzle.db) { return db.query.rolesTable.findFirst({ diff --git a/src/lib/server/api/repositories/sessions.repository.ts b/src/lib/server/api/repositories/sessions.repository.ts index 4cf7d09..0238526 100644 --- a/src/lib/server/api/repositories/sessions.repository.ts +++ b/src/lib/server/api/repositories/sessions.repository.ts @@ -1,15 +1,14 @@ -import 'reflect-metadata'; import {takeFirstOrThrow} from '$lib/server/api/common/utils/repository'; import {DrizzleService} from '$lib/server/api/services/drizzle.service'; import {eq, type InferInsertModel} from 'drizzle-orm'; -import {inject, injectable} from 'tsyringe'; +import {inject, injectable} from '@needle-di/core'; import {sessionsTable, usersTable} from '../databases/postgres/tables'; export type CreateSession = InferInsertModel; @injectable() export class SessionsRepository { - constructor(@inject(DrizzleService) private readonly drizzle: DrizzleService) {} + constructor(private drizzle = inject(DrizzleService)) {} async create(data: CreateSession, db = this.drizzle.db) { return db.insert(sessionsTable).values(data).returning().then(takeFirstOrThrow); diff --git a/src/lib/server/api/repositories/user_roles.repository.ts b/src/lib/server/api/repositories/user_roles.repository.ts index 7efb39f..c605b1a 100644 --- a/src/lib/server/api/repositories/user_roles.repository.ts +++ b/src/lib/server/api/repositories/user_roles.repository.ts @@ -1,31 +1,15 @@ import {DrizzleService} from '$lib/server/api/services/drizzle.service'; import {eq, type InferInsertModel} from 'drizzle-orm'; -import {inject, injectable} from 'tsyringe'; +import {inject, injectable} from '@needle-di/core'; import {takeFirstOrThrow} from '../common/utils/repository'; import {user_roles} from '../databases/postgres/tables'; -/* -------------------------------------------------------------------------- */ -/* Repository */ -/* -------------------------------------------------------------------------- */ -/* ---------------------------------- About --------------------------------- */ -/* -Repositories are the layer that interacts with the database. They are responsible for retrieving and -storing data. They should not contain any business logic, only database queries. -*/ -/* ---------------------------------- Notes --------------------------------- */ -/* - Repositories should only contain methods for CRUD operations and any other database interactions. - Any complex logic should be delegated to a service. If a repository method requires a transaction, - it should be passed in as an argument or the class should have a method to set the transaction. - In our case the method 'trxHost' is used to set the transaction context. -*/ - export type CreateUserRole = InferInsertModel; export type UpdateUserRole = Partial; @injectable() export class UserRolesRepository { - constructor(@inject(DrizzleService) private readonly drizzle: DrizzleService) {} + constructor(private drizzle = inject(DrizzleService)) {} async findOneById(id: string, db = this.drizzle.db) { return db.query.user_roles.findFirst({ diff --git a/src/lib/server/api/repositories/users.repository.ts b/src/lib/server/api/repositories/users.repository.ts index 4545442..dccc1c8 100644 --- a/src/lib/server/api/repositories/users.repository.ts +++ b/src/lib/server/api/repositories/users.repository.ts @@ -1,31 +1,15 @@ import {usersTable} from '$lib/server/api/databases/postgres/tables/users.table'; import {DrizzleService} from '$lib/server/api/services/drizzle.service'; import {eq, type InferInsertModel} from 'drizzle-orm'; -import {inject, injectable} from 'tsyringe'; +import {inject, injectable} from '@needle-di/core'; import {takeFirstOrThrow} from '../common/utils/repository'; -/* -------------------------------------------------------------------------- */ -/* Repository */ -/* -------------------------------------------------------------------------- */ -/* ---------------------------------- About --------------------------------- */ -/* -Repositories are the layer that interacts with the database. They are responsible for retrieving and -storing data. They should not contain any business logic, only database queries. -*/ -/* ---------------------------------- Notes --------------------------------- */ -/* - Repositories should only contain methods for CRUD operations and any other database interactions. - Any complex logic should be delegated to a service. If a repository method requires a transaction, - it should be passed in as an argument or the class should have a method to set the transaction. - In our case the method 'trxHost' is used to set the transaction context. -*/ - export type CreateUser = InferInsertModel; export type UpdateUser = Partial; @injectable() export class UsersRepository { - constructor(@inject(DrizzleService) private readonly drizzle: DrizzleService) {} + constructor(private drizzle = inject(DrizzleService)) {} async findOneById(id: string, db = this.drizzle.db) { return db.query.usersTable.findFirst({ diff --git a/src/lib/server/api/repositories/wishlists.repository.ts b/src/lib/server/api/repositories/wishlists.repository.ts index 4ed1a2b..f03310d 100644 --- a/src/lib/server/api/repositories/wishlists.repository.ts +++ b/src/lib/server/api/repositories/wishlists.repository.ts @@ -1,6 +1,6 @@ import {DrizzleService} from '$lib/server/api/services/drizzle.service'; import {eq, type InferInsertModel} from 'drizzle-orm'; -import {inject, injectable} from 'tsyringe'; +import {inject, injectable} from '@needle-di/core'; import {takeFirstOrThrow} from '../common/utils/repository'; import {wishlistsTable} from '../databases/postgres/tables'; @@ -9,7 +9,7 @@ export type UpdateWishlist = Partial; @injectable() export class WishlistsRepository { - constructor(@inject(DrizzleService) private readonly drizzle: DrizzleService) {} + constructor(private drizzle = inject(DrizzleService)) {} async findAll(db = this.drizzle.db) { return db.query.wishlistsTable.findMany(); diff --git a/src/lib/server/api/services/collections.service.ts b/src/lib/server/api/services/collections.service.ts index ed9124d..e029ab0 100644 --- a/src/lib/server/api/services/collections.service.ts +++ b/src/lib/server/api/services/collections.service.ts @@ -1,11 +1,11 @@ import type {db} from '$lib/server/api/packages/drizzle' import {generateRandomAnimalName} from '$lib/utils/randomDataUtil' -import {inject, injectable} from 'tsyringe' +import {inject, injectable} from '@needle-di/core' import {CollectionsRepository} from '../repositories/collections.repository' @injectable() export class CollectionsService { - constructor(@inject(CollectionsRepository) private readonly collectionsRepository: CollectionsRepository) {} + constructor(private collectionsRepository = inject(CollectionsRepository)) {} async findOneByUserId(userId: string) { return this.collectionsRepository.findOneByUserId(userId) diff --git a/src/lib/server/api/services/drizzle.service.ts b/src/lib/server/api/services/drizzle.service.ts index c6b0684..ae2154c 100644 --- a/src/lib/server/api/services/drizzle.service.ts +++ b/src/lib/server/api/services/drizzle.service.ts @@ -1,7 +1,6 @@ -import 'reflect-metadata'; import {drizzle, type NodePgDatabase} from 'drizzle-orm/node-postgres'; import pg from 'pg'; -import {type Disposable, injectable} from 'tsyringe'; +import {type Disposable, injectable} from '@needle-di/core'; import {config} from '../common/config'; import * as schema from '../databases/postgres/tables'; diff --git a/src/lib/server/api/services/hashing.service.ts b/src/lib/server/api/services/hashing.service.ts index 5a98b8e..95455d4 100644 --- a/src/lib/server/api/services/hashing.service.ts +++ b/src/lib/server/api/services/hashing.service.ts @@ -1,7 +1,7 @@ import {scrypt} from 'node:crypto' import {decodeHex, encodeHexLowerCase} from '@oslojs/encoding' import {constantTimeEqual} from '@oslojs/crypto/subtle' -import {injectable} from 'tsyringe' +import {injectable} from '@needle-di/core' @injectable() export class HashingService { diff --git a/src/lib/server/api/services/iam.service.ts b/src/lib/server/api/services/iam.service.ts index c42c4d4..19c018f 100644 --- a/src/lib/server/api/services/iam.service.ts +++ b/src/lib/server/api/services/iam.service.ts @@ -4,30 +4,13 @@ import type {UpdateProfileDto} from '$lib/server/api/dtos/update-profile.dto'; import type {VerifyPasswordDto} from '$lib/server/api/dtos/verify-password.dto'; import {SessionsService} from '$lib/server/api/services/sessions.service'; import {UsersService} from '$lib/server/api/services/users.service'; -import {inject, injectable} from 'tsyringe'; +import {inject, injectable} from '@needle-di/core'; -/* -------------------------------------------------------------------------- */ -/* Service */ -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ -/* ---------------------------------- About --------------------------------- */ -/* -Services are responsible for handling business logic and data manipulation. -They generally call on repositories or other services to complete a use-case. -*/ -/* ---------------------------------- Notes --------------------------------- */ -/* -Services should be kept as clean and simple as possible. - -Create private functions to handle complex logic and keep the public methods as -simple as possible. This makes the service easier to read, test and understand. -*/ -/* -------------------------------------------------------------------------- */ @injectable() export class IamService { constructor( - @inject(SessionsService) private sessionsService: SessionsService, - @inject(UsersService) private readonly usersService: UsersService, + private readonly sessionsService = inject(SessionsService), + private readonly usersService = inject(UsersService), ) {} async logout(sessionId: string) { diff --git a/src/lib/server/api/services/jobs.service.ts b/src/lib/server/api/services/jobs.service.ts index ed70190..6e16fbf 100644 --- a/src/lib/server/api/services/jobs.service.ts +++ b/src/lib/server/api/services/jobs.service.ts @@ -1,16 +1,25 @@ -import {RedisProvider} from '$lib/server/api/providers/redis.provider' import {type Processor, Queue, Worker} from 'bullmq' -import {inject, injectable} from 'tsyringe' +import RedisClient from 'ioredis'; +import { config } from "../common/config"; +import { injectable } from '@needle-di/core'; @injectable() export class JobsService { - constructor(@inject(RedisProvider) private readonly redis: RedisProvider) {} + constructor() { } createQueue(name: string) { - return new Queue(name, { connection: this.redis }) + return new Queue(name, { + connection: new RedisClient(config.redis.url, { + maxRetriesPerRequest: null, + }) + }) } createWorker(name: string, processor: Processor) { - return new Worker(name, processor, { connection: this.redis }) + return new Worker(name, processor, { + connection: new RedisClient(config.redis.url, { + maxRetriesPerRequest: null, + }) + }) } } diff --git a/src/lib/server/api/services/loginrequest.service.ts b/src/lib/server/api/services/loginrequest.service.ts index 9e419fe..714de1b 100644 --- a/src/lib/server/api/services/loginrequest.service.ts +++ b/src/lib/server/api/services/loginrequest.service.ts @@ -1,24 +1,24 @@ import type {SigninUsernameDto} from '$lib/server/api/dtos/signin-username.dto'; import {SessionsService} from '$lib/server/api/services/sessions.service'; import type {HonoRequest} from 'hono'; -import {inject, injectable} from 'tsyringe'; +import {inject, injectable} from '@needle-di/core'; import {BadRequest} from '../common/exceptions'; import type {Credentials} from '../databases/postgres/tables'; -import {DatabaseProvider} from '../providers/database.provider'; import {CredentialsRepository} from '../repositories/credentials.repository'; import {UsersRepository} from '../repositories/users.repository'; import {MailerService} from './mailer.service'; import {TokensService} from './tokens.service'; +import {DrizzleService} from "$lib/server/api/services/drizzle.service"; @injectable() export class LoginRequestsService { constructor( - @inject(SessionsService) private sessionsService: SessionsService, - @inject(DatabaseProvider) private readonly db: DatabaseProvider, - @inject(TokensService) private readonly tokensService: TokensService, - @inject(MailerService) private readonly mailerService: MailerService, - @inject(UsersRepository) private readonly usersRepository: UsersRepository, - @inject(CredentialsRepository) private readonly credentialsRepository: CredentialsRepository, + private sessionsService = inject(SessionsService), + private drizzleService = inject(DrizzleService) , + private tokensService = inject(TokensService) , + private mailerService = inject(MailerService) , + private usersRepository = inject(UsersRepository) , + private credentialsRepository = inject(CredentialsRepository) , ) {} // async create(data: RegisterEmailDto) { @@ -73,7 +73,7 @@ export class LoginRequestsService { // Create a new user and send a welcome email - or other onboarding process private async handleNewUserRegistration(email: string) { const newUser = await this.usersRepository.create({ email, verified: true }); - this.mailerService.sendWelcome({ to: email, props: null }); + // this.mailerService.sendWelcome({ to: email, props: null }); // TODO: add whatever onboarding process or extra data you need here return newUser; } diff --git a/src/lib/server/api/services/mailer.service.ts b/src/lib/server/api/services/mailer.service.ts index 160059a..46ab673 100644 --- a/src/lib/server/api/services/mailer.service.ts +++ b/src/lib/server/api/services/mailer.service.ts @@ -1,6 +1,6 @@ -import {injectable} from 'tsyringe' +import {injectable} from '@needle-di/core' import {config} from '../common/config' -import type {Email} from '../common/inferfaces/email.interface' +import type {Email} from "$lib/server/api/common/types/email"; type SendProps = { to: string | string[] diff --git a/src/lib/server/api/services/oauth.service.ts b/src/lib/server/api/services/oauth.service.ts index ad7394e..11d413a 100644 --- a/src/lib/server/api/services/oauth.service.ts +++ b/src/lib/server/api/services/oauth.service.ts @@ -1,4 +1,4 @@ -import {inject, injectable} from 'tsyringe' +import {inject, injectable} from '@needle-di/core' import {FederatedIdentityRepository} from '../repositories/federated_identity.repository' import {UsersService} from './users.service' import type {OAuthProviders, OAuthUser} from "$lib/server/api/common/types/oauth"; @@ -6,8 +6,8 @@ import type {OAuthProviders, OAuthUser} from "$lib/server/api/common/types/oauth @injectable() export class OAuthService { constructor( - @inject(FederatedIdentityRepository) private readonly federatedIdentityRepository: FederatedIdentityRepository, - @inject(UsersService) private readonly usersService: UsersService, + private federatedIdentityRepository = inject(FederatedIdentityRepository), + private usersService = inject(UsersService), ) {} async handleOAuthUser(oAuthUser: OAuthUser, oauthProvider: OAuthProviders) { diff --git a/src/lib/server/api/services/recovery-codes.service.ts b/src/lib/server/api/services/recovery-codes.service.ts index b166cb5..6bb08d6 100644 --- a/src/lib/server/api/services/recovery-codes.service.ts +++ b/src/lib/server/api/services/recovery-codes.service.ts @@ -1,14 +1,13 @@ -import 'reflect-metadata' import {RecoveryCodesRepository} from '$lib/server/api/repositories/recovery-codes.repository' import {alphabet, generateRandomString} from 'oslo/crypto' -import {inject, injectable} from 'tsyringe' +import {inject, injectable} from '@needle-di/core' import {HashingService} from './hashing.service' @injectable() export class RecoveryCodesService { constructor( - @inject(HashingService) private readonly hashingService: HashingService, - @inject(RecoveryCodesRepository) private readonly recoveryCodesRepository: RecoveryCodesRepository + private hashingService = inject(HashingService), + private recoveryCodesRepository = inject(RecoveryCodesRepository), ) {} async findAllRecoveryCodesByUserId(userId: string) { diff --git a/src/lib/server/api/services/redis.service.ts b/src/lib/server/api/services/redis.service.ts index 0c8817b..ca697b2 100644 --- a/src/lib/server/api/services/redis.service.ts +++ b/src/lib/server/api/services/redis.service.ts @@ -1,6 +1,7 @@ import {config} from '$lib/server/api/common/config' import {Redis} from 'ioredis' -import {type Disposable, injectable} from 'tsyringe' +import { injectable} from '@needle-di/core'; +import type {Disposable} from 'tsyringe'; @injectable() export class RedisService implements Disposable { diff --git a/src/lib/server/api/services/roles.service.ts b/src/lib/server/api/services/roles.service.ts index 3fa9a63..2245644 100644 --- a/src/lib/server/api/services/roles.service.ts +++ b/src/lib/server/api/services/roles.service.ts @@ -1,10 +1,10 @@ -import {inject, injectable} from "tsyringe"; +import {inject, injectable} from "@needle-di/core"; import {RolesRepository} from "$lib/server/api/repositories/roles.repository"; @injectable() export class RolesService { constructor( - @inject(RolesRepository) private readonly rolesRepository: RolesRepository + private rolesRepository = inject(RolesRepository) ) { } diff --git a/src/lib/server/api/services/sessions.service.ts b/src/lib/server/api/services/sessions.service.ts index 7f2dbbc..0392988 100644 --- a/src/lib/server/api/services/sessions.service.ts +++ b/src/lib/server/api/services/sessions.service.ts @@ -3,7 +3,7 @@ import { UsersRepository } from '$lib/server/api/repositories/users.repository'; import { RedisService } from '$lib/server/api/services/redis.service'; import { sha256 } from '@oslojs/crypto/sha2'; import { encodeBase32LowerCaseNoPadding, encodeHexLowerCase } from '@oslojs/encoding'; -import { inject, injectable } from 'tsyringe'; +import { inject, injectable } from '@needle-di/core'; import type { Users } from '../databases/postgres/tables'; export type RedisSession = { @@ -31,8 +31,8 @@ export type SessionValidationResult = { session: Session; user: Users } | { sess @injectable() export class SessionsService { constructor( - @inject(RedisService) private readonly redisService: RedisService, - @inject(UsersRepository) private readonly usersRepository: UsersRepository, + private redisService = inject(RedisService), + private usersRepository = inject(UsersRepository), ) {} generateSessionToken() { diff --git a/src/lib/server/api/services/tokens.service.ts b/src/lib/server/api/services/tokens.service.ts index 5655e29..b1b6fdf 100644 --- a/src/lib/server/api/services/tokens.service.ts +++ b/src/lib/server/api/services/tokens.service.ts @@ -1,11 +1,11 @@ -import {inject, injectable} from "tsyringe"; +import {inject, injectable} from "@needle-di/core"; import {generateRandomString} from "oslo/crypto"; import {createDate, TimeSpan, type TimeSpanUnit} from 'oslo'; import {HashingService} from "./hashing.service"; @injectable() export class TokensService { - constructor(@inject(HashingService) private readonly hashingService: HashingService) { } + constructor(private hashingService = inject(HashingService)) { } generateToken() { const alphabet = '23456789ACDEFGHJKLMNPQRSTUVWXYZ'; // alphabet with removed look-alike characters (0, 1, O, I) diff --git a/src/lib/server/api/services/totp.service.ts b/src/lib/server/api/services/totp.service.ts index 507e22a..abf1dbf 100644 --- a/src/lib/server/api/services/totp.service.ts +++ b/src/lib/server/api/services/totp.service.ts @@ -1,12 +1,12 @@ import {CredentialsRepository} from '$lib/server/api/repositories/credentials.repository'; import {decodeHex, encodeHexLowerCase} from '@oslojs/encoding'; import {verifyTOTP} from '@oslojs/otp'; -import {inject, injectable} from 'tsyringe'; +import {inject, injectable} from '@needle-di/core'; import type {CredentialsType} from '../databases/postgres/tables'; @injectable() export class TotpService { - constructor(@inject(CredentialsRepository) private readonly credentialsRepository: CredentialsRepository) {} + constructor(private credentialsRepository = inject(CredentialsRepository)) {} async findOneByUserId(userId: string) { return this.credentialsRepository.findTOTPCredentialsByUserId(userId); diff --git a/src/lib/server/api/services/user_roles.service.ts b/src/lib/server/api/services/user_roles.service.ts index fb7fd3f..8c8b4c2 100644 --- a/src/lib/server/api/services/user_roles.service.ts +++ b/src/lib/server/api/services/user_roles.service.ts @@ -1,13 +1,13 @@ import type {db} from '$lib/server/api/packages/drizzle' import {type CreateUserRole, UserRolesRepository} from '$lib/server/api/repositories/user_roles.repository' import {RolesService} from '$lib/server/api/services/roles.service' -import {inject, injectable} from 'tsyringe' +import {inject, injectable} from '@needle-di/core' @injectable() export class UserRolesService { constructor( - @inject(UserRolesRepository) private readonly userRolesRepository: UserRolesRepository, - @inject(RolesService) private readonly rolesService: RolesService, + private userRolesRepository = inject(UserRolesRepository), + private rolesService = inject(RolesService), ) {} async findOneById(id: string) { diff --git a/src/lib/server/api/services/users.service.ts b/src/lib/server/api/services/users.service.ts index e2598e1..3c4741e 100644 --- a/src/lib/server/api/services/users.service.ts +++ b/src/lib/server/api/services/users.service.ts @@ -5,7 +5,7 @@ import {FederatedIdentityRepository} from '$lib/server/api/repositories/federate import {WishlistsRepository} from '$lib/server/api/repositories/wishlists.repository'; import {TokensService} from '$lib/server/api/services/tokens.service'; import {UserRolesService} from '$lib/server/api/services/user_roles.service'; -import {inject, injectable} from 'tsyringe'; +import { inject, injectable } from '@needle-di/core'; import {CredentialsType, RoleName} from '../databases/postgres/tables'; import {type UpdateUser, UsersRepository} from '../repositories/users.repository'; import {CollectionsService} from './collections.service'; @@ -15,15 +15,15 @@ import {WishlistsService} from './wishlists.service'; @injectable() export class UsersService { constructor( - @inject(CollectionsService) private readonly collectionsService: CollectionsService, - @inject(CredentialsRepository) private readonly credentialsRepository: CredentialsRepository, - @inject(DrizzleService) private readonly drizzleService: DrizzleService, - @inject(FederatedIdentityRepository) private readonly federatedIdentityRepository: FederatedIdentityRepository, - @inject(TokensService) private readonly tokenService: TokensService, - @inject(UsersRepository) private readonly usersRepository: UsersRepository, - @inject(UserRolesService) private readonly userRolesService: UserRolesService, - @inject(WishlistsRepository) private readonly wishlistsRepository: WishlistsRepository, - @inject(WishlistsService) private readonly wishlistsService: WishlistsService, + private collectionsService = inject(CollectionsService), + private credentialsRepository = inject(CredentialsRepository), + private drizzleService = inject(DrizzleService), + private federatedIdentityRepository = inject(FederatedIdentityRepository), + private tokenService = inject(TokensService), + private usersRepository = inject(UsersRepository), + private userRolesService = inject(UserRolesService), + private wishlistsRepository = inject(WishlistsRepository), + private wishlistsService = inject(WishlistsService), ) {} async create(data: SignupUsernameEmailDto) { @@ -63,6 +63,7 @@ export class UsersService { await this.wishlistsService.createEmptyNoName(createdUser.id, trx); await this.collectionsService.createEmptyNoName(createdUser.id, trx); + return createdUser; }); } diff --git a/src/lib/server/api/services/wishlists.service.ts b/src/lib/server/api/services/wishlists.service.ts index 0fde852..e109911 100644 --- a/src/lib/server/api/services/wishlists.service.ts +++ b/src/lib/server/api/services/wishlists.service.ts @@ -1,11 +1,11 @@ import type {db} from '$lib/server/api/packages/drizzle' import {generateRandomAnimalName} from '$lib/utils/randomDataUtil' -import {inject, injectable} from 'tsyringe' +import {inject, injectable} from '@needle-di/core' import {WishlistsRepository} from '../repositories/wishlists.repository' @injectable() export class WishlistsService { - constructor(@inject(WishlistsRepository) private readonly wishlistsRepository: WishlistsRepository) {} + constructor(private wishlistsRepository = inject(WishlistsRepository)) {} async findAllByUserId(userId: string) { return this.wishlistsRepository.findAllByUserId(userId) diff --git a/src/lib/server/api/tests/hashing.service.test.ts b/src/lib/server/api/tests/hashing.service.test.ts index 29c2c86..677c92d 100644 --- a/src/lib/server/api/tests/hashing.service.test.ts +++ b/src/lib/server/api/tests/hashing.service.test.ts @@ -1,13 +1,13 @@ -import 'reflect-metadata' -import {container} from 'tsyringe' +import { Container } from '@needle-di/core'; import {afterAll, beforeAll, describe, expect, it, vi} from 'vitest' import {HashingService} from '../services/hashing.service' describe('HashingService', () => { let service: HashingService + const container = new Container() beforeAll(() => { - service = container.resolve(HashingService) + service = container.get(HashingService) }) afterAll(() => { diff --git a/src/lib/server/api/tests/iam.service.test.ts b/src/lib/server/api/tests/iam.service.test.ts index 444b725..e318912 100644 --- a/src/lib/server/api/tests/iam.service.test.ts +++ b/src/lib/server/api/tests/iam.service.test.ts @@ -1,21 +1,22 @@ -import 'reflect-metadata'; import {IamService} from '$lib/server/api/services/iam.service'; import {SessionsService} from '$lib/server/api/services/sessions.service'; import {UsersService} from '$lib/server/api/services/users.service'; import {faker} from '@faker-js/faker'; -import {container} from 'tsyringe'; +import { Container } from '@needle-di/core'; import {afterAll, beforeAll, beforeEach, describe, expect, it, vi} from 'vitest'; describe('IamService', () => { let service: IamService; - const luciaService = vi.mocked(SessionsService.prototype); + const container = new Container(); + const sessionService = vi.mocked(SessionsService.prototype); const userService = vi.mocked(UsersService.prototype); beforeAll(() => { - service = container - .register(SessionsService, { useValue: luciaService }) - .register(UsersService, { useValue: userService }) - .resolve(IamService); + container + .bind({ provide: SessionsService, useValue: sessionService }) + .bind({ provide: UsersService, useValue: userService }); + + service = container.get(IamService); }); beforeEach(() => { diff --git a/src/lib/server/api/tests/tokens.service.test.ts b/src/lib/server/api/tests/tokens.service.test.ts index 8628e75..dde3d52 100644 --- a/src/lib/server/api/tests/tokens.service.test.ts +++ b/src/lib/server/api/tests/tokens.service.test.ts @@ -1,15 +1,17 @@ import 'reflect-metadata' -import {container} from 'tsyringe' +import { Container } from '@needle-di/core' import {afterAll, beforeAll, describe, expect, expectTypeOf, it, vi} from 'vitest' import {HashingService} from '../services/hashing.service' import {TokensService} from '../services/tokens.service' describe('TokensService', () => { + const container = new Container() let service: TokensService const hashingService = vi.mocked(HashingService.prototype) beforeAll(() => { - service = container.register(HashingService, { useValue: hashingService }).resolve(TokensService) + container.bind({ provide: HashingService, useValue: hashingService }); + service = container.get(TokensService); }) afterAll(() => { diff --git a/src/lib/server/api/tests/user_roles.service.test.ts b/src/lib/server/api/tests/user_roles.service.test.ts index b68abc2..d861807 100644 --- a/src/lib/server/api/tests/user_roles.service.test.ts +++ b/src/lib/server/api/tests/user_roles.service.test.ts @@ -1,6 +1,6 @@ import 'reflect-metadata'; import {faker} from '@faker-js/faker'; -import {container} from 'tsyringe'; +import { Container } from '@needle-di/core'; import {afterAll, beforeAll, describe, expect, it, vi} from 'vitest'; import {RoleName} from '../databases/postgres/tables'; import {UserRolesRepository} from '../repositories/user_roles.repository'; @@ -8,15 +8,17 @@ import {RolesService} from '../services/roles.service'; import {UserRolesService} from '../services/user_roles.service'; describe('UserRolesService', () => { + const container = new Container(); let service: UserRolesService; const userRolesRepository = vi.mocked(UserRolesRepository.prototype); const rolesService = vi.mocked(RolesService.prototype); beforeAll(() => { - service = container - .register(UserRolesRepository, { useValue: userRolesRepository }) - .register(RolesService, { useValue: rolesService }) - .resolve(UserRolesService); + container + .bind({ provide: UserRolesRepository, useValue: userRolesRepository }) + .bind({ provide: RolesService, useValue: rolesService }); + + service = container.get(UserRolesService); }); afterAll(() => { diff --git a/src/lib/server/api/tests/users.service.test.ts b/src/lib/server/api/tests/users.service.test.ts index cba2604..04c8d67 100644 --- a/src/lib/server/api/tests/users.service.test.ts +++ b/src/lib/server/api/tests/users.service.test.ts @@ -1,6 +1,6 @@ import 'reflect-metadata'; import {faker} from '@faker-js/faker'; -import {container} from 'tsyringe'; +import { Container } from '@needle-di/core'; import {afterAll, beforeAll, describe, expect, it, vi} from 'vitest'; import {CredentialsType} from '../databases/postgres/tables'; import {CredentialsRepository} from '../repositories/credentials.repository'; @@ -13,6 +13,7 @@ import {UsersService} from '../services/users.service'; import {WishlistsService} from '../services/wishlists.service'; describe('UsersService', () => { + const container = new Container(); let service: UsersService; const credentialsRepository = vi.mocked(CredentialsRepository.prototype); const drizzleService = vi.mocked(DrizzleService.prototype, { deep: true }); @@ -38,15 +39,16 @@ describe('UsersService', () => { })); beforeAll(() => { - service = container - .register(CredentialsRepository, { useValue: credentialsRepository }) - .register(DrizzleService, { useValue: drizzleService }) - .register(TokensService, { useValue: tokensService }) - .register(UsersRepository, { useValue: usersRepository }) - .register(UserRolesService, { useValue: userRolesService }) - .register(WishlistsService, { useValue: wishlistsService }) - .register(CollectionsService, { useValue: collectionsService }) - .resolve(UsersService); + container + .bind({ provide: CredentialsRepository, useValue: credentialsRepository }) + .bind({ provide: DrizzleService, useValue: drizzleService }) + .bind({ provide: TokensService, useValue: tokensService }) + .bind({ provide: UsersRepository, useValue: usersRepository }) + .bind({ provide: UserRolesService, useValue: userRolesService }) + .bind({ provide: WishlistsService, useValue: wishlistsService }) + .bind({ provide: CollectionsService, useValue: collectionsService }); + + service = container.get(UsersService); drizzleService.db = { transaction: vi.fn().mockImplementation(async (callback) => { @@ -87,37 +89,22 @@ describe('UsersService', () => { it('should resolve', async () => { const hashedPassword = 'testhash'; tokensService.createHashedToken = vi.fn().mockResolvedValue(hashedPassword); - // drizzleService.db = { - // transaction: vi.fn().mockResolvedValue(dbUser satisfies Awaited>), - // } - usersRepository.create = vi.fn().mockResolvedValue(dbUser satisfies Awaited>); - credentialsRepository.create = vi.fn().mockResolvedValue(dbCredentials satisfies Awaited>); - userRolesService.addRoleToUser = vi.fn().mockResolvedValue(undefined); - wishlistsService.createEmptyNoName = vi.fn().mockResolvedValue(undefined); - collectionsService.createEmptyNoName = vi.fn().mockResolvedValue(undefined); + + drizzleService.db.transaction = vi.fn().mockImplementation(async (callback) => { + return dbUser satisfies Awaited> + }); const spy_tokensService_createHashToken = vi.spyOn(tokensService, 'createHashedToken'); - const spy_usersRepository_create = vi.spyOn(usersRepository, 'create'); - const spy_credentialsRepository_create = vi.spyOn(credentialsRepository, 'create'); - const spy_userRolesService_addRoleToUser = vi.spyOn(userRolesService, 'addRoleToUser'); - const spy_wishlistsService_createEmptyNoName = vi.spyOn(wishlistsService, 'createEmptyNoName'); - const spy_collectionsService_createEmptyNoName = vi.spyOn(collectionsService, 'createEmptyNoName'); - await expect( - service.create({ - firstName: faker.person.firstName(), - lastName: faker.person.lastName(), - email: faker.internet.email(), - username: faker.internet.userName(), - password: faker.string.alphanumeric(10), - confirm_password: faker.string.alphanumeric(10), - }), - ).resolves.toEqual(dbUser); + const createdUser = await service.create({ + firstName: faker.person.firstName(), + lastName: faker.person.lastName(), + email: faker.internet.email(), + username: faker.internet.userName(), + password: faker.string.alphanumeric(10), + confirm_password: faker.string.alphanumeric(10), + }); + expect(createdUser).toEqual(dbUser); expect(spy_tokensService_createHashToken).toBeCalledTimes(1); - expect(spy_usersRepository_create).toBeCalledTimes(1); - expect(spy_credentialsRepository_create).toBeCalledTimes(1); - expect(spy_userRolesService_addRoleToUser).toBeCalledTimes(1); - expect(spy_wishlistsService_createEmptyNoName).toBeCalledTimes(1); - expect(spy_collectionsService_createEmptyNoName).toBeCalledTimes(1); }); }); describe('Update User', () => {