@data-client/core 0.14.0 → 0.14.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +2 -1
  2. package/dist/index.js +43 -21
  3. package/dist/index.umd.min.js +1 -1
  4. package/legacy/controller/actions/createFetch.js +3 -3
  5. package/legacy/controller/actions/createOptimistic.js +3 -3
  6. package/legacy/controller/actions/createSet.js +2 -2
  7. package/legacy/controller/actions/createSetResponse.js +3 -3
  8. package/legacy/controller/actions/createSubscription.js +3 -3
  9. package/legacy/manager/DevtoolsManager.js +24 -2
  10. package/legacy/manager/applyManager.js +12 -4
  11. package/legacy/manager/devtoolsTypes.js +1 -1
  12. package/legacy/state/reducer/fetchReducer.js +2 -9
  13. package/lib/controller/actions/createFetch.js +3 -3
  14. package/lib/controller/actions/createOptimistic.js +3 -3
  15. package/lib/controller/actions/createSet.js +2 -2
  16. package/lib/controller/actions/createSetResponse.js +3 -3
  17. package/lib/controller/actions/createSubscription.js +3 -3
  18. package/lib/manager/DevtoolsManager.d.ts.map +1 -1
  19. package/lib/manager/DevtoolsManager.js +24 -2
  20. package/lib/manager/applyManager.d.ts.map +1 -1
  21. package/lib/manager/applyManager.js +12 -4
  22. package/lib/manager/devtoolsTypes.d.ts +5 -3
  23. package/lib/manager/devtoolsTypes.d.ts.map +1 -1
  24. package/lib/manager/devtoolsTypes.js +1 -1
  25. package/lib/state/reducer/fetchReducer.d.ts.map +1 -1
  26. package/lib/state/reducer/fetchReducer.js +2 -9
  27. package/lib/state/reducer/setReducer.d.ts +26 -1
  28. package/lib/state/reducer/setReducer.d.ts.map +1 -1
  29. package/lib/state/reducer/setResponseReducer.d.ts +28 -1
  30. package/lib/state/reducer/setResponseReducer.d.ts.map +1 -1
  31. package/package.json +2 -2
  32. package/src/controller/actions/createFetch.ts +2 -2
  33. package/src/controller/actions/createOptimistic.ts +2 -2
  34. package/src/controller/actions/createSet.ts +1 -1
  35. package/src/controller/actions/createSetResponse.ts +2 -2
  36. package/src/controller/actions/createSubscription.ts +2 -2
  37. package/src/manager/DevtoolsManager.ts +14 -1
  38. package/src/manager/__tests__/applyManager.ts +38 -0
  39. package/src/manager/applyManager.ts +16 -3
  40. package/src/manager/devtoolsTypes.ts +9 -3
  41. package/src/state/__tests__/reducer.ts +3 -2
  42. package/src/state/reducer/fetchReducer.ts +1 -13
  43. package/ts3.4/manager/devtoolsTypes.d.ts +5 -3
  44. package/ts3.4/state/reducer/setReducer.d.ts +26 -1
  45. package/ts3.4/state/reducer/setResponseReducer.d.ts +28 -1
