@intrig/react 0.0.6 → 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 ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "presets": [
3
+ [
4
+ "@nx/react/babel",
5
+ {
6
+ "runtime": "automatic",
7
+ "useBuiltIns": "usage"
8
+ }
9
+ ]
10
+ ],
11
+ "plugins": []
12
+ }
package/README.md CHANGED
@@ -1,7 +1,42 @@
1
1
  # @intrig/react
2
2
 
3
- This library was generated with [Nx](https://nx.dev).
3
+ This library serves as the placeholder for Intrig generated React content. It provides the necessary infrastructure and utilities for integrating with React applications.
4
4
 
5
- ## Running unit tests
5
+ ## Overview
6
6
 
7
- Run `nx test @intrig/react` to execute the unit tests via [Jest](https://jestjs.io).
7
+ @intrig/react is designed to work seamlessly with the Intrig Core ecosystem, providing specialized support for React applications. When you generate code using Intrig with the React generator, this library provides the foundation for that generated code.
8
+
9
+ ## Features
10
+
11
+ - **React Integration**: Specialized utilities for React applications
12
+ - **Custom Hooks**: React hooks for API integration
13
+ - **State Management Helpers**: Utilities for managing API state in React
14
+ - **Type Safety**: Full TypeScript support for all components
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install @intrig/react
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ The library is primarily used as a dependency for Intrig generated code. When you generate code using Intrig with the React generator, it will automatically use this library.
25
+
26
+ ```typescript
27
+ // Example of importing from the library
28
+ import { createReactClient } from '@intrig/react';
29
+
30
+ // Usage in your React application
31
+ const client = createReactClient({
32
+ // Configuration options
33
+ });
34
+ ```
35
+
36
+ ## Documentation
37
+
38
+ For more detailed documentation, please refer to the [Intrig Core documentation](https://docs.intrig.io).
39
+
40
+ ## License
41
+
42
+ This project is licensed under the MIT License - see the LICENSE file for details.
@@ -0,0 +1,12 @@
1
+ import nx from '@nx/eslint-plugin';
2
+ import baseConfig from '../../eslint.base.config.mjs';
3
+
4
+ export default [
5
+ ...baseConfig,
6
+ ...nx.configs['flat/react'],
7
+ {
8
+ files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
9
+ // Override or add rules here
10
+ rules: {},
11
+ },
12
+ ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intrig/react",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "type": "module",
5
5
  "main": "./index.esm.js",
6
6
  "module": "./index.esm.js",
@@ -39,9 +39,5 @@
39
39
  "import": "./index.esm.js",
40
40
  "default": "./index.esm.js"
41
41
  }
42
- },
43
- "files": [
44
- ".",
45
- "!**/*.tsbuildinfo"
46
- ]
42
+ }
47
43
  }
