@intrig/plugin-react 0.0.1 → 0.0.2-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.
- package/dist/index.cjs +4260 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +4235 -0
- package/package.json +6 -3
- package/.swcrc +0 -29
- package/README.md +0 -7
- package/eslint.config.mjs +0 -19
- package/project.json +0 -29
- package/rollup.config.cjs +0 -54
- package/rollup.config.mjs +0 -33
- package/src/index.ts +0 -2
- package/src/lib/code-generator.ts +0 -79
- package/src/lib/get-endpoint-documentation.ts +0 -35
- package/src/lib/get-schema-documentation.ts +0 -11
- package/src/lib/internal-types.ts +0 -15
- package/src/lib/plugin-react.ts +0 -22
- package/src/lib/templates/context.template.ts +0 -74
- package/src/lib/templates/docs/__snapshots__/async-hook.spec.ts.snap +0 -889
- package/src/lib/templates/docs/__snapshots__/download-hook.spec.ts.snap +0 -1445
- package/src/lib/templates/docs/__snapshots__/react-hook.spec.ts.snap +0 -1371
- package/src/lib/templates/docs/__snapshots__/sse-hook.spec.ts.snap +0 -2008
- package/src/lib/templates/docs/async-hook.spec.ts +0 -92
- package/src/lib/templates/docs/async-hook.ts +0 -226
- package/src/lib/templates/docs/download-hook.spec.ts +0 -182
- package/src/lib/templates/docs/download-hook.ts +0 -170
- package/src/lib/templates/docs/react-hook.spec.ts +0 -97
- package/src/lib/templates/docs/react-hook.ts +0 -323
- package/src/lib/templates/docs/schema.ts +0 -105
- package/src/lib/templates/docs/sse-hook.spec.ts +0 -207
- package/src/lib/templates/docs/sse-hook.ts +0 -221
- package/src/lib/templates/extra.template.ts +0 -198
- package/src/lib/templates/index.template.ts +0 -14
- package/src/lib/templates/intrigMiddleware.template.ts +0 -21
- package/src/lib/templates/logger.template.ts +0 -67
- package/src/lib/templates/media-type-utils.template.ts +0 -191
- package/src/lib/templates/network-state.template.ts +0 -702
- package/src/lib/templates/packageJson.template.ts +0 -63
- package/src/lib/templates/provider/__tests__/provider-templates.spec.ts +0 -209
- package/src/lib/templates/provider/axios-config.template.ts +0 -49
- package/src/lib/templates/provider/hooks.template.ts +0 -240
- package/src/lib/templates/provider/interfaces.template.ts +0 -72
- package/src/lib/templates/provider/intrig-provider-stub.template.ts +0 -73
- package/src/lib/templates/provider/intrig-provider.template.ts +0 -185
- package/src/lib/templates/provider/main.template.ts +0 -48
- package/src/lib/templates/provider/reducer.template.ts +0 -50
- package/src/lib/templates/provider/status-trap.template.ts +0 -80
- package/src/lib/templates/provider.template.ts +0 -698
- package/src/lib/templates/source/controller/method/asyncFunctionHook.template.ts +0 -196
- package/src/lib/templates/source/controller/method/clientIndex.template.ts +0 -38
- package/src/lib/templates/source/controller/method/download.template.ts +0 -256
- package/src/lib/templates/source/controller/method/params.template.ts +0 -31
- package/src/lib/templates/source/controller/method/requestHook.template.ts +0 -220
- package/src/lib/templates/source/type/typeTemplate.ts +0 -257
- package/src/lib/templates/swcrc.template.ts +0 -25
- package/src/lib/templates/tsconfig.template.ts +0 -37
- package/src/lib/templates/type-utils.template.ts +0 -28
- package/tsconfig.json +0 -13
- package/tsconfig.lib.json +0 -20
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { IntrigSourceConfig, typescript } from "@intrig/plugin-sdk";
|
|
2
|
-
import * as path from 'path';
|
|
3
|
-
|
|
4
|
-
export function reactIntrigProviderStubTemplate(_apisToSync: IntrigSourceConfig[]) {
|
|
5
|
-
const ts = typescript(path.resolve('src', 'intrig-provider-stub.tsx'));
|
|
6
|
-
return ts`import { useMemo, useReducer } from 'react';
|
|
7
|
-
import { ZodSchema } from 'zod';
|
|
8
|
-
import { Context, RequestType, GlobalState } from './intrig-context';
|
|
9
|
-
import { IntrigProviderStubProps } from './interfaces';
|
|
10
|
-
import { error, configError, init, NetworkState } from './network-state';
|
|
11
|
-
import { requestReducer } from './reducer';
|
|
12
|
-
|
|
13
|
-
export function IntrigProviderStub({
|
|
14
|
-
children,
|
|
15
|
-
configs = {},
|
|
16
|
-
stubs = () => {
|
|
17
|
-
//intentionally left blank
|
|
18
|
-
},
|
|
19
|
-
}: IntrigProviderStubProps) {
|
|
20
|
-
const [state, dispatch] = useReducer(requestReducer, {} as GlobalState);
|
|
21
|
-
|
|
22
|
-
const collectedStubs = useMemo(() => {
|
|
23
|
-
const fns: Record<string, (
|
|
24
|
-
params: any,
|
|
25
|
-
body: any,
|
|
26
|
-
dispatch: (state: NetworkState<any>) => void,
|
|
27
|
-
) => Promise<void>> = {};
|
|
28
|
-
function stub<P, B, T>(
|
|
29
|
-
hook: any,
|
|
30
|
-
fn: (
|
|
31
|
-
params: P,
|
|
32
|
-
body: B,
|
|
33
|
-
dispatch: (state: NetworkState<T>) => void,
|
|
34
|
-
) => Promise<void>,
|
|
35
|
-
) {
|
|
36
|
-
fns[hook.key] = fn;
|
|
37
|
-
}
|
|
38
|
-
stubs(stub);
|
|
39
|
-
return fns;
|
|
40
|
-
}, [stubs]);
|
|
41
|
-
|
|
42
|
-
const contextValue = useMemo(() => {
|
|
43
|
-
async function execute<T>(
|
|
44
|
-
request: RequestType,
|
|
45
|
-
dispatch: (state: NetworkState<T>) => void,
|
|
46
|
-
schema: ZodSchema<T> | undefined,
|
|
47
|
-
) {
|
|
48
|
-
const stub = collectedStubs[request.key];
|
|
49
|
-
|
|
50
|
-
if (stub) {
|
|
51
|
-
try {
|
|
52
|
-
await stub(request.params, request.data, dispatch);
|
|
53
|
-
} catch (e: any) {
|
|
54
|
-
dispatch(error(configError(e?.message ?? '')));
|
|
55
|
-
}
|
|
56
|
-
} else {
|
|
57
|
-
dispatch(init());
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return {
|
|
62
|
-
state,
|
|
63
|
-
dispatch,
|
|
64
|
-
filteredState: state,
|
|
65
|
-
configs,
|
|
66
|
-
execute,
|
|
67
|
-
};
|
|
68
|
-
}, [state, dispatch, configs, collectedStubs]);
|
|
69
|
-
|
|
70
|
-
return <Context.Provider value={contextValue}>{children}</Context.Provider>;
|
|
71
|
-
}
|
|
72
|
-
`;
|
|
73
|
-
}
|
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
import { IntrigSourceConfig, typescript } from "@intrig/plugin-sdk";
|
|
2
|
-
import * as path from 'path';
|
|
3
|
-
|
|
4
|
-
export function reactIntrigProviderTemplate(_apisToSync: IntrigSourceConfig[]) {
|
|
5
|
-
const ts = typescript(path.resolve('src', 'intrig-provider.tsx'));
|
|
6
|
-
return ts`import React, { useMemo, useReducer } from 'react';
|
|
7
|
-
import {
|
|
8
|
-
error,
|
|
9
|
-
NetworkState,
|
|
10
|
-
pending,
|
|
11
|
-
success,
|
|
12
|
-
responseValidationError,
|
|
13
|
-
configError,
|
|
14
|
-
httpError,
|
|
15
|
-
networkError,
|
|
16
|
-
} from './network-state';
|
|
17
|
-
import { Axios, AxiosResponse, isAxiosError } from 'axios';
|
|
18
|
-
import { ZodError, ZodSchema } from 'zod';
|
|
19
|
-
import { flushSync } from 'react-dom';
|
|
20
|
-
import { createParser } from 'eventsource-parser';
|
|
21
|
-
|
|
22
|
-
import { Context, RequestType, GlobalState } from './intrig-context';
|
|
23
|
-
import { IntrigProviderProps } from './interfaces';
|
|
24
|
-
import { createAxiosInstances } from './axios-config';
|
|
25
|
-
import { requestReducer, inferNetworkReason } from './reducer';
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* IntrigProvider is a context provider component that sets up global state management
|
|
29
|
-
* and provides Axios instances for API requests.
|
|
30
|
-
*/
|
|
31
|
-
export function IntrigProvider({ children, configs = {} }: IntrigProviderProps) {
|
|
32
|
-
const [state, dispatch] = useReducer(requestReducer, {} as GlobalState);
|
|
33
|
-
|
|
34
|
-
const axiosInstances: Record<string, Axios> = useMemo(() => {
|
|
35
|
-
return createAxiosInstances(configs);
|
|
36
|
-
}, [configs]);
|
|
37
|
-
|
|
38
|
-
const contextValue = useMemo(() => {
|
|
39
|
-
async function execute<T>(
|
|
40
|
-
request: RequestType,
|
|
41
|
-
setState: (s: NetworkState<T>) => void,
|
|
42
|
-
schema?: ZodSchema<T>, // success payload schema (optional)
|
|
43
|
-
errorSchema?: ZodSchema<any>, // error-body schema for non-2xx (optional)
|
|
44
|
-
) {
|
|
45
|
-
try {
|
|
46
|
-
setState(pending());
|
|
47
|
-
|
|
48
|
-
const axios = axiosInstances[request.source];
|
|
49
|
-
if (!axios) {
|
|
50
|
-
setState(error(configError(${"`Unknown axios source '${request.source}'`"})));
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const response = await axios.request(request);
|
|
55
|
-
const status = response.status;
|
|
56
|
-
const method = (response.config?.method || 'GET').toUpperCase();
|
|
57
|
-
const url = response.config?.url || '';
|
|
58
|
-
const ctype = String(response.headers?.['content-type'] || '');
|
|
59
|
-
|
|
60
|
-
// -------------------- 2xx branch --------------------
|
|
61
|
-
if (status >= 200 && status < 300) {
|
|
62
|
-
// SSE stream
|
|
63
|
-
if (ctype.includes('text/event-stream')) {
|
|
64
|
-
const reader = response.data.getReader();
|
|
65
|
-
const decoder = new TextDecoder();
|
|
66
|
-
|
|
67
|
-
let lastMessage: any;
|
|
68
|
-
|
|
69
|
-
const parser = createParser({
|
|
70
|
-
onEvent(evt) {
|
|
71
|
-
let decoded: unknown = evt.data;
|
|
72
|
-
|
|
73
|
-
// Try JSON parse; if schema is defined, we require valid JSON for validation
|
|
74
|
-
try {
|
|
75
|
-
let parsed: unknown = JSON.parse(String(decoded));
|
|
76
|
-
if (schema) {
|
|
77
|
-
const vr = schema.safeParse(parsed);
|
|
78
|
-
if (!vr.success) {
|
|
79
|
-
setState(error(responseValidationError(vr.error, parsed)));
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
parsed = vr.data;
|
|
83
|
-
}
|
|
84
|
-
decoded = parsed;
|
|
85
|
-
} catch (ignore) {
|
|
86
|
-
if (schema) {
|
|
87
|
-
// schema expects structured data but chunk wasn't JSON
|
|
88
|
-
setState(error(responseValidationError(new ZodError([]), decoded)));
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
// if no schema, pass raw text
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
lastMessage = decoded;
|
|
95
|
-
flushSync(() => setState(pending(undefined, decoded as T)));
|
|
96
|
-
},
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
while (true) {
|
|
100
|
-
const { done, value } = await reader.read();
|
|
101
|
-
if (done) {
|
|
102
|
-
flushSync(() => setState(success(lastMessage as T, response.headers)));
|
|
103
|
-
break;
|
|
104
|
-
}
|
|
105
|
-
parser.feed(decoder.decode(value, { stream: true }));
|
|
106
|
-
}
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Non-SSE: validate body if a schema is provided
|
|
111
|
-
if (schema) {
|
|
112
|
-
const parsed = schema.safeParse(response.data);
|
|
113
|
-
if (!parsed.success) {
|
|
114
|
-
setState(error(responseValidationError(parsed.error, response.data)));
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
setState(success(parsed.data, response.headers));
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// No schema → pass through
|
|
122
|
-
setState(success(response.data as T, response.headers));
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// -------------------- non-2xx (HTTP error) --------------------
|
|
127
|
-
let errorBody: unknown = response.data;
|
|
128
|
-
|
|
129
|
-
if (errorSchema) {
|
|
130
|
-
const ev = errorSchema.safeParse(errorBody ?? {});
|
|
131
|
-
if (!ev.success) {
|
|
132
|
-
setState(error(responseValidationError(ev.error, errorBody)));
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
errorBody = ev.data;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
setState(error(httpError(status, url, method, response.headers, errorBody)));
|
|
139
|
-
|
|
140
|
-
} catch (e: any) {
|
|
141
|
-
// -------------------- thrown / transport --------------------
|
|
142
|
-
if (isAxiosError(e)) {
|
|
143
|
-
const status = e.response?.status;
|
|
144
|
-
const method = (e.config?.method || 'GET').toUpperCase();
|
|
145
|
-
const url = e.config?.url || '';
|
|
146
|
-
|
|
147
|
-
if (status != null) {
|
|
148
|
-
// HTTP error with response
|
|
149
|
-
let errorBody: unknown = e.response?.data;
|
|
150
|
-
|
|
151
|
-
if (errorSchema) {
|
|
152
|
-
const ev = errorSchema.safeParse(errorBody ?? {});
|
|
153
|
-
if (!ev.success) {
|
|
154
|
-
setState(error(responseValidationError(ev.error, errorBody)));
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
errorBody = ev.data;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
setState(error(httpError(status, url, method, e.response?.headers, errorBody)));
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// No response → network layer
|
|
165
|
-
setState(error(networkError(inferNetworkReason(e), e.request)));
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// Non-Axios exception → treat as unknown network-ish failure
|
|
170
|
-
setState(error(networkError('unknown')));
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
return {
|
|
174
|
-
state,
|
|
175
|
-
dispatch,
|
|
176
|
-
filteredState: state,
|
|
177
|
-
configs,
|
|
178
|
-
execute,
|
|
179
|
-
};
|
|
180
|
-
}, [state, axiosInstances]);
|
|
181
|
-
|
|
182
|
-
return <Context.Provider value={contextValue}>{children}</Context.Provider>;
|
|
183
|
-
}
|
|
184
|
-
`;
|
|
185
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import {IntrigSourceConfig, typescript} from "@intrig/plugin-sdk";
|
|
2
|
-
import * as path from 'path'
|
|
3
|
-
|
|
4
|
-
export function providerMainTemplate(apisToSync: IntrigSourceConfig[]) {
|
|
5
|
-
const ts = typescript(path.resolve("src", "intrig-provider-main.tsx"))
|
|
6
|
-
return ts`// Re-export all provider functionality from modular templates
|
|
7
|
-
export * from './interfaces';
|
|
8
|
-
export * from './reducer';
|
|
9
|
-
export * from './axios-config';
|
|
10
|
-
export * from './intrig-provider';
|
|
11
|
-
export * from './intrig-provider-stub';
|
|
12
|
-
export * from './status-trap';
|
|
13
|
-
export * from './provider-hooks';
|
|
14
|
-
|
|
15
|
-
// Main provider exports for backward compatibility
|
|
16
|
-
export { IntrigProvider } from './intrig-provider';
|
|
17
|
-
export { IntrigProviderStub } from './intrig-provider-stub';
|
|
18
|
-
export { StatusTrap } from './status-trap';
|
|
19
|
-
|
|
20
|
-
export {
|
|
21
|
-
useNetworkState,
|
|
22
|
-
useTransitionCall,
|
|
23
|
-
useCentralError,
|
|
24
|
-
useCentralPendingState,
|
|
25
|
-
} from './provider-hooks';
|
|
26
|
-
|
|
27
|
-
export {
|
|
28
|
-
requestReducer,
|
|
29
|
-
inferNetworkReason,
|
|
30
|
-
debounce,
|
|
31
|
-
} from './reducer';
|
|
32
|
-
|
|
33
|
-
export {
|
|
34
|
-
createAxiosInstance,
|
|
35
|
-
createAxiosInstances,
|
|
36
|
-
} from './axios-config';
|
|
37
|
-
|
|
38
|
-
export type {
|
|
39
|
-
DefaultConfigs,
|
|
40
|
-
IntrigProviderProps,
|
|
41
|
-
IntrigProviderStubProps,
|
|
42
|
-
StatusTrapProps,
|
|
43
|
-
NetworkStateProps,
|
|
44
|
-
StubType,
|
|
45
|
-
WithStubSupport,
|
|
46
|
-
} from './interfaces';
|
|
47
|
-
`
|
|
48
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import {typescript} from "@intrig/plugin-sdk";
|
|
2
|
-
import * as path from 'path'
|
|
3
|
-
|
|
4
|
-
export function providerReducerTemplate() {
|
|
5
|
-
const ts = typescript(path.resolve("src", "reducer.ts"))
|
|
6
|
-
return ts`import {
|
|
7
|
-
NetworkAction,
|
|
8
|
-
} from './network-state';
|
|
9
|
-
import { GlobalState } from './intrig-context';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Handles state updates for network requests based on the provided action.
|
|
13
|
-
*
|
|
14
|
-
* @param {GlobalState} state - The current state of the application.
|
|
15
|
-
* @param {NetworkAction<unknown>} action - The action containing source, operation, key, and state.
|
|
16
|
-
* @return {GlobalState} - The updated state after applying the action.
|
|
17
|
-
*/
|
|
18
|
-
export function requestReducer(
|
|
19
|
-
state: GlobalState,
|
|
20
|
-
action: NetworkAction<unknown>,
|
|
21
|
-
): GlobalState {
|
|
22
|
-
return {
|
|
23
|
-
...state,
|
|
24
|
-
[${"`${action.source}:${action.operation}:${action.key}`"}]: action.state,
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function inferNetworkReason(e: any): 'timeout' | 'dns' | 'offline' | 'aborted' | 'unknown' {
|
|
29
|
-
if (e?.code === 'ECONNABORTED') return 'timeout';
|
|
30
|
-
if (typeof navigator !== 'undefined' && navigator.onLine === false) return 'offline';
|
|
31
|
-
if (e?.name === 'AbortError') return 'aborted';
|
|
32
|
-
return 'unknown';
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function debounce<T extends (...args: any[]) => void>(func: T, delay: number) {
|
|
36
|
-
let timeoutId: any;
|
|
37
|
-
|
|
38
|
-
return (...args: Parameters<T>) => {
|
|
39
|
-
if (timeoutId) {
|
|
40
|
-
clearTimeout(timeoutId);
|
|
41
|
-
}
|
|
42
|
-
timeoutId = setTimeout(() => {
|
|
43
|
-
func(...args);
|
|
44
|
-
}, delay);
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export { inferNetworkReason, debounce };
|
|
49
|
-
`
|
|
50
|
-
}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { IntrigSourceConfig, typescript } from "@intrig/plugin-sdk";
|
|
2
|
-
import * as path from 'path';
|
|
3
|
-
|
|
4
|
-
export function reactStatusTrapTemplate(_apisToSync: IntrigSourceConfig[]) {
|
|
5
|
-
const ts = typescript(path.resolve('src', 'status-trap.tsx'));
|
|
6
|
-
return ts`import React, { PropsWithChildren, useCallback, useContext, useMemo, useState } from 'react';
|
|
7
|
-
import { isError, isPending, NetworkState } from './network-state';
|
|
8
|
-
import { Context } from './intrig-context';
|
|
9
|
-
import { StatusTrapProps } from './interfaces';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* StatusTrap component is used to track and manage network request states.
|
|
13
|
-
*/
|
|
14
|
-
export function StatusTrap({
|
|
15
|
-
children,
|
|
16
|
-
type,
|
|
17
|
-
propagate = true,
|
|
18
|
-
}: PropsWithChildren<StatusTrapProps>) {
|
|
19
|
-
const ctx = useContext(Context);
|
|
20
|
-
|
|
21
|
-
const [requests, setRequests] = useState<string[]>([]);
|
|
22
|
-
|
|
23
|
-
const shouldHandleEvent = useCallback(
|
|
24
|
-
(state: NetworkState) => {
|
|
25
|
-
switch (type) {
|
|
26
|
-
case 'error':
|
|
27
|
-
return isError(state);
|
|
28
|
-
case 'pending':
|
|
29
|
-
return isPending(state);
|
|
30
|
-
case 'pending + error':
|
|
31
|
-
return isPending(state) || isError(state);
|
|
32
|
-
default:
|
|
33
|
-
return false;
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
[type],
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
const dispatch = useCallback(
|
|
40
|
-
(event: any) => {
|
|
41
|
-
const composite = ${"`${event.source}:${event.operation}:${event.key}`"};
|
|
42
|
-
if (!event.handled) {
|
|
43
|
-
if (shouldHandleEvent(event.state)) {
|
|
44
|
-
setRequests((prev) => [...prev, composite]);
|
|
45
|
-
if (!propagate) {
|
|
46
|
-
ctx.dispatch({
|
|
47
|
-
...event,
|
|
48
|
-
handled: true,
|
|
49
|
-
});
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
} else {
|
|
53
|
-
setRequests((prev) => prev.filter((k) => k !== composite));
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
ctx.dispatch(event);
|
|
57
|
-
},
|
|
58
|
-
[ctx, propagate, shouldHandleEvent],
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
const filteredState = useMemo(() => {
|
|
62
|
-
return Object.fromEntries(
|
|
63
|
-
Object.entries(ctx.state).filter(([key]) => requests.includes(key)),
|
|
64
|
-
);
|
|
65
|
-
}, [ctx.state, requests]);
|
|
66
|
-
|
|
67
|
-
return (
|
|
68
|
-
<Context.Provider
|
|
69
|
-
value={{
|
|
70
|
-
...ctx,
|
|
71
|
-
dispatch,
|
|
72
|
-
filteredState,
|
|
73
|
-
}}
|
|
74
|
-
>
|
|
75
|
-
{children}
|
|
76
|
-
</Context.Provider>
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
`;
|
|
80
|
-
}
|