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:
- Body (HTTP request body)
- Query (URL search query parameters)
- Params (custom path parameters, e.g.,
/:id
) - Headers (HTTP headers)
- 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:
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:
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:
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:
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
ofmultipart/form-data
.
Example:
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:
- Body (HTTP response body)
- Files (file uploads via
multipart/form-data
) - 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
ofmultipart/form-data
. If no files are included, theContent-Type
will default toapplication/json
.
Example:
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);