Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

restful-react

contiamo26.3kMIT15.9.4TypeScript support: included

A consistent, declarative way of interacting with RESTful backends, featuring code-generation from Swagger and OpenAPI specs

rest, restful, react, react-component, fetch, data fetching

readme

restful-react

npm

Building React apps that interact with a RESTful API presents a set of questions, challenges and potential gotchas. This project aims to remove such pitfalls, and provide a pleasant developer experience when crafting such applications.

It can be considered a thin wrapper around the fetch API in the form of React components and hooks.

When used in a setup with OpenAPI / Swagger specs and Typescript, restful-react ensures a reliable and always up to date contract between backend and frontend. It generates components and types from your specs and can be integrated quite comfortably into your development workflows (featuring for example the import of OpenAPI specs from your github repos).

restful-react is very well tested, production ready and powers all of our projects at Contiamo.

Overview

At its core, restful-react exposes a hook, called useGet. This component retrieves data, either on mount or later, and then handles error states, loading states, and other cases for you. As such, you get a component that gets stuff and then does stuff with it. Here's a quick overview what it looks like.

Edit restful-react demos

import React from "react";
import { useGet } from "restful-react";

const MyComponent = () => {
  const { data: randomDogImage } = useGet({
    path: "https://dog.ceo/api/breeds/image/random",
  });

  return <img alt="Here's a good boye!" src={randomDogImage && randomDogImage.message} />;
};

export default MyComponent;

and on React Native, Edit restful-react basic demo on Expo

import { AppRegistry, Image } from "react-native";
import React from "react";

import { useGet } from "restful-react";

const App = () => {
  const { data: randomDogImage } = useGet({
    path: "https://dog.ceo/api/breeds/image/random",
  });
  return (
    <>
      {randomDogImage && (
        <Image
          style={{ width: 250, height: 250 }}
          source={{
            uri: randomDogImage.message,
          }}
        />
      )}
    </>
  );
};

AppRegistry.registerComponent("react-native-app", () => App);

Getting Started

To install and use this library, install it by running yarn add restful-react, or npm i restful-react --save and you should be good to go. Don't forget to import { useGet } from "restful-react" or similar wherever you need it!

Features

restful-react ships with the following features that we think might be useful.

Global Configuration

REST API endpoints usually sit alongside a base, global URL. As a convenience, the RestfulProvider allows top-level configuration of your requests, that are then passed down the React tree to useGet hooks.

Consider,

Edit restful-react demos

// index.js

import React from "react";
import { RestfulProvider } from "restful-react";

import App from "./App.jsx";

const MyRestfulApp = () => (
  <RestfulProvider base="https://dog.ceo/api">
    <App />
  </RestfulProvider>
);

export default MyRestfulApp;

Meanwhile, in ./App.jsx,

// App.jsx

import React from "react";
import { useGet } from "restful-react";

const MyComponent = () => {
  const { data: randomDogImage } = useGet({
    // Inferred from RestfulProvider in index.js
    path: "breeds/image/random",
  });

  return <img alt="Here's a good boye!" src={randomDogImage && randomDogImage.message} />;
};

export default MyComponent;

Naturally, the request will be sent to the full path https://dog.ceo/api/breeds/image/random. The full API of the RestfulProvider is outlined below. Each configuration option is composable and can be overridden by Get components further down the tree.

RestfulProvider API

Here's a full overview of the API available through the RestfulProvider, along with its defaults.

// Interface
export interface RestfulReactProviderProps<T = any> {
  /** The backend URL where the RESTful resources live. */
  base: string;
  /**
   * The path that gets accumulated from each level of nesting
   * taking the absolute and relative nature of each path into consideration
   */
  parentPath?: string;
  /**
   * A function to resolve data return from the backend, most typically
   * used when the backend response needs to be adapted in some way.
   */
  resolve?: ResolveFunction<T>;
  /**
   * Options passed to the fetch request.
   */
  requestOptions?: ((url: string, method: string, requestBody?: string) => Partial<RequestInit>) | Partial<RequestInit>;
  /**
   * Trigger on each error.
   * For `Get` and `Mutation` calls, you can also call `retry` to retry the exact same request.
   * Please note that it's quite hard to retrieve the response data after a retry mutation in this case.
   * Depending of your case, it can be easier to add a `localErrorOnly` on your `Mutate` component
   * to deal with your retry locally instead of in the provider scope.
   */
  onError?: (err: any, retry: () => Promise<T | null>, response?: Response) => void;
  /**
   * Trigger on each request.
   */
  onRequest?: (req: Request) => void;
  /**
   * Trigger on each response.
   */
  onResponse?: (req: Response) => void;
  /**
   * Query parameters passed to each request.
   */
  queryParams?: { [key: string]: any };
  /**
   * Query parameter stringify options applied for each request.
   */
  queryParamStringifyOptions?: IStringifyOptions;
}