@@ -37,6 +37,18 @@ if (process.env.NODE_ENV !== 'production') {
37
37
  DEFAULT_CONFIG = {
38
38
  name: `Data Client: ${globalThis.document?.title}`,
39
39
  autoPause: true,
40
+ features: {
41
+ pause: true, // start/pause recording of dispatched actions
42
+ lock: true, // lock/unlock dispatching actions and side effects
43
+ persist: false, // persist states on page reloading
44
+ export: true, // export history of actions in a file
45
+ import: 'custom', // import history of actions from a file
46
+ jump: true, // jump back and forth (time travelling)
47
+ skip: true, // skip (cancel) actions
48
+ reorder: true, // drag and drop actions in the history list
49
+ dispatch: false, // dispatch custom actions or action creators
50
+ test: false, // generate tests for the selected actions
51
+ },
40
52
  actionSanitizer: (action: ActionTypes) => {
41
53
  if (!('endpoint' in action)) return action;
42
54
  return {
@@ -131,6 +143,7 @@ export default class DevToolsManager implements Manager {
131
143
  const reducer = createReducer(controller as any);
132
144
  let state = controller.getState();
133
145
  return next => action => {
146
+ const shouldSkip = skipLogging?.(action);
134
147
  const ret = next(action);
135
148
  if (this.started) {
136
149
  // we track state changes here since getState() will only update after a batch commit
@@ -139,7 +152,7 @@ export default class DevToolsManager implements Manager {
139
152
  state = controller.getState();
140
153
  }
141
154
  ret.then(() => {
142
- if (skipLogging?.(action)) return;
155
+ if (shouldSkip) return;
143
156
  this.handleAction(action, state.optimistic.reduce(reducer, state));
144
157
  });
145
158
  return ret;
@@ -0,0 +1,38 @@
1
+ import Controller from '../../controller/Controller';
2
+ import applyManager from '../applyManager';
3
+ import NetworkManager from '../NetworkManager';
4
+
5
+ function onError(e: any) {
6
+ e.preventDefault();
7
+ }
8
+ beforeEach(() => {
9
+ if (typeof addEventListener === 'function')
10
+ addEventListener('error', onError);
11
+ });
12
+ afterEach(() => {
13
+ if (typeof removeEventListener === 'function')
14
+ removeEventListener('error', onError);
15
+ });
16
+
17
+ it('applyManagers should console.warn() when no NetworkManager is provided', () => {
18
+ const warnspy = jest
19
+ .spyOn(global.console, 'warn')
20
+ .mockImplementation(() => {});
21
+ try {
22
+ applyManager([], new Controller());
23
+ expect(warnspy.mock.calls.length).toBe(2);
24
+ } finally {
25
+ warnspy.mockRestore();
26
+ }
27
+ });
28
+ it('applyManagers should not console.warn() when NetworkManager is provided', () => {
29
+ const warnspy = jest
30
+ .spyOn(global.console, 'warn')
31
+ .mockImplementation(() => {});
32
+ try {
33
+ applyManager([new NetworkManager()], new Controller());
34
+ expect(warnspy.mock.calls.length).toBe(0);
35
+ } finally {
36
+ warnspy.mockRestore();
37
+ }
38
+ });
@@ -1,3 +1,4 @@
1
+ import NetworkManager from './NetworkManager.js';
1
2
  import type Controller from '../controller/Controller.js';
2
3
  import type { Reducer, Dispatch, ReducerState } from '../middlewareTypes.js';
3
4
  import { Manager } from '../types.js';
@@ -6,11 +7,23 @@ export default function applyManager(
6
7
  managers: Manager[],
7
8
  controller: Controller,
8
9
  ): Middleware[] {
9
- return managers.map(manager => {
10
+ /* istanbul ignore next */
11
+ if (
12
+ process.env.NODE_ENV !== 'production' &&
13
+ !managers.find(mgr => mgr instanceof NetworkManager)
14
+ ) {
15
+ console.warn('NetworkManager not found; this is a required manager.');
16
+ console.warn(
17
+ 'See https://dataclient.io/docs/guides/redux for hooking up redux',
18
+ );
19
+ }
20
+ return managers.map((manager, i) => {
10
21
  const middleware = manager.getMiddleware();
11
22
  return ({ dispatch, getState }) => {
12
- (controller as any).dispatch = dispatch;
13
- (controller as any).getState = getState;
23
+ if (i === 0) {
24
+ (controller as any).dispatch = dispatch;
25
+ (controller as any).getState = getState;
26
+ }
14
27
  // controller is a superset of the middleware API
15
28
  return middleware(controller as Controller<any>);
16
29
  };
@@ -1,4 +1,7 @@
1
- type Action = any;
1
+ import { ActionTypes } from '../actions.js';
2
+ import { State } from '../types.js';
3
+
4
+ type Action = ActionTypes;
2
5
  type ActionCreator<T> = any;
3
6
 
4
7
  // taken from https://github.com/reduxjs/redux-devtools/blob/main/packages/redux-devtools-extension/src/index.ts
@@ -78,7 +81,7 @@ export interface EnhancerOptions {
78
81
  /**
79
82
  * function which takes `state` object and index as arguments, and should return `state` object back.
80
83
  */
81
- stateSanitizer?: <S>(state: S, index: number) => S;
84
+ stateSanitizer?: <S extends State<unknown>>(state: S, index: number) => S;
82
85
  /**
83
86
  * *string or array of strings as regex* - actions types to be hidden / shown in the monitors (while passed to the reducers).
84
87
  * If `actionsWhitelist` specified, `actionsBlacklist` is ignored.
@@ -105,7 +108,10 @@ export interface EnhancerOptions {
105
108
  * called for every action before sending, takes `state` and `action` object, and returns `true` in case it allows sending the current data to the monitor.
106
109
  * Use it as a more advanced version of `actionsDenylist`/`actionsAllowlist` parameters.
107
110
  */
108
- predicate?: <S, A extends Action>(state: S, action: A) => boolean;
111
+ predicate?: <S extends State<unknown>, A extends Action>(
112
+ state: S,
113
+ action: A,
114
+ ) => boolean;
109
115
  /**
110
116
  * if specified as `false`, it will not record the changes till clicking on `Start recording` button.
111
117
  * Available only for Redux enhancer, for others use `autoPause`.
@@ -595,7 +595,7 @@ describe('reducer', () => {
595
595
  const newState = reducer(iniState, action);
596
596
  expect(newState.entities).toBe(iniState.entities);
597
597
  });
598
- it('rdc/fetch should console.warn()', () => {
598
+ it('rdc/fetch should not console.warn()', () => {
599
599
  const warnspy = jest
600
600
  .spyOn(global.console, 'warn')
601
601
  .mockImplementation(() => {});
@@ -618,7 +618,8 @@ describe('reducer', () => {
618
618
  };
619
619
  const newState = reducer(iniState, action);
620
620
  expect(newState).toBe(iniState);
621
- expect(warnspy.mock.calls.length).toBe(2);
621
+ // moved warns to applyManager() vv
622
+ expect(warnspy.mock.calls.length).toBe(0);
622
623
  } finally {
623
624
  warnspy.mockRestore();
624
625
  }
@@ -12,18 +12,6 @@ export function fetchReducer(state: State<unknown>, action: FetchAction) {
12
12
  ...state,
13
13
  optimistic: [...state.optimistic, setAction],
14
14
  };
15
- } else {
16
- // If 'fetch' action reaches the reducer there are no middlewares installed to handle it
17
- /* istanbul ignore next */
18
- if (process.env.NODE_ENV !== 'production') {
19
- console.warn(
20
- 'Fetch appears unhandled - you are likely missing the NetworkManager middleware',
21
- );
22
- console.warn(
23
- 'See https://dataclient.io/docs/guides/redux for hooking up redux',
24
- );
25
- }
26
-
27
- return state;
28
15
  }
16
+ return state;
29
17
  }
@@ -1,4 +1,6 @@
1
- type Action = any;
1
+ import { ActionTypes } from '../actions.js';
2
+ import { State } from '../types.js';
3
+ type Action = ActionTypes;
2
4
  type ActionCreator<T> = any;
3
5
  export interface EnhancerOptions {
4
6
  /**
@@ -72,7 +74,7 @@ export interface EnhancerOptions {
72
74
  /**
73
75
  * function which takes `state` object and index as arguments, and should return `state` object back.
74
76
  */
75
- stateSanitizer?: <S>(state: S, index: number) => S;
77
+ stateSanitizer?: <S extends State<unknown>>(state: S, index: number) => S;
76
78
  /**
77
79
  * *string or array of strings as regex* - actions types to be hidden / shown in the monitors (while passed to the reducers).
78
80
  * If `actionsWhitelist` specified, `actionsBlacklist` is ignored.
@@ -99,7 +101,7 @@ export interface EnhancerOptions {
99
101
  * called for every action before sending, takes `state` and `action` object, and returns `true` in case it allows sending the current data to the monitor.
100
102
  * Use it as a more advanced version of `actionsDenylist`/`actionsAllowlist` parameters.
101
103
  */
102
- predicate?: <S, A extends Action>(state: S, action: A) => boolean;
104
+ predicate?: <S extends State<unknown>, A extends Action>(state: S, action: A) => boolean;
103
105
  /**
104
106
  * if specified as `false`, it will not record the changes till clicking on `Start recording` button.
105
107
  * Available only for Redux enhancer, for others use `autoPause`.
@@ -1,4 +1,29 @@
1
1
  import Controller from '../../controller/Controller.js';
2
2
  import { State, SetAction } from '../../types.js';
3
- export declare function setReducer(state: State<unknown>, action: SetAction, controller: Controller): State<unknown>;
3
+ export declare function setReducer(state: State<unknown>, action: SetAction, controller: Controller): State<unknown> | {
4
+ entities: {
5
+ [x: string]: any;
6
+ };
7
+ indexes: import("@data-client/normalizr").NormalizedIndex;
8
+ endpoints: {
9
+ readonly [key: string]: unknown;
10
+ };
11
+ entityMeta: import("packages/normalizr/lib/types.js").EntitiesToMeta<{
12
+ [x: string]: any;
13
+ }>;
14
+ meta: {
15
+ readonly [key: string]: {
16
+ readonly date: number;
17
+ readonly expiresAt: number;
18
+ readonly prevExpiresAt?: number;
19
+ readonly error?: import("@data-client/normalizr").ErrorTypes;
20
+ readonly invalidated?: boolean;
21
+ readonly errorPolicy?: "hard" | "soft" | undefined;
22
+ };
23
+ };
24
+ optimistic: (import("../../actions.js").SetResponseAction | import("../../actions.js").OptimisticAction<import("@data-client/normalizr").EndpointInterface<import("@data-client/normalizr").FetchFunction, import("@data-client/normalizr").Schema | undefined, boolean | undefined> & {
25
+ update?: import("../../index.js").EndpointUpdateFunction<import("@data-client/normalizr").EndpointInterface>;
26
+ }>)[];
27
+ lastReset: number;
28
+ };
4
29
  //# sourceMappingURL=setReducer.d.ts.map
@@ -1,4 +1,31 @@
1
1
  import Controller from '../../controller/Controller.js';
2
2
  import { State, SetResponseAction, OptimisticAction } from '../../types.js';
3
- export declare function setResponseReducer(state: State<unknown>, action: OptimisticAction | SetResponseAction, controller: Controller): State<unknown>;
3
+ export declare function setResponseReducer(state: State<unknown>, action: OptimisticAction | SetResponseAction, controller: Controller): State<unknown> | {
4
+ entities: {
5
+ [x: string]: any;
6
+ };
7
+ indexes: import("@data-client/normalizr").NormalizedIndex;
8
+ endpoints: Record<string, unknown>;
9
+ entityMeta: import("packages/normalizr/lib/types.js").EntitiesToMeta<{
10
+ [x: string]: any;
11
+ }>;
12
+ meta: {
13
+ [x: string]: {
14
+ readonly date: number;
15
+ readonly expiresAt: number;
16
+ readonly prevExpiresAt?: number;
17
+ readonly error?: import("@data-client/normalizr").ErrorTypes;
18
+ readonly invalidated?: boolean;
19
+ readonly errorPolicy?: "hard" | "soft" | undefined;
20
+ } | {
21
+ date: number;
22
+ expiresAt: number;
23
+ prevExpiresAt: number;
24
+ };
25
+ };
26
+ optimistic: (SetResponseAction | OptimisticAction<import("@data-client/normalizr").EndpointInterface<import("@data-client/normalizr").FetchFunction, import("@data-client/normalizr").Schema | undefined, boolean | undefined> & {
27
+ update?: import("../../index.js").EndpointUpdateFunction<import("@data-client/normalizr").EndpointInterface>;
28
+ }>)[];
29
+ lastReset: number;
30
+ };
4
31
  //# sourceMappingURL=setResponseReducer.d.ts.map