Reference Models

Sometimes you might find yourself declaring duplicated models, or re-use the same model multiple time.

With reference models, you can named your model and use it by referencing the name:

For example:

import { Teasim, t } from "teasim";

const app = new Teasim().post("/sign-in", ({ body }) => body, {
  body: t.Object({
    username: t.String(),
    password: t.String(),
  }),
  response: t.Object({
    username: t.String(),
    password: t.String(),
  }),
});

We can make it cleaner, by declaring the model as a variable.

import { Teasim, t } from "teasim";

// Maybe in a different file eg. models.ts
const SignDTO = t.Object({
  username: t.String(),
  password: t.String(),
});

const app = new Teasim().post("/sign-in", ({ body }) => body, {
  body: SignDTO,
  response: SignDTO,
});

This is a good approach to keeping the code clean by creating a separation of concerns.

As the complexity of the app increases, you may find yourself reusing multiple models with various controllers.

You can make it a bit cleaner by creating a "reference model".

Registering the models with setModel allows you to name a model and reference them directly in schema with auto-completion.

import { Teasim, t } from "teasim";

const app = new Teasim()
  .model({
    sign: t.Object({
      username: t.String(),
      password: t.String(),
    }),
  })
  .post("/sign-in", ({ body }) => body, {
    // with auto-completion for existing model name
    body: "sign",
    response: "sign",
  });

Now when we need to quickly access the model's group, we can separate a setModel into a plugin which when registered will provide a set of models.

// auth.model.ts
import { Teasim, t } from "teasim";

export const authModel = new Teasim().model({
  sign: t.Object({
    username: t.String(),
    password: t.String(),
  }),
});

// index.ts
import { Teasim } from "teasim";
import { authModel } from "./auth.model.ts";

const app = new Teasim().use(authModel).post("/sign-in", ({ body }) => body, {
  // with auto-completion for existing model name
  body: "sign",
  response: "sign",
});

Multiple Models

setModel accepts an object with the key as a model name and value as the model definition, multiple models are supported by default.

// auth.model.ts
import { Teasim, t } from "teasim";

export const authModel = new Teasim().model({
  sign: t.Object({
    username: t.String(),
    password: t.String(),
  }),
  number: t.Number(),
});

Naming Convention

Duplicated model names will cause Teasim to throw an error. To prevent declaring duplicate model names, you can use the following naming convention.

Let's say that you have all models stored at models/<name>.ts, you can declare the prefix of the model as a namespace.

// admin.model.ts
export const authModel = new Teasim().model({
  "admin.auth": t.Object({
    username: t.String(),
    password: t.String(),
  }),
});

// user.model.ts
export const authModel = new Teasim().model({
  "user.auth": t.Object({
    username: t.String(),
    password: t.String(),
  }),
});

This can prevent naming duplication at some level, but in the end, it's best to let the naming convention decision up to your team's agreement is the best option.

Teasim provides an opinionated option for you to decide to prevent decision fatigue.