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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@burnsred/endpoint

v1.0.1

Published

This library provides a convenient wrapper around an Axios client for making API calls using Entity classes.

Downloads

35

Readme

Endpoints

This library provides a convenient wrapper around an Axios client for making API calls using Entity classes.

Quick Start

First, create an Endpoint instance for your Entity.

import { axios } from "axios";

import { TodoEntity, type Todo } from "../todo";

export const TodoAPI = new EntityEndpoint<Todo>({
    entity: TodoEntity,
    baseUrl: "/todo/",
    client: axios,
});

Issue requests:


// By default, it will make a GET request, and expect a list response
const todos = TodoAPI.request({}); // GET /todo/

// By passing an ID, it switches to a detail response
const todo = TodoAPI.request({ id: 6 }); // GET /todo/6

// An action can also be appended
const todos = TodoAPI.request({ action: "toggle" }); // GET /todo/toggle
const todo = TodoAPI.request({ id: 6, action: "toggle" }); // GET /todo/6/toggle

// The response parsing can be overridden
const todo = TodoAPI.request({
    id: 6,
    action: "toggle",
    processResponse: (data) => OtherEntity.fromData(data),
});

Custom API calls

It's encouraged to encapsulate common API requests in methods on a sub-class to help DRY out the codebase.

class TodoEndpoint extends EntityEndpoint<Todo> {
  toggle(id: string) {
    return this.request({ action: "toggle", id });
  }
}

const TodoAPI = new TodoEndpoint({ ... });

TodoAPI.toggle("6");

DRF Entity API

This is a sub-class of EntityEndpoint with a few method added to support common CRUD operations.

For Entity<T> you get:

  list(params: QueryParams): Promise<T[]>
  create(record: T): Promise<T>
  get(id: string): Promise<T>
  save(record: T): Promise<T>
  delete(record: T): Promise<void>

useQuery

To make it easier to interact with a record from the API - especially with Forms

  • there is the useQuery hook.

function WidgetDetail() {
  const { id } = useParamms();

  const query = useQuery({ api: WidgetAPI, id });
  const { processing, value } = query;

  if (processing) return <Loading />;

  return (
    <Form {...query}>
      ...
    </Form>
  );
}

useApiList

Another helper hook is useApiList for working with lists of records.

function WidgetList() {
  const { isLoading, value, errors } = useApiList({ api: WidgetAPI });

  if (isLoading) return <Loading />;

  return (
    <>
      <h1> {value.count} results found! </h1>
      <ul>
        {value.results.map(widget => <li>{widget.name}</li>)}
      </ul>
    </>
  );
}

There is also a load function returned, which can be used to reload the results.

WARNING: Params

Note that if the params change (not the same object) the API request will re-fire.

This may unexpectedly cause a render loop!

BAD

function UserWidgets({ userId }) {
  const {} = useApiList({ api: WidgetAPI, params: { userId }})

  ...
}

Since the params object is re-defined each render, this will be seen as params changing.

This is an inherent limitation of how Object.is works, which is used by React for Memoising.

Good

function UserWidgets({ userId }) {

  const params = useMemo(() => ({ userId }), [userId]);

  const {} = useApiList({ api: WidgetAPI, params });

  ...
}