npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

repoint

v0.8.2

Published

Endpoint generator based on fetch

Downloads

33

Readme

repoint

What is this and why do I need it?

A small library for generating functions to make requests to the backend REST APIs for your client applications. Imagine you have an REST API written by backend team which has a lof of endpoints. You could go ahead and write ad-hoc ajax requests in "jquery" style:

$.ajax("/users")
  .done(function() {
    // success
  })
  .fail(function() {
    // error
  })

It will work, but there are a couple of problems here:

  1. URL hardcoding. What if you want to use the same request, but with different "success logic" in another place of your app? You would need to copy-paste it. And what if URL in backend API is changed, - you would need to go and replace the URL everywhere where you copy-pasted it.
  2. It is not composable. You have pieces of logic scattered all across the codebase. It would be better to have them in one place in some modular way, so you can have a client library for your REST API.
  3. Boilerplate. Even if you move them into separate modules/functions you would still have to write a lof of boilerplate code, which is exhausting and error-prone.

This library aims to solve above problems.

Important note

Repoint uses isomorphic-fetch under the hood, which requires ES6 Promise compatible polyfill. For more information refer to https://github.com/matthew-andrews/isomorphic-fetch#warnings

Installation

 npm install --save repoint
 npm install --save es6-promise

or any other polyfill

Basic Usage

import Repoint from 'repoint'

const repoint = new Repoint({ host: 'http://api.example.com/v1' })
const usersAPI = repoint.generate('users')

// makes GET request to http://api.example.com/v1/users
usersAPI.getCollection({})

// makes GET request to http://api.example.com/v1/users?some=1
usersAPI.getCollection({ some: 1 })

// makes GET request to http://api.example.com/v1/users/1
usersAPI.get({ id: 1 })

// makes POST request to http://api.example.com/v1/users with body { email: '[email protected]' } and ContentType: application/json
usersAPI.post({ email: '[email protected]' })
// OR
usersAPI.create({ email: '[email protected]' })

// makes PUT request to http://api.example.com/v1/users/1 with body { email: '[email protected]' } and ContentType: application/json
usersAPI.put({ id: 1, user: { email: '[email protected]' }})

// makes PATCH request to http://api.example.com/v1/users/1 with body { email: '[email protected]' } and ContentType: application/json
usersAPI.patch({ id: 1, user: { email: '[email protected]' }})
// OR
usersAPI.update({ id: 1, user: { email: '[email protected]' }})

// makes DELETE request to http://api.example.com/v1/users/1
usersAPI.delete({ id: 1 })
// OR
usersAPI.destroy({ id: 1 })

You can change idAttribute key for member URLs (get, update, destroy) by providing idAttribute option, the default value is 'id'

import Repoint from 'repoint'

const repoint = new Repoint({ host: 'http://api.example.com/v1' })
const usersAPI = repoint.generate('users', { idAttribute: 'slug' })

// makes GET request to http://api.example.com/v1/users/tom
usersAPI.get({ slug: 'tom' })

You can provide namespace as well:

import Repoint from 'repoint'

const repoint = new Repoint({ host: 'http://api.example.com/v1' })
const usersAPI = repoint.generate('users', { idAttribute: 'slug', namespace: 'admin' })

// makes GET request to http://api.example.com/v1/admin/users/tom
usersAPI.get({ slug: 'tom' })

Nested endpoints

To make requests to the nested route you use nestUnder option, which expects another endpoint:

import Repoint from 'repoint'

const repoint = new Repoint({ host: 'http://api.example.com/v1' })
const postsAPI = repoint.generate('posts', { nestUnder: repoint.generate('users') })

// makes GET request to http://api.example.com/v1/users/1/posts
// userId is generated by the following pattern:
// singularized endpoint name + capitalized idAttribute
// in this case, it is "user" + "Id"
postsAPI.getCollection({ userId: 1 })

// makes GET request to http://api.example.com/v1/users/1/posts/1
postsAPI.get({ userId: 1, id: 1 })

There is no limit for nesting level. idAttribute and namespace options also work for nested endpoints

Non-restful endpoints

It's often that you need to make request to a non-restful endpoint, e.g. /users/login

You can define them in the 3rd argument of generate function:

import Repoint from 'repoint'

const repoint = new Repoint({ host: 'http://api.example.com/v1' })
const usersAPI = repoint.generate('users', {}, [{ method: 'post', name: 'login', on: 'collection' }])

// makes POST request to http://api.example.com/v1/users/login
usersAPI.login({ /* params */ })

Singular endpoints

Those are URLs with no collectionURL and with no idAttributes (similar to Rails resource method in routes.rb)

You can define them in the following way:

import Repoint from 'repoint'

const repoint = new Repoint({ host: 'http://api.example.com/v1' })
const userAPI = repoint.generate('user', { singular: true })

// makes GET request to http://api.example.com/v1/user
userAPI.get({}) // no `id` to get the user

This will generate all the functions omitting getCollection. Also no idAttributes are necessary.

Notice that you are providing a 'singular' name, (of course you can provide any name, pluralization/singularization simply is not applied in this case).

Response decorators

When creating a Repoint instance, there is an additional config to transform the response for all the generated endpoints. By default, it returns what comes from the server as it is, but you can provide your own. I like to use humps to convert all of the object keys to camelCase or vice versa. You can do whatever you want, the only requirement is that it should be a function.

import Repoint from 'repoint'
import { camelizeKeys, decamelizeKeys } from 'humps'

const repoint = new Repoint({
  host: 'http://api.example.com/v1',
  // convert query params or body params keys (in case of POST/PATCH/PUT requests) to underscore-separated
  paramsTransform: (data) => decamelizeKeys(data),
  beforeSuccess: (data) => camelizeKeys(data),
  /* beforeError: same but for error */
  /* responseHandler: response decorator that receives Response promise. Useful for handling 204 statuses */
})
const usersAPI = repoint.generate('users')
usersAPI.get({ id: 1, firstName: 'Bob' /* will be converted to { id: 1, first_name: 'Bob' } */ })
        .then((data) => /* data will have all of its object keys converted to camelCase */)

Fetch options

There is a fetchOpts parameter for Repoint constructor which corresponds to init param in Fetch API.

For example, if you want to send cookies with every request, you must provide credentials: 'include' for fetchOpts.

import Repoint from 'repoint'

const repoint = new Repoint({
  host: 'http://api.example.com/v1',
  fetchOpts: { credentials: 'include' }
})