@intrig/next 0.0.7 → 0.0.8
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/.babelrc +12 -0
- package/package.json +2 -6
- package/project.json +15 -0
- package/rollup.config.cjs +31 -0
- package/src/extra.ts +268 -0
- package/src/index.ts +4 -0
- package/src/intrig-context.ts +72 -0
- package/src/intrig-layout.tsx +30 -0
- package/src/intrig-middleware.ts +55 -0
- package/src/intrig-provider.tsx +491 -0
- package/src/logger.ts +17 -0
- package/src/media-type-utils.ts +198 -0
- package/src/network-state.tsx +535 -0
- package/tsconfig.json +10 -0
- package/tsconfig.lib.json +34 -0
package/.babelrc
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intrig/next",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./index.esm.js",
|
|
6
6
|
"module": "./index.esm.js",
|
|
@@ -38,9 +38,5 @@
|
|
|
38
38
|
"import": "./index.esm.js",
|
|
39
39
|
"default": "./index.esm.js"
|
|
40
40
|
}
|
|
41
|
-
}
|
|
42
|
-
"files": [
|
|
43
|
-
".",
|
|
44
|
-
"!**/*.tsbuildinfo"
|
|
45
|
-
]
|
|
41
|
+
}
|
|
46
42
|
}
|
package/project.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@intrig/next",
|
|
3
|
+
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
|
4
|
+
"sourceRoot": "lib/next-client/src",
|
|
5
|
+
"projectType": "library",
|
|
6
|
+
"tags": [],
|
|
7
|
+
"// targets": "to see all targets run: nx show project @intrig/next --web",
|
|
8
|
+
"targets": {},
|
|
9
|
+
"nx-release-publish": {
|
|
10
|
+
"executor": "@nx/js:release-publish",
|
|
11
|
+
"options": {
|
|
12
|
+
"packageRoot": "dist/lib/next-client"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const { withNx } = require('@nx/rollup/with-nx');
|
|
2
|
+
const url = require('@rollup/plugin-url');
|
|
3
|
+
const svg = require('@svgr/rollup');
|
|
4
|
+
|
|
5
|
+
module.exports = withNx(
|
|
6
|
+
{
|
|
7
|
+
main: './src/index.ts',
|
|
8
|
+
outputPath: '../../dist/lib/next-client',
|
|
9
|
+
tsConfig: './tsconfig.lib.json',
|
|
10
|
+
compiler: 'babel',
|
|
11
|
+
external: ['react', 'react-dom', 'react/jsx-runtime'],
|
|
12
|
+
format: ['esm'],
|
|
13
|
+
assets: [
|
|
14
|
+
{ input: 'lib/next-client', output: '.', glob: 'README.md' },
|
|
15
|
+
{ input: 'lib/next-client', output: '.', glob: 'package.json' }
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
// Provide additional rollup configuration here. See: https://rollupjs.org/configuration-options
|
|
20
|
+
plugins: [
|
|
21
|
+
svg({
|
|
22
|
+
svgo: false,
|
|
23
|
+
titleProp: true,
|
|
24
|
+
ref: true,
|
|
25
|
+
}),
|
|
26
|
+
url({
|
|
27
|
+
limit: 10000, // 10kB
|
|
28
|
+
}),
|
|
29
|
+
],
|
|
30
|
+
},
|
|
31
|
+
);
|
package/src/extra.ts
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import {
|
|
3
|
+
BinaryFunctionHook,
|
|
4
|
+
BinaryHookOptions,
|
|
5
|
+
BinaryProduceHook,
|
|
6
|
+
ConstantHook,
|
|
7
|
+
error,
|
|
8
|
+
init,
|
|
9
|
+
IntrigHook,
|
|
10
|
+
IntrigHookOptions,
|
|
11
|
+
isError,
|
|
12
|
+
isSuccess,
|
|
13
|
+
isValidationError,
|
|
14
|
+
NetworkState,
|
|
15
|
+
pending,
|
|
16
|
+
success,
|
|
17
|
+
UnaryFunctionHook,
|
|
18
|
+
UnaryHookOptions,
|
|
19
|
+
UnaryProduceHook,
|
|
20
|
+
UnitHook,
|
|
21
|
+
UnitHookOptions,
|
|
22
|
+
} from './network-state';
|
|
23
|
+
import {
|
|
24
|
+
useCallback,
|
|
25
|
+
useEffect,
|
|
26
|
+
useId,
|
|
27
|
+
useMemo,
|
|
28
|
+
useRef,
|
|
29
|
+
useState,
|
|
30
|
+
} from 'react';
|
|
31
|
+
import { useIntrigContext } from './intrig-context';
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Converts a given hook into a promise-based function.
|
|
35
|
+
*
|
|
36
|
+
* @param {IntrigHook<P, B, T>} hook - The hook function to be converted.
|
|
37
|
+
* @param options
|
|
38
|
+
*
|
|
39
|
+
* @return {[(...params: Parameters<ReturnType<IntrigHook<P, B, T>>[1]>) => Promise<T>, () => void]}
|
|
40
|
+
* Returns a tuple containing a function that invokes the hook as a promise and a function to clear the state.
|
|
41
|
+
*/
|
|
42
|
+
export function useAsPromise<E>(
|
|
43
|
+
hook: UnitHook<E>,
|
|
44
|
+
options: UnitHookOptions,
|
|
45
|
+
): [() => Promise<never>, () => void];
|
|
46
|
+
export function useAsPromise<T, E>(
|
|
47
|
+
hook: ConstantHook<T, E>,
|
|
48
|
+
options: UnitHookOptions,
|
|
49
|
+
): [() => Promise<T>, () => void];
|
|
50
|
+
export function useAsPromise<P, E>(
|
|
51
|
+
hook: UnaryProduceHook<P, E>,
|
|
52
|
+
options?: UnaryHookOptions<P>,
|
|
53
|
+
): [(params: P) => Promise<never>, () => void];
|
|
54
|
+
export function useAsPromise<P, T, E>(
|
|
55
|
+
hook: UnaryFunctionHook<P, T, E>,
|
|
56
|
+
options?: UnaryHookOptions<P>,
|
|
57
|
+
): [(params: P) => Promise<T>, () => void];
|
|
58
|
+
export function useAsPromise<P, B, E>(
|
|
59
|
+
hook: BinaryProduceHook<P, B, E>,
|
|
60
|
+
options?: BinaryHookOptions<P, B>,
|
|
61
|
+
): [(body: B, params: P) => Promise<never>, () => void];
|
|
62
|
+
export function useAsPromise<P, B, T, E>(
|
|
63
|
+
hook: BinaryFunctionHook<P, B, T, E>,
|
|
64
|
+
options?: BinaryHookOptions<P, B>,
|
|
65
|
+
): [(body: B, params: P) => Promise<T>, () => void];
|
|
66
|
+
|
|
67
|
+
// **Implementation**
|
|
68
|
+
export function useAsPromise<P, B, T, E>(
|
|
69
|
+
hook: IntrigHook<P, B, T, E>,
|
|
70
|
+
options?: IntrigHookOptions<P, B>,
|
|
71
|
+
): [(...args: any[]) => Promise<T>, () => void] {
|
|
72
|
+
// <- Compatible return type
|
|
73
|
+
const resolveRef = useRef<(value: T) => void>(() => {
|
|
74
|
+
// intentionally kept empty
|
|
75
|
+
});
|
|
76
|
+
const rejectRef = useRef<(reason?: any) => void>(() => {
|
|
77
|
+
// intentionally kept empty
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const [state, dispatch, clear] = hook(options as any);
|
|
81
|
+
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
if (isSuccess(state)) {
|
|
84
|
+
resolveRef.current?.(state.data);
|
|
85
|
+
clear();
|
|
86
|
+
} else if (isError(state)) {
|
|
87
|
+
rejectRef.current?.(state.error);
|
|
88
|
+
clear();
|
|
89
|
+
}
|
|
90
|
+
}, [state]);
|
|
91
|
+
|
|
92
|
+
const promiseFn = useCallback(
|
|
93
|
+
(...args: any[]) => {
|
|
94
|
+
return new Promise<T>((resolve, reject) => {
|
|
95
|
+
resolveRef.current = resolve;
|
|
96
|
+
rejectRef.current = reject;
|
|
97
|
+
|
|
98
|
+
const dispatchState = (dispatch as any)(...args);
|
|
99
|
+
if (isValidationError(dispatchState)) {
|
|
100
|
+
reject(dispatchState.error);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
},
|
|
104
|
+
[dispatch],
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
return [promiseFn, clear];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* A custom hook that manages and returns the network state of a promise-based function,
|
|
112
|
+
* providing a way to execute the function and clear its state.
|
|
113
|
+
*
|
|
114
|
+
* @param fn The promise-based function whose network state is to be managed. It should be a function that returns a promise.
|
|
115
|
+
* @param key An optional identifier for the network state. Defaults to 'default'.
|
|
116
|
+
* @return A tuple containing the current network state, a function to execute the promise, and a function to clear the state.
|
|
117
|
+
*/
|
|
118
|
+
export function useAsNetworkState<T, F extends (...args: any) => Promise<T>>(
|
|
119
|
+
fn: F,
|
|
120
|
+
key = 'default',
|
|
121
|
+
): [NetworkState<T>, (...params: Parameters<F>) => void, () => void] {
|
|
122
|
+
const id = useId();
|
|
123
|
+
|
|
124
|
+
const context = useIntrigContext();
|
|
125
|
+
|
|
126
|
+
const networkState = useMemo(() => {
|
|
127
|
+
return context.state?.[`promiseState:${id}:${key}`] ?? init();
|
|
128
|
+
}, [context.state?.[`promiseState:${id}:${key}`]]);
|
|
129
|
+
|
|
130
|
+
const dispatch = useCallback(
|
|
131
|
+
(state: NetworkState<T>) => {
|
|
132
|
+
context.dispatch({ key, operation: id, source: 'promiseState', state });
|
|
133
|
+
},
|
|
134
|
+
[key, context.dispatch],
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
const execute = useCallback((...args: Parameters<F>) => {
|
|
138
|
+
dispatch(pending());
|
|
139
|
+
return fn(...args).then(
|
|
140
|
+
(data) => {
|
|
141
|
+
dispatch(success(data));
|
|
142
|
+
},
|
|
143
|
+
(e) => {
|
|
144
|
+
dispatch(error(e));
|
|
145
|
+
},
|
|
146
|
+
);
|
|
147
|
+
}, []);
|
|
148
|
+
|
|
149
|
+
const clear = useCallback(() => {
|
|
150
|
+
dispatch(init());
|
|
151
|
+
}, []);
|
|
152
|
+
|
|
153
|
+
return [networkState, execute, clear];
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* A custom hook that resolves the value from the provided hook's state and updates it whenever the state changes.
|
|
158
|
+
*
|
|
159
|
+
* @param {IntrigHook<P, B, T>} hook - The hook that provides the state to observe and resolve data from.
|
|
160
|
+
* @param options
|
|
161
|
+
* @return {T | undefined} The resolved value from the hook's state or undefined if the state is not successful.
|
|
162
|
+
*/
|
|
163
|
+
export function useResolvedValue<E>(
|
|
164
|
+
hook: UnitHook<E>,
|
|
165
|
+
options: UnitHookOptions,
|
|
166
|
+
): undefined;
|
|
167
|
+
|
|
168
|
+
export function useResolvedValue<T, E>(
|
|
169
|
+
hook: ConstantHook<T, E>,
|
|
170
|
+
options: UnitHookOptions,
|
|
171
|
+
): T | undefined;
|
|
172
|
+
|
|
173
|
+
export function useResolvedValue<P, E>(
|
|
174
|
+
hook: UnaryProduceHook<P, E>,
|
|
175
|
+
options: UnaryHookOptions<P>,
|
|
176
|
+
): undefined;
|
|
177
|
+
|
|
178
|
+
export function useResolvedValue<P, T, E>(
|
|
179
|
+
hook: UnaryFunctionHook<P, T, E>,
|
|
180
|
+
options: UnaryHookOptions<P>,
|
|
181
|
+
): T | undefined;
|
|
182
|
+
|
|
183
|
+
export function useResolvedValue<P, B, E>(
|
|
184
|
+
hook: BinaryProduceHook<P, B, E>,
|
|
185
|
+
options: BinaryHookOptions<P, B>,
|
|
186
|
+
): undefined;
|
|
187
|
+
|
|
188
|
+
export function useResolvedValue<P, B, T, E>(
|
|
189
|
+
hook: BinaryFunctionHook<P, B, T, E>,
|
|
190
|
+
options: BinaryHookOptions<P, B>,
|
|
191
|
+
): T | undefined;
|
|
192
|
+
|
|
193
|
+
// **Implementation**
|
|
194
|
+
export function useResolvedValue<P, B, T, E>(
|
|
195
|
+
hook: IntrigHook<P, B, T, E>,
|
|
196
|
+
options: IntrigHookOptions<P, B>,
|
|
197
|
+
): T | undefined {
|
|
198
|
+
const [value, setValue] = useState<T | undefined>();
|
|
199
|
+
|
|
200
|
+
const [state] = hook(options as any); // Ensure compatibility with different hook types
|
|
201
|
+
|
|
202
|
+
useEffect(() => {
|
|
203
|
+
if (isSuccess(state)) {
|
|
204
|
+
setValue(state.data);
|
|
205
|
+
} else {
|
|
206
|
+
setValue(undefined);
|
|
207
|
+
}
|
|
208
|
+
}, [state]);
|
|
209
|
+
|
|
210
|
+
return value;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* A custom hook that resolves and caches the value from a successful state provided by the given hook.
|
|
215
|
+
* The state is updated only when it is in a successful state.
|
|
216
|
+
*
|
|
217
|
+
* @param {IntrigHook<P, B, T>} hook - The hook that provides the state to observe and cache data from.
|
|
218
|
+
* @param options
|
|
219
|
+
* @return {T | undefined} The cached value from the hook's state or undefined if the state is not successful.
|
|
220
|
+
*/
|
|
221
|
+
export function useResolvedCachedValue<E>(
|
|
222
|
+
hook: UnitHook<E>,
|
|
223
|
+
options: UnitHookOptions,
|
|
224
|
+
): undefined;
|
|
225
|
+
|
|
226
|
+
export function useResolvedCachedValue<T, E>(
|
|
227
|
+
hook: ConstantHook<T, E>,
|
|
228
|
+
options: UnitHookOptions,
|
|
229
|
+
): T | undefined;
|
|
230
|
+
|
|
231
|
+
export function useResolvedCachedValue<P, E>(
|
|
232
|
+
hook: UnaryProduceHook<P, E>,
|
|
233
|
+
options: UnaryHookOptions<P>,
|
|
234
|
+
): undefined;
|
|
235
|
+
|
|
236
|
+
export function useResolvedCachedValue<P, T, E>(
|
|
237
|
+
hook: UnaryFunctionHook<P, T, E>,
|
|
238
|
+
options: UnaryHookOptions<P>,
|
|
239
|
+
): T | undefined;
|
|
240
|
+
|
|
241
|
+
export function useResolvedCachedValue<P, B, E>(
|
|
242
|
+
hook: BinaryProduceHook<P, B, E>,
|
|
243
|
+
options: BinaryHookOptions<P, B>,
|
|
244
|
+
): undefined;
|
|
245
|
+
|
|
246
|
+
export function useResolvedCachedValue<P, B, T, E>(
|
|
247
|
+
hook: BinaryFunctionHook<P, B, T, E>,
|
|
248
|
+
options: BinaryHookOptions<P, B>,
|
|
249
|
+
): T | undefined;
|
|
250
|
+
|
|
251
|
+
// **Implementation**
|
|
252
|
+
export function useResolvedCachedValue<P, B, T, E>(
|
|
253
|
+
hook: IntrigHook<P, B, T, E>,
|
|
254
|
+
options: IntrigHookOptions<P, B>,
|
|
255
|
+
): T | undefined {
|
|
256
|
+
const [cachedValue, setCachedValue] = useState<T | undefined>();
|
|
257
|
+
|
|
258
|
+
const [state] = hook(options as any); // Ensure compatibility with different hook types
|
|
259
|
+
|
|
260
|
+
useEffect(() => {
|
|
261
|
+
if (isSuccess(state)) {
|
|
262
|
+
setCachedValue(state.data);
|
|
263
|
+
}
|
|
264
|
+
// Do not clear cached value if state is unsuccessful
|
|
265
|
+
}, [state]);
|
|
266
|
+
|
|
267
|
+
return cachedValue;
|
|
268
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { NetworkAction, NetworkState } from './network-state';
|
|
3
|
+
import { AxiosProgressEvent, CreateAxiosDefaults } from 'axios';
|
|
4
|
+
import { ZodSchema } from 'zod';
|
|
5
|
+
import { createContext, useContext } from 'react';
|
|
6
|
+
|
|
7
|
+
export interface DefaultConfigs extends CreateAxiosDefaults {
|
|
8
|
+
debounceDelay?: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
type GlobalState = Record<string, NetworkState>;
|
|
12
|
+
|
|
13
|
+
interface RequestType<T = any> {
|
|
14
|
+
method: 'get' | 'post' | 'put' | 'delete';
|
|
15
|
+
url: string;
|
|
16
|
+
headers?: Record<string, string>;
|
|
17
|
+
params?: Record<string, any>;
|
|
18
|
+
data?: any; // This allows transformations, while retaining flexibility.
|
|
19
|
+
originalData?: T; // Keeps track of the original data type.
|
|
20
|
+
onUploadProgress?: (event: AxiosProgressEvent) => void;
|
|
21
|
+
onDownloadProgress?: (event: AxiosProgressEvent) => void;
|
|
22
|
+
signal?: AbortSignal;
|
|
23
|
+
key: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Defines the ContextType interface for managing global state, dispatching actions,
|
|
28
|
+
* and holding a collection of Axios instances.
|
|
29
|
+
*
|
|
30
|
+
* @interface ContextType
|
|
31
|
+
* @property {GlobalState} state - The global state of the application.
|
|
32
|
+
* @property {React.Dispatch<NetworkAction<unknown>>} dispatch - The dispatch function to send network actions.
|
|
33
|
+
* @property {Record<string, AxiosInstance>} axios - A record of Axios instances for making HTTP requests.
|
|
34
|
+
*/
|
|
35
|
+
export interface ContextType {
|
|
36
|
+
state: GlobalState;
|
|
37
|
+
filteredState: GlobalState;
|
|
38
|
+
dispatch: React.Dispatch<NetworkAction<unknown, unknown>>;
|
|
39
|
+
configs: DefaultConfigs;
|
|
40
|
+
execute: <T, E = unknown>(
|
|
41
|
+
request: RequestType,
|
|
42
|
+
dispatch: (state: NetworkState<T, E>) => void,
|
|
43
|
+
schema: ZodSchema<T> | undefined,
|
|
44
|
+
errorSchema: ZodSchema<E> | undefined,
|
|
45
|
+
) => Promise<void>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Context object created using `createContext` function. Provides a way to share state, dispatch functions,
|
|
50
|
+
* and axios instance across components without having to pass props down manually at every level.
|
|
51
|
+
*
|
|
52
|
+
* @type {ContextType}
|
|
53
|
+
*/
|
|
54
|
+
const Context = createContext<ContextType>({
|
|
55
|
+
state: {},
|
|
56
|
+
filteredState: {},
|
|
57
|
+
dispatch() {
|
|
58
|
+
// intentionally kept empty
|
|
59
|
+
},
|
|
60
|
+
configs: {},
|
|
61
|
+
async execute() {
|
|
62
|
+
// intentionally kept empty
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
export function useIntrigContext() {
|
|
67
|
+
return useContext(Context);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export {Context};
|
|
71
|
+
export type { GlobalState, RequestType };
|
|
72
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
|
|
3
|
+
import { headers } from 'next/headers';
|
|
4
|
+
import { IntrigProvider } from './intrig-provider';
|
|
5
|
+
import { DefaultConfigs } from './intrig-context';
|
|
6
|
+
|
|
7
|
+
export async function IntrigLayout({
|
|
8
|
+
children,
|
|
9
|
+
configs,
|
|
10
|
+
}: {
|
|
11
|
+
children: React.ReactNode;
|
|
12
|
+
configs?: DefaultConfigs;
|
|
13
|
+
}) {
|
|
14
|
+
const headersData = await headers();
|
|
15
|
+
const hydratedResponsesStr = headersData.get('INTRIG_HYDRATED');
|
|
16
|
+
const hydratedResponses = hydratedResponsesStr
|
|
17
|
+
? JSON.parse(hydratedResponsesStr)
|
|
18
|
+
: {};
|
|
19
|
+
headersData.delete('INTRIG_HYDRATED');
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<>
|
|
23
|
+
<IntrigProvider configs={configs} initState={hydratedResponses}>
|
|
24
|
+
{children}
|
|
25
|
+
</IntrigProvider>
|
|
26
|
+
</>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export default IntrigLayout;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import axios, {AxiosInstance} from 'axios';
|
|
2
|
+
import {headers} from 'next/headers';
|
|
3
|
+
|
|
4
|
+
interface RequestContext {
|
|
5
|
+
headers?: Record<string, string>;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const CONTEXT = new WeakMap<Headers, RequestContext>();
|
|
9
|
+
|
|
10
|
+
export async function addToHeaders(newHeaders: Record<string, string>) {
|
|
11
|
+
const _headers = await headers();
|
|
12
|
+
|
|
13
|
+
const ctx = CONTEXT.get(_headers) ?? {};
|
|
14
|
+
CONTEXT.set(_headers, {
|
|
15
|
+
...ctx,
|
|
16
|
+
headers: {
|
|
17
|
+
...ctx.headers,
|
|
18
|
+
...newHeaders
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export async function getHeaders() {
|
|
24
|
+
const _headers = await headers();
|
|
25
|
+
const ctx = CONTEXT.get(_headers) ?? {};
|
|
26
|
+
return ctx.headers;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const clients = new Map<string, AxiosInstance>();
|
|
30
|
+
|
|
31
|
+
export async function getAxiosInstance(key: string) {
|
|
32
|
+
if (clients.has(key)) {
|
|
33
|
+
return clients.get(key)!;
|
|
34
|
+
}
|
|
35
|
+
const baseURL = process.env[`${key.toUpperCase()}_API_URL`];
|
|
36
|
+
if (!baseURL) {
|
|
37
|
+
throw new Error(
|
|
38
|
+
`Environment variable ${key.toUpperCase()}_API_URL is not defined.`,
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const axiosInstance = axios.create({
|
|
43
|
+
baseURL
|
|
44
|
+
});
|
|
45
|
+
clients.set(key, axiosInstance);
|
|
46
|
+
return axiosInstance;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export async function addResponseToHydrate(key: string, responseData: any) {
|
|
50
|
+
const _headers = await headers();
|
|
51
|
+
const intrigHydrated = _headers.get('INTRIG_HYDRATED');
|
|
52
|
+
const ob = intrigHydrated ? JSON.parse(intrigHydrated) : {};
|
|
53
|
+
ob[key] = responseData;
|
|
54
|
+
_headers.set('INTRIG_HYDRATED', JSON.stringify(ob));
|
|
55
|
+
}
|