0.0.25 • Published 1 year ago

@tvili999/request-descriptors-express v0.0.25

Weekly downloads
-
License
-
Repository
-
Last release
1 year ago

Request descriptor

This package is to make you be able to create request definitions in TypeScript you can use in both backend and frontend.

This library is highly inspired by zod, and relies heavily on type inference to make it very easy to develop with typescript.

You can describe a schema for your requests and responses, and then use them from a shared package.

These schemas can be extended with each other by having a slot mechanism, to make your api layer less coupled.

It is not tied to any framework or library, you can craft your own adapter for your prefer of choice.

Example

You can define your schema like this:

// shared.ts
import s, { SchemaType } from "@tvili999/request-descriptors";

const meSchema = s.object({
    email: s.string.email(),
    fullName: s.string.notEmpty(),
    age: s.optional(s.integer()),
    admin: s.boolean()
});

export type Me = SchemaType<typeof meSchema>

export const meRequest = s.request("GET", "/api/me", s.object({
    token: s.header("authorization"),
}))

export const meResponse = s.response(200, s.body(meSchema))

export const me = s.endpoint({
    request: meRequest,
    responses: [meResponse]
})

Then you can use it with adapters (more info in the docs) to actually use it with other frameworks:

// server.ts
import route from "./route" // this is just an example, it does not exist
import express from "express";
import {me, meResponse} from "./shared.ts";

const app = express()

route(app, meRequest, (req, res) => {
    console.log(req.validatedBody); // {token: <your token>};

    res.sendValidated(meResponse, {
        email: "some@email.com",
        fullName: "Full Name",
        age: 26,
        admin: false
    })
})
// client.ts
import fetchEndpoint from "./fetchEndpoint.ts" // this too is just an example
import {me} from "./shared.ts"

const result = await fetchEndpoint(me, {});

console.log(result) // {email: "some@email.com", ...}

If you use typescript, type inference will work very heavily:

  • The SchemaType utility type can infer object type from schemas.
  • The validatedBody in the example can have a type correct representation based on the schema
  • The res.sendValidated will only let you send a response that fits the endpoint.
  • The fetchEndpoint in the client code will infer its second argument, so it will know what request data it can allow
  • The result object will have the correct type from me, even if you specify multiple responses.

Short explanation

Requests can contain query params, path params, custom headers, body etc. This package will make you be able to transform an object to a well defined form that extracts all these different data, or creates the object structure.

Our main goal is to have an endpoint. This describes a request and multiple corresponding response objects.

This endpoint will describe your requests and responses so that it is fully validated.

See examples folder to get a better idea on how it works.