Input & Output

Defining and Validating Input & Output Types

Tarin simplifies HTTP request handling by abstracting it into two key components: Input and Output. Clients send inputs and expect outputs, and Tarin enables you to define both with robust type validation. These definitions are automatically validated and also serve as the foundation for generating API documentation in the OpenAPI Specification standard.


To understand how Input and Output work, you first need to know the base types provided by the SchemaValidator component:

  • string
  • number
  • boolean
  • object
  • array
  • file

The SchemaValidator lets you create these types easily:

SchemaValidator.string();
SchemaValidator.number();
SchemaValidator.boolean();
SchemaValidator.object();
SchemaValidator.array();
SchemaValidator.file();

You can also make any type optional by adding .optional():

SchemaValidator.string().optional();
SchemaValidator.number().optional();
SchemaValidator.boolean().optional();
SchemaValidator.object().optional();
SchemaValidator.array().optional();
SchemaValidator.file().optional();

These types are used to define Input and Output in the Endpoint component. They are converted to TypeScript types for use in the handleLogic callback, ensuring better developer experience with type safety and autocompletion.

Now that you know the basics, you can explore Input and Output definitions.

Input Type

Input types in Tarin are categorized into five distinct groups:

  1. Body (HTTP request body)
  2. Query (URL search query parameters)
  3. Params (custom path parameters, e.g., /:id)
  4. Headers (HTTP headers)
  5. Files (file uploads via multipart/form-data)

Body

The Body represents the HTTP request payload. Tarin uses a TarinType that supports basic types such as object, string, number, boolean, and array. File types are excluded and should instead be defined under the Files section.

Tarin automatically validates the body input and returns validation errors to the client if any are found. Upon successful validation, the flow proceeds to the handler function (handleLogic) with the correctly typed input, ensuring seamless integration.

Example:

index.ts
import { SchemaValidator, endpoint } from "tarin";
 
// Server initialization
...
 
// Endpoint definition
const signInEndpoint = endpoint.post("/api/sign_in").input({
  body: SchemaValidator.object({
    username: SchemaValidator.string(),
    password: SchemaValidator.string(),
  }),
  // Additional input definitions...
}) // Additional endpoint code (handleLogic & etc)....
 
tarin.addEndpoints(signInEndpoint);

Query

The Query represents URL query parameters. Tarin uses TarinObject, which allows only string, number, or boolean types (no arrays or nested objects). Query parameters are automatically parsed, and parsing errors are returned to the client if they occur. If validation passes, the flow proceeds to handleLogic with the parsed query.

Example:

index.ts
import { SchemaValidator, endpoint } from "tarin";
 
// Server initialization
...
 
// Endpoint definition
const searchEndpoint = endpoint.get("/api/search").input({
  query: SchemaValidator.object({
    q: SchemaValidator.string(),
  }),
  // Additional input definitions...
}) // Additional endpoint code (handleLogic & etc)....
 
tarin.addEndpoints(searchEndpoint);

Params

The Params represent custom path parameters (e.g., /:id). Similar to Query, Params support only string, number, or boolean types, excluding arrays and nested objects. Tarin automatically parses and validates the parameters, returning parsing errors if necessary. Valid inputs are passed to handleLogic.

Example:

index.ts
import { SchemaValidator, endpoint } from "tarin";
 
// Server initialization
...
 
// Endpoint definition
const productEndpoint = endpoint.get("/api/products/:id").input({
  params: SchemaValidator.object({
    id: SchemaValidator.string(),
  }),
  // Additional input definitions...
}) // Additional endpoint code (handleLogic & etc)....
 
tarin.addEndpoints(productEndpoint);

Headers

The Headers represent HTTP headers. Similar to Query, Headers support only string, number, or boolean types, excluding arrays and nested objects. Tarin automatically handles parsing and validation of headers, returning parsing errors if the headers are invalid. Valid inputs are then passed to the handleLogic method for further processing.

Example:

index.ts
import { SchemaValidator, endpoint } from "tarin";
 
// Server initialization
...
 
// Endpoint definition
const productEndpoint = endpoint.get("/api/products/:id")
  .input({
    headers: SchemaValidator.object({
      Authorization: SchemaValidator.string(),
    }),
    // Additional input definitions...
  })
  // Additional endpoint code (handleLogic, etc.)...
 
tarin.addEndpoints(productEndpoint);

Files

The Files input type handles file uploads via multipart/form-data. Tarin uses TarinObject, which exclusively accepts file types. Files are validated based on the provided schema, and validation errors are returned to the client if encountered. Valid files are passed to handleLogic.

Note: When an input type includes file definitions, the HTTP request body is expected to have a Content-Type of multipart/form-data.

Example:

index.ts
import { SchemaValidator, endpoint } from "tarin";
 
// Server initialization
...
 
// Endpoint definition
const uploadImageEndpoint = endpoint.post("/api/upload_image").input({
  files: SchemaValidator.object({
    image: SchemaValidator.file({
      maxSize: 1024 * 1024, // 1MB in bytes
    }),
  }),
  // Additional input definitions...
}) // Additional endpoint code (handleLogic & etc)....
 
tarin.addEndpoints(uploadImageEndpoint);

Output Type

Output types in Tarin are categorized into three groups:

  1. Body (HTTP response body)
  2. Files (file uploads via multipart/form-data)
  3. Headers (http headers)

Output type definitions follow the same principles and structure as input types, ensuring consistency and reliability in API responses.

Note: When an output type includes file definitions, the HTTP response body will have a Content-Type of multipart/form-data. If no files are included, the Content-Type will default to application/json.

Example:

index.ts
import { SchemaValidator, endpoint } from "tarin";
 
// Server initialization
...
 
// Endpoint definition
const productEndpoint = endpoint.get("/api/products/:id").input({
  params: SchemaValidator.object({
    id: SchemaValidator.string(),
  }),
  // Additional input definitions...
}).output({
  body: SchemaValidator.object({
    id: SchemaValidator.string(),
    name: SchemaValidator.string(),
    description: SchemaValidator.string(),
    price: SchemaValidator.number(),
    // properties...
  }),
}) // Additional endpoint code (handleLogic & etc)....
 
tarin.addEndpoints(productEndpoint);