docs
env
git
hbs
html
husky
jest
lintstaged
lisp
node
prettier
python
react
readme
schema
style
util
vue
web
$ tmpl api [name]
Creates an interface for talking with a rest endpoint. It will generate a file that uses fetch with a try/catch wrapper, schema validation, logging and unit test boiler plate.
Files
project
└─src
└──api
└───__tests__
└────foo.test.js
└───foo.js
↑ foo.test.js
// Recomendation: Wire node-fetch into your jest setupimport fetch from "node-fetch";//@ts-ignorewindow.fetch = fetch;import nock from "nock";import { fetchResource, fooDomain } from "../foo";describe("API foo", () => {describe("fetchData()", () => {it("should have success status with expected data", async () => {// Arrangeconst mockRequest = { some: "input" };const mockResponse = { id: 1, value: "foobar" };nock(fooDomain).post("/endpoint", mockRequest).reply(200, mockResponse);// Actconst result = await fetchResource(mockRequest);// Assertexpect(result.status).toEqual("SUCCESS");expect(result.data).toEqual(mockResponse);});it("should have invalid status for invalid data", async () => {// Arrangeconst mockRequest = { some: "input" };const mockResponse = { id: 1 };nock(fooDomain).post("/endpoint", mockRequest).reply(200, mockResponse);// Actconst result = await fetchResource(mockRequest);// Assertexpect(result.status).toEqual("INVALID");expect(result.data).toBeUndefined();});it("should have error status with undefined data", async () => {// Arrangeconst errorRestore = console.error;console.error = () => {};const mockRequest = { some: "input" };nock(fooDomain).post("/endpoint", mockRequest).reply(500);// Actconst result = await fetchResource(mockRequest);// Assertexpect(result.status).toEqual("ERROR");expect(result.data).toBeUndefined();// Cleanupconsole.error = errorRestore;});});});
↑ foo.js
import Schema from "validate";export const fooDomain = "https://some-domain.com";const dataSchema = new Schema({id: { "type": Number, required: true },value: { "type": String, required: true }})export const fetchResourceValidate = (response) => {try {const unknown = await response.json();if (dataSchema.validate(unknown).length > 0) {return { data: undefined, status: "INVALID" };}return { data: unknown, status: "SUCCESS" };} catch(err) {return { data: undefined, status: "ERROR" };}}export const fetchResource = async (payload) => {try {const response = await fetch(`${ fooDomain}/endpoint`, {method: "post",body: JSON.stringify(payload),headers: { "Content-Type": "application/json" }});if (response.statusCode >= 400) {const body = await response.text();throw Error(`Error talking to service - ${response.statusCode} - ${body});}return fetchResourceValidate(response);} catch (err) {console.error(err);return { data: undefined, status: "ERROR" };}};