@elogroup-sereduc/ser-front-core-client 1.1.1 → 2.0.0

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.
Files changed (47) hide show
  1. package/OAUTH_MIGRATION.md +86 -0
  2. package/README.md +143 -388
  3. package/dist/{axios.d.ts → api-client.d.ts} +3 -3
  4. package/dist/api-client.d.ts.map +1 -0
  5. package/dist/{axios.js → api-client.js} +11 -11
  6. package/dist/api-client.js.map +1 -0
  7. package/dist/auth/bootstrap.d.ts +5 -0
  8. package/dist/auth/bootstrap.d.ts.map +1 -0
  9. package/dist/auth/bootstrap.js +28 -0
  10. package/dist/auth/bootstrap.js.map +1 -0
  11. package/dist/auth/http-client.d.ts +3 -0
  12. package/dist/auth/http-client.d.ts.map +1 -0
  13. package/dist/auth/http-client.js +31 -0
  14. package/dist/auth/http-client.js.map +1 -0
  15. package/dist/auth/index.d.ts +18 -0
  16. package/dist/auth/index.d.ts.map +1 -0
  17. package/dist/auth/index.js +22 -0
  18. package/dist/auth/index.js.map +1 -0
  19. package/dist/auth/route-guards.d.ts +14 -0
  20. package/dist/auth/route-guards.d.ts.map +1 -0
  21. package/dist/auth/route-guards.js +23 -0
  22. package/dist/auth/route-guards.js.map +1 -0
  23. package/dist/auth/ser-oauth-js.d.ts +54 -0
  24. package/dist/auth/ser-oauth-js.d.ts.map +1 -0
  25. package/dist/auth/ser-oauth-js.js +405 -0
  26. package/dist/auth/ser-oauth-js.js.map +1 -0
  27. package/dist/auth/store.d.ts +14 -0
  28. package/dist/auth/store.d.ts.map +1 -0
  29. package/dist/auth/store.js +20 -0
  30. package/dist/auth/store.js.map +1 -0
  31. package/dist/index.d.ts +3 -6
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +2 -4
  34. package/dist/index.js.map +1 -1
  35. package/dist/keycloak.d.ts +12 -2
  36. package/dist/keycloak.d.ts.map +1 -1
  37. package/dist/keycloak.js +168 -125
  38. package/dist/keycloak.js.map +1 -1
  39. package/dist/utils/auth.d.ts +8 -0
  40. package/dist/utils/auth.d.ts.map +1 -1
  41. package/dist/utils/auth.js +13 -2
  42. package/dist/utils/auth.js.map +1 -1
  43. package/package.json +8 -6
  44. package/public/silent-callback.html +19 -0
  45. package/public/silent-check-sso.html +30 -0
  46. package/dist/axios.d.ts.map +0 -1
  47. package/dist/axios.js.map +0 -1
package/README.md CHANGED
@@ -1,474 +1,229 @@
1
- # @elogroup-sereduc/ser-front-core-client
1
+ # Ser Auth Library
2
2
 
3
- Keycloak-based authentication and API client for Portal do Aluno and Backoffices.
3
+ Sistema de autenticação OAuth/OIDC compatível com Keycloak, desenvolvido como substituto para keycloak-js com suporte a Silent SSO, PKCE S256, e gerenciamento automático de tokens.
4
4
 
5
- ## Features
5
+ ## Características
6
6
 
7
- - ✅ Keycloak authentication integration
8
- - ✅ Memory-only JWT token storage (secure)
9
- - ✅ Proactive token refresh (30-second threshold)
10
- - ✅ Axios-based API client with automatic Bearer token injection
11
- - ✅ TypeScript support with full type definitions
12
- - ✅ Configurable error handling
13
- - ✅ Authentication utilities and helpers
7
+ - ✅ **Silent SSO**: Autenticação invisível via iframe
8
+ - ✅ **PKCE S256**: Segurança para SPAs (Single Page Applications)
9
+ - ✅ **Token Refresh**: Renovação automática de tokens
10
+ - ✅ **API Client**: Cliente HTTP com interceptadores automáticos
11
+ - ✅ **Route Guards**: Proteção de rotas para frameworks como TanStack Router
12
+ - ✅ **Zustand Store**: Gerenciamento de estado em memória
13
+ - ✅ **IDP Hint**: Suporte a redirecionamento automático para provedores específicos
14
14
 
