@rest-hooks/endpoint
Advanced tools
Comparing version 0.2.0 to 0.3.0
@@ -6,2 +6,12 @@ # Change Log | ||
## 0.3.0 (2020-07-13) | ||
* feat: Infer return type from schema ([2dccff4](https://github.com/coinbase/rest-hooks/commit/2dccff4)) | ||
* docs: Add more to readme ([2fc29e5](https://github.com/coinbase/rest-hooks/commit/2fc29e5)) | ||
* docs: Fix tags ([987f0ed](https://github.com/coinbase/rest-hooks/commit/987f0ed)) | ||
## 0.2.0 (2020-07-12) | ||
@@ -8,0 +18,0 @@ |
export type { EndpointInterface, ReadEndpoint, MutateEndpoint, IndexInterface, IndexParams, ArrayElement, } from './interface'; | ||
export type { EndpointOptions, FetchFunction } from './endpoint'; | ||
export type { EndpointExtraOptions } from './types'; | ||
export type { EndpointOptions } from './endpoint'; | ||
export type { EndpointExtraOptions, FetchFunction, OptimisticUpdateParams, UpdateFunction, } from './types'; | ||
export type { ResolveType, InferReturn } from './utility'; | ||
export { default as Endpoint } from './endpoint'; | ||
export { default as Index } from './indexEndpoint'; | ||
//# sourceMappingURL=index.d.ts.map |
export { default as Endpoint } from './endpoint'; | ||
export { default as Index } from './indexEndpoint'; | ||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9pbmRleC50cyJdLCJuYW1lcyI6WyJkZWZhdWx0IiwiRW5kcG9pbnQiLCJJbmRleCJdLCJtYXBwaW5ncyI6IkFBV0EsU0FBU0EsT0FBTyxJQUFJQyxRQUFwQixRQUFvQyxZQUFwQztBQUNBLFNBQVNELE9BQU8sSUFBSUUsS0FBcEIsUUFBaUMsaUJBQWpDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IHR5cGUge1xuICBFbmRwb2ludEludGVyZmFjZSxcbiAgUmVhZEVuZHBvaW50LFxuICBNdXRhdGVFbmRwb2ludCxcbiAgSW5kZXhJbnRlcmZhY2UsXG4gIEluZGV4UGFyYW1zLFxuICBBcnJheUVsZW1lbnQsXG59IGZyb20gJy4vaW50ZXJmYWNlJztcbmV4cG9ydCB0eXBlIHsgRW5kcG9pbnRPcHRpb25zLCBGZXRjaEZ1bmN0aW9uIH0gZnJvbSAnLi9lbmRwb2ludCc7XG5leHBvcnQgdHlwZSB7IEVuZHBvaW50RXh0cmFPcHRpb25zIH0gZnJvbSAnLi90eXBlcyc7XG5cbmV4cG9ydCB7IGRlZmF1bHQgYXMgRW5kcG9pbnQgfSBmcm9tICcuL2VuZHBvaW50JztcbmV4cG9ydCB7IGRlZmF1bHQgYXMgSW5kZXggfSBmcm9tICcuL2luZGV4RW5kcG9pbnQnO1xuIl19 | ||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9pbmRleC50cyJdLCJuYW1lcyI6WyJkZWZhdWx0IiwiRW5kcG9pbnQiLCJJbmRleCJdLCJtYXBwaW5ncyI6IkFBaUJBLFNBQVNBLE9BQU8sSUFBSUMsUUFBcEIsUUFBb0MsWUFBcEM7QUFDQSxTQUFTRCxPQUFPLElBQUlFLEtBQXBCLFFBQWlDLGlCQUFqQyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCB0eXBlIHtcbiAgRW5kcG9pbnRJbnRlcmZhY2UsXG4gIFJlYWRFbmRwb2ludCxcbiAgTXV0YXRlRW5kcG9pbnQsXG4gIEluZGV4SW50ZXJmYWNlLFxuICBJbmRleFBhcmFtcyxcbiAgQXJyYXlFbGVtZW50LFxufSBmcm9tICcuL2ludGVyZmFjZSc7XG5leHBvcnQgdHlwZSB7IEVuZHBvaW50T3B0aW9ucyB9IGZyb20gJy4vZW5kcG9pbnQnO1xuZXhwb3J0IHR5cGUge1xuICBFbmRwb2ludEV4dHJhT3B0aW9ucyxcbiAgRmV0Y2hGdW5jdGlvbixcbiAgT3B0aW1pc3RpY1VwZGF0ZVBhcmFtcyxcbiAgVXBkYXRlRnVuY3Rpb24sXG59IGZyb20gJy4vdHlwZXMnO1xuZXhwb3J0IHR5cGUgeyBSZXNvbHZlVHlwZSwgSW5mZXJSZXR1cm4gfSBmcm9tICcuL3V0aWxpdHknO1xuXG5leHBvcnQgeyBkZWZhdWx0IGFzIEVuZHBvaW50IH0gZnJvbSAnLi9lbmRwb2ludCc7XG5leHBvcnQgeyBkZWZhdWx0IGFzIEluZGV4IH0gZnJvbSAnLi9pbmRleEVuZHBvaW50JztcbiJdfQ== |
import { Schema, Entity } from '@rest-hooks/normalizr'; | ||
import type { EndpointExtraOptions } from './types'; | ||
import type { EndpointExtraOptions, FetchFunction } from './types'; | ||
import { InferReturn } from './utility'; | ||
/** Defines a networking endpoint */ | ||
export interface EndpointInterface<F extends (params?: any, body?: any) => Promise<any>, S extends Schema | undefined = undefined, M extends true | undefined = undefined> extends EndpointExtraOptions { | ||
(...args: Parameters<F>): ReturnType<F>; | ||
export interface EndpointInterface<F extends (params?: any, body?: any) => Promise<any> = FetchFunction, S extends Schema | undefined = undefined, M extends true | undefined = undefined> extends EndpointExtraOptions { | ||
(...args: Parameters<F>): InferReturn<F, S>; | ||
key(parmas?: Readonly<Parameters<F>[0]>): string; | ||
@@ -11,7 +12,7 @@ readonly sideEffect?: M; | ||
/** To change values on the server */ | ||
export interface MutateEndpoint<F extends (params?: any, body?: any) => Promise<any>, S extends Schema | undefined = undefined> extends EndpointInterface<F, S, true> { | ||
export interface MutateEndpoint<F extends (params?: any, body?: any) => Promise<any> = FetchFunction, S extends Schema | undefined = undefined> extends EndpointInterface<F, S, true> { | ||
fetch(params: Readonly<Parameters<F>[0]>, body: Readonly<Parameters<F>[1]>): ReturnType<F>; | ||
} | ||
/** For retrieval requests */ | ||
export interface ReadEndpoint<F extends (params?: any) => Promise<any>, S extends Schema | undefined = undefined> extends EndpointInterface<F, S> { | ||
export interface ReadEndpoint<F extends (params?: any) => Promise<any> = FetchFunction, S extends Schema | undefined = undefined> extends EndpointInterface<F, S> { | ||
fetch(params: Readonly<Parameters<F>[0]>): ReturnType<F>; | ||
@@ -18,0 +19,0 @@ } |
@@ -0,1 +1,3 @@ | ||
import { Schema, Normalize } from '@rest-hooks/normalizr'; | ||
import { EndpointInterface } from './interface'; | ||
export interface EndpointExtraOptions { | ||
@@ -15,2 +17,5 @@ /** Default data expiry length, will fall back to NetworkManager default if not defined */ | ||
} | ||
export declare type FetchFunction<P = any> = (params?: P, body?: any) => Promise<any>; | ||
export declare type OptimisticUpdateParams<SourceSchema extends Schema, Dest extends EndpointInterface<FetchFunction, Schema, any>> = [Dest, Parameters<Dest>[0], UpdateFunction<SourceSchema, Exclude<Dest['schema'], undefined>>]; | ||
export declare type UpdateFunction<SourceSchema extends Schema, DestSchema extends Schema> = (sourceResults: Normalize<SourceSchema>, destResults: Normalize<DestSchema> | undefined) => Normalize<DestSchema>; | ||
//# sourceMappingURL=types.d.ts.map |
{ | ||
"name": "@rest-hooks/endpoint", | ||
"version": "0.2.0", | ||
"version": "0.3.0", | ||
"description": "Declarative Network Interface Definitions", | ||
@@ -31,10 +31,5 @@ "sideEffects": false, | ||
"keywords": [ | ||
"react", | ||
"flux", | ||
"ajax", | ||
"networking", | ||
"suspense", | ||
"concurrent mode", | ||
"fetch", | ||
"hook", | ||
"typescript", | ||
@@ -46,3 +41,3 @@ "data fetching", | ||
"normalized cache", | ||
"swr" | ||
"subject pattern" | ||
], | ||
@@ -62,5 +57,5 @@ "author": "Nathaniel Tucker <me@ntucker.me> (https://github.com/ntucker)", | ||
"@babel/runtime": "^7.7.2", | ||
"@rest-hooks/normalizr": "^6.0.0-delta.0" | ||
"@rest-hooks/normalizr": "^6.0.0-h.0" | ||
}, | ||
"gitHead": "c129210e08797526c0df8a721cb461bf703d1413" | ||
"gitHead": "c0fb0d84e41cf81ee78840532645b3b6f17753e0" | ||
} |
@@ -45,4 +45,23 @@ # TypeScript Standard Endpoints | ||
Storing the results of networking calls in a cache like Rest Hooks requires | ||
There is a distinction between | ||
- What are networking API is | ||
- How to make a request, expected response fields, etc. | ||
- How it is used | ||
- Binding data, polling, triggering imperative fetch, etc. | ||
Thus, there are many benefits to creating a distinct seperation of concerns between | ||
these two concepts. | ||
With `TypeScript Standard Endpoints`, we define a standard for declaring in | ||
TypeScript the definition of a networking API. | ||
- Allows API authors to publish npm packages containing their API interfaces | ||
- Definitions can be consumed by any supporting library, allowing easy consumption across libraries like Vue, React, Angular | ||
- Writing codegen pipelines becomes much easier as the output is minimal | ||
- Product developers can use the definitions in a multitude of contexts where behaviors vary | ||
- Product developers can easily share code across platforms with distinct behaviors needs like React Native and React Web | ||
### What's in an Endpoint | ||
- A function that resolves the results | ||
@@ -156,7 +175,19 @@ - A function to uniquely store those results | ||
```typescript | ||
import { Entity } from '@rest-hooks/normalizr'; | ||
import { Index } from '@rest-hooks/endpoint'; | ||
class User extends Entity { | ||
readonly id: string = ''; | ||
readonly username: string = ''; | ||
pk() { return this.id;} | ||
static indexes = ['username'] as const; | ||
} | ||
const UserIndex = new Index(User) | ||
const bob = useCache(UserIndex, { username: 'bob' }); | ||
// @ts-expect-error Indexes don't fetch, they just retrieve already existing data | ||
const bob = useResource(UserIndex, { username: 'bob' }); | ||
``` |
import nock from 'nock'; | ||
import { Schema } from '@rest-hooks/normalizr'; | ||
import { Schema, Entity } from '@rest-hooks/normalizr'; | ||
import { camelCase, snakeCase } from 'lodash'; | ||
import Endpoint, { FetchFunction, EndpointOptions } from '../endpoint'; | ||
import Endpoint from '../endpoint'; | ||
import { EndpointInterface } from '../interface'; | ||
@@ -90,2 +90,3 @@ | ||
it('should work when extended', async () => { | ||
const BaseFetch = new Endpoint(fetchUsers); | ||
const UserDetail = new Endpoint(fetchUsers).extend({ | ||
@@ -101,3 +102,3 @@ sideEffect: true, | ||
t(UserDetail); | ||
t(new Endpoint(fetchUsers)); | ||
t(BaseFetch); | ||
@@ -144,2 +145,29 @@ expect(UserDetail.key({ id: '500' })).toMatchInlineSnapshot( | ||
it('should infer return type when schema is specified but fetch function has no typing', async () => { | ||
class User extends Entity { | ||
readonly id: string = ''; | ||
readonly username: string = ''; | ||
pk() { | ||
return this.id; | ||
} | ||
} | ||
class User2 extends User { | ||
readonly extra: number = 0; | ||
} | ||
const UserDetail = new Endpoint( | ||
({ id }: { id: string }) => fetch(`/users/${id}`).then(res => res.json()), | ||
{ schema: User }, | ||
); | ||
const user = await UserDetail({ id: payload.id }); | ||
expect(user).toEqual(payload); | ||
expect(user.username).toBe(payload.username); | ||
// extends | ||
const Extended = UserDetail.extend({ schema: User2 }); | ||
const user2 = await Extended({ id: payload.id }); | ||
expect(user2).toEqual(payload); | ||
// doesn't actually generate class | ||
expect(user2.extra).toBe(undefined); | ||
}); | ||
describe('auth patterns (usage with `this`)', () => { | ||
@@ -146,0 +174,0 @@ function fetchAuthd(this: { token: string }): Promise<typeof payload> { |
@@ -103,3 +103,3 @@ /* eslint-disable @typescript-eslint/ban-types */ | ||
: E['sideEffect'] | ||
> & { prototype: E }; | ||
>; | ||
} | ||
@@ -111,3 +111,3 @@ | ||
S extends Schema | undefined = undefined, | ||
M extends true | undefined | ||
M extends true | undefined = undefined | ||
>( | ||
@@ -114,0 +114,0 @@ fetchFunction: F, |
@@ -9,6 +9,12 @@ export type { | ||
} from './interface'; | ||
export type { EndpointOptions, FetchFunction } from './endpoint'; | ||
export type { EndpointExtraOptions } from './types'; | ||
export type { EndpointOptions } from './endpoint'; | ||
export type { | ||
EndpointExtraOptions, | ||
FetchFunction, | ||
OptimisticUpdateParams, | ||
UpdateFunction, | ||
} from './types'; | ||
export type { ResolveType, InferReturn } from './utility'; | ||
export { default as Endpoint } from './endpoint'; | ||
export { default as Index } from './indexEndpoint'; |
import { Schema, Entity } from '@rest-hooks/normalizr'; | ||
import type { EndpointExtraOptions } from './types'; | ||
import type { EndpointExtraOptions, FetchFunction } from './types'; | ||
import { InferReturn } from './utility'; | ||
/** Defines a networking endpoint */ | ||
export interface EndpointInterface< | ||
F extends (params?: any, body?: any) => Promise<any>, | ||
F extends (params?: any, body?: any) => Promise<any> = FetchFunction, | ||
S extends Schema | undefined = undefined, | ||
M extends true | undefined = undefined | ||
> extends EndpointExtraOptions { | ||
(...args: Parameters<F>): ReturnType<F>; | ||
(...args: Parameters<F>): InferReturn<F, S>; | ||
key(parmas?: Readonly<Parameters<F>[0]>): string; | ||
@@ -19,3 +20,3 @@ readonly sideEffect?: M; | ||
export interface MutateEndpoint< | ||
F extends (params?: any, body?: any) => Promise<any>, | ||
F extends (params?: any, body?: any) => Promise<any> = FetchFunction, | ||
S extends Schema | undefined = undefined | ||
@@ -31,3 +32,3 @@ > extends EndpointInterface<F, S, true> { | ||
export interface ReadEndpoint< | ||
F extends (params?: any) => Promise<any>, | ||
F extends (params?: any) => Promise<any> = FetchFunction, | ||
S extends Schema | undefined = undefined | ||
@@ -34,0 +35,0 @@ > extends EndpointInterface<F, S> { |
@@ -0,1 +1,5 @@ | ||
import { Schema, Normalize } from '@rest-hooks/normalizr'; | ||
import { EndpointInterface } from './interface'; | ||
export interface EndpointExtraOptions { | ||
@@ -18,1 +22,19 @@ /** Default data expiry length, will fall back to NetworkManager default if not defined */ | ||
} | ||
export type FetchFunction<P = any> = (params?: P, body?: any) => Promise<any>; | ||
export type OptimisticUpdateParams< | ||
SourceSchema extends Schema, | ||
Dest extends EndpointInterface<FetchFunction, Schema, any> | ||
> = [ | ||
Dest, | ||
Parameters<Dest>[0], | ||
UpdateFunction<SourceSchema, Exclude<Dest['schema'], undefined>>, | ||
]; | ||
export type UpdateFunction< | ||
SourceSchema extends Schema, | ||
DestSchema extends Schema | ||
> = ( | ||
sourceResults: Normalize<SourceSchema>, | ||
destResults: Normalize<DestSchema> | undefined, | ||
) => Normalize<DestSchema>; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
59015
30
767
192