# hookifyResource

`hookifyResource()` Turns any [Resource](https://dataclient.io/rest/api/resource.md) (collection of [RestEndpoints](https://dataclient.io/rest/api/RestEndpoint.md)) into a collection
of hooks that return [RestEndpoints](https://dataclient.io/rest/api/RestEndpoint.md).

> **Info**
>
> TypeScript >=4.3 is required for generative types to work correctly.

```ts title="resources/Article"
import React from 'react';
import { Collection, Entity, Invalidate, hookifyResource, resource } from '@data-client/rest';

class Article extends Entity {
  id = '';
  title = '';
  content = '';
}
const AuthContext = React.createContext('');

const ArticleResourceBase = resource({
  urlPrefix: 'http://test.com',
  path: '/article/:id',
  schema: Article,
});
export const ArticleResource = hookifyResource(
  ArticleResourceBase,
  function useInit() {
    const accessToken = React.useContext(AuthContext);
    return {
      headers: {
        'Access-Token': accessToken,
      },
    };
  },
);
```

```tsx title="ArticleDetail"
import { useSuspense, useController } from '@data-client/react';
import { ArticleResource } from './resources/Article';
import ArticleForm from './ArticleForm';

function ArticleDetail({ id }) {
  const article = useSuspense(ArticleResource.useGet(), { id });
  const updateArticle = ArticleResource.useUpdate();
  const ctrl = useController();
  const onSubmit = (body: any) => ctrl.fetch(updateArticle, { id }, body);

  return <ArticleForm onSubmit={onSubmit} initialValues={article} />;
}
render(<ArticleDetail id="1" />);
```

## Members

Assuming you use the unchanged result of [resource()](https://dataclient.io/rest/api/resource.md), these will be your methods

### useGet()

- method: 'GET'
- path: `path`
- schema: [schema](https://dataclient.io/rest/api/Entity.md)

```typescript
// GET //test.com/api/abc/xyz
hookifyResource(
  resource({ urlPrefix: '//test.com', path: '/api/:group/:id' }),
).useGet()({
  group: 'abc',
  id: 'xyz',
});
```

Commonly used with [useSuspense()](https://dataclient.io/docs/api/useSuspense.md), [Controller.invalidate](https://dataclient.io/docs/api/Controller.md#invalidate)

### useGetList()

- method: 'GET'
- path: `shortenPath(path)`
  - Removes the last `:param` or `*wildcard` token:
    ```ts
    hookifyResource(resource({ path: '/:first/:second' })).useGetList()
      .path === '/:first';
    hookifyResource(resource({ path: '/:first' })).useGetList().path ===
      '/';
    hookifyResource(resource({ path: '/:owner/*path' })).useGetList()
      .path === '/:owner';
    ```
- schema: [\[schema\]](https://dataclient.io/rest/api/Array.md)

```typescript
// GET //test.com/api/abc?isExtra=xyz
hookifyResource(
  resource({ urlPrefix: '//test.com', path: '/api/:group/:id' }),
).useGetList()({
  group: 'abc',
  isExtra: 'xyz',
});
```

Commonly used with [useSuspense()](https://dataclient.io/docs/api/useSuspense.md), [Controller.invalidate](https://dataclient.io/docs/api/Controller.md#invalidate)

### useGetList().push {#push}

[push](https://dataclient.io/rest/api/RestEndpoint.md#push) creates a new entity and pushes it to the end of useGetList().

- method: 'POST'
- path: `shortenPath(path)`
- schema: `useGetList().schema.push`

```typescript
// POST //test.com/api/abc
// BODY { "title": "winning" }
hookifyResource(
  resource({ urlPrefix: '//test.com', path: '/api/:group/:id' }),
).useGetList().push({ group: 'abc' }, { title: 'winning' });
```

Commonly used with [Controller.fetch](https://dataclient.io/docs/api/Controller.md#fetch)

### useGetList().unshift {#unshift}

[unshift](https://dataclient.io/rest/api/RestEndpoint.md#unshift) creates a new entity and pushes it to the beginning of useGetList().

- method: 'POST'
- path: `shortenPath(path)`
- schema: `useGetList().schema.unshift`

```typescript
// POST //test.com/api/abc
// BODY { "title": "winning" }
hookifyResource(
  resource({ urlPrefix: '//test.com', path: '/api/:group/:id' }),
).useGetList().unshift({ group: 'abc' }, { title: 'winning' });
```

Commonly used with [Controller.fetch](https://dataclient.io/docs/api/Controller.md#fetch)

### useGetList().getPage {#getpage}

[getPage](https://dataclient.io/rest/api/RestEndpoint.md#getpage) retrieves another [page](https://dataclient.io/rest/guides/pagination.md#infinite-scrolling) appending to useGetList() ensuring there are no duplicates.

- method: 'GET'
- args: `shortenPath(path) & { [paginationField]: string | number } & searchParams`
- schema: [new Collection(\[schema\]).addWith(paginatedMerge, paginatedFilter(removeCursor))](https://dataclient.io/rest/api/Collection.md)

```typescript
// GET //test.com/api/abc?isExtra=xyz&page=2
hookifyResource(
  resource({
    urlPrefix: '//test.com',
    path: '/api/:group/:id',
    paginationField: 'page',
  }),
).useGetList().getPage({
  group: 'abc',
  isExtra: 'xyz',
  page: '2',
});
```

Commonly used with [Controller.fetch](https://dataclient.io/docs/api/Controller.md#fetch)

### useUpdate()

- method: 'PUT'
- path: `path`
- schema: `schema`

```typescript
// PUT //test.com/api/abc/xyz
// BODY { "title": "winning" }
hookifyResource(
  resource({ urlPrefix: '//test.com', path: '/api/:group/:id' }),
).useUpdate()({ group: 'abc', id: 'xyz' }, { title: 'winning' });
```

Commonly used with [Controller.fetch](https://dataclient.io/docs/api/Controller.md#fetch)

### usePartialUpdate()

- method: 'PATCH'
- path: `path`
- schema: `schema`

```typescript
// PATCH //test.com/api/abc/xyz
// BODY { "title": "winning" }
hookifyResource(
  resource({ urlPrefix: '//test.com', path: '/api/:group/:id' }),
).usePartialUpdate()({ group: 'abc', id: 'xyz' }, { title: 'winning' });
```

Commonly used with [Controller.fetch](https://dataclient.io/docs/api/Controller.md#fetch)

### useDelete()

- method: 'DELETE'
- path: `path`
- schema: [new Invalidate(schema)](https://dataclient.io/rest/api/Invalidate.md)
- process:
  ```ts
  (value, params) {
    return value && Object.keys(value).length ? value : params;
  },
  ```

```typescript
// DELETE //test.com/api/abc/xyz
hookifyResource(
  resource({ urlPrefix: '//test.com', path: '/api/:group/:id' }),
).useDelete()({
  group: 'abc',
  id: 'xyz',
});
```

Commonly used with [Controller.fetch](https://dataclient.io/docs/api/Controller.md#fetch)