15
- ## Installation
15
+ ## Instalação
16
16
 
17
17
  ```bash
18
18
  npm install @elogroup-sereduc/ser-front-core-client
19
19
  ```
20
20
 
21
- ## Quick Start
21
+ ## Setup Básico
22
22
 
23
- ### Basic API Client
23
+ ### 1. Configuração Inicial
24
24
 
25
25
  ```typescript
26
- import { createApiClient } from "@elogroup-sereduc/ser-front-core-client";
27
-
28
- // Create an API client with Keycloak authentication
29
- const apiClient = createApiClient({
30
- keycloak: {
31
- url: "https://your-keycloak-server",
32
- realm: "your-realm",
33
- clientId: "your-client-id",
34
- },
35
- api: {
36
- baseURL: "https://your-api-server",
37
- },
38
- });
39
-
40
- // Use like a normal axios instance
41
- const users = await apiClient.get("/users");
42
- const newUser = await apiClient.post("/users", userData);
43
- ```
44
-
45
- ### Simple Client Factory
26
+ import {
27
+ createKeycloakAuthFromUrl,
28
+ initAuth,
29
+ } from "@elogroup-sereduc/ser-front-core-client";
46
30
 
47
- ```typescript
48
- import { createSimpleApiClient } from "@elogroup-sereduc/ser-front-core-client";
31
+ // Criar instância do SerOAuth
32
+ const kc = createKeycloakAuthFromUrl(
33
+ "https://seu-keycloak.com/realms/seu-realm/protocol/openid-connect/auth",
34
+ "seu-client-id",
35
+ "seu-idp-hint", // opcional
36
+ );
49
37
 
50
- const apiClient = createSimpleApiClient("https://your-api-server", {
51
- url: "https://your-keycloak-server",
52
- realm: "your-realm",
53
- clientId: "your-client-id",
54
- });
38
+ // Inicializar autenticação
39
+ const authenticated = await initAuth(kc, "/seu-base-path");
55
40
  ```
56
41
 
57
- ## Configuration
42
+ ### 2. Arquivo Silent-Check-SSO
58
43
 
59
- ### Application Base Path Support
44
+ Copie o arquivo `public/silent-check-sso.html` para a pasta `public` da sua aplicação.
60
45
 
61
- For applications that don't run at the domain root (e.g., `/portal-aluno`, `/backoffice`), configure the `basePath`:
46
+ ### 3. Context de Autenticação (React)
62
47
 
63
48
  ```typescript
64
- const config = {
65
- keycloak: {
66
- url: "https://your-keycloak-server",
67
- realm: "your-realm",
68
- clientId: "your-client-id",
69
- basePath: "/portal-aluno", // Application base path
70
- },
71
- api: {
72
- baseURL: "https://your-api-server",
73
- },
74
- };
75
-
76
- const apiClient = createApiClient(config);
77
- ```
78
-
79
- The `basePath` is used to construct correct redirect URIs for:
80
-
81
- - Silent SSO check redirects
82
- - Login/logout redirects
83
- - Error handling redirects
49
+ import { useAuthStore } from '@elogroup-sereduc/ser-front-core-client'
84
50
 
