#How can I use Typescript to better reuse the instancing of blocks of code full of dependencies?

9 messages · Page 1 of 1 (latest)

grave cove
#

Hello! I'm developing a Node.JS/Express API with Typescript, and there is a certain Service (or use case), which is used in a number of routes, that has many dependencies (I.E: database Repositories and other Services), so everytime I have to instance Service X on the controller, I need to instance a bunch of repositories and other services (which themselves have their dependencies, some of which are in common with ServiceX) , and finally pass them as dependencies on the constructor of ServiceX.

I'm already using the Dependency Inversion pattern, so that it is the client code that needs to instance those dependencies and pass it to them, but I'd like to define a "factory" somehow (not sure if literally using the Factory pattern, or just as a way of saying), and then call this "factory" in all the places I need this Service.

Thanks in advance for any help! I can provide a code example if this sounds confusing, just didn't want to paste a giant block of code for no reason.

crude path
#

How are your controllers? I mean, the general pattern with express would be to augment the context object using declaration merging with whatever you need and use a middleware to actually put the stuff there

#

(The context object being "req" here)

grave cove
#

My controllers are straightforward: I receive a request in a route (e.g user.routes), call the controller action that handles that route (e.g userController.create), and that controller basically instances all the required repositories and services required for that use case (eg. I instance UserRepository, instance CreateUserService and pass UserRepository to it), and then return the result of that service (if any) as an express response.

I have done one thing that "augments" the request object: I have added the "logged user" (the one which is authenticated with JWT) as request.user, and I use it inside the controllers and services to make sure this user is only accessing resources that are allowed to him (e.g forbid him from seeing other peoples' private information). I've never added repositories and even services to the express request. Could you help with tha concept, or point me to some resource I can read up on that?

crude path
#

Do you really need to recreate the instances of all your repositories/services on every request? I mean, I can see some use-case for "request-scoped" services or even plain data. If you're going the classic "controller as a class" way then did you looking into DI containers (like inversify)?

Augmenting the request object is more common in scenarios where classes aren't used for routes, then you still need a way to inject your services/repositories in your route handlers. Here's an example, unfortunately, the types are messed up with express on the playground because they conflict with the DOM ones.

runic daggerBOT
#
RogerC#3099

Preview:```ts
import Express from "express"

interface User {
id: string
name: string
}

interface UserRepository {
findById: (id: string) => Promise<User | null>
}
interface UserService {}
interface BookRepository {}
interface BookService {}

interface Repositories
...```

grave cove
# crude path Do you really need to recreate the instances of all your repositories/services o...

I haven't yet considered application-scoped services because the app was not supposed to have such a large codebase, features nested dependencies between services, etc, but now that you've suggested it, my services and repositories are all stateless, so it would make sense to reuse them throughout the application. Besides "state-sharing leaks" for different requests, are there any pitfalls I should watch out for when moving from request-scoped to application-scoped? I've decided to give TSyringe a try as dependency injector.

Also, I have never thought to use the request object that way, so thank you very much for providing me a code example and expanding my horizons 😃

crude path
#

I haven't personally used TSyringe but I believe you'll be fine with it 🙂

grave cove
#

Thanks again for your help!