// Usage
<RestfulProvider
  base="String!"
  resolve={data => data}
  requestOptions={(url, method, requestBody) => ({ headers: { Authorization: authToken } })}
/>;

Here's some docs about the RequestInit type of request options.

Loading and Error States

useGet hooks return an object with loading and error states, to allow for state handling. Consider,

Edit restful-react demos

import React from "react";
import { useGet } from "restful-react";

const MyComponent = () => {
  const { data: randomDogImage, loading } = useGet({
    path: "https://dog.ceo/api/breeds/image/random",
  });

  return loading ? <h1>Loading...</h1> : <img alt="Here's a good boye!" src={randomDogImage.message} />;
};

export default MyComponent;

Lazy Fetching

It is possible to use a useGet hook and defer the fetch to a later stage. This is done with the lazy boolean property. This is great for displaying UI immediately, and then allowing parts of it to be fetched as a response to an event: like the click of a button, for instance. Consider,

Edit restful-react demos

import React from "react";
import { useGet } from "restful-react";

const MyComponent = () => {
  const { data: randomDogImage, loading, refetch } = useGet({
    path: "https://dog.ceo/api/breeds/image/random",
    lazy: true,
  });

  return !randomDogImage && loading ? (
    <h1>Loading!</h1>
  ) : (
    <div>
      <div>
        <h1>Welcome to my image getter!</h1>
        <button onClick={() => refetch()}>Get a good boye!</button>
      </div>
      <div>{randomDogImage && <img alt="Here's a good boye!" src={randomDogImage.message} />}</div>
    </div>
  );
};

export default MyComponent;

The above example will display your UI, and then load good boyes on demand.

Response Resolution

Sometimes, your backend responses arrive in a shape that you might want to adapt, validate, or restructure. Other times, maybe your data consistently arrives in a { data: {} } shape, with data containing the stuff you want.

At the RestfulProvider level, or on the useGet level, a resolve prop will take the data and do stuff to it, providing the final resolved or unwrapped data to the children. Consider,

Edit restful-react demos

import React from "react";
import { useGet } from "restful-react";

const MyComponent = () => {
  const { data: imageUrl } = useGet({
    path: "https://dog.ceo/api/breeds/image/random",
    resolve: image => image && image.message,
  });

  return imageUrl && <img alt="Here's a good boye!" src={imageUrl} />;
};

export default MyComponent;

Debouncing Requests

