# Platform API
Ts.ED uses now the Platform API to create an application. Platform API gives an abstraction layer between your code written with Ts.ED and the Express.js (opens new window) code. It means that a large part of your code isn't coupled with Express.js itself and can be used with another Platform like Koa.js (opens new window).
There are some changes between ServerLoader API (v4/v5) and Platform API (v5.56.0+/v6), to get the original Express Application, Request or Response. This page will describe how you can get these instances with the new API.
# Platform classes
# Create application
The way to create a Ts.ED application, add middlewares, configure Express or Koa, all are impacted by the new Platform API.
If you use ServerLoader
, you'll probably know this example to create a Ts.ED application:
import {ServerLoader, ServerSettings} from "@tsed/common";
import {MyMiddleware} from "./MyMiddleware";
import compress from "compression";
import cookieParser from "cookie-parser";
import methodOverride from "method-override";
@Configuration({
viewsDir: `${process.cwd()}/views`,
middlewares: [MyMiddleware, cookieParser(), compress({}), methodOverride()]
})
export class Server extends ServerLoader {
$beforeRoutesInit() {
// configure express app
this.set("views", this.settings.get("viewsDir"));
this.engine("ejs", ejs);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
With Platform API you have to inject
PlatformApplication
to register a middleware and set configuration to Express.Application
:
import {Configuration, PlatformApplication} from "@tsed/common";
import {Inject, Constant} from "@tsed/di";
import {MyMiddleware} from "./MyMiddleware";
import compress from "compression";
import cookieParser from "cookie-parser";
import methodOverride from "method-override";
@Configuration({
views: {
root: `${process.cwd()}/views`,
viewEngine: "ejs"
},
middlewares: [MyMiddleware, cookieParser(), compress({}), methodOverride()]
})
export class Server {
@Constant("viewsDir")
viewsDir: string;
$beforeRoutesInit() {
console.log(this.viewsDir);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
TIP
With Platform API, the Server class is considered as a Provider . It means that you can use decorators like Constant and Inject to get any configuration, provider or service from the DI registry.
# Inject service in the Server
With ServerLoader
, injecting a provider can be done as follows:
import {ServerLoader, ServerSettings} from "@tsed/common";
import {MyService} from "./services/MyService";
@ServerLoader({})
export class Server extends ServerLoader {
$beforeRoutesInit() {
const myService = this.injector.get<MyService>(MyService);
myService.getSomething();
}
}
2
3
4
5
6
7
8
9
10
11
Now with Platform API, the Server class is considered as a Provider . It means that you can use decorators like Constant and Inject to get any configuration, provider or service from the DI registry.
import {Configuration} from "@tsed/common";
import {Inject} from "@tsed/di";
import {MyService} from "./services/MyService";
@Configuration({})
export class Server {
@Inject()
protected myService: MyService;
$beforeRoutesInit() {
this.myService.getSomething();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
# Bootstrap application
In v5, boostrap a Server
can be done with the ServerLoader.boostrap
method:
import {$log, ServerLoader} from "@tsed/common";
import {Server} from "./server";
async function bootstrap() {
try {
$log.debug("Start server...");
const platform = await ServerLoader.bootstrap(Server, {
// extra settings
});
await platform.listen();
$log.debug("Server initialized");
} catch (er) {
$log.error(er);
}
}
bootstrap();
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Now with Platform API, you have to install @tsed/platform-express
(or @tsed/platform-koa
) and change the code by the following example:
import {$log} from "@tsed/common";
import {PlatformExpress} from "@tsed/platform-express";
import {Server} from "./server";
async function bootstrap() {
try {
$log.debug("Start server...");
const platform = await PlatformExpress.bootstrap(Server, {
// extra settings
});
await platform.listen();
$log.debug("Server initialized");
} catch (er) {
$log.error(er);
}
}
bootstrap();
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Get Application
Before with v5, to get Express.Application
, you had to use ExpressApplication
decorator:
import {Injectable} from "@tsed/di";
import {ExpressApplication} from "@tsed/common";
@Injectable()
class MyService {
constructor(@ExpressApplication private app: ExpressApplication) {}
getExpressApp() {
return this.app;
}
}
2
3
4
5
6
7
8
9
10
11
With Platform API, you have to inject
PlatformApplication
and use the app.raw
or app.getApp()
to get the Express.Application
:
import {Injectable, Inject} from "@tsed/di";
import {PlatformApplication} from "@tsed/common";
import {MyMiddleware} from "../middlewares/MyMiddleware";
@Injectable()
class MyService {
@Inject()
protected app: PlatformApplication<Express.Application>;
getExpressApp() {
return this.app.getApp(); // GET Express raw Application. E.g.: const app = express()
}
$onInit() {
// With Platform API, it is also possible to add middlewares with a service, module, etc...
this.app.use(MyMiddleware);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Request and Response
There is no big change over Response and Request, you can always get Request and Response by using decorators. With the Platform API, you are also able to use Context decorator to deal with the PlatformRequest or PlatformResponse high level API.
See Request context page to get more details.
# Statics files
Since v5.65.0, Platform API manages also the statics files. The
ServeStaticService
is now deprecated in favor of PlatformApplication.statics()
method.
Before:
import {Injectable} from "@tsed/di";
import {ServeStaticService} from "@tsed/common";
import {join} from "path";
@Injectable()
class MyService {
constructor(private service: ServeStaticService) {}
$onReady() {
this.service.statics({"/endpoint": join(process.cwd(), "../publics")});
}
}
2
3
4
5
6
7
8
9
10
11
12
After:
import {Injectable} from "@tsed/di";
import {PlatformApplication} from "@tsed/common";
import {join} from "path";
@Injectable()
class MyService {
constructor(private app: PlatformApplication) {}
$onReady() {
this.app.statics("/endpoint", {root: join(process.cwd(), "../publics")});
}
}
2
3
4
5
6
7
8
9
10
11
12
# Catch exceptions
The new Platform API introduces a new way to catch an exception with the Catch decorator, and to let you control the exact flow of control and the response's content sent back to the client.
See Exception filter page to get more details.
Other topics
- Session & cookies
- Passport.js
- Keycloak
- Prisma
- TypeORM
- MikroORM
- Mongoose
- GraphQL
- Socket.io
- Swagger
- AJV
- Multer
- Serve static files
- Templating
- Serverless HTTP
- Seq
- OIDC
- Stripe
- Agenda
- Terminus
- Serverless
- IORedis
- Controllers
- Providers
- Model
- JsonMapper
- Middlewares
- Pipes
- Interceptors
- Authentication
- Hooks
- Exceptions
- Throw HTTP Exceptions
- Cache
- Command
- Response Filter
- Injection scopes
- Custom providers
- Lazy-loading provider
- Custom endpoint decorator
- Testing
- Customize 404