Skip to content

Commit

Permalink
docs: Update readme in packages
Browse files Browse the repository at this point in the history
  • Loading branch information
ntucker committed Sep 21, 2023
1 parent 16e90b2 commit 4b01c32
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 116 deletions.
7 changes: 7 additions & 0 deletions .changeset/few-eyes-remember.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@data-client/normalizr': patch
'@data-client/rest': patch
'@data-client/ssr': patch
---

docs: Update readme
2 changes: 1 addition & 1 deletion packages/normalizr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![CircleCI](https://circleci.com/gh/reactive/data-client/tree/master.svg?style=shield)](https://circleci.com/gh/data-clientdata-clients)
[![Coverage Status](https://img.shields.io/codecov/c/gh/reactive/data-client/master.svg?style=flat-square)](https://app.codecov.io/gh/data-clientdata-clients?branch=master)
[![npm version](https://img.shields.io/npm/v/@data-client/normalizr.svg?style=flat-square)](https://www.npmjs.com/package/data-clients/normalizr) [![npm downloads](https://img.shields.io/npm/dmdata-clientks/normalizr.svg?style=flat-square)](https://www.npmjs.com/packagdata-clientoks/normalizr)
[![npm version](https://img.shields.io/npm/v/@data-client/normalizr.svg?style=flat-square)](https://www.npmjs.com/package/data-clients/normalizr) [![npm downloads](https://img.shields.io/npm/dm/@data-client/normalizr.svg?style=flat-square)](https://www.npmjs.com/packagdata-clientoks/normalizr)

## Install

Expand Down
118 changes: 73 additions & 45 deletions packages/rest/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Data Client for REST
# TypeScript HTTP definitions

[![CircleCI](https://circleci.com/gh/reactive/data-client/tree/master.svg?style=shield)](https://circleci.com/gh/reactive/data-client)
[![Coverage Status](https://img.shields.io/codecov/c/gh/reactive/data-client/master.svg?style=flat-square)](https://app.codecov.io/gh/reactive/data-client?branch=master)
Expand All @@ -8,76 +8,106 @@
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
[![Chat](https://img.shields.io/discord/768254430381735967.svg?style=flat-square&colorB=758ED3)](https://discord.gg/35nb8Mz)

Extensible CRUD patterns for REST APIs.

<div align="center">

**[📖Read The Docs](https://dataclient.io/rest)** &nbsp;|&nbsp; [🎮Github Demo](https://stackblitz.com/github/reactive/data-client/tree/master/examples/github-app?file=src%2Fresources%2FIssue.tsx)
**[📖Read The Docs](https://dataclient.io/rest)** &nbsp;|&nbsp; [🎮Todo Demo](https://stackblitz.com/github/reactive/data-client/tree/master/examples/todo-app?file=src%2Fresources%2FTodoResource.ts) &nbsp;|&nbsp; [🎮Github Demo](https://stackblitz.com/github/reactive/data-client/tree/master/examples/github-app?file=src%2Fresources%2FIssue.tsx)

</div>

### Simple TypeScript definition
## RestEndpoint

Simplify TypeScript fetch functions with [RestEndpoint](https://dataclient.io/rest/api/RestEndpoint)

```typescript
import { Entity, createResource } from '@data-client/rest';
const getTodo = new RestEndpoint({
urlPrefix: 'https://jsonplaceholder.typicode.com',
path: '/todos/:id',
});
```

class Article extends Entity {
id: number | undefined = undefined;
title = '';
body = '';
[RestEndpoint](https://dataclient.io/rest/api/RestEndpoint) infers [path-to-regex](https://github.com/pillarjs/path-to-regexp#compile-reverse-path-to-regexp)
argument types, enabling enforcement of function calls

pk() {
return this.id;
}
}
const ArticleResource = createResource({
path: '/articles/:id',
schema: Article,
});
```typescript
// signature requires id!
const todo = await getTodo({ id: 5 });
```

[Entity](https://dataclient.io/rest/api/Entity) defines a data model.
[createResource](https://dataclient.io/rest/api/createResource) creates a [collection](https://dataclient.io/rest/api/createResource#members)
of six [RestEndpoints](https://dataclient.io/rest/api/RestEndpoint)
It automatically handles REST concepts like JSON serialization, consolidated error handling and more.

[RestEndpoints](https://dataclient.io/rest/api/RestEndpoint) are functions (and more) that return a Promise.
Both call parameters and return value are [automatically inferred](https://dataclient.io/rest/api/RestEndpoint#typing) from
the options used to construct them.
## Resources

`path` is a templating language using [path-to-regex compile](https://github.com/pillarjs/path-to-regexp#compile-reverse-path-to-regexp).
Simplify related CRUD endpoints with [Resources](https://dataclient.io/rest/api/createResource)

### [Standard CRUD Endpoints](https://dataclient.io/rest/api/createResource#members)
[Resources](https://dataclient.io/rest/api/createResource) are a collection of `methods` for a given `data model`.

#### Reads
[Entities](https://dataclient.io/rest/api/Entity) and [Schemas](https://dataclient.io/concepts/normalization) declaratively define the _data model_.
[RestEndpoints](https://dataclient.io/rest/api/RestEndpoint) are the [_methods_](<https://en.wikipedia.org/wiki/Method_(computer_programming)>) on
that data.

```typescript
const article = useSuspense(ArticleResource.get, { id: 5 });
const articles = useSuspense(ArticleResource.getList);
class Todo extends Entity {
id = 0;
userId = 0;
title = '';
completed = false;
pk() {
return `${this.id}`;
}
}
const TodoResource = createResource({
urlPrefix: 'https://jsonplaceholder.typicode.com',
path: '/todos/:id',
searchParams: {} as { userId?: string | number },
schema: Todo,
paginationField: 'page',
});
```

One Resource defines [seven endpoints](https://dataclient.io/rest/api/createResource#members):

```typescript
const [article, setArticle] = useState();
useEffect(() => {
setArticle(await ArticleResource.get({ id: 5 }));
}, []);
// GET https://jsonplaceholder.typicode.com/todos/5
let todo5 = await TodoResource.get({ id: 5 });
// GET https://jsonplaceholder.typicode.com/todos
const todoList = await TodoResource.getList();
// GET https://jsonplaceholder.typicode.com/todos?userId=1
const userOneTodos = await TodoResource.getList({ userId: 1 });
// POST https://jsonplaceholder.typicode.com/todos
const newTodo = await TodoResource.getList.push({ title: 'my todo' });
// POST https://jsonplaceholder.typicode.com/todos?userId=1
const newUserOneTodo = await TodoResource.getList.push({ userId: 1 }, { title: 'my todo' });
// GET https://jsonplaceholder.typicode.com/todos?userId=1&page=2
const nextPageOfTodos = await TodoResource.getList.getPage({ userId: 1, page: 2 });
// PUT https://jsonplaceholder.typicode.com/todos/5
todo5 = await TodoResource.update({ id: 5 }, { title: 'my todo' });
// PATCH https://jsonplaceholder.typicode.com/todos/5
todo5 = await TodoResource.partialUpdate({ id: 5 }, { title: 'my todo' });
// DELETE https://jsonplaceholder.typicode.com/todos/5
await TodoResource.delete({ id: 5 });
```

#### Mutates
## Free React Integration

No need for any custom hooks. All endpoints are 100% compatible with
the fastest way to fetch and mutate REST data: [Reactive Data Client](https://dataclient.io)

#### [Rendering](https://dataclient.io/docs/getting-started/data-dependency)

```typescript
const ctrl = useController();
const updateArticle = data => ctrl.fetch(ArticleResource.update, { id }, data);
const partialUpdateArticle = data =>
ctrl.fetch(ArticleResource.partialUpdate, { id }, data);
const createArticle = data => ctrl.fetch(ArticleResource.getList.push, data);
const deleteArticle = data => ctrl.fetch(ArticleResource.delete, { id });
const todo = useSuspense(TodoResource.get, { id: 5 });
const todoList = useSuspense(TodoResource.getList);
```

### Use with Node
#### [Mutations](https://dataclient.io/docs/getting-started/mutations)

```typescript
const article = await ArticleResource.get({ id: 5 });
const articles = await ArticleResource.getList();
const ctrl = useController();
const updateTodo = data => ctrl.fetch(TodoResource.update, { id }, data);
const partialUpdateTodo= data =>
ctrl.fetch(TodoResource.partialUpdate, { id }, data);
const createTodo = data => ctrl.fetch(TodoResource.getList.push, data);
const deleteTodo = data => ctrl.fetch(TodoResource.delete, { id });
```

### [Programmatic queries](https://dataclient.io/rest/api/Query)
Expand All @@ -102,8 +132,6 @@ const articlesDescending = useCache(sortedArticles, { asc: false });
TypeScript is optional, but will only work with 4.0 or above. 4.1 is needed for stronger types as it
supports inferring argument types from the path templates.

Version 5.x can be used for older TypeScript versions.

### Prior Art

- [Backbone Model](https://backbonejs.org/#Model)
Expand Down
154 changes: 84 additions & 70 deletions packages/ssr/README.md
Original file line number Diff line number Diff line change
@@ -1,91 +1,33 @@
# Data Client Server Side Rendering helpers
# [![Reactive Data Client](./data_client_logo_and_text.png?sanitize=true)](https://dataclient.io)

[![CircleCI](https://circleci.com/gh/reactive/data-client/tree/master.svg?style=shield)](https://circleci.com/gh/reactive/data-client)
[![Coverage Status](https://img.shields.io/codecov/c/gh/reactive/data-client/master.svg?style=flat-square)](https://app.codecov.io/gh/reactive/data-client?branch=master)
[![npm downloads](https://img.shields.io/npm/dm/@data-client/ssr.svg?style=flat-square)](https://www.npmjs.com/package/@data-client/ssr)
[![bundle size](https://img.shields.io/bundlephobia/minzip/@data-client/ssr?style=flat-square)](https://bundlephobia.com/result?p=@data-client/ssr)
[![npm version](https://img.shields.io/npm/v/@data-client/ssr.svg?style=flat-square)](https://www.npmjs.com/package/@data-client/ssr)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
[![Chat](https://img.shields.io/discord/768254430381735967.svg?style=flat-square&colorB=758ED3)](https://discord.gg/35nb8Mz)

<div align="center">

**[📖Read The Docs](https://dataclient.io/docs/guides/ssr)** &nbsp;|&nbsp;
[🎮NextJS SSR Demo](https://stackblitz.com/github/reactive/data-client/tree/master/examples/nextjs?file=pages%2FAssetPrice.tsx)
[🎮NextJS Demo](https://stackblitz.com/github/reactive/data-client/tree/master/examples/nextjs?file=pages%2FAssetPrice.tsx)

</div>

Hydrate/dehydration utilities for [Data Client](https://dataclient.io)
Hydrate/dehydration utilities for Server Side Rendering with the [Reactive Data Client](https://dataclient.io)

## Server side
## Usage

```tsx
import express from 'express';
import { renderToPipeableStream } from 'react-dom/server';
import {
createPersistedStore,
createServerDataComponent,
} from '@data-client/ssr';
Integration with

const rootId = 'react-root';
- [NextJS](https://dataclient.io/docs/guides/ssr#nextjs)
- Anansi
```bash
npx @anansi/cli hatch my-project
```
- [ExpressJS](https://dataclient.io/docs/guides/ssr#express-js)

const app = express();
app.get('/*', (req: any, res: any) => {
const [ServerCacheProvider, useReadyCacheState, controller] =
createPersistedStore();
const ServerDataComponent = createServerDataComponent(useReadyCacheState);

controller.fetch(NeededForPage, { id: 5 });

const { pipe, abort } = renderToPipeableStream(
<Document
assets={assets}
scripts={[<ServerDataComponent key="server-data" />]}
rootId={rootId}
>
<ServerCacheProvider>{children}</ServerCacheProvider>
</Document>,

{
onCompleteShell() {
// If something errored before we started streaming, we set the error code appropriately.
res.statusCode = didError ? 500 : 200;
res.setHeader('Content-type', 'text/html');
pipe(res);
},
onError(x: any) {
didError = true;
console.error(x);
res.statusCode = 500;
pipe(res);
},
},
);
// Abandon and switch to client rendering if enough time passes.
// Try lowering this to see the client recover.
setTimeout(abort, 1000);
});

app.listen(3000, () => {
console.log(`Listening at ${PORT}...`);
});
```

## Client

```tsx
import { hydrateRoot } from 'react-dom';
import { awaitInitialData } from '@data-client/ssr';

const rootId = 'react-root';

awaitInitialData().then(initialState => {
hydrateRoot(
document.getElementById(rootId),
<CacheProvider initialState={initialState}>{children}</CacheProvider>,
);
});
```
For more details, see the [Server Side Rendering docs page](https://dataclient.io/docs/guides/ssr).

## NextJS

Expand Down Expand Up @@ -191,6 +133,78 @@ export default class MyDocument extends DataClientDocument {

</details>

## Express JS

### Server side

```tsx
import express from 'express';
import { renderToPipeableStream } from 'react-dom/server';
import {
createPersistedStore,
createServerDataComponent,
} from '@data-client/ssr';

const rootId = 'react-root';

const app = express();
app.get('/*', (req: any, res: any) => {
const [ServerCacheProvider, useReadyCacheState, controller] =
createPersistedStore();
const ServerDataComponent = createServerDataComponent(useReadyCacheState);

controller.fetch(NeededForPage, { id: 5 });

const { pipe, abort } = renderToPipeableStream(
<Document
assets={assets}
scripts={[<ServerDataComponent key="server-data" />]}
rootId={rootId}
>
<ServerCacheProvider>{children}</ServerCacheProvider>
</Document>,

{
onCompleteShell() {
// If something errored before we started streaming, we set the error code appropriately.
res.statusCode = didError ? 500 : 200;
res.setHeader('Content-type', 'text/html');
pipe(res);
},
onError(x: any) {
didError = true;
console.error(x);
res.statusCode = 500;
pipe(res);
},
},
);
// Abandon and switch to client rendering if enough time passes.
// Try lowering this to see the client recover.
setTimeout(abort, 1000);
});

app.listen(3000, () => {
console.log(`Listening at ${PORT}...`);
});
```

### Client

```tsx
import { hydrateRoot } from 'react-dom';
import { awaitInitialData } from '@data-client/ssr';

const rootId = 'react-root';

awaitInitialData().then(initialState => {
hydrateRoot(
document.getElementById(rootId),
<CacheProvider initialState={initialState}>{children}</CacheProvider>,
);
});
```

## API

### createPersistedStore(managers) => [ServerCacheProvider, useReadyCacheState, controller, store]
Expand Down
Binary file added packages/ssr/data_client_logo_and_text.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 4b01c32

Please sign in to comment.