package/project.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "@intrig/react",
3
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
4
+ "sourceRoot": "lib/react-client/src",
5
+ "projectType": "library",
6
+ "tags": [],
7
+ "// targets": "to see all targets run: nx show project @intrig/react --web",
8
+ "targets": {},
9
+ "nx-release-publish": {
10
+ "executor": "@nx/js:release-publish",
11
+ "options": {
12
+ "packageRoot": "dist/lib/react-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/react-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/react-client', output: '.', glob: 'README.md' },
15
+ { input: 'lib/react-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,267 @@
1
+ import {
2
+ BinaryFunctionHook,
3
+ BinaryHookOptions,
4
+ BinaryProduceHook,
5
+ ConstantHook,
6
+ error,
7
+ init,
8
+ IntrigHook,
9
+ IntrigHookOptions,
10
+ isError,
11
+ isSuccess,
12
+ isValidationError,
13
+ NetworkState,
14
+ pending,
15
+ success,
16
+ UnaryFunctionHook,
17
+ UnaryHookOptions,
18
+ UnaryProduceHook,
19
+ UnitHook,
20
+ UnitHookOptions,
21
+ } from '@intrig/react/network-state';
22
+ import {
23
+ useCallback,
24
+ useEffect,
25
+ useId,
26
+ useMemo,
27
+ useRef,
28
+ useState,
29
+ } from 'react';
30
+ import { useIntrigContext } from '@intrig/react/intrig-context';
31
+
32
+ /**
33
+ * Converts a given hook into a promise-based function.
34
+ *
35
+ * @param {IntrigHook<P, B, T>} hook - The hook function to be converted.
36
+ * @param {string} [key='default'] - An optional key to uniquely identify the hook instance.
37
+ *
38
+ * @return {[(...params: Parameters<ReturnType<IntrigHook<P, B, T>>[1]>) => Promise<T>, () => void]}
39
+ * Returns a tuple containing a function that invokes the hook as a promise and a function to clear the state.
40
+ */
41
+ export function useAsPromise<E>(
42
+ hook: UnitHook<E>,
43
+ options: UnitHookOptions,
44
+ ): [() => Promise<never>, () => void];
45
+ export function useAsPromise<T, E>(
46
+ hook: ConstantHook<T, E>,
47
+ options: UnitHookOptions,
48
+ ): [() => Promise<T>, () => void];
49
+ export function useAsPromise<P, E>(
50
+ hook: UnaryProduceHook<P, E>,
51
+ options?: UnaryHookOptions<P>,
52
+ ): [(params: P) => Promise<never>, () => void];
53
+ export function useAsPromise<P, T, E>(
54
+ hook: UnaryFunctionHook<P, T, E>,
55
+ options?: UnaryHookOptions<P>,
56
+ ): [(params: P) => Promise<T>, () => void];
57
+ export function useAsPromise<P, B, E>(
58
+ hook: BinaryProduceHook<P, B, E>,
59
+ options?: BinaryHookOptions<P, B>,
60
+ ): [(body: B, params: P) => Promise<never>, () => void];
61
+ export function useAsPromise<P, B, T, E>(
62
+ hook: BinaryFunctionHook<P, B, T, E>,
63
+ options?: BinaryHookOptions<P, B>,
64
+ ): [(body: B, params: P) => Promise<T>, () => void];
65
+
66
+ // **Implementation**
67
+ export function useAsPromise<P, B, T, E>(
68
+ hook: IntrigHook<P, B, T, E>,
69
+ options?: IntrigHookOptions<P, B>,
70
+ ): [(...args: any[]) => Promise<T>, () => void] {
71
+ // <- Compatible return type
72
+ const resolveRef = useRef<(value: T) => void>(() => {
73
+ // intentionally kept empty
74
+ });
75
+ const rejectRef = useRef<(reason?: any) => void>(() => {
76
+ // intentionally kept empty
77
+ });
78
+
79
+ const [state, dispatch, clear] = hook(options as any);
80
+
81
+ useEffect(() => {
82
+ if (isSuccess(state)) {
83
+ resolveRef.current?.(state.data);
84
+ clear();
85
+ } else if (isError(state)) {
86
+ rejectRef.current?.(state.error);
87
+ clear();
88
+ }
89
+ }, [state]);
90
+
91
+ const promiseFn = useCallback(
92
+ (...args: Parameters<ReturnType<IntrigHook<P, B, T>>[1]>) => {
93
+ return new Promise<T>((resolve, reject) => {
94
+ resolveRef.current = resolve;
95
+ rejectRef.current = reject;
96
+
97
+ const dispatchState = (dispatch as any)(...args);
98
+ if (isValidationError(dispatchState)) {
99
+ reject(dispatchState.error);
100
+ }
101
+ });
102
+ },
103
+ [dispatch],
104
+ );
105
+
106
+ return [promiseFn, clear];
107
+ }
108
+
109
+ /**
110
+ * A custom hook that manages and returns the network state of a promise-based function,
111
+ * providing a way to execute the function and clear its state.
112
+ *
113
+ * @param fn The promise-based function whose network state is to be managed. It should be a function that returns a promise.
114
+ * @param key An optional identifier for the network state. Defaults to 'default'.
115
+ * @return A tuple containing the current network state, a function to execute the promise, and a function to clear the state.
116
+ */
117
+ export function useAsNetworkState<T, F extends (...args: any) => Promise<T>>(
118
+ fn: F,
119
+ key = 'default',
120
+ ): [NetworkState<T>, (...params: Parameters<F>) => void, () => void] {
121
+ const id = useId();
122
+
123
+ const context = useIntrigContext();
124
+
125
+ const networkState = useMemo(() => {
126
+ return context.state?.[`promiseState:${id}:${key}}`] ?? init();
127
+ }, [context.state?.[`promiseState:${id}:${key}}`]]);
128
+
129
+ const dispatch = useCallback(
130
+ (state: NetworkState<T>) => {
131
+ context.dispatch({ key, operation: id, source: 'promiseState', state });
132
+ },
133
+ [key, context.dispatch],
134
+ );
135
+
136
+ const execute = useCallback((...args: Parameters<F>) => {
137
+ dispatch(pending());
138
+ return fn(...args).then(
139
+ (data) => {
140
+ dispatch(success(data));
141
+ },
142
+ (e) => {
143
+ dispatch(error(e));
144
+ },
145
+ );
146
+ }, []);
147
+
148
+ const clear = useCallback(() => {
149
+ dispatch(init());
150
+ }, []);
151
+
152
+ return [networkState, execute, clear];
153
+ }
154
+
155
+ /**
156
+ * A custom hook that resolves the value from the provided hook's state and updates it whenever the state changes.
157
+ *
158
+ * @param {IntrigHook<P, B, T>} hook - The hook that provides the state to observe and resolve data from.
159
+ * @param options
160
+ * @return {T | undefined} The resolved value from the hook's state or undefined if the state is not successful.
161
+ */
162
+ export function useResolvedValue<E>(
163
+ hook: UnitHook<E>,
164
+ options: UnitHookOptions,
165
+ ): undefined;
166
+
167
+ export function useResolvedValue<T, E>(
168
+ hook: ConstantHook<T, E>,
169
+ options: UnitHookOptions,
170
+ ): T | undefined;
171
+
172
+ export function useResolvedValue<P, E>(
173
+ hook: UnaryProduceHook<P, E>,
174
+ options: UnaryHookOptions<P>,
175
+ ): undefined;
176
+
177
+ export function useResolvedValue<P, T, E>(
178
+ hook: UnaryFunctionHook<P, T, E>,
179
+ options: UnaryHookOptions<P>,
180
+ ): T | undefined;
181
+
182
+ export function useResolvedValue<P, B, E>(
183
+ hook: BinaryProduceHook<P, B, E>,
184
+ options: BinaryHookOptions<P, B>,
185
+ ): undefined;
186
+
187
+ export function useResolvedValue<P, B, T, E>(
188
+ hook: BinaryFunctionHook<P, B, T, E>,
189
+ options: BinaryHookOptions<P, B>,
190
+ ): T | undefined;
191
+
192
+ // **Implementation**
193
+ export function useResolvedValue<P, B, T, E>(
194
+ hook: IntrigHook<P, B, T, E>,
195
+ options: IntrigHookOptions<P, B>,
196
+ ): T | undefined {
197
+ const [value, setValue] = useState<T | undefined>();
198
+
199
+ const [state] = hook(options as any); // Ensure compatibility with different hook types
200
+
201
+ useEffect(() => {
202
+ if (isSuccess(state)) {
203
+ setValue(state.data);
204
+ } else {
205
+ setValue(undefined);
206
+ }
207
+ }, [state]);
208
+
209
+ return value;
210
+ }
211
+
212
+ /**
213
+ * A custom hook that resolves and caches the value from a successful state provided by the given hook.
214
+ * The state is updated only when it is in a successful state.
215
+ *
216
+ * @param {IntrigHook<P, B, T>} hook - The hook that provides the state to observe and cache data from.
217
+ * @param options
218
+ * @return {T | undefined} The cached value from the hook's state or undefined if the state is not successful.
219
+ */
220
+ export function useResolvedCachedValue<E>(
221
+ hook: UnitHook<E>,
222
+ options: UnitHookOptions,
223
+ ): undefined;
224
+
225
+ export function useResolvedCachedValue<T, E>(
226
+ hook: ConstantHook<T, E>,
227
+ options: UnitHookOptions,
228
+ ): T | undefined;
229
+
230
+ export function useResolvedCachedValue<P, E>(
231
+ hook: UnaryProduceHook<P, E>,
232
+ options: UnaryHookOptions<P>,
233
+ ): undefined;
234
+
235
+ export function useResolvedCachedValue<P, T, E>(
236
+ hook: UnaryFunctionHook<P, T, E>,
237
+ options: UnaryHookOptions<P>,
238
+ ): T | undefined;
239
+
240
+ export function useResolvedCachedValue<P, B, E>(
241
+ hook: BinaryProduceHook<P, B, E>,
242
+ options: BinaryHookOptions<P, B>,
243
+ ): undefined;
244
+
245
+ export function useResolvedCachedValue<P, B, T, E>(
246
+ hook: BinaryFunctionHook<P, B, T, E>,
247
+ options: BinaryHookOptions<P, B>,
248
+ ): T | undefined;
249
+
250
+ // **Implementation**
251
+ export function useResolvedCachedValue<P, B, T, E>(
252
+ hook: IntrigHook<P, B, T, E>,
253
+ options: IntrigHookOptions<P, B>,
254
+ ): T | undefined {
255
+ const [cachedValue, setCachedValue] = useState<T | undefined>();
256
+
257
+ const [state] = hook(options as any); // Ensure compatibility with different hook types
258
+
259
+ useEffect(() => {
260
+ if (isSuccess(state)) {
261
+ setCachedValue(state.data);
262
+ }
263
+ // Do not clear cached value if state is unsuccessful
264
+ }, [state]);
265
+
266
+ return cachedValue;
267
+ }
package/src/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ export * from './intrig-provider';
2
+ export * from './network-state';
3
+ export * from './extra';
4
+ export * from './media-type-utils';
@@ -0,0 +1,61 @@
1
+ import { NetworkAction, NetworkState } from '@intrig/react/network-state';
2
+ import { AxiosRequestConfig } from 'axios';
3
+ import { ZodSchema } from 'zod';
4
+ import { createContext, useContext } from 'react';
5
+ import { DefaultConfigs } from '@intrig/react/intrig-provider';
6
+
7
+ type GlobalState = Record<string, NetworkState>;
8
+
9
+ interface RequestType<T = any> extends AxiosRequestConfig {
10
+ originalData?: T; // Keeps track of the original data type.
11
+ key: string;
12
+ source: string;
13
+ }
14
+
15
+ /**
16
+ * Defines the ContextType interface for managing global state, dispatching actions,
17
+ * and holding a collection of Axios instances.
18
+ *
19
+ * @interface ContextType
20
+ * @property {GlobalState} state - The global state of the application.
21
+ * @property {React.Dispatch<NetworkAction<unknown>>} dispatch - The dispatch function to send network actions.
22
+ * @property {Record<string, AxiosInstance>} axios - A record of Axios instances for making HTTP requests.
23
+ */
24
+ export interface ContextType {
25
+ state: GlobalState;
26
+ filteredState: GlobalState;
27
+ dispatch: React.Dispatch<NetworkAction<unknown, unknown>>;
28
+ configs: DefaultConfigs;
29
+ execute: <T>(
30
+ request: RequestType,
31
+ dispatch: (state: NetworkState<T>) => void,
32
+ schema: ZodSchema<T> | undefined,
33
+ errorSchema: ZodSchema<T> | undefined,
34
+ ) => Promise<void>;
35
+ }
36
+
37
+ /**
38
+ * Context object created using `createContext` function. Provides a way to share state, dispatch functions,
39
+ * and axios instance across components without having to pass props down manually at every level.
40
+ *
41
+ * @type {ContextType}
42
+ */
43
+ const Context = createContext<ContextType>({
44
+ state: {},
45
+ filteredState: {},
46
+ dispatch() {
47
+ // intentionally kept empty
48
+ },
49
+ configs: {},
50
+ async execute() {
51
+ // intentionally kept empty
52
+ },
53
+ });
54
+
55
+ export function useIntrigContext() {
56
+ return useContext(Context);
57
+ }
58
+
59
+ export {Context};
60
+ export type { GlobalState, RequestType };
61
+