@next-feature/client 0.1.0-beta → 0.1.1
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 -12
- package/README.md +7 -518
- package/eslint.config.mjs +12 -12
- package/{jest.config.ts → jest.config.cts} +10 -10
- package/package.json +6 -4
- package/project.json +32 -32
- package/src/components/api-error-boundary.tsx +58 -58
- package/src/hooks/use-api-error.tsx +39 -39
- package/src/index.ts +30 -6
- package/src/lib/client.ts +431 -431
- package/src/lib/error.ts +169 -166
- package/src/lib/types/index.ts +13 -13
- package/src/lib/utils/error.ts +136 -136
- package/src/lib/utils/helper.ts +20 -20
- package/tsconfig.json +20 -20
- package/tsconfig.lib.json +29 -28
- package/tsconfig.spec.json +23 -22
- package/vite.config.ts +51 -48
|
@@ -1,58 +1,58 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import React, { Component, ErrorInfo, ReactNode } from 'react';
|
|
4
|
-
import { ApiError } from '../lib/error';
|
|
5
|
-
import { getErrorMessage } from '../lib/utils/error';
|
|
6
|
-
|
|
7
|
-
interface Props {
|
|
8
|
-
children: ReactNode;
|
|
9
|
-
fallback?: (error: ApiError) => ReactNode;
|
|
10
|
-
onError?: (error: Error, errorInfo: ErrorInfo) => void;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
interface State {
|
|
14
|
-
hasError: boolean;
|
|
15
|
-
error: Error | null;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export class ApiErrorBoundary extends Component<Props, State> {
|
|
19
|
-
constructor(props: Props) {
|
|
20
|
-
super(props);
|
|
21
|
-
this.state = { hasError: false, error: null };
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
static getDerivedStateFromError(error: Error): State {
|
|
25
|
-
return { hasError: true, error };
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
|
29
|
-
console.error('ApiErrorBoundary caught error:', error, errorInfo);
|
|
30
|
-
|
|
31
|
-
if (this.props.onError) {
|
|
32
|
-
this.props.onError(error, errorInfo);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
render() {
|
|
37
|
-
if (this.state.hasError && this.state.error) {
|
|
38
|
-
if (this.state.error instanceof ApiError && this.props.fallback) {
|
|
39
|
-
return this.props.fallback(this.state.error);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Default error UI
|
|
43
|
-
return (
|
|
44
|
-
<div className="error-container">
|
|
45
|
-
<h2>Something went wrong</h2>
|
|
46
|
-
<p>{getErrorMessage(this.state.error)}</p>
|
|
47
|
-
<button
|
|
48
|
-
onClick={() => this.setState({ hasError: false, error: null })}
|
|
49
|
-
>
|
|
50
|
-
Try again
|
|
51
|
-
</button>
|
|
52
|
-
</div>
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return this.props.children;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import React, { Component, ErrorInfo, ReactNode } from 'react';
|
|
4
|
+
import { ApiError } from '../lib/error';
|
|
5
|
+
import { getErrorMessage } from '../lib/utils/error';
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
children: ReactNode;
|
|
9
|
+
fallback?: (error: ApiError) => ReactNode;
|
|
10
|
+
onError?: (error: Error, errorInfo: ErrorInfo) => void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface State {
|
|
14
|
+
hasError: boolean;
|
|
15
|
+
error: Error | null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class ApiErrorBoundary extends Component<Props, State> {
|
|
19
|
+
constructor(props: Props) {
|
|
20
|
+
super(props);
|
|
21
|
+
this.state = { hasError: false, error: null };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static getDerivedStateFromError(error: Error): State {
|
|
25
|
+
return { hasError: true, error };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
|
29
|
+
console.error('ApiErrorBoundary caught error:', error, errorInfo);
|
|
30
|
+
|
|
31
|
+
if (this.props.onError) {
|
|
32
|
+
this.props.onError(error, errorInfo);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
render() {
|
|
37
|
+
if (this.state.hasError && this.state.error) {
|
|
38
|
+
if (this.state.error instanceof ApiError && this.props.fallback) {
|
|
39
|
+
return this.props.fallback(this.state.error);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Default error UI
|
|
43
|
+
return (
|
|
44
|
+
<div className="error-container">
|
|
45
|
+
<h2>Something went wrong</h2>
|
|
46
|
+
<p>{getErrorMessage(this.state.error)}</p>
|
|
47
|
+
<button
|
|
48
|
+
onClick={() => this.setState({ hasError: false, error: null })}
|
|
49
|
+
>
|
|
50
|
+
Try again
|
|
51
|
+
</button>
|
|
52
|
+
</div>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return this.props.children;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { useState, useCallback } from 'react';
|
|
4
|
-
import { ApiError } from '../lib/error';
|
|
5
|
-
import { getErrorMessage } from '../lib/utils/error';
|
|
6
|
-
|
|
7
|
-
interface UseApiErrorResult {
|
|
8
|
-
error: ApiError | null;
|
|
9
|
-
setError: (error: ApiError | null) => void;
|
|
10
|
-
clearError: () => void;
|
|
11
|
-
handleError: (error: unknown) => void;
|
|
12
|
-
errorMessage: string | null;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function useApiError(): UseApiErrorResult {
|
|
16
|
-
const [error, setError] = useState<ApiError | null>(null);
|
|
17
|
-
|
|
18
|
-
const clearError = useCallback(() => {
|
|
19
|
-
setError(null);
|
|
20
|
-
}, []);
|
|
21
|
-
|
|
22
|
-
const handleError = useCallback((err: unknown) => {
|
|
23
|
-
if (err instanceof ApiError) {
|
|
24
|
-
setError(err);
|
|
25
|
-
} else {
|
|
26
|
-
console.error('Non-API error:', err);
|
|
27
|
-
}
|
|
28
|
-
}, []);
|
|
29
|
-
|
|
30
|
-
const errorMessage = error ? getErrorMessage(error) : null;
|
|
31
|
-
|
|
32
|
-
return {
|
|
33
|
-
error,
|
|
34
|
-
setError,
|
|
35
|
-
clearError,
|
|
36
|
-
handleError,
|
|
37
|
-
errorMessage,
|
|
38
|
-
};
|
|
39
|
-
}
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useState, useCallback } from 'react';
|
|
4
|
+
import { ApiError } from '../lib/error';
|
|
5
|
+
import { getErrorMessage } from '../lib/utils/error';
|
|
6
|
+
|
|
7
|
+
interface UseApiErrorResult {
|
|
8
|
+
error: ApiError | null;
|
|
9
|
+
setError: (error: ApiError | null) => void;
|
|
10
|
+
clearError: () => void;
|
|
11
|
+
handleError: (error: unknown) => void;
|
|
12
|
+
errorMessage: string | null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function useApiError(): UseApiErrorResult {
|
|
16
|
+
const [error, setError] = useState<ApiError | null>(null);
|
|
17
|
+
|
|
18
|
+
const clearError = useCallback(() => {
|
|
19
|
+
setError(null);
|
|
20
|
+
}, []);
|
|
21
|
+
|
|
22
|
+
const handleError = useCallback((err: unknown) => {
|
|
23
|
+
if (err instanceof ApiError) {
|
|
24
|
+
setError(err);
|
|
25
|
+
} else {
|
|
26
|
+
console.error('Non-API error:', err);
|
|
27
|
+
}
|
|
28
|
+
}, []);
|
|
29
|
+
|
|
30
|
+
const errorMessage = error ? getErrorMessage(error) : null;
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
error,
|
|
34
|
+
setError,
|
|
35
|
+
clearError,
|
|
36
|
+
handleError,
|
|
37
|
+
errorMessage,
|
|
38
|
+
};
|
|
39
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Client package exports
|
|
3
|
+
*
|
|
4
|
+
* This client package provides all necessary API client utilities.
|
|
5
|
+
* All implementations are self-contained and do not depend on external packages.
|
|
6
|
+
*
|
|
7
|
+
* CUSTOMIZATION:
|
|
8
|
+
* You can easily customize any part of the implementation:
|
|
9
|
+
*
|
|
10
|
+
* 1. For custom ApiClient/ApiError logic with interceptors:
|
|
11
|
+
* - Run: npx nx g next-feature:client-config --projectName=<your-project>
|
|
12
|
+
* - This creates lib/client/config.ts for centralized setup
|
|
13
|
+
*
|
|
14
|
+
* 2. For full custom implementations:
|
|
15
|
+
* - Edit src/lib/client.ts to customize ApiClient behavior
|
|
16
|
+
* - Edit src/lib/error.ts to customize error handling
|
|
17
|
+
* - The changes are immediately reflected in all imports
|
|
18
|
+
*
|
|
19
|
+
* 3. For project-specific hooks/components:
|
|
20
|
+
* - Import directly: import { useApiError } from './hooks/use-api-error'
|
|
21
|
+
* - Customize src/hooks/use-api-error.tsx
|
|
22
|
+
* - Customize src/components/api-error-boundary.tsx
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
// Core API utilities
|
|
26
|
+
export { ApiClient, type ApiClientConfig } from './lib/client';
|
|
27
|
+
export { ApiError, ApiErrorBuilder, type ProblemDetail } from './lib/error';
|
|
28
|
+
export * from './lib/types';
|
|
29
|
+
export * from './lib/utils/error';
|
|
30
|
+
export * from './lib/utils/helper';
|