Skip to content

Commit

Permalink
Merge 0ee7a2a into d6a8993
Browse files Browse the repository at this point in the history
  • Loading branch information
ricokahler committed Oct 30, 2019
2 parents d6a8993 + 0ee7a2a commit 1ab9c0f
Show file tree
Hide file tree
Showing 155 changed files with 24,365 additions and 1,434 deletions.
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*/node_modules
*.log
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@ node_modules
build
coverage
.DS_Store
website/build
docs/api/**/*
!docs/api/about-api-docs.md
21 changes: 21 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Jest Current File",
"program": "${workspaceFolder}/node_modules/.bin/jest",
"args": ["${fileBasenameNoExtension}", "--config", "jest.config.js"],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"disableOptimisticBPs": true,
"windows": {
"program": "${workspaceFolder}/node_modules/jest/bin/jest"
}
}
]
}
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"workbench.colorCustomizations": {}
}
10 changes: 10 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM node:8.11.4

WORKDIR /app/website

EXPOSE 3000 35729
COPY ./docs /app/docs
COPY ./website /app/website
RUN yarn install

CMD ["yarn", "start"]
36 changes: 32 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,37 @@
# ReSift · [![Build Status](https://travis-ci.org/JustSift/ReSift.svg?branch=master)](https://travis-ci.org/JustSift/ReSift) [![Coverage Status](https://coveralls.io/repos/github/JustSift/ReSift/badge.svg?branch=master)](https://coveralls.io/github/JustSift/ReSift?branch=master)

A work-in-progress. This will be the home of the open source version of ReSift.
> 👋 **Too many words? Head over to the [Quick glance](./quick-glance.md)** 👉
Check back soon. There are no released versions yet.
**ReSift is a state management library for fetches** with the goal of giving your team a capable standard for fetching, storing, and reacting to data.

