dorsale v0.0.106
dorsale
Dorsale is an attempt at creating a TS equivalent of Spring for Java. It is built on top of Fastify and uses
decorators to define elements of your application.
It is a work in progress, and is not ready for
production use.
If you benchmark it, please let me know the results!
Installation
Dorsale is available on npm. You can install it with:
npm install dorsale
Getting started
Bootstrapping
The setup is intentionally minimalistic. Bootstrapping a Dorsale application is as simple as:
import { dorsale } from 'dorsale';
dorsale({ port: 8080 });
This will start a server on port 8080. You can then add controllers, services, and repositories to your application.
Full application example
A full example could look like this:
src
├── index.ts
├── user.ts
├── userFinder.ts
├── userManager.ts
├── userController.ts
// index.ts
import { dorsale } from 'dorsale';
dorsale({ port: 8080 });
// user.ts
export interface User {
id: string;
email: string;
password: string;
}
// userFinder.ts
import { User } from "./user";
export interface UserFinder {
findAllUsers(): Promise<User[]>;
findUserById(id: string): Promise<User | undefined>;
findUserByEmail(email: string): Promise<User | undefined>;
}
// userManager.ts
import { UserEditor } from "./userEditor";
import { UserFinder } from "./userFinder";
import { User } from "./user";
import { Component } from "dorsale";
@Component
export class UserManager implements UserFinder {
users: User[] // = [... some users];
findAllUsers(): Promise<User[]> {
return Promise.resolve(this.users);
}
findUserByEmail(email: string): Promise<User | undefined> {
const user = this.users.find((u) => u.email === email);
return Promise.resolve(user);
}
findUserById(id: string): Promise<User | undefined> {
const user = this.users.find((u) => u.id === id);
return Promise.resolve(user);
}
}
// userController.ts
import { Controller, Get } from "dorsale";
import { UserFinder } from "./userFinder";
@Controller()
export class UserController {
constructor(private readonly userFinder: UserFinder) {
}
@Get("/")
getAll() {
return this.userFinder.findAllUsers();
}
@Get("/:id")
getById(id: string) {
return this.userFinder.findUserById(id);
}
}
You just have to run the file containing the dorsale
call, and you're good to go!
The other components will be automatically discovered and injected. This reduces the amount of boilerplate code you have
to write.
By default, Dorsale will look for components in the src
folder, but you can change this by passing a rootDir
option
to the dorsale
call.
dorsale({ port: 8080, rootDir: "myFolder/relative/to/the/current/file" });
Controllers
Controller classes
Controllers are classes that define the routes exposed by your application. They are decorated with @Controller()
.
import { Controller } from "dorsale";
@Controller()
export class UserController {
// ... your routes
}
You can also specify a prefix for all the routes defined in a controller by passing it as an argument to the decorator.
@Controller("/users")
export class UserController {
// ... your routes
}
Routes
Routes are defined by decorating methods with @Get
, @Post
, @Put
, @Patch
, or @Delete
.
import { Controller, Get } from "dorsale";
@Controller()
export class UserController {
@Get("/hello")
getHello() {
return "Hello world!";
}
}
In the example above, a GET route will be exposed at /hello
, and will return the string "Hello world!"
.
Route parameters
You can define route parameters by adding a colon (:
) before the parameter name in the route path.
import { Controller, Get } from "dorsale";
@Controller()
export class UserController {
@Get("/users/:id")
getUserById(id: string) {
// ...
}
}
Query parameters
Query parameters are defined by adding a @Query
decorator to the parameter.
import { Controller, Get, Query } from "dorsale";
@Controller()
export class UserController {
@Get("/users") // e.g. GET /users?page=1&limit=10
getUsers(@Query page: number, @Query limit: number) {
// ...
}
}
If some query parameters are not provided in the request, they will be undefined
.
Body
You can access the body of the request by adding a @Body
decorator to a parameter.
import { Controller, Post, Body } from "dorsale";
@Controller()
export class UserController {
@Post("/users")
createUser(@Body user: User) {
// ...
}
}
Body validation
You can validate the body of a request by adding a @BodySchema
decorator to a route.
import { Controller, Post, Body, BodySchema } from "dorsale";
@Controller()
export class UserController {
@Post("/users")
@BodySchema({
type: "object",
properties: {
email: { type: "string" },
password: { type: "string" },
},
required: ["email", "password"],
})
createUser(@Body user: User) {
// ...
}
}
This uses Fastify's JSON Schema validation.
Testing
Coming soon!
Contributing
Contributions are welcome! Feel free to open an issue or a PR if you have any suggestions or bug reports. Please follow the GitHub flow when contributing (see here for more information). Thanks for your interest in Dorsale!
27 days ago
27 days ago
1 month ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
11 months ago