{"id":14957699,"url":"https://github.com/msabo1/expressts","last_synced_at":"2026-02-15T03:02:53.141Z","repository":{"id":52270825,"uuid":"353069246","full_name":"msabo1/expressts","owner":"msabo1","description":"Express TypeScript is decorator driven TypeScript framework on top of Express.js that allows you to use Express truly TypeScript way.","archived":false,"fork":false,"pushed_at":"2021-05-02T10:06:35.000Z","size":88,"stargazers_count":0,"open_issues_count":3,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-18T17:27:48.632Z","etag":null,"topics":["adapter","backend","decorators","express","express-js","expressjs","framework","nodejs","typescript","typescript-framework"],"latest_commit_sha":null,"homepage":"https://msabo1.github.io/expressts/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/msabo1.png","metadata":{"files":{"readme":"readme.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-03-30T16:31:46.000Z","updated_at":"2021-05-02T10:04:38.000Z","dependencies_parsed_at":"2022-09-20T02:55:58.862Z","dependency_job_id":null,"html_url":"https://github.com/msabo1/expressts","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/msabo1/expressts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/msabo1%2Fexpressts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/msabo1%2Fexpressts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/msabo1%2Fexpressts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/msabo1%2Fexpressts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/msabo1","download_url":"https://codeload.github.com/msabo1/expressts/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/msabo1%2Fexpressts/sbom","scorecard":{"id":665152,"data":{"date":"2025-08-11","repo":{"name":"github.com/msabo1/expressts","commit":"f74ff76987b8f8bd2731eef9044d0b6b367bda77"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.9,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":0,"reason":"Found 0/14 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 20 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":1,"reason":"9 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-qwcr-r2fm-qrc7","Warn: Project is vulnerable to: GHSA-pxg6-pf52-xh8x","Warn: Project is vulnerable to: GHSA-rv95-896h-c2vc","Warn: Project is vulnerable to: GHSA-qw6h-vgh9-j6wx","Warn: Project is vulnerable to: GHSA-9wv6-86v2-598j","Warn: Project is vulnerable to: GHSA-rhx6-c78j-4q9w","Warn: Project is vulnerable to: GHSA-hrpp-h998-j3pp","Warn: Project is vulnerable to: GHSA-m6fv-jmcg-4jfg","Warn: Project is vulnerable to: GHSA-cm22-4g7w-348p"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-21T17:45:19.785Z","repository_id":52270825,"created_at":"2025-08-21T17:45:19.786Z","updated_at":"2025-08-21T17:45:19.786Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278655146,"owners_count":26022968,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-06T02:00:05.630Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["adapter","backend","decorators","express","express-js","expressjs","framework","nodejs","typescript","typescript-framework"],"created_at":"2024-09-24T13:15:21.760Z","updated_at":"2025-10-06T18:07:52.326Z","avatar_url":"https://github.com/msabo1.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Description\n\nExpressTS (Express TypeScript) is decorator driven TypeScript framework on top of Express.js that allows you to use Express truly TypeScript way.\n\n[Github](https://github.com/msabo1/expressts)\n[Npm](https://www.npmjs.com/package/@msabo1/expressts)\n\n# Why\n\nLet's say you have decided you want use Express with Typescript. Great, there are type definitions for Express, just install them and you are using Express with TypeScript. But soon you realize that there is basically zero benefits of using TypeScript with Express that way (it even gets much more complicated). So you come up with idea to encapsulate some stuff in classes, it gets a bit prettier and you have some structure in your project. But again you realize you have actually done nothing. What to do next?\n\nThis framework may be a solution. It takes advantage of TypeScript decorators and takes away all the ugly stuff behind the scenes and allows you to create structured object-oriented application just the way you wanted it at begging of the story.\n\n# Features\n\nThere are a few frameworks like this one, but most of them are trying to be frameworks on their own, having bunch of extra features (which is good thing for more complex use-cases).\n\nExpressTS provides decorators to abstract logic only for Express.js API.\n\nOnly extra feature is simple dependency injection container because I think is necessary to have this feature out of the box if you really want to feel advantage of using this framework.\n\n# How to use it\n\n## Setup\n\nFirst you need to init npm project with\n\n`npm init`\n\nThen install ExpressTS with\n\n`npm i @msabo1/expressts`\n\nNow create `tsconfig.json` file at root level and add following options inside of `compilerOptions` object\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true\n  }\n}\n```\n\nOr you can just execute `tsc --init` in your prompt from project root and it will generate `tsconfig.json` with all options commented out, so you just uncomment those two options.\n\nOptionally you can set `outDir` option (you probably want this) to `dist` or something of your choice to redirect compiled files to that directory.\n\nIt's recommended to create `src` directory and put there all of code you will additionally create but it isn't required. In this guide we will create such directory.\n\nFrom now on, all namings (names of files, classes...) are matter of choice, if not said otherwise, so you don't have to follow names blindly.\n\nThere is one more thing to do and we can start our server.\n\nIn `src` directory create application root. We will call it `main.ts`.\nInside of that file create new class and decorate it with `App` decorator imported from `@msabo1/expressts`. `App` decorator takes one object as parameter which has one mandatory property `port` which is obviously port our server will listen on.\n\n```typescript\nimport { App } from '@msabo1/expressts';\n\n@App({ port: 3000 })\nexport class Application {}\n```\n\n## Controllers\n\nControllers combine routers, HTTP methods and route handlers in elegant way.\n\nLet's create hello world controller which will handle `/hello-world` route.\n\nInside of `src` create `hello-world.controller.ts` file and inside of it create new class decorated with `Controller` decorator. It takes one argument `route` which is base route for our controller and it must start with `/`.\n\n```typescript\nimport { Controller } from '@msabo1/expressts';\n\n@Controller('/hello-world')\nexport class HelloWorldController {} //note that class name can be whatever you like\n```\n\nNow we need to register that controller. Let's move back to `src/main.ts`. Object `App` decorator takes as argument has optional property `controllers` which is array of controllers. All of controllers have to be listed there to make them work.\n\n```typescript\nimport { App } from '@msabo1/expressts';\nimport { HelloWorldController } from './hello-world.controller';\n\n@App({\n  port: 3000,\n  controllers: [HelloWorldController],\n})\nexport class Application {}\n```\n\nNow move back to our controller and let's bind some routes. Inside of `HelloWorldController` create new method decorated with `Get` decorator. It takes one optional parameter `path` which is route extension, it also must start with `/`. It is equivalent to express path and it can take dynamic parameters. We will leave it empty.\nThis will bind `GET` method to `/hello-world` route. Obviously there is corresponding decorator for every HTTP method.\n\n```typescript\nimport { Controller, Get } from '@msabo1/expressts';\n\n@Controller('/hello-world')\nexport class HelloWorldController {\n  @Get()\n  get() /* note that method name can be whatever you like */ {\n    return 'Hello world'; //whatever is return from method will be response\n  }\n}\n```\n\n### Route, query, body params\n\nTo access route, query and body params we use method argument decorators `RequestParams`, `RequestBody` and `RequestQuery`. It will inject corresponding params to desired argument.\n\nExpressTS uses json body parer by default.\n\n```typescript\nimport { Controller, Get, RequestParams } from '@msabo1/expressts';\n\n@Controller('/hello-world')\nexport class HelloWorldController {\n  @Get('/:id')\n  get(@RequestParams() params: any /* note that argument name can be whatever you like */) {\n    return params;\n  }\n}\n```\n\nIf we make GET request to `/hello-world/1`, response will be\n\n```typescript\n{\n  id: '1';\n}\n```\n\nWe can make use of object destructuring here\n\n```typescript\n@Get('/:id')\nget(@RequestParams() { id }: any /* note that now it has to be named id, because that is what we called out param */) {\n    return id;\n  }\n```\n\nThis will return just the id.\n\n### Request and response objects\n\nSame as request params we can take more control and inject `req` and `res` objects to our methods using `Request` and `Response` decorators.\n\n```typescript\n@Get('/:id')\nget(@RequestParams() { id }: any, @Response res: any) {\n    res.set(...)\n    return id;\n  }\n```\n\n### Change response status code\n\nYou can change response status code using `DefaultHttpStatus` decorator. It takes one mandatory parameter `code` of type `number` which represents HTTP status code. You can apply that decorator to controller (it will obviously change default status code for all route handlers) or you can apply it to method.\n\n```typescript\nimport { Controller, Get, Post, DefaultStatusCode } from '@msabo1/expressts';\n\n@Controller('/hello-world')\n@DefaultHttpStatus(201)\nexport class HelloWorldController {\n  @Get()\n  @DefaultHttpStatus(500)\n  get() {\n    return 'Hello world';\n  }\n\n  @Post()\n  create() {\n    return 'Hello world created';\n  }\n}\n```\n\nIn this example `POST` request will have response code `201` because that is controller's default code. `GET` request will have response code `500` because we overrode default one.\n\nIf you want to change status code dynamically, you will have to inject `res` object and use its `status` method inside of method's body. Doing it this way will override all defaults.\n\n```typescript\nimport { Controller, Get, Response } from '@msabo1/expressts';\n\n@Controller('/hello-world')\nexport class HelloWorldController {\n  @Get()\n  get(@Response() res: any) {\n    res.status(500);\n    return 'Hello world';\n  }\n}\n```\n\n### Set headers\n\nYou can set headers using `Headers` decorator. It takes one mandatory argument `headers` which is object whose keys are header keys and values are header values. Values must be of type `string`. You can apply that decorator to controller (it will obviously set headers for all route handlers) or you can apply it to method.\nIf same headers are set controller and method level, method's headers will override controller's.\n\n```typescript\nimport { Controller, Get, Post, Headers } from '@msabo1/expressts';\n\n@Controller('/hello-world')\n@Headers({ hello: 'world' })\nexport class HelloWorldController {\n  @Get()\n  @Headers({\n    'my-header': 'my-value',\n    myHeader: 'myValue',\n  })\n  get() {\n    return 'Hello world';\n  }\n}\n```\n\nIf you want to set headers dynamically you will need to inject `res` object and use its `set` method. If header existed before (default or set with `Headers` decorator) this will override it.\n\n## Middlewares\n\nExpressTS is compatible with every Express.js middleware.\n\nJust like in Express.js you can bind middlewares globally, router level (controller level) and route level.\n\n### Global middlewares\n\nTo bind middlewares globally to all routes you need to register it in app root (in this case `src/main.ts`). `App` decorator properties object has optional property `useGlobalMiddlewares` which is array of middlewares and you just need to list them there.\n\n```typescript\nimport { App } from '@msabo1/expressts';\nimport { HelloWorldController } from './hello-world.controller';\nimport express from 'express';\n\n@App({\n  port: 3000,\n  controllers: [HelloWorldController],\n  useGlobalMiddlewares: [express.urlencoded()],\n})\nexport class Application {}\n```\n\n### Controller and route level middlewares\n\nTo bind middlewares to all routes of some controller, you need to decorate it with `UseMiddlewares` decorator which takes list of middlewares as parameters (note that it doesn't take array of middlewares, you just pass middlewares).\n\nIf you want to bind middlewares route level, just use the same decorator but applied to route handler.\n\n```typescript\nimport { Controller, Get, UseMiddlewares } from '@msabo1/expressts';\nimport express from express;\n\n@UseMiddlewares(express.urlencoded(), express.text()) // order of decorators doesn't matter in this case\n@Controller('/hello-world')\nexport class HelloWorldController {\n  @Get()\n  @UseMiddlewares(express.static(...)) // order of decorators doesn't matter in this case either\n  get() {\n    return 'Hello world';\n  }\n}\n```\n\n## Services and dependency injection\n\nAs mentioned before, there is one extra feature and that is dependency injection container. It makes use of this framework much more elegant.\n\n### Services\n\nYou should extract your business to services (and/or more layers) and use controllers only to directly handle requests and responses.\n\nWhen you create your service, you will want to connect it with controller somehow. That is where dependency injection comes to play (well you can instantiate services inside of controller constructors, but NO).\nAs your logic grows you will want to connect services together and more. ExpressTS makes all of that really easy.\n\nFirst you need to decorate you service class with `Injectable` decorator. It is required because of TypeScript limitations, and without it you can't inject dependencies to service.\n\nBy default all services are registered as singletons (there will exist only one instance of service in container and it will be shared everywhere). If you want it not to be singleton, `Injectable` takes object as optional argument which has optional `boolean` property `singleton`. Obviously if set to `false` service won't be singleton and will be reinstantiated whenever injected.\n\nLet's create `src/hello-world.service.ts` and create class decorated with `Injectable` inside of it.\n\n```typescript\nimport { Injectable } from '@msabo1/expressts';\n\nInjectable();\nexport class HelloWorldService {\n  findMessage(): string {\n    return 'Hello world!';\n  }\n}\n```\n\nNow you just list it as controllers constructor parameter and ExpressTS will instantiate and inject it for you.\nIt is important that you add correct type annotation because that is actually how DI mechanism knows what to inject.\n\nIf you want to inject service inside of other service, steps are exactly the same.\n\n```typescript\nimport { Controller, Get } from '@msabo1/expressts';\nimport { HelloWorldService } from './hello-world.service';\n\n@Controller('/hello-world')\nexport class HelloWorldController {\n  constructor(private readonly helloWorldService: HelloWorldService) {}\n\n  @Get()\n  get() {\n    return this.helloWorldService.findMessage();\n  }\n}\n```\n\n### Custom providers\n\nExcept services, you can register custom providers that you can later inject. They can have `string` tokens, or you can redefine what is injected instead of class instance using obviously `class` token.\n\nCustom providers are registered inside of `App` decorator at root of application. `App` decorator properties object has optional property `customProviders` which is array of providers.\n\nFor each provider you need to specify `token` which is of type `string` or some constructible type (class reference) and `instance` which is of type `any`.\n\n```typescript\nimport { App } from '@msabo1/expressts';\nimport { HelloWorldController } from './hello-world.controller';\nimport { HelloWorldService } from './hello-world.service';\n\n@App({\n  port: 3000,\n  controllers: [HelloWorldController],\n  customProviders: [\n    { token: 'helloWorldService', instance: new HelloWorldService() },\n    { token: HelloWorldService, instance: { findMessage: () =\u003e 'Hello world 2!' } },\n  ],\n})\nexport class Application {}\n```\n\nIn this example we created two custom providers. What is actually going on here is that we set `string` token provider to provide instance of `HelloWorldService` and we overrode `class` token provider `HelloWorldService` to provide some custom object. That is really strange thing to do, at least in this context but we did it just to make point.\n\nWhat is left unclear is how to inject `string` token providers. To make that happen we use `Inject` decorator to decorate constructor arguments. `Inject` takes one mandatory argument which is `string` token we want to inject.\n\n```typescript\nimport { Controller, Get, Inject } from '@msabo1/expressts';\nimport { HelloWorldService } from './hello-world.service';\n\n@Controller('/hello-world')\nexport class HelloWorldController {\n  constructor(\n    @Inject('helloWorldService') private readonly helloWorldService: HelloWorldService,\n    private readonly helloWorldService2: HelloWorldService,\n  ) {}\n\n  @Get()\n  get() {\n    return this.helloWorldService.findMessage();\n  }\n\n  @Get('/other')\n  get2() {\n    return this.helloWorldService2.findMessage();\n  }\n}\n```\n\nIn this example, real `HelloWorldService` instance is `helloWorldService`, and custom object is `helloWorldService2`.\n\n## Lifecycle hooks\n\nYou can hook and execute code before or after certain points in application bootstrap process. In order to do that you need to implement methods inside of you app root class (in our examples that is `Application` class inside of `src/main.ts`). Methods need to be decorated with proper decorator. Possible decorators (and obviously hooks) are (listed in order how they are actually executed):\n\n`BeforeGlobalMiddlewaresBound`\n\n`AfterGlobalMiddlewaresBound`\n\n`BeforeRoutesBound`\n\n`AfterRoutesBound`\n\n`BeforeListenStarted`\n\n`AfterListenStarted`\n\nSome of hooks overlap and they are equivalent but you shouldn't assume that. You should use exact hook you need because order of execution can change at any version and it won't be considered breaking change (if no other side effects).\n\n```typescript\nimport { App, BeforeRoutesBound } from '@msabo1/expressts';\nimport { HelloWorldController } from './hello-world.controller';\nimport { HelloWorldService } from './hello-world.service';\n\n@App({\n  port: 3000,\n  controllers: [HelloWorldController],\n})\nexport class Application {\n  constructor(private readonly helloWorldService: HelloWorldService) {}\n\n  @BeforeRoutesBound()\n  private beforeRoutes() {\n    console.log('I am executed just before routes are bound');\n    console.log(this.helloWorldService.findMessage());\n  }\n}\n```\n\nAs you can see in this example, you can inject services and custom providers inside of your application root. You can inject controllers as well.\n\n## Express app instance\n\nYou can access express app instance used to build server by injecting it in constructors with `ExpressAppInstance` decorator.\n\n```typescript\nimport {\n  App,\n  BeforeRoutesBound,\n  AfterGlobalMiddlewaresBound,\n  ExpressAppInstance,\n} from '@msabo1/expressts';\nimport { HelloWorldController } from './hello-world.controller';\nimport { HelloWorldService } from './hello-world.service';\nimport express from 'express';\n\n@App({\n  port: 3000,\n  controllers: [HelloWorldController],\n})\nexport class Application {\n  constructor(\n    private readonly helloWorldService: HelloWorldService,\n    @ExpressAppInstance() private readonly expressApp: any,\n  ) {}\n\n  @BeforeRoutesBound()\n  private beforeRoutes() {\n    console.log('I am executed just before routes are bound');\n    console.log(this.helloWorldService.findMessage());\n  }\n\n  @AfterGlobalMiddlewaresBound()\n  private afterMiddlewares() {\n    this.expressApp.use(express.urlencoded());\n  }\n}\n```\n\nYou can inject express app instance to controllers and services as well.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmsabo1%2Fexpressts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmsabo1%2Fexpressts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmsabo1%2Fexpressts/lists"}