85
- ### KeycloakConfig
51
+ export function AuthContext({ children }) {
52
+ const authState = useAuthStore()
86
53
 
87
- ```typescript
88
- interface KeycloakConfig {
89
- url: string; // Keycloak server URL
90
- realm: string; // Keycloak realm
91
- clientId: string; // Client ID
92
- basePath?: string; // Application base path (e.g., '/portal-aluno', '/backoffice')
93
- initOptions?: {
94
- // Optional Keycloak initialization options
95
- onLoad?: "login-required" | "check-sso";
96
- silentCheckSsoRedirectUri?: string;
97
- checkLoginIframe?: boolean;
98
- // ... other KeycloakInitOptions
99
- };
54
+ return (
55
+ <AuthProvider value={{
56
+ authenticated: authState.authenticated,
57
+ user: extractUserFromToken(authState.idToken),
58
+ login: () => kc.login(),
59
+ logout: () => kc.logout(),
60
+ }}>
61
+ {children}
62
+ </AuthProvider>
63
+ )
100
64
  }
101
65
  ```
102
66
 
103
- ### ApiClientConfig
67
+ ### 4. Cliente API
104
68
 
105
69
  ```typescript
106
- interface ApiClientConfig {
107
- baseURL: string; // API base URL
108
- headers?: Record<string, string>; // Default headers
109
- withCredentials?: boolean; // Include cookies (default: true)
110
- onTokenRefreshFailed?: (error: Error) => void; // Custom error handler
111
- loginRedirectUrl?: string; // Custom login redirect URL
112
- }
113
- ```
114
-
115
- ### Login Interfaces
70
+ import { createApiClient } from "@elogroup-sereduc/ser-front-core-client";
116
71
 
117
- ```typescript
118
- interface DirectLoginCredentials {
119
- username: string; // Username for direct login
120
- password: string; // Password for direct login
121
- }
72
+ const api = createApiClient(kc, "https://sua-api.com");
122
73
 
123
- interface LoginOptions {
124
- redirectUri?: string; // Custom redirect URI after login
125
- credentials?: DirectLoginCredentials; // For direct login (internal users)
126
- loginHint?: string; // Login hint for external login
127
- prompt?: "none" | "login" | "consent" | "select_account"; // OIDC prompt parameter
128
- }
74
+ // O cliente automaticamente:
75
+ // - Adiciona Bearer token nos headers
76
+ // - Renova token em caso de 401
77
+ // - Retenta requisição com novo token
129
78
  ```
130
79
 
131
- ## Authentication Management
132
-
133
- ### Login Types
134
-
135
- This package supports three types of login:
136
-
137
- 1. **External Login (Default)**: Redirects to Keycloak login page
138
- 2. **Direct Login (Internal Users)**: Uses username/password without external redirect
139
- 3. **Silent Login**: Checks authentication status without user interaction
140
-
141
- ### External Login (Standard Flow)
80
+ ### 5. Route Guards
142
81
 
143
82
  ```typescript
144
- import { createAuthService } from "@elogroup-sereduc/ser-front-core-client";
145
-
146
- const authService = await createAuthService({
147
- url: "https://your-keycloak-server",
148
- realm: "your-realm",
149
- clientId: "your-client-id",
150
- });
151
-
152
- // Redirects user to Keycloak login page
153
- await authService.login();
154
- ```
155
-
156
- ### Direct Login (Internal Users)
157
-
158
- For internal users that don't need external redirect, you can use direct login with username/password:
83
+ import { createAuthGuard } from "@elogroup-sereduc/ser-front-core-client";
84
+ import { createFileRoute } from "@tanstack/react-router";
159
85
 
160
- ```typescript
161
- import {
162
- createAuthService,
163
- type DirectLoginCredentials,
164
- DirectLoginError,
165
- } from "@elogroup-sereduc/ser-front-core-client";
86
+ const requireAuth = createAuthGuard(kc);
166
87
 
167
- const authService = await createAuthService(keycloakConfig);
168
-
169
- // Direct login without external redirect
170
- try {
171
- await authService.login({
172
- credentials: {
173
- username: "internal.user@company.com",
174
- password: "userPassword123",
175
- },
176
- });
177
- console.log("User logged in successfully!");
178
- } catch (error) {
179
- if (error instanceof DirectLoginError) {
180
- console.error("Direct login failed:", error.message);
181
- // Handle specific direct login errors:
182
- // - Invalid credentials
183
- // - Account locked
184
- // - Client not configured for direct access
185
- }
186
- }
88
+ export const Route = createFileRoute("/protected")({
89
+ beforeLoad: requireAuth,
90
+ component: ProtectedComponent,
91
+ });
187
92
  ```
188
93
 
189
- **📋 Keycloak Configuration Requirements for Direct Login:**
190
-
191
- 1. In Keycloak Admin Console, go to your client settings
192
- 2. Enable "Direct Access Grants Enabled" in the Capability config
193
- 3. Ensure the client has the appropriate roles and scope mappings
194
- 4. For production, consider IP restrictions and additional security measures
94
+ ## API Reference
195
95
 
196
- ### Silent Login
197
-
198
- Silent login allows checking authentication status without user interaction, perfect for checking if a user is already logged in:
96
+ ### SerOAuth
199
97
 
200
98
  ```typescript
201
- import {
202
- createAuthService,
203
- AuthenticationError,
204
- } from "@elogroup-sereduc/ser-front-core-client";
99
+ class SerOAuth {
100
+ constructor(config: SerOAuthConfig);
205
101
 
206
- const authService = await createAuthService(keycloakConfig);
207
-
208
- // Check if user is already authenticated silently
209
- try {
210
- const isAuthenticated = await authService.silentLogin();
211
- if (isAuthenticated) {
212
- console.log("User is already logged in");
213
- // Continue with app
214
- } else {
215
- console.log("User needs to login");
216
- // Show login form or redirect to login
217
- }
218
- } catch (error) {
219
- console.error("Silent login check failed:", error);
220
- // Fallback to normal login flow
221
- }
222
- ```
223
-
224
- **📋 Keycloak Configuration Requirements for Silent Login:**
102
+ // Métodos principais
103
+ async init(options?: InitOptions): Promise<boolean>;
104
+ async login(options?: LoginOptions): Promise<void>;
105
+ async logout(options?: LogoutOptions): Promise<void>;
106
+ async updateToken(minValidity?: number): Promise<boolean>;
225
107
 
226
- 1. In Keycloak Admin Console, add to Valid Redirect URIs:
227
- - `https://your-domain.com/silent-callback`
228
- - `https://your-domain.com/your-base-path/silent-callback` (if using basePath)
229
- 2. Ensure "Standard Flow Enabled" is enabled
230
- 3. Create `public/silent-callback.html` file (provided with package)
108
+ // Propriedades
109
+ get authenticated(): boolean;
110
+ get token(): string | null;
111
+ get refreshToken(): string | null;
112
+ get idToken(): string | null;
231
113
 
232
- ### Mixed Login Scenarios
233
-
234
- You can handle both internal and external users in the same application:
235
-
236
- ```typescript
237
- async function handleLogin(
238
- isInternalUser: boolean,
239
- credentials?: DirectLoginCredentials,
240
- ) {
241
- try {
242
- if (isInternalUser && credentials) {
243
- // Direct login for internal users
244
- await authService.login({ credentials });
245
- } else {
246
- // External redirect for external users
247
- await authService.login();
248
- }
249
- } catch (error) {
250
- console.error("Login failed:", error);
251
- }
114
+ // Callbacks
115
+ onAuthSuccess?: () => void;
116
+ onAuthError?: (err: unknown) => void;
117
+ onAuthLogout?: () => void;
118
+ onTokenExpired?: () => void;
119
+ onTokenRefreshed?: () => void;
252
120
  }
253
121
  ```
254
122
 
255
- ### Manual Authentication
123
+ ### Configuração
256
124
 
257
125
  ```typescript
258
- import {
259
- createAuthService,
260
- getAuthState,
261
- } from "@elogroup-sereduc/ser-front-core-client";
262
-
263
- // Create standalone auth service
264
- const authService = await createAuthService({
265
- url: "https://your-keycloak-server",
266
- realm: "your-realm",
267
- clientId: "your-client-id",
268
- });
269
-
270
- // Check authentication state
271
- const authState = getAuthState(authService);
272
- console.log("Is authenticated:", authState.isAuthenticated);
273
-
274
- // Login (external redirect)
275
- if (!authState.isAuthenticated) {
276
- await authService.login();
277
- }
278
-
279
- // Direct login for internal users (no external redirect)
280
- if (!authState.isAuthenticated) {
281
- await authService.login({
282
- credentials: {
283
- username: "internal.user@company.com",
284
- password: "userPassword123",
285
- },
286
- });
287
- }
126
+ type SerOAuthConfig = {
127
+ url: string; // https://seu-keycloak.com
128
+ realm: string; // nome-do-realm
129
+ clientId: string; // seu-client-id
130
+ idp?: string; // hint para IDP específico
131
+ };
288
132
 
289
- // Logout
290
- await authService.logout();
133
+ type InitOptions = {
134
+ onLoad?: "check-sso" | "login-required";
135
+ silentCheckSsoRedirectUri?: string;
136
+ pkceMethod?: "S256";
137
+ };
291
138
  ```
292
139
 
293
- ### Access Keycloak Service from API Client
140
+ ### Store (Zustand)
294
141
 
295
142
  ```typescript
296
- import { getKeycloakService } from "@elogroup-sereduc/ser-front-core-client";
297
-
298
- const apiClient = createApiClient(config);
299
- const keycloakService = getKeycloakService(apiClient);
300
-
301
- if (keycloakService) {
302
- const authState = keycloakService.getAuthState();
303
- console.log("User info:", authState.userInfo);
304
- }
143
+ const authState = useAuthStore();
144
+ // {
145
+ // accessToken: string | null
146
+ // refreshToken: string | null
147
+ // idToken: string | null
148
+ // accessExpiresAt: number | null
149
+ // authenticated: boolean
150
+ // setTokens: (tokens: TokenSet) => void
151
+ // clear: () => void
152
+ // }
305
153
  ```
306
154
 
307
- ## Authentication Utilities
155
+ ## Migração do keycloak-js
308
156
 
309
- ### Token Management
157
+ ### Antes (keycloak-js)
310
158
 
311
159
  ```typescript
312
- import {
313
- isTokenExpired,
314
- parseTokenUserInfo,
315
- hasRole,
316
- getUserRoles,
317
- } from "@elogroup-sereduc/ser-front-core-client";
318
-
319
- // Check if token is expired
320
- const expired = isTokenExpired(token, 30); // 30-second buffer
160
+ import Keycloak from "keycloak-js";
321
161
 
322
- // Parse user info from token
323
- const userInfo = parseTokenUserInfo(token);
162
+ const keycloak = new Keycloak({
163
+ url: "https://keycloak.com",
164
+ realm: "myrealm",
165
+ clientId: "myclient",
166
+ });
324
167
 
325
- // Check user roles
326
- const isAdmin = hasRole(token, "admin");
327
- const userRoles = getUserRoles(token);
168
+ await keycloak.init({ onLoad: "check-sso" });
328
169
  ```
329
170
 
330
- ### URL Building with Base Path
171
+ ### Depois (ser-auth)
331
172
 
332
173
  ```typescript
333
174
  import {
334
- buildUrl,
335
- logout,
336
- redirectToLogin,
175
+ createSerOAuth,
176
+ initAuth,
337
177
  } from "@elogroup-sereduc/ser-front-core-client";
338
178
 
339
- // Build URLs with base path support
340
- const silentSsoUrl = buildUrl("/silent-check-sso.html", "/portal-aluno");
341
- // Result: 'https://domain.com/portal-aluno/silent-check-sso.html'
342
-
343
- const homeUrl = buildUrl("/", "/backoffice");
344
- // Result: 'https://domain.com/backoffice/'
345
-
346
- // Use with auth functions
347
- const keycloakService = getKeycloakService(apiClient);
348
-
349
- // Logout with base path
350
- await logout(keycloakService, undefined, "/portal-aluno");
179
+ const kc = createSerOAuth({
180
+ url: "https://keycloak.com",
181
+ realm: "myrealm",
182
+ clientId: "myclient",
183
+ });
351
184
 
352
- // Redirect to login with base path
353
- redirectToLogin(undefined, "/portal-aluno");
185
+ await initAuth(kc);
354
186
  ```
355
187
 
356
- ## Error Handling
357
-
358
- ### Improved Error Messages
188
+ ## Exemplos Avançados
359
189
 
360
- The package now provides detailed error messages for common issues:
190
+ ### Custom Error Handling
361
191
 
362
192
  ```typescript
363
- import {
364
- createAuthService,
365
- AuthenticationError,
366
- } from "@elogroup-sereduc/ser-front-core-client";
193
+ kc.onAuthError = (error) => {
194
+ console.error("Auth error:", error);
195
+ // Redirecionar para página de erro
196
+ };
367
197
 
368
- try {
369
- const authService = await createAuthService({
370
- url: "https://invalid-keycloak-server",
371
- realm: "nonexistent-realm",
372
- clientId: "wrong-client-id",
373
- });
374
- } catch (error) {
375
- if (error instanceof AuthenticationError) {
376
- console.error("Detailed error:", error.message);
377
- // Possible messages:
378
- // - "Keycloak URL is required"
379
- // - "Invalid Keycloak URL: ..."
380
- // - "Cannot connect to Keycloak server at ..."
381
- // - "Keycloak realm 'nonexistent-realm' not found"
382
- // - "CORS error connecting to Keycloak..."
383
- }
384
- }
198
+ kc.onTokenExpired = () => {
199
+ console.log("Token expirado, renovando...");
200
+ };
385
201
  ```
386
202
 
387
- ### Default Behavior
388
-
389
- By default, when token refresh fails, the user is redirected to the login page.
390
-
391
- ### Custom Error Handling
203
+ ### Múltiplas Instâncias
392
204
 
393
205
  ```typescript
394
- const apiClient = createApiClient({
395
- keycloak: {
396
- /* ... */
397
- },
398
- api: {
399
- baseURL: "https://api.example.com",
400
- onTokenRefreshFailed: (error) => {
401
- console.error("Auth failed:", error);
402
- // Custom handling - show modal, redirect to specific page, etc.
403
- showAuthErrorModal();
404
- },
405
- },
206
+ const adminKc = createSerOAuth({
207
+ url: "https://admin-sso.com",
208
+ realm: "admin",
209
+ clientId: "admin-client",
406
210
  });
407
- ```
408
211
 
409
- ## Silent SSO Setup
410
-
411
- For silent SSO, create a `silent-check-sso.html` file in your public folder:
412
-
413
- ```html
414
- <!doctype html>
415
- <html>
416
- <body>
417
- <script>
418
- parent.postMessage(location.href, location.origin);
419
- </script>
420
- </body>
421
- </html>
212
+ const userKc = createSerOAuth({
213
+ url: "https://user-sso.com",
214
+ realm: "users",
215
+ clientId: "user-client",
216
+ });
422
217
  ```
423
218
 
424
- Then configure your client:
219
+ ### Interceptação Customizada
425
220
 
426
221
  ```typescript
427
- const config = {
428
- keycloak: {
429
- url: "https://your-keycloak-server",
430
- realm: "your-realm",
431
- clientId: "your-client-id",
432
- initOptions: {
433
- onLoad: "check-sso",
434
- silentCheckSsoRedirectUri: `${window.location.origin}/silent-check-sso.html`,
435
- },
436
- },
437
- // ...
438
- };
439
- ```
440
-
441
- ## TypeScript Support
222
+ const api = createApiClient(kc);
442
223
 
443
- Full TypeScript support with comprehensive type definitions:
444
-
445
- ```typescript
446
- import type {
447
- CoreClientConfig,
448
- AuthState,
449
- KeycloakConfig,
450
- LoginOptions,
451
- DirectLoginCredentials,
452
- AuthenticationError,
453
- TokenRefreshError,
454
- DirectLoginError,
455
- } from "@elogroup-sereduc/ser-front-core-client";
224
+ api.interceptors.request.use((config) => {
225
+ // Adicionar headers customizados
226
+ config.headers["X-Custom-Header"] = "value";
227
+ return config;
228
+ });
456
229
  ```
457
-
458
- ## Differences from portal-aluno-api-client
459
-
460
- - ✅ **Memory-only storage**: Tokens stored in memory (more secure)
461
- - ✅ **Proactive refresh**: Uses `updateToken(30)` before requests instead of 401/403 retry
462
- - ✅ **Keycloak integration**: OIDC-based authentication instead of session-based
463
- - ✅ **Per-client config**: Keycloak config provided per API client
464
- - ✅ **No retry logic**: Does not retry requests on auth failure
465
- - ✅ **Direct login support**: Internal users can login with username/password without external redirect
466
- - ✅ **Silent login support**: Check authentication status without user interaction using OIDC prompt=none
467
- - ✅ **Base path support**: Applications running in subfolders (e.g., /portal-aluno, /backoffice) are fully supported
468
- - ✅ **Mixed authentication**: Supports both internal (direct) and external (redirect) users in the same app
469
- - ✅ **Enhanced error handling**: Detailed error messages for debugging connection and configuration issues
470
- - ✅ **Automatic validation**: Configuration validation with specific error messages
471
-
472
- ## License
473
-
474
- MIT
@@ -1,7 +1,7 @@
1
1
  import { type AxiosInstance } from "axios";
2
2
  import { KeycloakService } from "./keycloak.js";
3
- import type { CoreClientConfig, ApiClientConfig } from "./types/index.js";
3
+ import type { CoreClientConfig } from "./types/index.js";
4
4
  export declare function createApiClient(config: CoreClientConfig): AxiosInstance;
5
- export declare function createSimpleApiClient(baseURL: string, keycloakConfig: CoreClientConfig["keycloak"], options?: Partial<ApiClientConfig>): AxiosInstance;
5
+ export declare function createSimpleApiClient(config: CoreClientConfig): AxiosInstance;
6
6
  export declare function getKeycloakService(apiClient: AxiosInstance): KeycloakService | undefined;
7
- //# sourceMappingURL=axios.d.ts.map
7
+ //# sourceMappingURL=api-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAAA,OAAc,EACZ,KAAK,aAAa,EAGnB,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,gBAAgB,EAAmB,MAAM,kBAAkB,CAAC;AAM1E,wBAAgB,eAAe,CAAC,MAAM,EAAE,gBAAgB,GAAG,aAAa,CA8EvE;AAyBD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,gBAAgB,GAAG,aAAa,CAE7E;AAKD,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,aAAa,GACvB,eAAe,GAAG,SAAS,CAE7B"}
@@ -2,8 +2,14 @@ import axios from "axios";
2
2
  import { KeycloakService } from "./keycloak.js";
3
3
  import { AuthenticationError, TokenRefreshError } from "./types/index.js";
4
4
  export function createApiClient(config) {
5
- const keycloakService = new KeycloakService(config.keycloak);
6
- const initPromise = keycloakService.initialize();
5
+ const keycloakService = KeycloakService.getInstance(config.keycloak);
6
+ let initPromise;
7
+ if (!keycloakService.isInitialized) {
8
+ initPromise = keycloakService.initialize();
9
+ }
10
+ else {
11
+ initPromise = Promise.resolve(true);
12
+ }
7
13
  const apiClient = axios.create({
8
14
  baseURL: config.api.baseURL,
9
15
  withCredentials: config.api.withCredentials ?? true,
@@ -57,16 +63,10 @@ async function handleAuthenticationFailure(error, config) {
57
63
  window.location.href = redirectUrl;
58
64
  }
59
65
  }
60
- export function createSimpleApiClient(baseURL, keycloakConfig, options) {
61
- return createApiClient({
62
- keycloak: keycloakConfig,
63
- api: {
64
- baseURL,
65
- ...options,
66
- },
67
- });
66
+ export function createSimpleApiClient(config) {
67
+ return createApiClient(config);
68
68
  }
69
69
  export function getKeycloakService(apiClient) {
70
70
  return apiClient.keycloak;
71
71
  }
72
- //# sourceMappingURL=axios.js.map
72
+ //# sourceMappingURL=api-client.js.map