Skip to content

Scalar

This page shows you how you can configure Scalar with Ts.ED. Scalar uses the OpenApi to describe a Rest API. Ts.ED uses existing decorators to build a specification compliant with Scalar.

Installation

Run this command to install required dependencies by @tsed/scalar:

bash
npm install --save @tsed/scalar

Then add the following configuration in your Server:

ts
import "@tsed/platform-express";
import "@tsed/scalar"; // import scalar Ts.ED module

import {Configuration} from "@tsed/di";

@Configuration({
  scalar: [
    {
      path: "/doc",
      specVersion: "3.0.1"
    }
  ]
})
export class Server {}

TIP

The path option for Scalar will be used to expose the documentation on: http://localhost:8000/doc

Ts.ED will print the scalar url in the console.

WARNING

When using helmet, there may be a problem with CSP, to solve this collision, configure the CSP as shown below:

typescript
@Configuration({
  middlewares: [
    helmet({
      contentSecurityPolicy: {
        directives: {
          defaultSrc: [`'self'`],
          styleSrc: [`'self'`, `'unsafe-inline'`],
          imgSrc: [`'self'`, "data:", "validator.scalar.io"],
          scriptSrc: [`'self'`, `https: 'unsafe-inline'`]
        }
      }
    })
  ]
})
export class Server {}

// If you are not going to use CSP at all, you can use this:
@Configuration({
  middlewares: [
    helmet({
      contentSecurityPolicy: false
    })
  ]
})
export class Server {}

Scalar options

Some options are available to configure Scalar, Ts.ED and the default spec information.

KeyExampleDescription
path/api-docThe url subpath to access to the documentation.
specVersion3.0.1The OpenSpec version.
fileNameopenapi.jsonOpenAPI file name. By default openapi.json.
dochidden-docThe documentation key used by @Docs decorator to create several openapi documentations.
viewPath${rootDir}/views/scalar.ejs or falseThe path to the ejs template. Set false to disabled scalar.
cssPath${rootDir}/assets/scalar.cssThe path to the CSS file.
showExplorertrueDisplay the search field in the navbar.
spec{openapi: "3.1.0"}The default information spec.
specPath${rootDir}/spec/openapi.base.jsonLoad the base spec documentation from the specified path.
outFile${rootDir}/spec/openapi.jsonWrite the openapi.json spec documentation on the specified path.
hiddentrueHide the documentation in the dropdown explorer list.
optionsScalar optionsScalar options. See (https://github.com/scalar/scalar/tree/main/packages/api-reference#props)
operationIdFormatter(name: string, propertyKey: string, path: string) => stringA function to generate the operationId.
operationIdPattern%c_%mA pattern to generate the operationId. Format of operationId field (%c: class name, %m: method name).
pathPatterns[]Include only controllers whose paths match the pattern list provided.
sortPathstrueSort paths by alphabetical order.

Multi documentations

By decorators

It's also possible to create several openapi documentations with the doc option:

ts
import "@tsed/platform-express";
import "@tsed/scalar"; // import scalar Ts.ED module

import {Configuration} from "@tsed/di";

@Configuration({
  swagger: [
    {
      path: "/api-docs-v1",
      doc: "api-v1"
    },
    {
      path: "/api-docs-v2",
      doc: "api-v2"
    }
  ]
})
export class Server {}

Then use @Docs decorators on your controllers to specify where the controllers should be displayed.

ts
import {Controller} from "@tsed/di";
import {Docs} from "@tsed/scalar";

@Controller("/calendars")
@Docs("api-v2") // display this controllers only for api-docs-v2
export class CalendarCtrlV2 {}

// OR
@Controller("/calendars")
@Docs("api-v2", "api-v1") // display this controllers for api-docs-v2 and api-docs-v1
export class CalendarCtrl {}

By Path patterns

You can use the pathPatterns options to include only controllers whose paths match the pattern list provided.

typescript
import {Configuration} from "@tsed/common";
import "@tsed/platform-express";
import "@tsed/scalar"; // import scalar Ts.ED module

@Configuration({
  scalar: [
    {
      path: "/api-admin",
      pathPatterns: ["/rest/admin/**"]
    },
    {
      path: "/api-all",
      pathPatterns: ["!/rest/admin/**"]
    }
  ]
})
export class Server {}

Model documentation

One of the features of Ts.ED is the model definition to serialize or deserialize a JSON Object based on JsonSchema (See model documentation).

A model can be used on a method controller along with BodyParams or other decorators.

ts
import {Description, Example, Property, Title} from "@tsed/schema";

export class CalendarModel {
  @Title("iD")
  @Description("Description of calendar model id")
  @Example("Description example")
  @Property()
  public id: string;

  @Property()
  public name: string;
}

Endpoint documentation

This example shows you how to use the decorators to generate Scalar documentation for an endpoint:

ts
import {Controller} from "@tsed/di";
import {BodyParams, QueryParams} from "@tsed/platform-params";
import {Deprecated, Description, Get, Post, Returns, Security, Summary} from "@tsed/schema";

import {CalendarModel} from "./models/Calendar";

@Controller("/calendars")
export class CalendarCtrl {
  @Get("/:id")
  @Summary("Summary of this route")
  @Description("Return a calendar from the given id")
  @Returns(200, CalendarModel)
  @(Returns(404).Description("Not found"))
  async getCalendar(
    @Description("A calendar Id")
    @QueryParams()
    id: string
  ): Promise<CalendarModel> {
    return {};
  }

  @Get("/")
  @Description("Return a list of Calendar")
  @Returns(200, CalendarModel)
  async getCalendars(): Promise<CalendarModel[]> {
    return [];
  }

  @Get("/v0/:id")
  @Deprecated()
  @Description("Deprecated route, use /rest/calendars/:id instead of.")
  @Returns(CalendarModel)
  @Returns(404, {description: "Not found"})
  async getCalendarDeprecated(@QueryParams("id") id: string): Promise<CalendarModel> {
    return {};
  }

  @Post("/")
  @Security("calendar_auth", "write:calendar", "read:calendar")
  @Returns(CalendarModel)
  async createCalendar(@BodyParams() body: any): Promise<CalendarModel> {
    return {};
  }
}

Extra parameters

Sometimes you want to display extra in parameters like headers without consuming it in an endpoint. It's possible to describe extra parameters by using the In decorator over the method.

ts
import {Controller} from "@tsed/di";
import {BodyParams} from "@tsed/platform-params";
import {In, Post, Security} from "@tsed/schema";

import {CalendarModel} from "./models/Calendar";

@Controller("/calendars")
export class CalendarCtrl {
  @Post("/")
  @(In("header").Name("authorization").Type(String).Description("Bearer authorization"))
  @Security("oidc")
  async createCalendar(@BodyParams() body: any): Promise<CalendarModel> {
    return {};
  }
}

Authors

Maintainers

Released under the MIT License.