Skip to content

apicase/services

Repository files navigation

Apicase services

Powerful API layer based on @apicase/core

Full documentation

Quick start with Apicase
Apicase services

Installation

yarn add @apicase/services
npm install @apicase/services

Create service

import fetch from '@apicase/adapter-fetch'
import { ApiService } from '@apicase/services'

const SomeService = new ApiService({
  adapter: fetch,
  url: '/api/posts'
  method: 'GET'
})

// { "url": "/api/posts", "method": "GET", "query": { "userId": 1 } }
SomeService.doRequest({
  query: { userId: 1 }
})

ApiTree

To reduce boilerplate code, you can declare your services as JSON object

import { ApiTree } from '@apicase/services'

const api = new ApiTree([
  { url: '/api', children: [
    { url: 'posts', children: [
      { name: 'getAllPosts',   url: '',    method: 'GET'    },
      { name: 'createPost',    url: '',    method: 'POST'   },
      { name: 'getOnePost',    url: ':id', method: 'GET'    },
      { name: 'updateOnePost', url: ':id', method: 'PUT'    },
      { name: 'removeOnePost', url: ':id', method: 'REMOVE' }
    ] },
    { url: 'profile', children: [...] }
  ] }
])

api('getAllPosts').doRequest()
api('createPost').doRequest({ body })

Parent service

You can also pass parent service instead of adapter. It may flatten structure

const Root = new ApiService(fetch, { url: '/api' })

const api = new ApiTree(Root, [
  { url: 'posts', children: [
    { name: 'getAllPosts',   url: '',    method: 'GET'    },
    { name: 'createPost',    url: '',    method: 'POST'   },
    { name: 'getOnePost',    url: ':id', method: 'GET'    },
    { name: 'updateOnePost', url: ':id', method: 'PUT'    },
    { name: 'removeOnePost', url: ':id', method: 'REMOVE' }
  ] },
  { url: 'profile', children: [...] }
])

Shorter requests

api("someService", payload) === api("someService").doRequest(payload)

ApiObjectTree helper

Alternative way to avoid string api (but there are no children option):

import { ApiObjectTree } from '@apicase/services'

const api = new ApiTree(BaseService, {
  getAllPosts: { url: '' },
  createPost:  { url: '',    method: 'POST' },
  getOnePost:  { url: ':id', method: 'POST' },
  updOnePost:  { url: ':id', method: 'PUT' },
  rmvOnePost:  { url: ':id', method: 'DELETE' }
})

api.getAllPosts.doRequest()
api.createPost.doRequest({ body })

rest and wrappedRest helpers

Helper to work with REST APIs just automatically generates urls, methods and names

import { ApiTree, rest } from "@apicase/services"

/*
  If you are lucky - default structure doesn't need to write URL's
  postsGetAll: GET    /
  postsGetOne: GET    /:id
  postsCreate: POST   /
  postsUpdOne: PUT    /:id
  postsRmvOne: DELETE /:id
*/
const posts = rest("posts", ["getAll", "getOne", "create", "updOne", "rmvOne"])

/* Skip 2nd argument to get just all routes */
const posts = rest("posts")

/* Otherwise, still OK */
const profile = rest("profile", {
  getAll: { url: "we/have" },
  create: { url: "custom/routes" },
  getOne: { url: "no_refactoring/:id" },
  updOne: { url: "since_2008/:id" },
  rmvOne: { url: "legacy_shit" }
})

new ApiTree(Root, [
  { url: "posts", children: posts },
  { url: "profile", children: profile }
])

wrappedRest helper is similar to rest but also wraps it into url with name:

import { ApiTree, wrappedRest } from "@apicase/services"

new ApiTree(Root, [wrappedRest("posts"), wrappedRest("profile")])

License

MIT © Anton Kosykh