TypeScript framework for creating enterprise-grade (web) applications with simple and minimalistic API, that allows you to focus on business logic. Based on declarative and imperative programming, inspiried by ASP.NET / Spring.
Check Docs for more details.
Odi provides feature set for creation of easy supportable and scalable web applications.
Features Overview:
- MVC
- Full-typed DI / IoT
- Authentication
- WebSockets
- TypeORM integration
- GraphQL
- AOP
- SSR
For future updates check Roadmap
Got an idea, proposal or feature request? Feel free to Submit it!
-
Install npm package
npm install odi --save
-
Install reflect-metadata
npm install reflect-metadata --save
-
Import reflect-metadata (for example in
index.ts
):
import "reflect-metadata";
-
Enabled the following settings in
tsconfig.json
"emitDecoratorMetadata": true, "experimentalDecorators": true
Controllers serve as a simple yet powerful routing mechanism in a minimalistic style.
@Controller('foo')
export class FooController extends IController {
@RoutePatch('{id}')
bar(id: string, payload: FooDTO) {
...some updates..
return Ok();
}
@Get index() {
return 'Foo';
}
}
So, as you see, there no need to provide any additional param decorators for injection data from the HTTP request. It's just a small controller overview, there are a lot of other possibilities.You can read more in docs.
Odi has powerful dependency injection mechanism out of the box.
(Let's imagine that we already have FooRepository
)
//foo.service.ts
@Service()
export class FooService {
β
@Autowired()
repository: FooRepository;
β
public getFoo(id: string) {
return this.repository.findOne(id);
}β
}
//foo.controller.ts
@Controller('foo')
export class OrderController extends IController {
β
@Autowired()
fooService: OrderService;
@Get async '{id}' (id: string) {
const foo = this.fooService.getFoo(id);
if(!foo)
return NotFound();
return foo;
}β
}
As you can see, all dependencies will be automatically provided to all application components.
Currently, Odi support 3 ways of injection:
- By constructor
- By property
- By method
Classes that are not Odi components can participate in DI. You can simply define behaviour with preset properties and constructor args.
class Pet {
...
}
βdefine(Pet)
.set('default', {
constructorArgs: [...],
props: {...},
type: 'singleton'
})
.set('special', {
constructorArgs: [...],
props: {...},
type: 'scoped'
});
It's a common scenario when web server should validate data before processing. DTO can optimize and automate this process.
@Data()
export class TodoDTO {
@MaxLength(80)
title: string;
@IsOptional()
@MaxLength(255)
desctiption: string;
}
Then, DTO class should be added as an argument for the controller method
@Controller('todo')
export class TodoController extends IController {
@Autowired()
todoService: TodoService;
@Post async index(payload: TodoDTO) {
...
}β
}
And it's all! Odi will automatically inject the validated request body in this argument. If there are some errors during validation, 400 status code will be sent with errors description.
Odi provides a wide set for DTO description, supporting nested DTOs, arrays, enums and etc.
It was a small overview of some features. If you interested in more, check the Docs.
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Please make sure to update tests as appropriate.