From 00b3b83074c7733c8f2054011d768fd6837d055d Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Sat, 24 May 2025 21:05:12 -0500 Subject: [PATCH] chore: run format and lint --- .vscode/settings.json | 7 ++----- README.md | 38 ++++++++++++++++++++++---------------- src/index.ts | 32 ++++++++++++++++---------------- tests/index.spec.ts | 7 +++---- 4 files changed, 43 insertions(+), 41 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index e7e2c0a..9844d3f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,3 @@ { - "cSpell.words": [ - "netdi", - "stevanfreeborn" - ] -} \ No newline at end of file + "cSpell.words": ["netdi", "stevanfreeborn"] +} diff --git a/README.md b/README.md index a5b77ce..fc32a8f 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,13 @@ pnpm add @stevanfreeborn/hono-netdi hono ```typescript import { Hono } from 'hono'; -import { ServiceCollection, createServiceIdentifier, injectable, injectServices, useService } from '@stevanfreeborn/hono-netdi'; +import { + ServiceCollection, + createServiceIdentifier, + injectable, + injectServices, + useService, +} from '@stevanfreeborn/hono-netdi'; // Define your service interface and implementation interface IUserService { @@ -56,7 +62,7 @@ const app = new Hono(); app.use(injectServices(serviceProvider)); // Use services in your routes -app.get('/users/:id', async (c) => { +app.get('/users/:id', async c => { const userService = useService(c, IUserService); const user = await userService.getUser(c.req.param('id')); return c.json(user); @@ -135,7 +141,7 @@ import { injectable, inject } from '@stevanfreeborn/hono-netdi'; class UserService implements IUserService { constructor( @inject(IUserRepository) private userRepository: IUserRepository, - @inject(ILogger) private logger: ILogger + @inject(ILogger) private logger: ILogger, ) {} } ``` @@ -232,7 +238,7 @@ class UserRepository implements IUserRepository { class UserService implements IUserService { constructor( @inject(IUserRepository) private userRepository: IUserRepository, - @inject(ILogger) private logger: ILogger + @inject(ILogger) private logger: ILogger, ) {} async getUser(id: string): Promise { @@ -284,13 +290,13 @@ services.addScoped(EmailNotification, EmailNotificationService); services.addScoped(SmsNotification, SmsNotificationService); // Use in routes -app.post('/notify', async (c) => { +app.post('/notify', async c => { const emailService = useService(c, EmailNotification); const smsService = useService(c, SmsNotification); - + await emailService.send('Hello via email!'); await smsService.send('Hello via SMS!'); - + return c.json({ success: true }); }); ``` @@ -326,10 +332,10 @@ const IDatabase = createServiceIdentifier(); services.addSingleton(IDatabaseConfig, () => ({ connectionString: process.env.DB_CONNECTION_STRING!, - timeout: 30000 + timeout: 30000, })); -services.addScoped(IDatabase, (provider) => { +services.addScoped(IDatabase, provider => { const config = provider.getService(IDatabaseConfig); return new Database(config); }); @@ -340,9 +346,9 @@ services.addScoped(IDatabase, (provider) => { The middleware automatically handles service scope disposal even when errors occur: ```typescript -app.get('/error-example', async (c) => { +app.get('/error-example', async c => { const userService = useService(c, IUserService); - + try { // This might throw an error const user = await userService.getUser('invalid-id'); @@ -369,7 +375,7 @@ app.use(cors()); app.use(logger()); // Routes can now use services -app.get('/', (c) => { +app.get('/', c => { const service = useService(c, IMyService); return c.json(service.getData()); }); @@ -408,7 +414,7 @@ const ILogger = createServiceIdentifier(); @injectable() class UserService { constructor(@inject(ILogger) private logger: ILogger) {} - + async getUser(id: string): Promise { this.logger.log(`Getting user ${id}`); // Implementation @@ -444,7 +450,7 @@ Keep dependencies minimal and well-defined: class UserService implements IUserService { constructor( @inject(IUserRepository) private userRepository: IUserRepository, - @inject(ILogger) private logger: ILogger + @inject(ILogger) private logger: ILogger, ) {} } @@ -471,10 +477,10 @@ class UserService implements IUserService { ```typescript // ✅ Correct order app.use(injectServices(serviceProvider)); -app.get('/', (c) => useService(c, IMyService)); +app.get('/', c => useService(c, IMyService)); // ❌ Wrong order -app.get('/', (c) => useService(c, IMyService)); +app.get('/', c => useService(c, IMyService)); app.use(injectServices(serviceProvider)); ``` diff --git a/src/index.ts b/src/index.ts index 2314f7e..1532001 100644 --- a/src/index.ts +++ b/src/index.ts @@ -17,35 +17,35 @@ declare module 'hono' { /** * Creates a Hono middleware that manages dependency injection service scopes for each request. - * + * * This middleware creates a new service scope at the beginning of each request and automatically * disposes of it when the request completes, ensuring proper resource cleanup and preventing * memory leaks. The service scope is stored in the Hono context and can be accessed by subsequent * middleware and route handlers. - * + * * @param serviceProvider - The root service provider from which to create scoped instances * @returns A Hono middleware handler that manages service scope lifecycle - * + * * @example * ```typescript * import { Hono } from 'hono'; * import { injectServices, useService, ServiceCollection } from '@stevanfreeborn/hono-netdi'; - * + * * // Configure services * const services = new ServiceCollection(); * services.addScoped(MyService); * const serviceProvider = services.build(); - * + * * // Create Hono app with DI middleware * const app = new Hono(); * app.use(injectServices(serviceProvider)); - * + * * app.get('/', (c) => { * const myService = useService(c, MyService); * return c.json({ data: myService.getData() }); * }); * ``` - * + * * @throws {Error} If the service provider is null or undefined * @see {@link useService} for accessing services within request handlers */ @@ -65,40 +65,40 @@ export function injectServices(serviceProvider: IServiceProvider): MiddlewareHan /** * Retrieves a service instance from the current request's dependency injection scope. - * + * * This function extracts the service scope from the Hono context (which must have been * set by the `injectServices` middleware) and uses it to resolve the requested service. * Services are resolved according to their configured lifetime (singleton, scoped, or transient). - * + * * @template T - The type of service to retrieve * @param c - The Hono context containing the service scope * @param serviceType - The service identifier used to resolve the service instance * @returns The resolved service instance of type T - * + * * @example * ```typescript * import { Context } from 'hono'; * import { useService, createServiceIdentifier } from '@stevanfreeborn/hono-netdi'; - * + * * interface IUserService { * getUser(id: string): Promise; * } - * + * * const userServiceId = createServiceIdentifier(); - * + * * app.get('/users/:id', async (c: Context) => { * const userService = useService(c, userServiceId); * const user = await userService.getUser(c.req.param('id')); * return c.json(user); * }); * ``` - * + * * @throws {Error} When the service scope is not found in the context (typically when * `injectServices` middleware was not properly configured) * @throws {Error} When the service scope is not a valid ServiceScope instance * @throws {Error} When the requested service cannot be resolved (service not registered, * missing dependencies, etc.) - * + * * @see {@link injectServices} for setting up the dependency injection middleware */ export function useService(c: Context, serviceType: ServiceIdentifier): T { @@ -117,4 +117,4 @@ export function useService(c: Context, serviceType: ServiceIdentifier): T return scope.serviceProvider.getService(serviceType); } -export * from '@stevanfreeborn/netdi'; \ No newline at end of file +export * from '@stevanfreeborn/netdi'; diff --git a/tests/index.spec.ts b/tests/index.spec.ts index a229ee8..fafd17f 100644 --- a/tests/index.spec.ts +++ b/tests/index.spec.ts @@ -48,7 +48,7 @@ describe('injectServices', () => { describe('useService', () => { test('it should throw an error if the service scope is not found in context', async () => { type ITestService = object; - + const serviceId = createServiceIdentifier(); const app = new Hono(); @@ -68,13 +68,13 @@ describe('useService', () => { test('it should throw an error if the service scope is not an instance of ServiceScope', async () => { type ITestService = object; - + const serviceId = createServiceIdentifier(); const app = new Hono(); app.get('/', c => { c.set('serviceScope', {} as IServiceScope); - + try { useService(c, serviceId); return c.text('Service scope found', 200); @@ -115,7 +115,6 @@ describe('useService', () => { expect(res.status).toBe(500); }); - test('it should return the service from the service scope', async () => { interface ITestService { id(): string;