Initial release roadmap/todo list: https://github.com/JustSift/ReSift/issues/6
We like to think of ReSift as the [Relay](https://relay.dev/) of REST. ReSift is in the same class of tools as [Relay](https://relay.dev/) and [the Apollo Client](https://www.apollographql.com/docs/react/). However, ReSift does _not_ require GraphQL.

If you're looking for the internal version [see here](https://github.com/JustSift/ReSift-Internal)
[See this doc for definitions and comparisons of ReSift vs Relay/Apollo](../guides/resift-vs-apollo-relay.md).

## Motivation

When developing a React application, you might realize that there is a lot more than meets the eye regarding data fetching.

With every fetch we need to know:

- If the data request is inflight (so we can show a loading indicator)
- Where the resulting data will be stored, and how to later retrieve it
- If it's related to other fetches so they update consistently
- If the response was an error so we can try to recover

These tasks themselves aren't overly complicated, but doing them over and over and over again _will_ take time away from your product.

To make matters worse, there is an infinite number of ways to accomplish said tasks, and managing these differences while working on a team can be confusing and hard to manage.

## Introducing ReSift

ReSift is a capable and versatile library for data fetches. ReSift is opinionated where it matters but also pluggable to suit your different data fetching needs.

**Features:**

- 💾 Framework for storing and retrieving responses from data requests
- 📬 Monitoring and updating the status of inflight requests
- 🔌 Pluggable via custom "data services"
- 🌐 Universal — Share code amongst your apps. **Works with React Native!**
- 🎣 Hooks API
- 🤝 Full TypeScript support
18 changes: 18 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
version: "3"

services:
docusaurus:
build: .
ports:
- 3000:3000
- 35729:35729
volumes:
- ./docs:/app/docs
- ./website/blog:/app/website/blog
- ./website/core:/app/website/core
- ./website/i18n:/app/website/i18n
- ./website/pages:/app/website/pages
- ./website/static:/app/website/static
- ./website/sidebars.json:/app/website/sidebars.json
- ./website/siteConfig.js:/app/website/siteConfig.js
working_dir: /app/website
109 changes: 109 additions & 0 deletions docs/api/about-api-docs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
---
id: about-api-docs
title: About API docs
sidebar_label: About these docs
---

These docs are auto-generated by [`generate-api-docs.js`](https://github.com/JustSift/ReSift/blob/master/website/generate-api-doc.js) which generates the docs based on the ambient typings files within the repository (the `*.d.ts` files). [See below for more info.](#how-these-docs-work)

If you are using an editor that uses the typescript language service (e.g. vs-code, visual studio, webstorm/intelliJ), then you should be able to hover over the definitions within your editor to get the same documentation.

Please open any issues if you find any within these docs. Open pull requests modifying the `*.d.ts` files.

## How these docs work

These docs work by parsing the ambient typings files (`*.d.ts`) files in `/src` and turning them into markdown files (`*.md`).

This works by using the typescript API (i.e. `const ts = require('typescript');`) to parse the ambient typings for JS doc comments, interfaces, and other code.

The generator will only pick up code that is commented with a JSDoc comment that contains the `@docs` directive.

```ts
// this comment must be a JSDoc comment
// 👇 (which is more than a multi-line comment)
/**
* @docs Title of `module`
*
* Description of module. You can also put _markdown_ in **here**
*/
function myModule(x: number): string;
```

This will generate the following document:

---

#### Title of `module`

Description of module. You can also put _markdown_ in **here**

```ts
function module(x: number): string;
```

---

## Generating tables for `interface`s

When you put the `@docs` directive above an interface, the generator will go through all the property declarations and generate a table.

```ts
/**
* @docs `ExampleModule`
*
* This is a description of `ExampleModule`
*/
interface ExampleModule {
/**
* This is the description of foo.
*/
foo: string;
/**
* This is the description of bar.
*/
bar?: number;
}
```

---

#### `ExampleModule`

This is a description of `ExampleModule`

| Name | Description | Type | Required |
| ---- | ------------------------------- | ------------------- | -------- |
| foo | This is the description of foo. | <code>string</code> | yes |
| bar | This is the description of bar. | <code>number</code> | no |

---

## Other code behavior

When the generator sees the `@docs` directive in a JSDoc comment before anything else that isn't an `interface`, it will simply take the declaration and wrap it in a code block with one difference—it will remove the generics from the types (e.g. `<T>`).

Why? Non-TS users are confused by generics. Simply removing the generics declaration (i.e. the stuff between the `<>`s) fixes the readability issue while also keeping the generics there.

For example, see the input code block vs the output code block.

Input:

```ts
export function myModule<Foo, Bar, Args extends any[], Result>(
...args: Args
): {
foo: Foo;
bar: (bar: Bar) => Result;
};
```

Output (more readable to JS users):

```ts
function myModule(
...args: Args
): {
foo: Foo;
bar: (bar: Bar) => Result;
};
```
Binary file added docs/assets/component_sketch_genre.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/component_sketch_movie_drawer.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/component_sketch_movie_form.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/section_1_finished.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/section_1_redux_dev_console.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/section_2_finished.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/section_3_finished.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/section_4_finished.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/section_5_finished.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions docs/examples/infinite-scroll.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
id: infinite-scroll
title: Infinite scroll
sidebar_label: Infinite scroll
---

The following demo is from the [Sharing state between fetches](../main-concepts/sharing-state-between-fetches.md#merges) doc. This example demonstrates how you can use `share.merge` do infinite scrolling.

<iframe src="https://codesandbox.io/embed/resift-infinite-scroll-df5kt?fontsize=14"
style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;"
title="ReSift Infinite Scroll"
allow="geolocation; microphone; camera; midi; vr; accelerometer; gyroscope; payment; ambient-light-sensor; encrypted-media; usb"
sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"
></iframe>
<br />
Don't hesitate to reach out if you've found an issue.
14 changes: 14 additions & 0 deletions docs/examples/resift-notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
id: resift-notes
title: ReSift Notes
sidebar_label: ReSift Notes (CRUD)
---

The following application is a basic CRUD application made to be a quick reference in how to do CRUD and loading spinner correctly.

Read the notes and explore the code.

<iframe src="https://codesandbox.io/embed/resift-notesj-xwp9r?fontsize=14" title="ReSift Notes" allow="geolocation; microphone; camera; midi; vr; accelerometer; gyroscope; payment; ambient-light-sensor; encrypted-media; usb" style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"></iframe>

<br />
Don't hesitate to reach out if you've found an issue.
7 changes: 7 additions & 0 deletions docs/examples/resift-rentals.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
id: resift-rentals
title: ReSift Rentals
sidebar_label: ReSift Rentals
---

This doc will contain the finished demo from the tutorial.
134 changes: 134 additions & 0 deletions docs/guides/http-proxies.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
---
id: http-proxies
title: HTTP proxies
sidebar_label: HTTP proxies
---

HTTP Proxies are a feature of the HTTP [data service](../main-concepts/what-are-data-services.md).

HTTP proxies allow you to intercept `http` data service calls within fetches and potentially do something else.

You define an HTTP proxy by calling `createHttpProxy` from ReSift.

A common use case of HTTP proxies is to use them for mocking an HTTP server. We use HTTP proxies to power the demos in these docs.

`mockApi.js`

```js
import { createHttpProxy } from 'resift';

export const mockPeopleEndpoint = createHttpProxy(
'/people/:personId',
async ({ match, requestParams, http }) => {
// ...
},
);
```

After you create your proxy, add it to the `proxies` array when you create the HTTP service:

```js
import { createDataService, createHttpService } from 'resift';
import { mockPeopleEndpoint } from './mockApi';

const http = createHttpService({
proxies: [mockPeopleEndpoint],
});

const dataService = createDataService({
services: { http },
onError: e => {
throw e;
},
});

export default dataService;
```

When you create an HTTP proxy, you provide a path or path options. The HTTP service will iterate through the proxies until it finds a match. The first match found will be the proxy it uses.

The matching algorithm is a blatant copy/paste of `react-router`'s [`matchPath`](https://reacttraining.com/react-router/web/api/matchPath)

## `createHttpProxy` API

The first argument to `createHttpProxy` is the path you'd like to match. If an `http` call matches this path, the second argument, the handler, will run.

In the handler, you can destructure: `requestParams`, `http`, `match`, and [more](../api/create-http-proxy.md#httpproxyparams)

- The `requestParams` are the parameters the caller (in the data service) passes to the `http` call
- `http` is the original `http` service. You can call it to make an actual HTTP request.
- `match` is the result of react-router's [`matchPath`](https://reacttraining.com/react-router/web/api/matchPath) function. It contains the match params in `match.params`

Here are some example mock endpoints from the [ReSift Notes example](../examples/resift-notes.md).

```js
import { createHttpProxy } from 'resift';
import shortId from 'shortid';
import delay from 'delay';
import moment from 'moment';
import { stripIndent } from 'common-tags';

const waitTime = 1000;

let noteData = [
{
id: 'sJxbrzBcn',
content: stripIndent`
# This is a note
`,
updatedAt: moment().toISOString(),
},
];

export const notes = createHttpProxy({ path: '/notes', exact: true }, async ({ requestParams }) => {
await delay(waitTime);

const { method, data } = requestParams;

if (method === 'GET') {
// send a shallow copy just in case.
// with a real API, the object returned would always be fresh references
return [...noteData];
}

if (method === 'POST') {
const newNote = {
...data,
id: shortId(),
};
noteData.push(newNote);

return newNote;
}
});

export const note = createHttpProxy('/notes/:id', async ({ requestParams, match }) => {
await delay(waitTime);

const { method, data } = requestParams;
const { id } = match.params;

if (method === 'GET') {
const note = noteData.find(note => note.id === id);
if (!note) throw new Error('Not Found');

return note;
}

if (method === 'PUT') {
const index = noteData.findIndex(note => note.id === id);
if (index === -1) throw new Error('Not Found');

noteData[index] = data;
return data;
}

if (method === 'DELETE') {
const note = noteData.find(note => note.id === id);
if (!note) throw new Error('Not Found');

noteData = noteData.filter(note => note.id !== id);
return undefined;
}
});
```
Loading

0 comments on commit 1ab9c0f

Please sign in to comment.