Some requests fire in response to a rapid succession of user events: things like autocomplete or resizing a window. For this reason, users sometimes need to wait until all the keystrokes are typed (until everything's done), before sending a request.

restful-react exposes a debounce prop on Get that does exactly this.

Here's an example:

const SearchThis = props => {
  const { data } = useGet({
    path: "/hello/world",
    debounce: true,
  });

  return (
    <div>
      <h1>Here's all the things I search</h1>
      <ul>
        {data.map(thing => (
          <li>{thing}</li>
        ))}
      </ul>
    </div>
  );
};

Debounce also accepts a number, which tells useGet how long to wait until doing the request.

const SearchThis = props => {
  const { data } = useGet({
    path: "/hello/world",
-    debounce: true,
+    debounce: 200 /* ms */,
  })

  return <div>
        <h1>Here's all the things I search</h1>
        <ul>
          {data.map(thing => (
            <li>{thing}</li>
          ))}
        </ul>
      </div>
}

It uses lodash's debounce function under the hood, so you get all the benefits of it out of the box like so!


const SearchThis = props => {
  const { data } = useGet({
    path: "/hello/world",
-    debounce: 200,
+    debounce: { wait: 200, options: { leading: true, maxWait: 300, trailing: false } } /* ms */,
  })

  return <div>
        <h1>Here's all the things I search</h1>
        <ul>
          {data.map(thing => (
            <li>{thing}</li>
          ))}
        </ul>
      </div>
}

TypeScript Integration

One of the most powerful features of restful-react is that each component exported is strongly typed, empowering developers through self-documenting APIs.

Using restful-react in VS Code

Query Parameters

All components in this library support query params (https://my.site/?query=param) via a queryParams prop. Each useGet, useMutate and Poll instance is generic, having a type signature of useGet<TData, TError, TQueryParams>. If described, the queryParams prop is fully type-safe in usage and provides autocomplete functionality.

Autocompletion on QueryParams

Please note that the above example was built using our OpenAPI generator in order to infer the type of component from the specification and automatically generate the entire type-safe component in a very quick and easy way.

Mutations with useMutate

restful-react exposes an additional hook called useMutate. These components allow sending requests with other HTTP verbs in order to mutate backend resources.

Edit restful-react demos

import React from "react";
import { useGet, useMutate } from "restful-react";

const base = "https://jsonplaceholder.typicode.com";

const ListItem = ({ id, children }) => {
  const { mutate: del, loading } = useMutate({
    verb: "DELETE",
    path: `/posts/`,
    base,
  });

  return (
    <li key={id}>
      {loading ? (
        "Deleting..."
      ) : (
        <button onClick={() => del(id).then(() => alert("Deleted successfully. Pretend it got removed from the DOM."))}>
          ❌
        </button>
      )}
      &nbsp;{children}
    </li>
  );
};

const MyHugeList = () => {
  const { data: posts } = useGet({
    path: "/posts",
    base,
  });
  return (
    <div>
      <h1>Posts</h1>
      <ul>
        {posts &&
          posts.map(post => (
            <ListItem key={post.id} id={post.id}>
              {post.title}
            </ListItem>
          ))}
      </ul>
    </div>
  );
};
export default MyHugeList;

useMutate is strongly typed, and provides intelligent autocompletion out of the box, complete with other available HTTP verbs.

Mutate

Each mutation returns a promise that can then be used to update local component state, dispatch an action, or do something else depending on your use case.

Mocks

No backend support yet for your amazing feature? Need to isolate an edge case? You can easily provide a mock to useMutate and useGet to bypass the classic flow.

/!\ If mock option is provided, no requests will be send to the server. /!\

import React from "react";
import { useGet, useMutate } from "restful-react";

const base = "https://jsonplaceholder.typicode.com";

// Mock the `mutate` handler
const { mutate: del, loading } = useMutate({
  verb: "DELETE",
  path: `/posts/`,
  base,
  // This will avoid any server call in favor of mock response
  mock: {
    mutate: id => console.log(`The item ${id} was deleted`),
  },
});

// Mock the `loading`, so it's easy to isolate the loading state
const { data: posts } = useGet({
  path: "/posts",
  base,
  // This will avoid any server call in favor of mock response
  mock: {
    loading: true,
  },
});

// Mock the `error`, so it's easy to isolate the error state
const { data: posts } = useGet({
  path: "/posts",
  base,
  // This will avoid any server call in favor of mock response
  mock: {
    error: "oh no!",
  },
});

Polling with Poll

restful-react also exports a Poll render props component that will poll a backend endpoint over a predetermined interval until a stop condition is met. Consider,

import { Poll } from "restful-react"

<Poll path="/deployLogs" resolve={data => data && data.data}>
  {(deployLogs: DeployLog[], { loading }) =>
    loading ? (
      <PageSpinner />
    ) : (
      <DataTable
        columns={["createdAt", "deployId", "status", "sha", "message"]}
        orderBy="createdAt"
        data={deployLogs}
        formatters={{
          createdAt: (d: DeployLog["createdAt"]) => title(formatRelative(d, Date.now())),
          sha: (i: DeployLog["sha"]) => i && i.slice(0, 7),
        }}
      />
    )
  }
</Poll>

Poll supports:

  • an interval prop that will poll at a specified interval (defaults to polling 1 second), and
  • an until prop that accepts a condition expressed as a function that returns a boolean value. When this condition is met, polling will stop.

    The signature of this function is (data: T, response: ResponseInit) => boolean. As a developer, you have access to the returned data, along with the response object in case you'd like to stop polling if response.ok === false, for example.

Below is a more convoluted example that employs nearly the full power of the Poll component.

<Poll path="/status" until={(_, response) => response && response.ok} interval={0} lazy>
  {(_, { loading, error, finished, polling }, { start }) => {
    return loading ? (
      <Progress error={error} />
    ) : (
      <Button
        loading={editorLoading || polling}
        condensed
        icon="ExternalLink"
        color="ghost"
        onClick={() => {
          if (finished) {
            return window.open(editor.url);
          }
          requestEditor();
          start();
        }}
      >
        {finished ? "Launch Editor" : "Request Editor"}
      </Button>
    );
  }}
</Poll>

Note from the previous example, Poll also exposes more states: finished, and polling that allow better flow control, as well as lazy-start polls that can also be programmatically stopped at a later stage.

Long Polling

At Contiamo, we have a powerful Long Polling specification in place that allows us to build real-time apps over HTTPS, as opposed to WebSockets. At a glance the specification can be distilled into:

  • Web UI sends a request with a Prefer header that contains:
    • a time, in seconds, to keep requests open (60s), and
    • a polling index that is a server-sent hash ahpiegh.
    • all together, the client sends a request with a header Prefer: wait=60s;index=939192.
  • The backend server responds, either with:
    • an empty response with status 304 Not Modified
    • a successful response with data and a new polling index.

The polling index allow the client and the server to stay in sync: the client says "the last stuff I got was at this index". The server says "oh, let me get you up to speed and send you a new index".

Visually, this is represented as below.

Contiamo Poll.

To get this functionality in restful-react, this means specifying a wait prop on your Poll component, provided your server implements this specification as well.

Full Poll Component API

Polling and Code Generation

By default we generate a Poll component when the prefer header is specified in the OpenAPI/Swagger specs (more information about this design decision here -> https://github.com/contiamo/restful-react#long-polling).

We do not generate an equivalent hook version. Polling is quite trivial in a react hook, so we usually just use useEffect when we need some polling feature.

Example:

// Poll data if no completedAt
useEffect(() => {
  if (error) {
    return onError();
  } else if (data && !data.completedAt) {
    const timerId = window.setTimeout(() => refetch(), 1000);
    return () => window.clearTimeout(timerId);
  } else {
    return;
  }
}, [data, refetch, error]);

Code Generation from OpenAPI / Swagger specs

restful-react is able to generate React hooks with appropriate type-signatures (TypeScript) from any valid OpenAPI v3 or Swagger v2 specification, either in yaml or json formats.

Usage

Type-safe React data fetchers can be generated from an OpenAPI specification using the following command:

  • restful-react import --file MY_OPENAPI_SPEC.yaml --output my-awesome-generated-types.tsx

This command can be invoked by either:

  • Installing restful-react globally and running it in the terminal: npm i -g restful-react, or
  • Adding a script to your package.json like so:
      "scripts": {
        "start": "webpack-dev-server",
        "build": "webpack -p",
+       "generate-fetcher": "restful-react import --file MY_SWAGGER_DOCS.json --output FETCHERS.tsx"
      }

Your components can then be generated by running npm run generate-fetcher. Optionally, we recommend linting/prettifying the output for readability like so:

      "scripts": {
        "start": "webpack-dev-server",
        "build": "webpack -p",
        "generate-fetcher": "restful-react import --file MY_SWAGGER_DOCS.json --output FETCHERS.tsx",
+       "postgenerate-fetcher": "prettier FETCHERS.d.tsx --write"
      }

Validation of the OpenAPI specification

To enforce the best quality as possible of specification, we have integrated the amazing OpenAPI linter from IBM. We strongly encourage you to setup your custom rules with a .validaterc file, you can find all useful information about this configuration here.

To activate this, add a --validation flag to your restful-react call.

API Versioning

The generated file will include an exported constant SPEC_VERSION that will contain to the OpenAPI info.version property's value.

Import from URL

Adding the --url flag to restful-react import instead of using the --file flag will attempt to fetch the spec from that endpoint.

  • restful-react import --url https://api.mine.com/openapi.json --output my-awesome-generated-types.tsx

Import from GitHub

Adding the --github flag to restful-react import instead of using the --file flag allows us to create React components from an OpenAPI spec remotely hosted on GitHub. (how is this real life 🔥 )

To generate components from remote specifications, you'll need to follow the following steps:

  1. Visit your GitHub settings.
  2. Click Generate New Token and choose the following:

    Token Description: (enter anything)
    Scopes:
        [X] repo
            [X] repo:status
            [X] repo_deployment
            [X] public_repo
            [X] repo:invite
            [X] security_events
  3. Click Generate token.

  4. Copy the generated string.
  5. Open a terminal and run restful-react import --github username:repo:branch:path/to/openapi.yaml --output MY_FETCHERS.tsx, substituting things where necessary.
  6. You will be prompted for a token.
  7. Paste your token.
  8. You will be asked if you'd like to save it for later. This is entirely up to you and completely safe: it is saved in your home directory.
  9. You're done! 🎉

Note: For CI environment, you can also provide the github token with the environment variable called GITHUB_TOKEN

Transforming an Original Spec

In some cases, you might need to augment an existing OpenAPI specification on the fly, for code-generation purposes. Our CLI makes this quite straightforward:

  restful-react import --file myspec.yaml --output mybettercomponents.tsx --transformer path/to/my-transformer.js

The function specified in --transformer is pure: it imports your --file, transforms it, and passes the augmented OpenAPI specification to restful-react's generator. Here's how it can be used:

// /path/to/my-transformer.js

/**
 * Transformer function for restful-react.
 *
 * @param {OpenAPIObject} schema
 * @return {OpenAPIObject}
 */
module.exports = inputSchema => ({
  ...inputSchema,
  // Place your augmentations here
  paths: Object.entries(schema.paths).reduce(
    (mem, [path, pathItem]) => ({
      ...mem,
      [path]: Object.entries(pathItem).reduce(
        (pathItemMem, [verb, operation]) => ({
          ...pathItemMem,
          [verb]: {
            ...fixOperationId(path, verb, operation),
          },
        }),
        {},
      ),
    }),
    {},
  ),
});

Advanced configuration

restful-react supports the concept of "schema stitching" in a RESTful ecosystem as well. We are able to tie multiple backends together and generate code using a single configuration file, restful-react.config.js

To activate this "advanced mode", replace all flags from your restful-react call with the config flag: --config restful-react.config.js (or any filename that you want).

⚠️ Note: using a config file makes use of all of the options contained therein, and ignores all other CLI flags.

Config File Format
interface RestfulReactConfig {
  [backend: string]: {
    // classic configuration
    output: string;
    file?: string;
    github?: string;
    transformer?: string;
    validation?: boolean;
    skipReact?: boolean;

    // advanced configuration
    customImport?: string;
    customProps?: {
      base?: string;
    };
    pathParametersEncodingMode?: "uriComponent" | "rfc3986";
    customGenerator?: (data: {
      componentName: string;
      verb: string;
      route: string;
      description: string;
      genericsTypes: string;
      operation: OperationObject;
      paramsInPath: string[];
      paramsTypes: string;
    }) => string;
  };
}
Config File Example
// restful-react.config.js
/**
 * Restful-react configuration.
 *
 * @type {import("restful-react/dist/bin/config").RestfulReactAdvancedConfiguration}
 */
module.exports = {
  myFirstBackend: {
    output: "src/queries/myFirstBackend.tsx",
    file: "specs/my-first-backend.yaml",
    customProps: {
      base: `"http://my-first-backend.com"`,
    },
  },
  configurableBackend: {
    output: "src/queries/configurableBackend.tsx",
    github: "contiamo:restful-react:master:docs/swagger.json",
    customImport: `import { getConfig } from "../components/Config.tsx";`,
    customProps: {
      base: `{getConfig("backendBasePath")}`,
    },
  },
};
// package.json
{
  "scripts": {
    "gen": "restful-react import --config restful-react.config.js",
    "gen-first": "restful-react import --config restful-react.config.js myFirstBackend"
  }
}
Custom generator

To support even more advanced usecases (like a promise base API, mock generator or anything else that can infer from your specs), you can define your own template in customGenerator. This function will be call for each route with some useful computed values (see the types above) and the resulted string will be added to the generated file.

You can see a concrete usage inside the examples folder and try yourself in this repository with the following command:

  • yarn build
  • yarn example:advanced petstore-custom-fetch

You can inspect the result inside /examples/petstoreFromFileSpecWithCustomFetch.tsx

Only generating custom code (no react hooks/components)

In some cases you might want to use the familiar restful-react to generate code for non-react environments (e.g. promise-based fetchers for nodejs or other frameworks). In this case, you can disable react code generation altogether by passing the --skipReact flag or, if you are using a configuration file, setting skipReact: true.

When set, only your custom generators will be executed.

Contributing

All contributions are welcome – especially:

  • documentation,
  • bug reports and issues,
  • code contributions.

Code

If you'd like to actively develop or help maintain this project then there are existing tests against which you can test the library with. Typically, this looks like

  • git clone git@github.com:contiamo/restful-react.git
  • cd restful-react
  • yarn install
  • yarn test --watch

From there, you should be able to start developing without problems.

How to publish to npm

Just update the version in package.json!

As soon as your branch will be merged to master, a new npm version will be automatically published for you.

@without-cli npm package

If for any reasons you don't want to use our CLI to generate restful-react components, we provide a without-cli version of the package.

Just npm install restful-react@without-cli to have this light version.

This version will follow latest but without the cli part (more details into publish-without-cli.js).

Next Steps

We're actively developing this at Contiamo to meet our use cases as they arise. If you have a use case that you'd like to implement, do it! Open an issue, submit a Pull Request, have fun! We're friendly.

changelog

Changelog

All notable changes to this project will be documented in this file. Dates are displayed in UTC.

Generated by auto-changelog.

v15.9.2

v15.9.1

24 September 2021

  • Fix: empty required should not generate invalid types. #374

v15.9.0

16 August 2021

  • Bump ibm-openapi-validator feab4bc

v15.8.0

20 July 2021

  • Add unit test b94cff0
  • support required at root level e179727
  • Fix parameter getting replaced from path e18fa08

v15.7.0

13 July 2021

  • Add yarn d0aad44
  • Bump browserslist from 4.16.3 to 4.16.6 bdcff08
  • Bump handlebars from 4.7.6 to 4.7.7 90606b0

v15.5.1

22 April 2021

  • minor: update babel deps in lockfile e3f50de

v15.5.0

22 April 2021

  • stabilize the identity of useGet and its refetch method #186
  • stabilize across multiple calls fix even more 5d2ad1e
  • minor test fix (toEqual -> toBe) b145405

v15.4.2

16 April 2021

  • Expose more customProps & add some metadata 6c97387
  • Implement resolve for Mutate 3945ad0
    • support form-data on mutate function (already fixed for useMutate) e6a1d0f

v15.3.0

22 March 2021

  • Stabilize the identity of the mutate function b75d2a6

v15.2.0

1 February 2021

  • Include spec version in generated file. 9407357

v15.1.4

4 January 2021

v15.1.3

11 December 2020

  • Fix allOf in requestBodies generation #317
  • fix: Avoid including undefined bodies in DELETE d7e7648
  • Bump dot-prop from 4.2.0 to 4.2.1 01b145b
  • Bump ini from 1.3.5 to 1.3.7 2bf6808

v15.1.2

6 November 2020

  • Fix allOf in requestBodies generation #317
  • Fix path generation ec6d49a

v15.1.1

14 October 2020

v15.1.0

12 October 2020

  • Fix changelog 30abf57
  • Remove originalResponse flag e1896fa
  • Update Readme with more information on code generation. d9e9623

v15.0.0

7 October 2020

  • Wrap path params with url encoding function 0bd6866
  • Remove default encoding function (pathParametersEncodingMode) b4fdbbd
  • Add --skip-react flag a9a0e73

v14.4.0

11 August 2020

  • Resolve parameters $ref #259
  • Support queryParamStringifyOptions on RestfulProvider level 81a4020
  • Handle body object for DELETE request 53ad85c
  • Bump lodash from 4.17.15 to 4.17.19 4452f57

v14.2.1

10 July 2020

  • Resolve parameters $ref #259
  • Fix npm-publish-without-cli CI a189eaa

v14.2.0

10 July 2020

  • Replace yamljs with js-yaml #280
  • Clone response before passing to onResponse cc1a801
  • Fix build (babel helper-compilation-targets workaround) c4b0494

v14.1.1

9 July 2020

v14.1.0

9 July 2020

  • Allow content-type wildcard (/) pattern #279

v14.0.2

24 June 2020

  • Refetch when provider props change c5c0fe0
  • Add pathParams to the watching list to refetch 42d5694

v14.0.1

24 June 2020

  • Add mocks support on hooks 5b25523
  • Avoid shallowed variable in generated paramsInPath 1b737fb
  • Deal with empty interface in schema 82b6d98

v14.0.0

15 June 2020

v13.0.0

5 June 2020

  • feat: add support for path params is useMutate f50da00
  • feat: add support for path params is useMutate 63fe965
  • feat: add support for path params is useMutate 96fd119

v12.0.0

4 May 2020

  • 261 - processResponse support blob & Co b258d7b

  • 261 - processResponse support blob & Co 5d26fee

v11.2.0

12 April 2020

  • add support for passing queryParams in mutate method 617a3e0
  • support formdata 23f6324
  • Fix a random test fail… (not critical) bf8e1f2

v11.1.0

12 April 2020

  • Added onRequest & onResponse in RestfulProvider b00c0b1
  • Trigger onError on useGet catch case 1abf095
  • Improve onError types 0f9eab8

v11.0.0

27 March 2020

  • Trigger onError on useGet catch case 3e4b4e0
  • Improve onError types 88db463
  • Resolve the scalar for delete type 3e8f56c

v10.0.1

23 March 2020

  • Use type from specs for delete operations eb569d4
  • Deal with schema ref 3a8320e
  • Resolve the scalar for delete type 50ee413

v10.0.0

20 March 2020

  • Extract usage of AbortController into own hook to check if it is available #243
  • Add querystring params 2c15815
  • Use type from specs for delete operations ae63296
  • Allow passing options to qs.stringify 3a2700e

v9.12.0

18 February 2020

  • Remove danger.js eed1135
  • Add a publish flow with "without-cli" version b930d47
  • Add querystring params 1805ecd

v9.11.1

11 February 2020

  • fix: fix codegen for array of enums 74a342f
  • fix: fix codegen for array of enums 84e2c88

v9.11.0

4 February 2020

  • Deal with charset #231
  • Improve block readability ab65d3e
  • Save token in home instead of node_modules 87fb25b
  • Update github help link c041227

v9.10.1

3 February 2020

v9.10.0

28 January 2020

  • Add documentation / example for custom generator d8b1cc5
  • Extract requestBody type if inline a6919e1
  • Fix empty object vs free form object specs e5b1ca6

v9.9.1

22 January 2020

  • Export RestfulReactProviderProps 74572ed

v9.9.0

22 January 2020

  • Replace @operational/scripts with tsdx f2adece
  • build: update yarn.lock file to use public npm registry 396e6ba
  • Add lodash-es 29fcc5f

v9.7.1

13 January 2020

  • Bump handlebars from 4.1.2 to 4.5.3 #204
  • build: updated dependencies such as @testing-library 2998855
  • build: update husky definition in package.json 2d2693a
  • Update yarn.lock f37cc0c

v9.7.0

9 January 2020

  • Add schema description as documentation 0746e93

v9.6.2

9 January 2020

  • Handle importSpecs error #99
  • Add docs to query params 396eeac

v9.6.1

23 December 2019

  • Handle importSpecs error #99

v9.6.0

16 December 2019

  • Add documentation on hooks version 25f9686
  • Generate docs for object properties and fix components docs b79b234
  • Add Response description b6614dc

v9.5.0

13 December 2019

  • fix get tests c654cc1
  • add promise test to get and poll components 93aacc7
  • Make request options asyncable d10cbe4

v9.4.2

11 December 2019

  • fix: add double quotes for special properties 23f0e7f
  • Do not report user aborted requests as errors 9b75814
  • fix: add double quotes for query params 4afa1a9

v9.4.1

11 December 2019

  • fix: set displayName correctly 98d248c

v9.4.0

25 November 2019

  • Improve the generated type of additionalProperties #187

v9.3.0

22 November 2019

  • Update React peer dependency #182
  • Support pulling spec from URL #169
  • Fix type definition of refetch() #174
  • Fix undefined in success message #158
  • Add: Getting started with react native and editable example on expo. Bumped react version to 16.8.5 from 16.8.4 to match react-dom dependency and added react to dev dependency #161
  • Fix: Path resolution when base path is null/empty #160
  • Support Global queryparams #157
  • Add support for global queryParams and composition 80bac52
  • Deal with discriminator pattern 0ce7bb6
  • feat: add displayName to Context component b41a230

v9.1.0

21 October 2019

v9.0.1

18 September 2019

  • Add basic configuration support 0db9d09
  • Handle customProps & customImport 0a3db29
  • Deal with customProps in hooks 5259378

v8.1.4

10 September 2019

  • Move request to dependencies 23e9501

v8.1.3

31 July 2019

  • Deal with nullable attribute fbae11c

v8.1.2

30 July 2019

  • Fix useMutate with delete generation a972ca8

v8.1.1

30 July 2019

v8.1.0

29 July 2019

  • Bump lodash from 4.17.11 to 4.17.13 #138
  • Add a unit test for non-json error responses - Closed #140 #140
  • Add a onMutate callback. 708ee4c
  • Keep tsconfig 9efe082
  • Add fix for #136 3ad53b2

v8.0.0

5 July 2019

  • Unify error message format with Get #135

v7.6.4

3 July 2019

  • fix/132 handle fetch error mutate #134

v7.6.3

21 June 2019

v7.6.2

21 June 2019

  • Fix delete without id case #131
  • Bump js-yaml from 3.13.0 to 3.13.1 #128
  • Bump handlebars from 4.1.1 to 4.1.2 #129
  • Generate useMutate components #126
  • Handle empty response (204 status) #125
  • Avoid to use reserved keyword in the example #122
  • Propagate the error on Mutate #121
  • Add dependencies 4b6cebc
  • Add the useMutate 3ef62e7
  • Generate useMutate from openAPI f0b4171

v7.6.1

8 May 2019

v7.6.0

23 April 2019

  • useGetProps take only 2 generics #117
  • new tag version v7.6.0 a6321de
  • exporting missing UseGetProps 217f0e3

v7.5.0

23 April 2019

v7.4.0

23 April 2019

  • exporting missing UseGetProps 0ff29fb

v7.3.1

23 April 2019

  • useGetProps take only 2 generics #117
  • exporting missing UseGetProps 217f0e3

v7.3.0

23 April 2019

  • Fix useGet url composition pattern #114
  • Add support for requestOptions as a method to Poll #113
  • Add requestOptions in the watch list for refetch #110
  • Add useGet generator adb1ae6
  • Fixed a case with merging request options in Poll 1914b50

v7.2.3

1 April 2019

  • Fix/use get error clearing #109

v7.2.2

29 March 2019

  • Recreate an abortController for the next call 32f6b72

v7.2.1

27 March 2019

v7.1.1

2 February 2019

  • Fix infinite request loop because of queryParam equality #100

v7.1.0

12 December 2018

v7.0.1

10 December 2018

  • Fix Get reload on queryParams change 4ccf8b5

v7.0.0

7 December 2018

  • Open api import #28
  • Add @types/commander 121f38b
  • Add open-api scripts dependencies 372f35e
  • Update operational-scripts fbba9ca

v6.1.1

20 November 2018

  • Fix React import on generated d.ts #95

v6.1.0

13 November 2018

  • Add Response in the onError callback 04fcd52

v6.0.2

7 November 2018

  • Fix delete with id ef00272
  • Add test to verify polling doesn't happen if no index 13f118e
  • Fix Delete composition 81644b1

v6.0.1

1 November 2018

  • Fix base path propagation to ignore parentPath b4683d4
  • Avoid requests side effects once component unmounts 237c08a
  • Fix an infinite loop on fetching without a resolve function 4cba6ad

v6.0.0

31 October 2018

  • Feature: Add support for validators that are promise-based or throw errors #72
  • compose urls for relative paths cases #64
  • Refetch when resolve prop changes #70
  • Export method types #73
  • relative and absolute url composition 431abc5
  • Add support for validators that are promise-based or throw errors 086f94a
  • Add comments for resolve issue when rerendiring Provider 48452d2

v5.2.1

24 September 2018

  • Fix the error case on Get with wait property #56
  • Remove engine in package.json #55
  • Update nock to the latest version 🚀 #50
  • Update danger to the latest version 🚀 #49
  • Feat provider error handling #48
  • Add a provider error handler 871182e
  • Add a retry on error 4b27585
  • chore(package): update lockfile yarn.lock 632e75e

v5.1.1

12 September 2018

  • Improve the error management for Poll #46
  • Prettier 985c64a

v5.1.0

12 September 2018

  • Add null to prevData in case it's null #45
  • 5.1.0 #44
  • Add a clean way to consolidate data in Poll #43
  • Delete package-lock.json a4ace6a
  • Add unit tests and optimize Poll 7912452
  • Add prevData in the Poll resolver ee2839b

v5.0.1

10 September 2018

  • 5.0.1 #42
  • Fix return type #41

v5.0.0

10 September 2018

  • Update mainfile #40

v4.1.3

10 September 2018

v4.1.2

5 September 2018

  • Update tsconfig because Greenkeeper changed things 45c8210

v4.1.1

5 September 2018

v4.1.0

5 September 2018

  • Add debounce #35
  • Add a debounce option to Get #32
  • Update dependencies to enable Greenkeeper 🌴 #34
  • v4.0.2: Updated error handling #31
  • Improve the error layer #30
  • Update Docs 898230e
  • Deal with json parsing error b8b800f
  • Refactor to put all the logic inside processResponse 5f02ce4

v4.0.2

27 August 2018

  • 4.0.1 #27
  • Remove package-lock in favor of yarn 60f4947

v4.0.1

14 August 2018

v4.0.0

8 August 2018

  • Release v4 #23
  • Update Docs #21
  • Fix #2: Add codesandbox links #2
  • Link to interfaces instead of displaying them e20f744
  • Update examples 11b29ae
  • Link to docs with lines 1208f67

v4.0.0-10

8 August 2018

  • Factor out handling of response content type handler #22
  • response -> rawResponse 7742532
  • Add await to processResponse 4841466

v4.0.0-9

8 August 2018

  • Update typescript, remove npm lockfile since we use yarn 1096553
  • Add jest-dom and react-testing-library dependencies 2140493
  • Separate Mutations into different component, clean up Get 61b52bd

v4.0.0-8

6 August 2018

  • Unit tests - Get component #18
  • Add Unit tests for Get component #17
  • Add jest-dom and react-testing-library dependencies 5af7154
  • Add Get classic usage tests 7701a1d
  • Improve the typing with generics 5af9348

v4.0.0-7

3 August 2018

  • Fix error handling and resource deletion #16
  • Contiamo poll #15

v4.0.0-6

1 August 2018

  • Implement Contiamo Polling 223bb03
  • Add doc 33a8c3c
  • Finishing touches to implementing Contiamo Polling spec 02847e5

v4.0.0-5

19 July 2018

  • Poll state #14
  • Add error handling to Poll, do not rerender polled results unless content changes 8dc1ee0

v4.0.0-4

18 July 2018

  • Refactor URL handling to account for query params #13
  • Enhance/compose paths #11
  • Update implementation for cleaner mutations #7
  • Update typescript, remove npm lockfile since we use yarn 103c783
  • Separate Mutations into different component, clean up Get 94c533f
  • Throw error responses and leave error handling to the user b7aa426

v4.0.0-1

8 August 2018

  • Factor out handling of response content type handler #22
  • Update HTTP verbs in mutations to be uppercase #8
  • Update typescript, remove npm lockfile since we use yarn 1096553
  • Add jest-dom and react-testing-library dependencies 2140493
  • Separate Mutations into different component, clean up Get 61b52bd

v3.1.0

6 July 2018

v3.0.3

10 July 2018

  • Update HTTP verbs in mutations to be uppercase #8
  • Throw a response object if a mutation fails #5

v3.0.2

2 July 2018

v3.0.1

2 July 2018