Skip to content

Commit

Permalink
enhance: Simplify action shapes
Browse files Browse the repository at this point in the history
  • Loading branch information
ntucker committed Jul 11, 2024
1 parent 01b5908 commit fc4406f
Show file tree
Hide file tree
Showing 55 changed files with 600 additions and 556 deletions.
6 changes: 6 additions & 0 deletions .changeset/hip-queens-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@data-client/core': minor
'@data-client/react': patch
---

action.meta.args -> action.args
10 changes: 5 additions & 5 deletions examples/benchmark/normalizr.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ const queryInfer = queryMemo.buildQueryKey(

let githubState = normalize(User, userData);

const date = Date.now()
const actionMeta = {
fetchedAt: Date.now(),
date: Date.now(),
expiresAt: Date.now() + 10000000,
args: [],
fetchedAt: date,
date,
expiresAt: date + 10000000,
};

export default function addNormlizrSuite(suite) {
Expand All @@ -55,7 +55,7 @@ export default function addNormlizrSuite(suite) {
let curState = initialState;
return suite
.add('normalizeLong', () => {
normalize(ProjectSchema, data, actionMeta, curState);
normalize(ProjectSchema, data, [], curState, actionMeta);
curState = { ...initialState, entities: {}, endpoints: {} };
})
.add('infer All', () => {
Expand Down
65 changes: 32 additions & 33 deletions packages/core/src/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type {
EndpointInterface,
Queryable,
ResolveType,
SchemaArgs,
UnknownError,
} from '@data-client/normalizr';

Expand All @@ -28,98 +29,98 @@ type EndpointDefault = EndpointInterface & {
update?: EndpointUpdateFunction<EndpointInterface>;
};

/* SET */
export interface SetMeta {
args: readonly any[];
/** General meta-data for operators */
export interface ActionMeta {
fetchedAt: number;
date: number;
expiresAt: number;
}

/** Action for Controller.set() */
export interface SetAction<S extends Queryable = any> {
type: typeof SET_TYPE;
schema: S;
meta: SetMeta;
args: readonly any[];
meta: ActionMeta;
value: {} | ((previousValue: Denormalize<S>) => {});
}

/* setResponse */
export interface SetResponseMeta {
export interface SetResponseActionBase<
E extends EndpointAndUpdate<E> = EndpointDefault,
> {
type: typeof SET_RESPONSE_TYPE;
endpoint: E;
args: readonly any[];
key: string;
fetchedAt: number;
date: number;
expiresAt: number;
meta: ActionMeta;
}
export interface SetResponseActionSuccess<
E extends EndpointAndUpdate<E> = EndpointDefault,
> {
type: typeof SET_RESPONSE_TYPE;
endpoint: E;
meta: SetResponseMeta;
> extends SetResponseActionBase<E> {
response: ResolveType<E>;
error?: false;
}
export interface SetResponseActionError<
E extends EndpointAndUpdate<E> = EndpointDefault,
> {
type: typeof SET_RESPONSE_TYPE;
endpoint: E;
meta: SetResponseMeta;
> extends SetResponseActionBase<E> {
response: UnknownError;
error: true;
}
/** Action for Controller.setResponse() */
export type SetResponseAction<
E extends EndpointAndUpdate<E> = EndpointDefault,
> = SetResponseActionSuccess<E> | SetResponseActionError<E>;

/* FETCH */
export interface FetchMeta<A extends readonly any[] = readonly any[]> {
args: A;
key: string;
export interface FetchMeta {
fetchedAt: number;
resolve: (value?: any | PromiseLike<any>) => void;
reject: (reason?: any) => void;
promise: PromiseLike<any>;
fetchedAt: number;
}

/** Action for Controller.fetch() */
export interface FetchAction<E extends EndpointAndUpdate<E> = EndpointDefault> {
type: typeof FETCH_TYPE;
endpoint: E;
meta: FetchMeta<readonly [...Parameters<E>]>;
args: readonly [...Parameters<E>];
key: string;
meta: FetchMeta;
}

/* OPTIMISTIC */
/** Action for Endpoint.getOptimisticResponse() */
export interface OptimisticAction<
E extends EndpointAndUpdate<E> = EndpointDefault,
> {
type: typeof OPTIMISTIC_TYPE;
endpoint: E;
meta: SetResponseMeta;
args: readonly any[];
key: string;
meta: ActionMeta;
error?: false;
}

/* SUBSCRIBE */
/** Action for Controller.subscribe() */
export interface SubscribeAction<
E extends EndpointAndUpdate<E> = EndpointDefault,
> {
type: typeof SUBSCRIBE_TYPE;
endpoint: E;
meta: {
args: readonly any[];
key: string;
};
args: readonly any[];
key: string;
}

/** Action for Controller.unsubscribe() */
export interface UnsubscribeAction<
E extends EndpointAndUpdate<E> = EndpointDefault,
> {
type: typeof UNSUBSCRIBE_TYPE;
endpoint: E;
meta: {
args: readonly any[];
key: string;
};
args: readonly any[];
key: string;
}

/* EXPIRY */
Expand All @@ -136,9 +137,7 @@ export interface InvalidateAllAction {

export interface InvalidateAction {
type: typeof INVALIDATE_TYPE;
meta: {
key: string;
};
key: string;
}

/* RESET */
Expand Down
18 changes: 10 additions & 8 deletions packages/core/src/controller/Controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,19 @@ import {
} from '@data-client/normalizr';

import AbortOptimistic from './AbortOptimistic.js';
import createExpireAll from './createExpireAll.js';
import createFetch from './createFetch.js';
import createInvalidate from './createInvalidate.js';
import createInvalidateAll from './createInvalidateAll.js';
import createReset from './createReset.js';
import createSet from './createSet.js';
import createSetResponse from './createSetResponse.js';
import {
createUnsubscription,
createSubscription,
} from './createSubscription.js';
} from './actions/createSubscription.js';
import {
createExpireAll,
createFetch,
createInvalidate,
createInvalidateAll,
createReset,
createSet,
createSetResponse,
} from './actions/index.js';
import ensurePojo from './ensurePojo.js';
import type { EndpointUpdateFunction } from './types.js';
import { initialState } from '../state/reducer/createReducer.js';
Expand Down
11 changes: 11 additions & 0 deletions packages/core/src/controller/actions/createExpireAll.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { EXPIREALL_TYPE } from '../../actionTypes.js';
import type { ExpireAllAction } from '../../types.js';

export function createExpireAll(
testKey: (key: string) => boolean,
): ExpireAllAction {
return {
type: EXPIREALL_TYPE,
testKey,
};
}
Original file line number Diff line number Diff line change
@@ -1,36 +1,35 @@
import type { EndpointInterface, NI } from '@data-client/normalizr';

import { EndpointUpdateFunction } from './types.js';
import { FETCH_TYPE } from '../actionTypes.js';
import type { FetchAction, FetchMeta } from '../types.js';
import { FETCH_TYPE } from '../../actionTypes.js';
import type { FetchAction, FetchMeta } from '../../types.js';
import { EndpointUpdateFunction } from '../types.js';

/**
* Requesting a fetch to begin
*/
export default function createFetch<
export function createFetch<
E extends EndpointInterface & { update?: EndpointUpdateFunction<E> },
>(
endpoint: E,
{ args }: { args: readonly [...Parameters<E>] },
): FetchAction<E> {
const key = endpoint.key(...args);
let resolve: (value?: any | PromiseLike<any>) => void = 0 as any;
let reject: (reason?: any) => void = 0 as any;
const promise = new Promise<any>((a, b) => {
[resolve, reject] = [a, b];
});
const meta: FetchMeta<typeof args> = {
args,
key,
const meta: FetchMeta = {
fetchedAt: Date.now(),
resolve,
reject,
promise,
fetchedAt: Date.now(),
};

return {
type: FETCH_TYPE,
meta,
endpoint,
args,
key: endpoint.key(...args),
meta,
};
}
14 changes: 14 additions & 0 deletions packages/core/src/controller/actions/createInvalidate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { EndpointInterface } from '@data-client/normalizr';

import { INVALIDATE_TYPE } from '../../actionTypes.js';
import type { InvalidateAction } from '../../types.js';

export function createInvalidate<E extends EndpointInterface>(
endpoint: E,
{ args }: { args: readonly [...Parameters<E>] },
): InvalidateAction {
return {
type: INVALIDATE_TYPE,
key: endpoint.key(...args),
};
}
11 changes: 11 additions & 0 deletions packages/core/src/controller/actions/createInvalidateAll.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { INVALIDATEALL_TYPE } from '../../actionTypes.js';
import type { InvalidateAllAction } from '../../types.js';

export function createInvalidateAll(
testKey: (key: string) => boolean,
): InvalidateAllAction {
return {
type: INVALIDATEALL_TYPE,
testKey,
};
}
13 changes: 13 additions & 0 deletions packages/core/src/controller/actions/createMeta.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { ActionMeta } from '../../actions.js';

export function createMeta(
expiryLength: number,
fetchedAt?: number,
): ActionMeta {
const now = Date.now();
return {
fetchedAt: fetchedAt ?? now,
date: now,
expiresAt: now + expiryLength,
};
}
32 changes: 32 additions & 0 deletions packages/core/src/controller/actions/createOptimistic.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import type { EndpointInterface } from '@data-client/normalizr';

import { createMeta } from './createMeta.js';
import { OPTIMISTIC_TYPE } from '../../actionTypes.js';
import type { OptimisticAction } from '../../types.js';
import type { EndpointUpdateFunction } from '../types.js';

export function createOptimistic<
E extends EndpointInterface & {
update?: EndpointUpdateFunction<E>;
},
>(
endpoint: E,
args: readonly [...Parameters<E>],
fetchedAt: number,
): OptimisticAction<E> {
/* istanbul ignore next */
if (
process.env.NODE_ENV === 'development' &&
(endpoint.dataExpiryLength ?? 0) < 0
) {
throw new Error('Negative expiry length are not allowed.');
}

return {
type: OPTIMISTIC_TYPE,
endpoint,
args,
key: endpoint.key(...args),
meta: createMeta(endpoint.dataExpiryLength ?? 60000, fetchedAt),
};
}
9 changes: 9 additions & 0 deletions packages/core/src/controller/actions/createReset.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { RESET_TYPE } from '../../actionTypes.js';
import type { ResetAction } from '../../types.js';

export function createReset(): ResetAction {
return {
type: RESET_TYPE,
date: Date.now(),
};
}
32 changes: 32 additions & 0 deletions packages/core/src/controller/actions/createSet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import type {
Denormalize,
Queryable,
SchemaArgs,
} from '@data-client/normalizr';

import { createMeta } from './createMeta.js';
import { SET_TYPE } from '../../actionTypes.js';
import type { SetAction } from '../../types.js';
import ensurePojo from '../ensurePojo.js';

export function createSet<S extends Queryable>(
schema: S,
{
args,
fetchedAt,
value,
}: {
args: readonly [...SchemaArgs<S>];
value: {} | ((previousValue: Denormalize<S>) => {});
fetchedAt?: number;
},
): SetAction<S> {
const action: SetAction<S> = {
type: SET_TYPE,
schema,
value,
args: args.map(ensurePojo) as SchemaArgs<S>,
meta: createMeta(60000, fetchedAt),
};
return action;
}
Loading

0 comments on commit fc4406f

Please sign in to comment.