Skip to content

Commit

Permalink
enhance: setResponseAction.payload -> setResponseAction.response; rem…
Browse files Browse the repository at this point in the history
…ove fetchAction.payload (#3141)
  • Loading branch information
ntucker committed Jul 9, 2024
1 parent 6834bff commit d225595
Show file tree
Hide file tree
Showing 28 changed files with 225 additions and 131 deletions.
50 changes: 50 additions & 0 deletions .changeset/big-crews-pump.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
'@data-client/core': minor
'@data-client/react': patch
'@data-client/test': patch
---

BREAKING CHANGE: setResponseAction.payload -> setResponseAction.response

This only affects those writing custom [Managers](https://dataclient.io/docs/concepts/managers) that
inspect `SET_RESPONSE_TYPE` `action.payload`.

#### Before

```ts
import { SET_RESPONSE_TYPE, type Manager, type Middleware } from '@data-client/react';

export default class MyManager implements Manager {
getMiddleware = (): Middleware => controller => next => async action => {
switch (action.type) {
case SET_RESPONSE_TYPE:
console.log('Resolved with value', action.payload);
return next(action);
default:
return next(action);
}
};

cleanup() {}
}
```

#### After

```ts
import { SET_RESPONSE_TYPE, type Manager, type Middleware } from '@data-client/react';

export default class MyManager implements Manager {
getMiddleware = (): Middleware => controller => next => async action => {
switch (action.type) {
case SET_RESPONSE_TYPE:
console.log('Resolved with value', action.response);
return next(action);
default:
return next(action);
}
};

cleanup() {}
}
```
53 changes: 53 additions & 0 deletions .changeset/light-tables-guess.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
'@data-client/core': minor
'@data-client/react': patch
'@data-client/test': patch
---

BREAKING CHANGE: remove fetchAction.payload

This only affects those writing custom [Managers](https://dataclient.io/docs/concepts/managers) that
inspect `FETCH_TYPE` `action.fetch`.

#### Before

```ts
import { FETCH_TYPE, type Manager, type Middleware } from '@data-client/react';

export default class MyManager implements Manager {
getMiddleware = (): Middleware => controller => next => async action => {
switch (action.type) {
case FETCH_TYPE:
// consume fetch, and print the resolution
action.fetch().then(response => console.log(response));
default:
return next(action);
}
};

cleanup() {}
}
```

#### After

```ts
import { FETCH_TYPE, type Manager, type Middleware } from '@data-client/react';

export default class MyManager implements Manager {
getMiddleware = (): Middleware => controller => next => async action => {
switch (action.type) {
case FETCH_TYPE:
// consume fetch, and print the resolution
action
.endpoint(...action.meta.args)
.fetch()
.then(response => console.log(response));
default:
return next(action);
}
};

cleanup() {}
}
```
5 changes: 2 additions & 3 deletions packages/core/src/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export interface SetResponseActionSuccess<
type: typeof SET_RESPONSE_TYPE;
endpoint: E;
meta: SetResponseMeta;
payload: ResolveType<E>;
response: ResolveType<E>;
error?: false;
}
export interface SetResponseActionError<
Expand All @@ -66,7 +66,7 @@ export interface SetResponseActionError<
type: typeof SET_RESPONSE_TYPE;
endpoint: E;
meta: SetResponseMeta;
payload: UnknownError;
response: UnknownError;
error: true;
}
export type SetResponseAction<
Expand All @@ -87,7 +87,6 @@ export interface FetchAction<E extends EndpointAndUpdate<E> = EndpointDefault> {
type: typeof FETCH_TYPE;
endpoint: E;
meta: FetchMeta<readonly [...Parameters<E>]>;
payload: () => ReturnType<E>;
}

/* OPTIMISTIC */
Expand Down
1 change: 0 additions & 1 deletion packages/core/src/controller/createFetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export default function createFetch<

return {
type: FETCH_TYPE,
payload: () => endpoint(...args) as any,
meta,
endpoint,
};
Expand Down
12 changes: 6 additions & 6 deletions packages/core/src/controller/createSetResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,19 +59,19 @@ export default function createSetResponse<
if (process.env.NODE_ENV === 'development' && expiryLength < 0) {
throw new Error('Negative expiry length are not allowed.');
}
const now = Date.now();
const date = Date.now();
const meta: SetResponseMeta = {
args: args.map(ensurePojo),
fetchedAt: fetchedAt ?? now,
date: now,
expiresAt: now + expiryLength,
fetchedAt: fetchedAt ?? date,
date,
expiresAt: date + expiryLength,
key: endpoint.key(...args),
};

const action: SetResponseAction<E> = {
type: SET_RESPONSE_TYPE,
payload: response,
endpoint: endpoint,
response,
endpoint,
meta,
};
if (error) (action as any).error = true;
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/manager/LogoutManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default class LogoutManager implements Manager {
if (
action.type === SET_RESPONSE_TYPE &&
action.error &&
this.shouldLogout(action.payload)
this.shouldLogout(action.response)
) {
this.handleLogout(controller);
}
Expand Down
5 changes: 2 additions & 3 deletions packages/core/src/manager/NetworkManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,11 @@ export default class NetworkManager implements Manager {
* for ensures mutation requests always go through.
*/
protected handleFetch(action: FetchAction) {
const fetch = action.payload;
const { key, resolve, reject, fetchedAt } = action.meta;
const throttle = !action.endpoint.sideEffect;

const deferedFetch = () => {
let promise = fetch();
let promise = action.endpoint(...action.meta.args);
const resolvePromise = (
promise: Promise<string | number | object | null>,
) =>
Expand Down Expand Up @@ -237,7 +236,7 @@ export default class NetworkManager implements Manager {
} else {
promiseHandler = this.resolvers[action.meta.key];
}
promiseHandler(action.payload);
promiseHandler(action.response);
// since we're resolved we no longer need to keep track of this promise
this.clear(action.meta.key);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ exports[`PollingSubscription fresh data should call after period 1`] = `
"reject": [Function],
"resolve": [Function],
},
"payload": [Function],
"type": "rdc/fetch",
},
]
Expand All @@ -34,7 +33,6 @@ exports[`PollingSubscription fresh data should call after period 2`] = `
"reject": [Function],
"resolve": [Function],
},
"payload": [Function],
"type": "rdc/fetch",
},
]
Expand Down
38 changes: 23 additions & 15 deletions packages/core/src/manager/__tests__/networkManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Controller from '../../controller/Controller';
import createFetch from '../../controller/createFetch';
import NetworkManager from '../../manager/NetworkManager';
import { initialState } from '../../state/reducer/createReducer';
import { Middleware } from '../../types';
import { Middleware, SetResponseAction } from '../../types';

describe('NetworkManager', () => {
const manager = new NetworkManager();
Expand Down Expand Up @@ -154,15 +154,17 @@ describe('NetworkManager', () => {

middleware(API)(next)(fetchResolveAction);

const data = await fetchResolveAction.payload();
const response = await fetchResolveAction.endpoint(
...fetchResolveAction.meta.args,
);

// mutations resolve before dispatch, so we must wait for next tick to see set
await new Promise(resolve => setTimeout(resolve, 0));

const action = {
const action: SetResponseAction = {
type: SET_RESPONSE_TYPE,
endpoint: fetchResolveAction.endpoint,
payload: data,
response,
meta: {
args: fetchResolveAction.meta.args,
key: fetchResolveAction.meta.key,
Expand All @@ -187,15 +189,17 @@ describe('NetworkManager', () => {

middleware(API)(next)(fetchSetWithUpdatersAction);

const data = await fetchSetWithUpdatersAction.payload();
const response = await fetchSetWithUpdatersAction.endpoint(
...fetchSetWithUpdatersAction.meta.args,
);

// mutations resolve before dispatch, so we must wait for next tick to see set
await new Promise(resolve => setTimeout(resolve, 0));

const action = {
const action: SetResponseAction = {
type: SET_RESPONSE_TYPE,
endpoint: fetchSetWithUpdatersAction.endpoint,
payload: data,
response,
meta: {
args: fetchSetWithUpdatersAction.meta.args,
key: fetchSetWithUpdatersAction.meta.key,
Expand All @@ -220,15 +224,17 @@ describe('NetworkManager', () => {

middleware(API)(next)(fetchRpcWithUpdatersAction);

const data = await fetchRpcWithUpdatersAction.payload();
const response = await fetchRpcWithUpdatersAction.endpoint(
...fetchRpcWithUpdatersAction.meta.args,
);

// mutations resolve before dispatch, so we must wait for next tick to see set
await new Promise(resolve => setTimeout(resolve, 0));

const action = {
const action: SetResponseAction = {
type: SET_RESPONSE_TYPE,
endpoint: fetchRpcWithUpdatersAction.endpoint,
payload: data,
response,
meta: {
args: fetchRpcWithUpdatersAction.meta.args,
key: fetchRpcWithUpdatersAction.meta.key,
Expand All @@ -253,15 +259,17 @@ describe('NetworkManager', () => {

middleware(API)(next)(fetchRpcWithUpdatersAndOptimisticAction);

const data = await fetchRpcWithUpdatersAndOptimisticAction.payload();
const response = await fetchRpcWithUpdatersAndOptimisticAction.endpoint(
...fetchRpcWithUpdatersAndOptimisticAction.meta.args,
);

expect(next).toHaveBeenCalled();
// mutations resolve before dispatch, so we must wait for next tick to see set
await new Promise(resolve => setTimeout(resolve, 0));
expect(dispatch).toHaveBeenCalledWith({
type: SET_RESPONSE_TYPE,
endpoint: fetchRpcWithUpdatersAndOptimisticAction.endpoint,
payload: data,
response,
meta: {
args: fetchRpcWithUpdatersAndOptimisticAction.meta.args,
key: fetchRpcWithUpdatersAndOptimisticAction.meta.key,
Expand All @@ -286,7 +294,7 @@ describe('NetworkManager', () => {
endpoint: detailEndpoint.extend({ dataExpiryLength: 314 }),
});

await fetchResolveAction.payload();
await fetchResolveAction.endpoint(...fetchResolveAction.meta.args);

expect(dispatch).toHaveBeenCalled();
const { meta } = dispatch.mock.calls[0][0];
Expand All @@ -307,7 +315,7 @@ describe('NetworkManager', () => {
endpoint: detailEndpoint.extend({ dataExpiryLength: undefined }),
});

await fetchResolveAction.payload();
await fetchResolveAction.endpoint(...fetchResolveAction.meta.args);

expect(dispatch).toHaveBeenCalled();
const { meta } = dispatch.mock.calls[0][0];
Expand All @@ -330,7 +338,7 @@ describe('NetworkManager', () => {
expect(next).not.toHaveBeenCalled();
expect(dispatch).toHaveBeenCalledWith({
type: SET_RESPONSE_TYPE,
payload: error,
response: error,
meta: {
key: fetchRejectAction.meta.key,
date: expect.any(Number),
Expand Down
14 changes: 7 additions & 7 deletions packages/core/src/manager/__tests__/subscriptionManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,31 +48,31 @@ describe('SubscriptionManager', () => {

describe('middleware', () => {
function createSubscribeAction(
payload: Record<string, any>,
response: Record<string, any>,
reject = false,
): SubscribeAction {
const fetch =
reject ?
() => Promise.reject(new Error('Failed'))
: () => Promise.resolve(payload);
: () => Promise.resolve(response);
return {
type: SUBSCRIBE_TYPE,
endpoint: PollingArticleResource.get,
meta: {
key: PollingArticleResource.get.key({ id: payload.id }),
args: [{ id: payload.id }],
key: PollingArticleResource.get.key({ id: response.id }),
args: [{ id: response.id }],
},
};
}
function createUnsubscribeAction(
payload: Record<string, any>,
response: Record<string, any>,
): UnsubscribeAction {
return {
type: UNSUBSCRIBE_TYPE,
endpoint: PollingArticleResource.get,
meta: {
key: PollingArticleResource.get.key({ id: payload.id }),
args: [{ id: payload.id }],
key: PollingArticleResource.get.key({ id: response.id }),
args: [{ id: response.id }],
},
};
}
Expand Down
Loading

0 comments on commit d225595

Please sign in to comment.