@orsetra/shared-ui 1.0.24 → 1.0.25
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/lib/http-client.ts +44 -2
- package/package.json +2 -2
package/lib/http-client.ts
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
export type AuthHeadersProvider = () => Promise<Record<string, string>> | Record<string, string>;
|
|
4
4
|
|
|
5
|
+
export class ApiError extends Error {
|
|
6
|
+
status: number;
|
|
7
|
+
code?: number;
|
|
8
|
+
details?: unknown;
|
|
9
|
+
raw?: unknown;
|
|
10
|
+
|
|
11
|
+
constructor(message: string, params: { status: number; code?: number; details?: unknown; raw?: unknown }) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.name = 'ApiError';
|
|
14
|
+
this.status = params.status;
|
|
15
|
+
this.code = params.code;
|
|
16
|
+
this.details = params.details;
|
|
17
|
+
this.raw = params.raw;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
5
21
|
class HttpClient {
|
|
6
22
|
private baseUrl: string;
|
|
7
23
|
private authHeadersProvider?: AuthHeadersProvider;
|
|
@@ -58,8 +74,9 @@ class HttpClient {
|
|
|
58
74
|
if (!response.ok) {
|
|
59
75
|
// Try to extract error message from API response
|
|
60
76
|
let errorMessage = `Request failed: ${response.status}`;
|
|
77
|
+
let errorBody: any = undefined;
|
|
61
78
|
try {
|
|
62
|
-
|
|
79
|
+
errorBody = await response.json();
|
|
63
80
|
// Zitadel API returns { code, message, details } on error
|
|
64
81
|
if (errorBody?.message) {
|
|
65
82
|
errorMessage = errorBody.message;
|
|
@@ -69,7 +86,32 @@ class HttpClient {
|
|
|
69
86
|
} catch {
|
|
70
87
|
// If we can't parse JSON, use the default message
|
|
71
88
|
}
|
|
72
|
-
|
|
89
|
+
|
|
90
|
+
const apiError = new ApiError(errorMessage, {
|
|
91
|
+
status: response.status,
|
|
92
|
+
code: typeof errorBody?.code === 'number' ? errorBody.code : undefined,
|
|
93
|
+
details: errorBody?.details,
|
|
94
|
+
raw: errorBody,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// Zitadel step-up requirement
|
|
98
|
+
const isMfaRequired =
|
|
99
|
+
apiError.code === 7 ||
|
|
100
|
+
(typeof errorMessage === 'string' && errorMessage.toLowerCase().includes('mfa required'));
|
|
101
|
+
|
|
102
|
+
if (isMfaRequired && typeof window !== 'undefined') {
|
|
103
|
+
try {
|
|
104
|
+
window.dispatchEvent(
|
|
105
|
+
new CustomEvent('zitadel:mfa-required', {
|
|
106
|
+
detail: { url, status: apiError.status, code: apiError.code, error: apiError.raw },
|
|
107
|
+
})
|
|
108
|
+
);
|
|
109
|
+
} catch {
|
|
110
|
+
// ignore event dispatch issues
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
throw apiError;
|
|
73
115
|
}
|
|
74
116
|
|
|
75
117
|
if (response.status === 204) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orsetra/shared-ui",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.25",
|
|
4
4
|
"description": "Shared UI components for Orsetra platform",
|
|
5
5
|
"main": "./index.ts",
|
|
6
6
|
"types": "./index.ts",
|
|
@@ -92,4 +92,4 @@
|
|
|
92
92
|
"next": "^16.0.7",
|
|
93
93
|
"typescript": "^5"
|
|
94
94
|
}
|
|
95
|
-
}
|
|
95
|
+
}
|