minosss / api

define type-safe API routes simply

Home Page:https://api-six-kohl.vercel.app

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Hey 👋, @yme/api is a package that defines the type-safe API routes. No server required and zero dependencies.

If you are developing a full-stack web application, you should take a look tRPC.

NPM version NPM Downloads Bundle Size

Why

  • I am a frond-end developer.
  • [module].[action] is good for me. (e.g. post.create(input))
  • I usually use axios but there may be others. (e.g. fetch)
  • It may be need some transformer for each api response. because my colleagues are very unrestrained

So I create this package to solve these problems. (I hope so)

🚧 TODOs

  • with react-query
  • generate from api docs e.g. swagger

Install

pnpm add @yme/api

Quick Start

import { createApi, createRouter } from '@yme/api';
import axios from 'axios';
import { z } from 'zod';

const request = axios.create({}).request;

const router = createRouter();

const createUserSchema = z.object({
  username: z.string().min(1),
  password: z.string().min(1),
  age: z.number().optional(),
});

type CreateUserInput = z.infer<typeof createUserSchema>;

interface UserType {
  id: number;
  username: string;
}

const routes = {
  users: {
    create: router
      .post('/users') // api.user.create({...}) => POST /users
      .validator(createUserSchema)
      .T<UserType>().selector(user => user.id), // (input: CreateUserInput): number
      // same as .selector((user: UserType) => user.id),
    delete: router
      .delete('/users/:id') // api.user.delete(123) replace path with input => DELETE /users/123
      .validator(z.number())
      .T<void>(), // (input: number): void
    update: router
      .put('/users/:id') // api.user.update(input) will replace with input[id] => PUT /users/{id}
      .validator(z.object({username: z.string().optional(), age: z.number().optional(), id: z.number()}))
      .T<UserType>(), // (input: {username?: string; age?: number; id: number}): UserType
    list: router
      // .get('/users'), api.user.list({page: 1}) => GET /users?page=1
      .T<{page: number}, {list: UserType[]}>()
      .validator(({page}) => page > 0)
      .selector(({list}) => list), // (input: {page: number}): UserType[]
  }
}

const api = createApi({
  http: request,
  routes,
});

declare module '@yme/api' {
  interface Register {
    api: typeof api;
  }
}

// use api
const userId = await api.users.create({username: 'yoyo', password: 'yoyo123'});
console.log(`user id: ${userId}`);
// delete user
await api.users.delete(userId);
// done.

How to define a route?

// method and path always required
router.post('/users');
// method, path and validator (input)
router.post('/users').validator(schema);
// with selector
router.post('/users').T<UserType>().selector((user) => user.id);
router.post('/users').selector((user: UserType) => user.id);
// method, path, validator (input) and selector (output)
router.post('/users').validator(schema).selector((user: UserType) => user.id);
// with types (input, output)
router.post('/users').T<In, Out>();
// validator and output
router.post('/users').validator(schema).T<Out>();
// types first
router.post('/users').T<In, Out>().validator((in) => in).selector(out => out);

License

MIT

About

define type-safe API routes simply

https://api-six-kohl.vercel.app

License:MIT License


Languages

Language:TypeScript 100.0%