@aifabrix/miso-client 3.8.2 → 4.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.
- package/CHANGELOG.md +1116 -1007
- package/dist/api/encryption.api.d.ts +31 -0
- package/dist/api/encryption.api.d.ts.map +1 -0
- package/dist/api/encryption.api.js +61 -0
- package/dist/api/encryption.api.js.map +1 -0
- package/dist/api/index.d.ts +5 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +2 -0
- package/dist/api/index.js.map +1 -1
- package/dist/api/types/encryption.types.d.ts +43 -0
- package/dist/api/types/encryption.types.d.ts.map +1 -0
- package/dist/api/types/encryption.types.js +7 -0
- package/dist/api/types/encryption.types.js.map +1 -0
- package/dist/express/index.d.ts +0 -1
- package/dist/express/index.d.ts.map +1 -1
- package/dist/express/index.js +1 -4
- package/dist/express/index.js.map +1 -1
- package/dist/index.d.ts +43 -158
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +50 -167
- package/dist/index.js.map +1 -1
- package/dist/services/auth-error-handler.d.ts +21 -0
- package/dist/services/auth-error-handler.d.ts.map +1 -0
- package/dist/services/auth-error-handler.js +68 -0
- package/dist/services/auth-error-handler.js.map +1 -0
- package/dist/services/auth.service.d.ts +0 -1
- package/dist/services/auth.service.d.ts.map +1 -1
- package/dist/services/auth.service.js +31 -298
- package/dist/services/auth.service.js.map +1 -1
- package/dist/services/encryption.service.d.ts +47 -0
- package/dist/services/encryption.service.d.ts.map +1 -0
- package/dist/services/encryption.service.js +64 -0
- package/dist/services/encryption.service.js.map +1 -0
- package/dist/services/logger/logger.service.d.ts +8 -80
- package/dist/services/logger/logger.service.d.ts.map +1 -1
- package/dist/services/logger/logger.service.js +8 -80
- package/dist/services/logger/logger.service.js.map +1 -1
- package/dist/services/permission.service.d.ts +0 -4
- package/dist/services/permission.service.d.ts.map +1 -1
- package/dist/services/permission.service.js +2 -23
- package/dist/services/permission.service.js.map +1 -1
- package/dist/services/role.service.d.ts +0 -4
- package/dist/services/role.service.d.ts.map +1 -1
- package/dist/services/role.service.js +2 -23
- package/dist/services/role.service.js.map +1 -1
- package/dist/types/config.types.d.ts +0 -1
- package/dist/types/config.types.d.ts.map +1 -1
- package/dist/types/config.types.js.map +1 -1
- package/dist/types/filter-schema.types.d.ts +104 -0
- package/dist/types/filter-schema.types.d.ts.map +1 -0
- package/dist/types/filter-schema.types.js +40 -0
- package/dist/types/filter-schema.types.js.map +1 -0
- package/dist/types/filter.types.d.ts +1 -1
- package/dist/types/filter.types.d.ts.map +1 -1
- package/dist/types/filter.types.js.map +1 -1
- package/dist/utils/config-loader.d.ts.map +1 -1
- package/dist/utils/config-loader.js +0 -4
- package/dist/utils/config-loader.js.map +1 -1
- package/dist/utils/data-client-auth.d.ts +5 -37
- package/dist/utils/data-client-auth.d.ts.map +1 -1
- package/dist/utils/data-client-auth.js +98 -377
- package/dist/utils/data-client-auth.js.map +1 -1
- package/dist/utils/data-client-init.d.ts +46 -0
- package/dist/utils/data-client-init.d.ts.map +1 -0
- package/dist/utils/data-client-init.js +128 -0
- package/dist/utils/data-client-init.js.map +1 -0
- package/dist/utils/data-client-oauth.d.ts +20 -0
- package/dist/utils/data-client-oauth.d.ts.map +1 -0
- package/dist/utils/data-client-oauth.js +138 -0
- package/dist/utils/data-client-oauth.js.map +1 -0
- package/dist/utils/data-client-permissions.d.ts +63 -0
- package/dist/utils/data-client-permissions.d.ts.map +1 -0
- package/dist/utils/data-client-permissions.js +123 -0
- package/dist/utils/data-client-permissions.js.map +1 -0
- package/dist/utils/data-client-request.d.ts +1 -1
- package/dist/utils/data-client-request.d.ts.map +1 -1
- package/dist/utils/data-client-request.js +35 -235
- package/dist/utils/data-client-request.js.map +1 -1
- package/dist/utils/data-client-response.d.ts +40 -0
- package/dist/utils/data-client-response.d.ts.map +1 -0
- package/dist/utils/data-client-response.js +144 -0
- package/dist/utils/data-client-response.js.map +1 -0
- package/dist/utils/data-client-roles.d.ts +63 -0
- package/dist/utils/data-client-roles.d.ts.map +1 -0
- package/dist/utils/data-client-roles.js +123 -0
- package/dist/utils/data-client-roles.js.map +1 -0
- package/dist/utils/data-client.d.ts +0 -185
- package/dist/utils/data-client.d.ts.map +1 -1
- package/dist/utils/data-client.js +66 -505
- package/dist/utils/data-client.js.map +1 -1
- package/dist/utils/encryption-error.d.ts +24 -0
- package/dist/utils/encryption-error.d.ts.map +1 -0
- package/dist/utils/encryption-error.js +31 -0
- package/dist/utils/encryption-error.js.map +1 -0
- package/dist/utils/filter-colon.utils.d.ts +26 -0
- package/dist/utils/filter-colon.utils.d.ts.map +1 -0
- package/dist/utils/filter-colon.utils.js +112 -0
- package/dist/utils/filter-colon.utils.js.map +1 -0
- package/dist/utils/filter-schema.utils.d.ts +84 -0
- package/dist/utils/filter-schema.utils.d.ts.map +1 -0
- package/dist/utils/filter-schema.utils.js +381 -0
- package/dist/utils/filter-schema.utils.js.map +1 -0
- package/dist/utils/filter.utils.d.ts +9 -85
- package/dist/utils/filter.utils.d.ts.map +1 -1
- package/dist/utils/filter.utils.js +79 -138
- package/dist/utils/filter.utils.js.map +1 -1
- package/dist/utils/http-error-handler.d.ts +22 -0
- package/dist/utils/http-error-handler.d.ts.map +1 -0
- package/dist/utils/http-error-handler.js +84 -0
- package/dist/utils/http-error-handler.js.map +1 -0
- package/dist/utils/http-response-validator.d.ts +15 -0
- package/dist/utils/http-response-validator.d.ts.map +1 -0
- package/dist/utils/http-response-validator.js +42 -0
- package/dist/utils/http-response-validator.js.map +1 -0
- package/dist/utils/internal-http-client.d.ts +4 -22
- package/dist/utils/internal-http-client.d.ts.map +1 -1
- package/dist/utils/internal-http-client.js +53 -337
- package/dist/utils/internal-http-client.js.map +1 -1
- package/dist/utils/token-utils.d.ts.map +1 -1
- package/dist/utils/token-utils.js +1 -29
- package/dist/utils/token-utils.js.map +1 -1
- package/package.json +84 -84
- package/dist/express/encryption.d.ts +0 -29
- package/dist/express/encryption.d.ts.map +0 -1
- package/dist/express/encryption.js +0 -95
- package/dist/express/encryption.js.map +0 -1
|
@@ -46,21 +46,14 @@ const data_client_cache_1 = require("./data-client-cache");
|
|
|
46
46
|
const data_client_request_1 = require("./data-client-request");
|
|
47
47
|
const data_client_auth_1 = require("./data-client-auth");
|
|
48
48
|
const data_client_redirect_1 = require("./data-client-redirect");
|
|
49
|
-
const
|
|
50
|
-
const
|
|
51
|
-
const
|
|
52
|
-
const http_client_1 = require("../utils/http-client");
|
|
53
|
-
const internal_http_client_1 = require("../utils/internal-http-client");
|
|
54
|
-
const api_1 = require("../api");
|
|
55
|
-
const logger_1 = require("../services/logger");
|
|
56
|
-
const redis_service_1 = require("../services/redis.service");
|
|
49
|
+
const data_client_init_1 = require("./data-client-init");
|
|
50
|
+
const permissionHelpers = __importStar(require("./data-client-permissions"));
|
|
51
|
+
const roleHelpers = __importStar(require("./data-client-roles"));
|
|
57
52
|
class DataClient {
|
|
58
53
|
constructor(config) {
|
|
59
54
|
this.misoClient = null;
|
|
60
55
|
this.cache = new Map();
|
|
61
56
|
this.pendingRequests = new Map();
|
|
62
|
-
// Track failed requests to prevent rapid re-requests (deduplication for failures)
|
|
63
|
-
// Extended cooldown period to prevent retry storms
|
|
64
57
|
this.failedRequests = new Map();
|
|
65
58
|
this.interceptors = {};
|
|
66
59
|
this.metrics = {
|
|
@@ -72,227 +65,85 @@ class DataClient {
|
|
|
72
65
|
};
|
|
73
66
|
this.permissionService = null;
|
|
74
67
|
this.roleService = null;
|
|
75
|
-
this.config =
|
|
76
|
-
|
|
77
|
-
loginUrl: "/login",
|
|
78
|
-
timeout: 30000,
|
|
79
|
-
cache: {
|
|
80
|
-
enabled: true,
|
|
81
|
-
defaultTTL: 300,
|
|
82
|
-
maxSize: 100,
|
|
83
|
-
},
|
|
84
|
-
retry: {
|
|
85
|
-
enabled: true,
|
|
86
|
-
maxRetries: 3,
|
|
87
|
-
baseDelay: 1000,
|
|
88
|
-
maxDelay: 10000,
|
|
89
|
-
},
|
|
90
|
-
audit: {
|
|
91
|
-
enabled: true,
|
|
92
|
-
level: "standard",
|
|
93
|
-
batchSize: 10,
|
|
94
|
-
maxResponseSize: 10000,
|
|
95
|
-
maxMaskingSize: 50000,
|
|
96
|
-
skipEndpoints: [],
|
|
97
|
-
},
|
|
98
|
-
...config,
|
|
99
|
-
};
|
|
100
|
-
// Security: Warn if clientSecret is provided in browser environment
|
|
101
|
-
// This is a security risk as clientSecret should never be exposed in client-side code
|
|
102
|
-
if ((0, data_client_utils_1.isBrowser)() && this.config.misoConfig?.clientSecret) {
|
|
103
|
-
console.warn("⚠️ SECURITY WARNING: clientSecret detected in browser environment. " +
|
|
104
|
-
"Client secrets should NEVER be exposed in client-side code. " +
|
|
105
|
-
"Use the client token pattern instead (clientToken + onClientTokenRefresh). " +
|
|
106
|
-
"See documentation for browser-safe configuration.");
|
|
107
|
-
}
|
|
68
|
+
this.config = (0, data_client_init_1.createDefaultConfig)(config);
|
|
69
|
+
(0, data_client_init_1.warnIfClientSecretInBrowser)(this.config);
|
|
108
70
|
// Initialize MisoClient if config provided
|
|
109
|
-
|
|
110
|
-
if (
|
|
111
|
-
// Automatically bridge DataClient.getEnvironmentToken() to MisoClient
|
|
112
|
-
// This allows MisoClient's logger service to get client tokens automatically
|
|
113
|
-
// Users don't need to manually provide onClientTokenRefresh!
|
|
114
|
-
misoConfigWithRefresh = {
|
|
115
|
-
...this.config.misoConfig,
|
|
116
|
-
// Only auto-bridge if:
|
|
117
|
-
// 1. User hasn't provided onClientTokenRefresh (allow override)
|
|
118
|
-
// 2. We're in browser (server-side uses clientSecret)
|
|
119
|
-
// 3. No clientSecret provided (would use that instead)
|
|
120
|
-
onClientTokenRefresh: this.config.misoConfig.onClientTokenRefresh ||
|
|
121
|
-
((0, data_client_utils_1.isBrowser)() && !this.config.misoConfig.clientSecret
|
|
122
|
-
? async () => {
|
|
123
|
-
const token = await this.getEnvironmentToken();
|
|
124
|
-
if (!token) {
|
|
125
|
-
throw new Error("Failed to get client token");
|
|
126
|
-
}
|
|
127
|
-
// Get expiration from localStorage (set by getEnvironmentToken)
|
|
128
|
-
const expiresAtStr = (0, data_client_utils_1.getLocalStorage)("miso:client-token-expires-at");
|
|
129
|
-
const expiresAt = expiresAtStr
|
|
130
|
-
? parseInt(expiresAtStr, 10)
|
|
131
|
-
: Date.now() + 3600000; // Default 1 hour
|
|
132
|
-
const expiresIn = Math.floor((expiresAt - Date.now()) / 1000);
|
|
133
|
-
return {
|
|
134
|
-
token,
|
|
135
|
-
expiresIn: expiresIn > 0 ? expiresIn : 3600, // Default 1 hour if invalid
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
: undefined),
|
|
139
|
-
};
|
|
71
|
+
const misoConfigWithRefresh = (0, data_client_init_1.createMisoConfigWithRefresh)(this.config, () => this.getEnvironmentToken());
|
|
72
|
+
if (misoConfigWithRefresh) {
|
|
140
73
|
this.misoClient = new index_1.MisoClient(misoConfigWithRefresh);
|
|
141
74
|
}
|
|
142
75
|
// Initialize DataMasker with config path if provided
|
|
143
76
|
if (this.config.misoConfig?.sensitiveFieldsConfig) {
|
|
144
77
|
data_masker_1.DataMasker.setConfigPath(this.config.misoConfig.sensitiveFieldsConfig);
|
|
145
78
|
}
|
|
146
|
-
// Initialize browser
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
// Use misoConfigWithRefresh which includes onClientTokenRefresh callback
|
|
151
|
-
const internalClient = new internal_http_client_1.InternalHttpClient(misoConfigWithRefresh);
|
|
152
|
-
// Create Redis service (will be undefined for browser, but needed for LoggerService)
|
|
153
|
-
const redis = new redis_service_1.RedisService(misoConfigWithRefresh.redis);
|
|
154
|
-
// Create LoggerService with InternalHttpClient (needs httpClient.request() and httpClient.config)
|
|
155
|
-
const logger = new logger_1.LoggerService(internalClient, redis);
|
|
156
|
-
// Create HttpClient that wraps InternalHttpClient with logger
|
|
157
|
-
// Use misoConfigWithRefresh which includes onClientTokenRefresh callback
|
|
158
|
-
const httpClient = new http_client_1.HttpClient(misoConfigWithRefresh, logger);
|
|
159
|
-
// Update LoggerService to use the new HttpClient (for logging)
|
|
160
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
161
|
-
logger.httpClient = httpClient;
|
|
162
|
-
// Create ApiClient that wraps HttpClient (provides typed API interfaces)
|
|
163
|
-
const apiClient = new api_1.ApiClient(httpClient);
|
|
164
|
-
// Set ApiClient in LoggerService (resolves circular dependency)
|
|
165
|
-
logger.setApiClient(apiClient);
|
|
166
|
-
// Create CacheService without Redis (in-memory only for browser)
|
|
167
|
-
const cacheService = new cache_service_1.CacheService(undefined);
|
|
168
|
-
// Create browser-compatible services (pass both httpClient and apiClient)
|
|
169
|
-
this.permissionService = new browser_permission_service_1.BrowserPermissionService(httpClient, apiClient, cacheService);
|
|
170
|
-
this.roleService = new browser_role_service_1.BrowserRoleService(httpClient, apiClient, cacheService);
|
|
171
|
-
}
|
|
79
|
+
// Initialize browser services
|
|
80
|
+
const services = (0, data_client_init_1.initializeBrowserServices)(this.misoClient, misoConfigWithRefresh);
|
|
81
|
+
this.permissionService = services.permissionService;
|
|
82
|
+
this.roleService = services.roleService;
|
|
172
83
|
// Auto-handle OAuth callback on initialization (browser only)
|
|
173
|
-
// This ensures tokens are extracted immediately when DataClient is created
|
|
174
84
|
if ((0, data_client_utils_1.isBrowser)()) {
|
|
175
85
|
this.handleOAuthCallback();
|
|
176
86
|
}
|
|
177
87
|
}
|
|
178
|
-
|
|
179
|
-
* Get authentication token from localStorage
|
|
180
|
-
*/
|
|
88
|
+
// ==================== PRIVATE HELPERS ====================
|
|
181
89
|
getToken() {
|
|
182
90
|
return (0, data_client_auth_1.getToken)(this.config.tokenKeys);
|
|
183
91
|
}
|
|
184
|
-
/**
|
|
185
|
-
* Check if client token is available (from localStorage cache or config)
|
|
186
|
-
*/
|
|
187
92
|
hasClientToken() {
|
|
188
93
|
return (0, data_client_auth_1.hasClientToken)(this.misoClient, this.config.misoConfig);
|
|
189
94
|
}
|
|
190
|
-
/**
|
|
191
|
-
* Check if any authentication token is available (user token OR client token)
|
|
192
|
-
*/
|
|
193
95
|
hasAnyToken() {
|
|
194
96
|
return (0, data_client_auth_1.hasAnyToken)(this.config.tokenKeys, this.misoClient, this.config.misoConfig);
|
|
195
97
|
}
|
|
196
|
-
/**
|
|
197
|
-
* Get client token for requests
|
|
198
|
-
* Checks localStorage cache first, then config, then calls getEnvironmentToken() if needed
|
|
199
|
-
* @returns Client token string or null if unavailable
|
|
200
|
-
*/
|
|
201
98
|
async getClientToken() {
|
|
202
99
|
return (0, data_client_auth_1.getClientToken)(this.config.misoConfig, this.config.baseUrl, () => this.getEnvironmentToken());
|
|
203
100
|
}
|
|
204
|
-
/**
|
|
205
|
-
* Build controller URL from configuration
|
|
206
|
-
* Uses controllerPublicUrl (browser) or controllerUrl (fallback)
|
|
207
|
-
* @returns Controller base URL or null if not configured
|
|
208
|
-
*/
|
|
209
101
|
getControllerUrl() {
|
|
210
102
|
return (0, data_client_auth_1.getControllerUrl)(this.config.misoConfig);
|
|
211
103
|
}
|
|
212
|
-
|
|
213
|
-
* Check if user is authenticated
|
|
214
|
-
*/
|
|
104
|
+
// ==================== PUBLIC AUTH METHODS ====================
|
|
215
105
|
isAuthenticated() {
|
|
216
106
|
return this.getToken() !== null;
|
|
217
107
|
}
|
|
218
|
-
/**
|
|
219
|
-
* Handle OAuth callback from authentication redirect
|
|
220
|
-
* Extracts token from URL hash fragment and stores securely
|
|
221
|
-
* ISO 27001 compliant with immediate cleanup and validation
|
|
222
|
-
*
|
|
223
|
-
* @returns Extracted token or null if not found/invalid
|
|
224
|
-
*/
|
|
225
108
|
handleOAuthCallback() {
|
|
226
109
|
return (0, data_client_auth_1.handleOAuthCallback)(this.config);
|
|
227
110
|
}
|
|
228
|
-
/**
|
|
229
|
-
* Redirect to login page via controller
|
|
230
|
-
* Calls the controller login endpoint with redirect parameter and x-client-token header
|
|
231
|
-
* @param redirectUrl - Optional redirect URL to return to after login (defaults to current page URL)
|
|
232
|
-
*/
|
|
233
111
|
async redirectToLogin(redirectUrl) {
|
|
234
112
|
return (0, data_client_redirect_1.redirectToLogin)(this.config, () => this.getClientToken(), redirectUrl);
|
|
235
113
|
}
|
|
236
|
-
/**
|
|
237
|
-
* Logout user and redirect
|
|
238
|
-
* Calls logout API with x-client-token header, clears tokens from localStorage, clears cache, and redirects
|
|
239
|
-
* @param redirectUrl - Optional redirect URL after logout (defaults to logoutUrl or loginUrl)
|
|
240
|
-
*/
|
|
241
114
|
async logout(redirectUrl) {
|
|
242
115
|
return (0, data_client_auth_1.logout)(this.config, () => this.getToken(), () => this.getClientToken(), () => this.clearCache(), redirectUrl, this.misoClient);
|
|
243
116
|
}
|
|
244
|
-
|
|
245
|
-
* Set interceptors
|
|
246
|
-
*/
|
|
117
|
+
// ==================== CONFIGURATION ====================
|
|
247
118
|
setInterceptors(config) {
|
|
248
119
|
this.interceptors = { ...this.interceptors, ...config };
|
|
249
120
|
}
|
|
250
|
-
/**
|
|
251
|
-
* Set audit configuration
|
|
252
|
-
*/
|
|
253
121
|
setAuditConfig(config) {
|
|
254
122
|
this.config.audit = { ...this.config.audit, ...config };
|
|
255
123
|
}
|
|
256
|
-
/**
|
|
257
|
-
* Set log level for MisoClient logger
|
|
258
|
-
* Note: This updates the MisoClient config logLevel if MisoClient is initialized
|
|
259
|
-
* @param level - Log level ('debug' | 'info' | 'warn' | 'error')
|
|
260
|
-
*/
|
|
261
124
|
setLogLevel(level) {
|
|
262
125
|
if (this.misoClient && this.config.misoConfig) {
|
|
263
|
-
// Update the config's logLevel
|
|
264
|
-
// Note: TypeScript readonly doesn't prevent runtime updates
|
|
265
126
|
this.config.misoConfig.logLevel = level;
|
|
266
|
-
// Also try to update MisoClient's internal config if accessible
|
|
267
127
|
try {
|
|
268
128
|
const misoConfig = this.misoClient.config;
|
|
269
|
-
if (misoConfig)
|
|
129
|
+
if (misoConfig)
|
|
270
130
|
misoConfig.logLevel = level;
|
|
271
|
-
}
|
|
272
131
|
}
|
|
273
132
|
catch {
|
|
274
133
|
// Silently ignore if config is not accessible
|
|
275
134
|
}
|
|
276
135
|
}
|
|
277
136
|
}
|
|
278
|
-
/**
|
|
279
|
-
* Clear all cached responses
|
|
280
|
-
*/
|
|
281
137
|
clearCache() {
|
|
282
138
|
this.cache.clear();
|
|
283
139
|
}
|
|
284
|
-
/**
|
|
285
|
-
* Get request metrics
|
|
286
|
-
*/
|
|
287
140
|
getMetrics() {
|
|
288
141
|
const responseTimes = (this.metrics.responseTimes || []).sort((a, b) => a - b);
|
|
289
142
|
const len = responseTimes.length;
|
|
290
143
|
return {
|
|
291
144
|
totalRequests: this.metrics.totalRequests,
|
|
292
145
|
totalFailures: this.metrics.totalFailures,
|
|
293
|
-
averageResponseTime: len > 0
|
|
294
|
-
? responseTimes.reduce((a, b) => a + b, 0) / len
|
|
295
|
-
: 0,
|
|
146
|
+
averageResponseTime: len > 0 ? responseTimes.reduce((a, b) => a + b, 0) / len : 0,
|
|
296
147
|
responseTimeDistribution: {
|
|
297
148
|
min: len > 0 ? responseTimes[0] : 0,
|
|
298
149
|
max: len > 0 ? responseTimes[len - 1] : 0,
|
|
@@ -300,128 +151,84 @@ class DataClient {
|
|
|
300
151
|
p95: len > 0 ? responseTimes[Math.floor(len * 0.95)] : 0,
|
|
301
152
|
p99: len > 0 ? responseTimes[Math.floor(len * 0.99)] : 0,
|
|
302
153
|
},
|
|
303
|
-
errorRate: this.metrics.totalRequests > 0
|
|
304
|
-
? this.metrics.totalFailures / this.metrics.totalRequests
|
|
305
|
-
: 0,
|
|
154
|
+
errorRate: this.metrics.totalRequests > 0 ? this.metrics.totalFailures / this.metrics.totalRequests : 0,
|
|
306
155
|
cacheHitRate: this.metrics.cacheHits + this.metrics.cacheMisses > 0
|
|
307
|
-
? this.metrics.cacheHits /
|
|
308
|
-
(this.metrics.cacheHits + this.metrics.cacheMisses)
|
|
156
|
+
? this.metrics.cacheHits / (this.metrics.cacheHits + this.metrics.cacheMisses)
|
|
309
157
|
: 0,
|
|
310
158
|
};
|
|
311
159
|
}
|
|
312
|
-
|
|
313
|
-
* Make HTTP request with all features (caching, retry, deduplication, audit)
|
|
314
|
-
*/
|
|
160
|
+
// ==================== HTTP REQUEST CORE ====================
|
|
315
161
|
async request(method, endpoint, options) {
|
|
316
162
|
const startTime = Date.now();
|
|
317
163
|
const fullUrl = `${this.config.baseUrl}${endpoint}`;
|
|
318
|
-
// Generate cache key with explicit method to ensure consistency
|
|
319
|
-
// Use method parameter (from get/post/etc) not options.method which might be undefined
|
|
320
164
|
const cacheKeyOptions = { ...options, method: method.toUpperCase() };
|
|
321
165
|
const cacheKey = (0, data_client_cache_1.getCacheKeyForRequest)(endpoint, cacheKeyOptions);
|
|
322
166
|
const isGetRequest = method.toUpperCase() === "GET";
|
|
323
167
|
const cacheEnabled = (0, data_client_cache_1.isCacheEnabled)(method, this.config.cache, options);
|
|
324
|
-
//
|
|
325
|
-
// This prevents any requests to failing endpoints, even if cache is cleared
|
|
168
|
+
// Circuit breaker check
|
|
326
169
|
const failedRequest = this.failedRequests.get(cacheKey);
|
|
327
170
|
if (failedRequest) {
|
|
328
171
|
const timeSinceFailure = Date.now() - failedRequest.timestamp;
|
|
329
172
|
const failureCount = failedRequest.count || 1;
|
|
330
|
-
// Exponential backoff: 5s, 15s, 30s, 30s...
|
|
331
173
|
const cooldownPeriod = failureCount === 1 ? 5000 : failureCount === 2 ? 15000 : 30000;
|
|
332
174
|
if (timeSinceFailure < cooldownPeriod) {
|
|
333
|
-
// Return rejected promise with the same error to prevent duplicate requests
|
|
334
|
-
// This prevents React Query and other retry mechanisms from hammering the server
|
|
335
|
-
// Re-throw the same error to maintain error consistency
|
|
336
175
|
throw failedRequest.error;
|
|
337
176
|
}
|
|
338
177
|
else {
|
|
339
|
-
// Clean up old failed request entry after cooldown expires
|
|
340
178
|
this.failedRequests.delete(cacheKey);
|
|
341
179
|
}
|
|
342
180
|
}
|
|
343
|
-
// Check cache for GET requests
|
|
181
|
+
// Check cache for GET requests
|
|
344
182
|
if (cacheEnabled) {
|
|
345
183
|
const cached = (0, data_client_cache_1.getCachedEntry)(this.cache, cacheKey, this.metrics);
|
|
346
|
-
if (cached !== null)
|
|
184
|
+
if (cached !== null)
|
|
347
185
|
return cached;
|
|
348
|
-
}
|
|
349
186
|
}
|
|
350
|
-
//
|
|
351
|
-
// This must be atomic to prevent race conditions when multiple requests arrive simultaneously
|
|
187
|
+
// Check for duplicate concurrent requests
|
|
352
188
|
if (isGetRequest) {
|
|
353
189
|
const pendingRequest = this.pendingRequests.get(cacheKey);
|
|
354
|
-
if (pendingRequest)
|
|
190
|
+
if (pendingRequest)
|
|
355
191
|
return pendingRequest;
|
|
356
|
-
}
|
|
357
192
|
}
|
|
358
|
-
//
|
|
359
|
-
// This prevents race conditions where multiple requests check before any are stored
|
|
193
|
+
// Execute request
|
|
360
194
|
let requestPromise;
|
|
361
195
|
if (isGetRequest) {
|
|
362
|
-
// For GET requests, create a promise that wraps the actual execution
|
|
363
|
-
// Store it immediately to prevent race conditions
|
|
364
196
|
requestPromise = (async () => {
|
|
365
197
|
try {
|
|
366
198
|
return await (0, data_client_request_1.executeHttpRequest)(method, fullUrl, endpoint, this.config, this.cache, cacheKey, cacheEnabled, startTime, this.misoClient, () => this.hasAnyToken(), () => this.getToken(), () => this.handleAuthError(), () => this.refreshUserToken(), this.interceptors, this.metrics, options);
|
|
367
199
|
}
|
|
368
200
|
finally {
|
|
369
|
-
// Cleanup pending request when done (success or failure)
|
|
370
201
|
this.pendingRequests.delete(cacheKey);
|
|
371
202
|
}
|
|
372
203
|
})();
|
|
373
|
-
// Store immediately - this is atomic and prevents race conditions
|
|
374
|
-
// If another request comes in now, it will see this promise and reuse it
|
|
375
204
|
this.pendingRequests.set(cacheKey, requestPromise);
|
|
376
205
|
}
|
|
377
206
|
else {
|
|
378
|
-
// For non-GET requests, execute directly (no deduplication)
|
|
379
207
|
requestPromise = (0, data_client_request_1.executeHttpRequest)(method, fullUrl, endpoint, this.config, this.cache, cacheKey, cacheEnabled, startTime, this.misoClient, () => this.hasAnyToken(), () => this.getToken(), () => this.handleAuthError(), () => this.refreshUserToken(), this.interceptors, this.metrics, options);
|
|
380
208
|
}
|
|
381
209
|
try {
|
|
382
210
|
const result = await requestPromise;
|
|
383
|
-
// Clean up failed request entry on success (works for all methods)
|
|
384
211
|
this.failedRequests.delete(cacheKey);
|
|
385
212
|
return result;
|
|
386
213
|
}
|
|
387
214
|
catch (error) {
|
|
388
|
-
// Store failed request to prevent rapid re-requests (works for all methods)
|
|
389
|
-
// Circuit breaker pattern: track failure count for exponential backoff
|
|
390
215
|
const existingFailure = this.failedRequests.get(cacheKey);
|
|
391
216
|
const failureCount = existingFailure ? (existingFailure.count || 1) + 1 : 1;
|
|
392
|
-
this.failedRequests.set(cacheKey, {
|
|
393
|
-
|
|
394
|
-
error: error,
|
|
395
|
-
count: failureCount,
|
|
396
|
-
});
|
|
397
|
-
// Clean up after maximum cooldown period (30 seconds)
|
|
398
|
-
// This prevents memory leaks while still providing protection
|
|
399
|
-
setTimeout(() => {
|
|
400
|
-
this.failedRequests.delete(cacheKey);
|
|
401
|
-
}, 30000);
|
|
217
|
+
this.failedRequests.set(cacheKey, { timestamp: Date.now(), error: error, count: failureCount });
|
|
218
|
+
setTimeout(() => this.failedRequests.delete(cacheKey), 30000);
|
|
402
219
|
throw error;
|
|
403
220
|
}
|
|
404
221
|
}
|
|
405
|
-
/**
|
|
406
|
-
* Refresh user token using onTokenRefresh callback
|
|
407
|
-
* @returns New token and expiration, or null if refresh failed
|
|
408
|
-
*/
|
|
409
222
|
async refreshUserToken() {
|
|
410
|
-
if (!this.config.onTokenRefresh)
|
|
223
|
+
if (!this.config.onTokenRefresh)
|
|
411
224
|
return null;
|
|
412
|
-
}
|
|
413
225
|
try {
|
|
414
226
|
const result = await this.config.onTokenRefresh();
|
|
415
|
-
// Update token in localStorage
|
|
416
227
|
if ((0, data_client_utils_1.isBrowser)() && result.token) {
|
|
417
228
|
const { setLocalStorage } = await Promise.resolve().then(() => __importStar(require("./data-client-utils")));
|
|
418
|
-
const
|
|
419
|
-
// Store token in all configured keys
|
|
420
|
-
for (const key of tokenKeys) {
|
|
229
|
+
for (const key of this.config.tokenKeys || ["token", "accessToken", "authToken"]) {
|
|
421
230
|
setLocalStorage(key, result.token);
|
|
422
231
|
}
|
|
423
|
-
// Note: Refresh token is NOT stored in localStorage for security
|
|
424
|
-
// The backend endpoint handles refresh token securely (httpOnly cookie or session)
|
|
425
232
|
}
|
|
426
233
|
return result;
|
|
427
234
|
}
|
|
@@ -430,360 +237,114 @@ class DataClient {
|
|
|
430
237
|
return null;
|
|
431
238
|
}
|
|
432
239
|
}
|
|
433
|
-
/**
|
|
434
|
-
* Handle authentication error
|
|
435
|
-
*/
|
|
436
240
|
handleAuthError() {
|
|
437
241
|
if ((0, data_client_utils_1.isBrowser)()) {
|
|
438
|
-
|
|
439
|
-
this.redirectToLogin().catch((error) => {
|
|
440
|
-
console.error("Failed to redirect to login:", error);
|
|
441
|
-
});
|
|
242
|
+
this.redirectToLogin().catch((error) => console.error("Failed to redirect to login:", error));
|
|
442
243
|
}
|
|
443
244
|
}
|
|
444
|
-
/**
|
|
445
|
-
* Apply request interceptor
|
|
446
|
-
*/
|
|
447
245
|
async applyRequestInterceptor(url, options) {
|
|
448
|
-
|
|
449
|
-
return await this.interceptors.onRequest(url, options);
|
|
450
|
-
}
|
|
451
|
-
return options;
|
|
246
|
+
return this.interceptors.onRequest ? await this.interceptors.onRequest(url, options) : options;
|
|
452
247
|
}
|
|
453
248
|
// ==================== HTTP METHODS ====================
|
|
454
|
-
/**
|
|
455
|
-
* GET request
|
|
456
|
-
*/
|
|
457
249
|
async get(endpoint, options) {
|
|
458
|
-
const finalOptions = await this.applyRequestInterceptor(endpoint, {
|
|
459
|
-
...options,
|
|
460
|
-
method: "GET",
|
|
461
|
-
});
|
|
250
|
+
const finalOptions = await this.applyRequestInterceptor(endpoint, { ...options, method: "GET" });
|
|
462
251
|
return this.request("GET", endpoint, finalOptions);
|
|
463
252
|
}
|
|
464
|
-
/**
|
|
465
|
-
* POST request
|
|
466
|
-
*/
|
|
467
253
|
async post(endpoint, data, options) {
|
|
468
254
|
const finalOptions = await this.applyRequestInterceptor(endpoint, {
|
|
469
|
-
...options,
|
|
470
|
-
|
|
471
|
-
body: data ? JSON.stringify(data) : undefined,
|
|
472
|
-
headers: {
|
|
473
|
-
"Content-Type": "application/json",
|
|
474
|
-
...options?.headers,
|
|
475
|
-
},
|
|
255
|
+
...options, method: "POST", body: data ? JSON.stringify(data) : undefined,
|
|
256
|
+
headers: { "Content-Type": "application/json", ...options?.headers },
|
|
476
257
|
});
|
|
477
258
|
return this.request("POST", endpoint, finalOptions);
|
|
478
259
|
}
|
|
479
|
-
/**
|
|
480
|
-
* PUT request
|
|
481
|
-
*/
|
|
482
260
|
async put(endpoint, data, options) {
|
|
483
261
|
const finalOptions = await this.applyRequestInterceptor(endpoint, {
|
|
484
|
-
...options,
|
|
485
|
-
|
|
486
|
-
body: data ? JSON.stringify(data) : undefined,
|
|
487
|
-
headers: {
|
|
488
|
-
"Content-Type": "application/json",
|
|
489
|
-
...options?.headers,
|
|
490
|
-
},
|
|
262
|
+
...options, method: "PUT", body: data ? JSON.stringify(data) : undefined,
|
|
263
|
+
headers: { "Content-Type": "application/json", ...options?.headers },
|
|
491
264
|
});
|
|
492
265
|
return this.request("PUT", endpoint, finalOptions);
|
|
493
266
|
}
|
|
494
|
-
/**
|
|
495
|
-
* PATCH request (uses fetch fallback since MisoClient doesn't support PATCH)
|
|
496
|
-
*/
|
|
497
267
|
async patch(endpoint, data, options) {
|
|
498
268
|
const finalOptions = await this.applyRequestInterceptor(endpoint, {
|
|
499
|
-
...options,
|
|
500
|
-
|
|
501
|
-
body: data ? JSON.stringify(data) : undefined,
|
|
502
|
-
headers: {
|
|
503
|
-
"Content-Type": "application/json",
|
|
504
|
-
...options?.headers,
|
|
505
|
-
},
|
|
269
|
+
...options, method: "PATCH", body: data ? JSON.stringify(data) : undefined,
|
|
270
|
+
headers: { "Content-Type": "application/json", ...options?.headers },
|
|
506
271
|
});
|
|
507
272
|
return this.request("PATCH", endpoint, finalOptions);
|
|
508
273
|
}
|
|
509
|
-
/**
|
|
510
|
-
* DELETE request
|
|
511
|
-
*/
|
|
512
274
|
async delete(endpoint, options) {
|
|
513
|
-
const finalOptions = await this.applyRequestInterceptor(endpoint, {
|
|
514
|
-
...options,
|
|
515
|
-
method: "DELETE",
|
|
516
|
-
});
|
|
275
|
+
const finalOptions = await this.applyRequestInterceptor(endpoint, { ...options, method: "DELETE" });
|
|
517
276
|
return this.request("DELETE", endpoint, finalOptions);
|
|
518
277
|
}
|
|
519
|
-
// ====================
|
|
520
|
-
/**
|
|
521
|
-
* Get user permissions (uses token from localStorage if not provided)
|
|
522
|
-
* @param token - Optional user authentication token (auto-retrieved from localStorage if not provided)
|
|
523
|
-
* @returns Array of permission strings
|
|
524
|
-
*/
|
|
278
|
+
// ==================== PERMISSION METHODS ====================
|
|
525
279
|
async getPermissions(token) {
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
}
|
|
529
|
-
const userToken = token || this.getToken();
|
|
530
|
-
if (!userToken) {
|
|
531
|
-
return [];
|
|
532
|
-
}
|
|
533
|
-
return this.permissionService.getPermissions(userToken);
|
|
534
|
-
}
|
|
535
|
-
/**
|
|
536
|
-
* Check if user has specific permission
|
|
537
|
-
* @param permission - Permission to check
|
|
538
|
-
* @param token - Optional user authentication token (auto-retrieved from localStorage if not provided)
|
|
539
|
-
* @returns True if user has the permission
|
|
540
|
-
*/
|
|
280
|
+
return permissionHelpers.getPermissions(this.permissionService, this.misoClient, () => this.getToken(), token);
|
|
281
|
+
}
|
|
541
282
|
async hasPermission(permission, token) {
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
}
|
|
545
|
-
const userToken = token || this.getToken();
|
|
546
|
-
if (!userToken) {
|
|
547
|
-
return false;
|
|
548
|
-
}
|
|
549
|
-
return this.permissionService.hasPermission(userToken, permission);
|
|
550
|
-
}
|
|
551
|
-
/**
|
|
552
|
-
* Check if user has any of the specified permissions
|
|
553
|
-
* @param permissions - Permissions to check
|
|
554
|
-
* @param token - Optional user authentication token (auto-retrieved from localStorage if not provided)
|
|
555
|
-
* @returns True if user has any of the permissions
|
|
556
|
-
*/
|
|
283
|
+
return permissionHelpers.hasPermission(this.permissionService, this.misoClient, () => this.getToken(), permission, token);
|
|
284
|
+
}
|
|
557
285
|
async hasAnyPermission(permissions, token) {
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
}
|
|
561
|
-
const userToken = token || this.getToken();
|
|
562
|
-
if (!userToken) {
|
|
563
|
-
return false;
|
|
564
|
-
}
|
|
565
|
-
return this.permissionService.hasAnyPermission(userToken, permissions);
|
|
566
|
-
}
|
|
567
|
-
/**
|
|
568
|
-
* Check if user has all of the specified permissions
|
|
569
|
-
* @param permissions - Permissions to check
|
|
570
|
-
* @param token - Optional user authentication token (auto-retrieved from localStorage if not provided)
|
|
571
|
-
* @returns True if user has all of the permissions
|
|
572
|
-
*/
|
|
286
|
+
return permissionHelpers.hasAnyPermission(this.permissionService, this.misoClient, () => this.getToken(), permissions, token);
|
|
287
|
+
}
|
|
573
288
|
async hasAllPermissions(permissions, token) {
|
|
574
|
-
|
|
575
|
-
return false;
|
|
576
|
-
}
|
|
577
|
-
const userToken = token || this.getToken();
|
|
578
|
-
if (!userToken) {
|
|
579
|
-
return false;
|
|
580
|
-
}
|
|
581
|
-
return this.permissionService.hasAllPermissions(userToken, permissions);
|
|
289
|
+
return permissionHelpers.hasAllPermissions(this.permissionService, this.misoClient, () => this.getToken(), permissions, token);
|
|
582
290
|
}
|
|
583
|
-
/**
|
|
584
|
-
* Force refresh permissions from controller (bypass cache)
|
|
585
|
-
* @param token - Optional user authentication token (auto-retrieved from localStorage if not provided)
|
|
586
|
-
* @returns Array of permission strings
|
|
587
|
-
*/
|
|
588
291
|
async refreshPermissions(token) {
|
|
589
|
-
|
|
590
|
-
return [];
|
|
591
|
-
}
|
|
592
|
-
const userToken = token || this.getToken();
|
|
593
|
-
if (!userToken) {
|
|
594
|
-
return [];
|
|
595
|
-
}
|
|
596
|
-
return this.permissionService.refreshPermissions(userToken);
|
|
292
|
+
return permissionHelpers.refreshPermissions(this.permissionService, this.misoClient, () => this.getToken(), token);
|
|
597
293
|
}
|
|
598
|
-
/**
|
|
599
|
-
* Clear cached permissions for a user
|
|
600
|
-
* @param token - Optional user authentication token (auto-retrieved from localStorage if not provided)
|
|
601
|
-
*/
|
|
602
294
|
async clearPermissionsCache(token) {
|
|
603
|
-
|
|
604
|
-
return;
|
|
605
|
-
}
|
|
606
|
-
const userToken = token || this.getToken();
|
|
607
|
-
if (!userToken) {
|
|
608
|
-
return;
|
|
609
|
-
}
|
|
610
|
-
return this.permissionService.clearPermissionsCache(userToken);
|
|
295
|
+
return permissionHelpers.clearPermissionsCache(this.permissionService, this.misoClient, () => this.getToken(), token);
|
|
611
296
|
}
|
|
612
|
-
|
|
613
|
-
* Get user roles (uses token from localStorage if not provided)
|
|
614
|
-
* @param token - Optional user authentication token (auto-retrieved from localStorage if not provided)
|
|
615
|
-
* @returns Array of role strings
|
|
616
|
-
*/
|
|
297
|
+
// ==================== ROLE METHODS ====================
|
|
617
298
|
async getRoles(token) {
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
}
|
|
621
|
-
const userToken = token || this.getToken();
|
|
622
|
-
if (!userToken) {
|
|
623
|
-
return [];
|
|
624
|
-
}
|
|
625
|
-
return this.roleService.getRoles(userToken);
|
|
626
|
-
}
|
|
627
|
-
/**
|
|
628
|
-
* Check if user has specific role
|
|
629
|
-
* @param role - Role to check
|
|
630
|
-
* @param token - Optional user authentication token (auto-retrieved from localStorage if not provided)
|
|
631
|
-
* @returns True if user has the role
|
|
632
|
-
*/
|
|
299
|
+
return roleHelpers.getRoles(this.roleService, this.misoClient, () => this.getToken(), token);
|
|
300
|
+
}
|
|
633
301
|
async hasRole(role, token) {
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
}
|
|
637
|
-
const userToken = token || this.getToken();
|
|
638
|
-
if (!userToken) {
|
|
639
|
-
return false;
|
|
640
|
-
}
|
|
641
|
-
return this.roleService.hasRole(userToken, role);
|
|
642
|
-
}
|
|
643
|
-
/**
|
|
644
|
-
* Check if user has any of the specified roles
|
|
645
|
-
* @param roles - Roles to check
|
|
646
|
-
* @param token - Optional user authentication token (auto-retrieved from localStorage if not provided)
|
|
647
|
-
* @returns True if user has any of the roles
|
|
648
|
-
*/
|
|
302
|
+
return roleHelpers.hasRole(this.roleService, this.misoClient, () => this.getToken(), role, token);
|
|
303
|
+
}
|
|
649
304
|
async hasAnyRole(roles, token) {
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
}
|
|
653
|
-
const userToken = token || this.getToken();
|
|
654
|
-
if (!userToken) {
|
|
655
|
-
return false;
|
|
656
|
-
}
|
|
657
|
-
return this.roleService.hasAnyRole(userToken, roles);
|
|
658
|
-
}
|
|
659
|
-
/**
|
|
660
|
-
* Check if user has all of the specified roles
|
|
661
|
-
* @param roles - Roles to check
|
|
662
|
-
* @param token - Optional user authentication token (auto-retrieved from localStorage if not provided)
|
|
663
|
-
* @returns True if user has all of the roles
|
|
664
|
-
*/
|
|
305
|
+
return roleHelpers.hasAnyRole(this.roleService, this.misoClient, () => this.getToken(), roles, token);
|
|
306
|
+
}
|
|
665
307
|
async hasAllRoles(roles, token) {
|
|
666
|
-
|
|
667
|
-
return false;
|
|
668
|
-
}
|
|
669
|
-
const userToken = token || this.getToken();
|
|
670
|
-
if (!userToken) {
|
|
671
|
-
return false;
|
|
672
|
-
}
|
|
673
|
-
return this.roleService.hasAllRoles(userToken, roles);
|
|
308
|
+
return roleHelpers.hasAllRoles(this.roleService, this.misoClient, () => this.getToken(), roles, token);
|
|
674
309
|
}
|
|
675
|
-
/**
|
|
676
|
-
* Force refresh roles from controller (bypass cache)
|
|
677
|
-
* @param token - Optional user authentication token (auto-retrieved from localStorage if not provided)
|
|
678
|
-
* @returns Array of role strings
|
|
679
|
-
*/
|
|
680
310
|
async refreshRoles(token) {
|
|
681
|
-
|
|
682
|
-
return [];
|
|
683
|
-
}
|
|
684
|
-
const userToken = token || this.getToken();
|
|
685
|
-
if (!userToken) {
|
|
686
|
-
return [];
|
|
687
|
-
}
|
|
688
|
-
return this.roleService.refreshRoles(userToken);
|
|
311
|
+
return roleHelpers.refreshRoles(this.roleService, this.misoClient, () => this.getToken(), token);
|
|
689
312
|
}
|
|
690
|
-
/**
|
|
691
|
-
* Clear cached roles for a user
|
|
692
|
-
* @param token - Optional user authentication token (auto-retrieved from localStorage if not provided)
|
|
693
|
-
*/
|
|
694
313
|
async clearRolesCache(token) {
|
|
695
|
-
|
|
696
|
-
return;
|
|
697
|
-
}
|
|
698
|
-
const userToken = token || this.getToken();
|
|
699
|
-
if (!userToken) {
|
|
700
|
-
return;
|
|
701
|
-
}
|
|
702
|
-
return this.roleService.clearRolesCache(userToken);
|
|
314
|
+
return roleHelpers.clearRolesCache(this.roleService, this.misoClient, () => this.getToken(), token);
|
|
703
315
|
}
|
|
704
316
|
// ==================== AUTHENTICATION METHODS ====================
|
|
705
|
-
/**
|
|
706
|
-
* Validate token (uses localStorage token if not provided)
|
|
707
|
-
* @param token - Optional user authentication token (auto-retrieved from localStorage if not provided)
|
|
708
|
-
* @returns True if token is valid
|
|
709
|
-
*/
|
|
710
317
|
async validateToken(token) {
|
|
711
|
-
if (!this.misoClient)
|
|
318
|
+
if (!this.misoClient)
|
|
712
319
|
return false;
|
|
713
|
-
}
|
|
714
320
|
const userToken = token || this.getToken();
|
|
715
|
-
|
|
716
|
-
return false;
|
|
717
|
-
}
|
|
718
|
-
return this.misoClient.validateToken(userToken);
|
|
321
|
+
return userToken ? this.misoClient.validateToken(userToken) : false;
|
|
719
322
|
}
|
|
720
|
-
/**
|
|
721
|
-
* Get user info from token (uses localStorage token if not provided)
|
|
722
|
-
* @param token - Optional user authentication token (auto-retrieved from localStorage if not provided)
|
|
723
|
-
* @returns User info or null if not authenticated
|
|
724
|
-
*/
|
|
725
323
|
async getUser(token) {
|
|
726
|
-
if (!this.misoClient)
|
|
324
|
+
if (!this.misoClient)
|
|
727
325
|
return null;
|
|
728
|
-
}
|
|
729
326
|
const userToken = token || this.getToken();
|
|
730
|
-
|
|
731
|
-
return null;
|
|
732
|
-
}
|
|
733
|
-
return this.misoClient.getUser(userToken);
|
|
327
|
+
return userToken ? this.misoClient.getUser(userToken) : null;
|
|
734
328
|
}
|
|
735
|
-
/**
|
|
736
|
-
* Get user info from API endpoint (uses localStorage token if not provided)
|
|
737
|
-
* @param token - Optional user authentication token (auto-retrieved from localStorage if not provided)
|
|
738
|
-
* @returns User info or null if not authenticated
|
|
739
|
-
*/
|
|
740
329
|
async getUserInfo(token) {
|
|
741
|
-
if (!this.misoClient)
|
|
330
|
+
if (!this.misoClient)
|
|
742
331
|
return null;
|
|
743
|
-
}
|
|
744
332
|
const userToken = token || this.getToken();
|
|
745
|
-
|
|
746
|
-
return null;
|
|
747
|
-
}
|
|
748
|
-
return this.misoClient.getUserInfo(userToken);
|
|
333
|
+
return userToken ? this.misoClient.getUserInfo(userToken) : null;
|
|
749
334
|
}
|
|
750
|
-
/**
|
|
751
|
-
* Check if authenticated (alias for validateToken)
|
|
752
|
-
* @param token - Optional user authentication token (auto-retrieved from localStorage if not provided)
|
|
753
|
-
* @returns True if authenticated
|
|
754
|
-
*/
|
|
755
335
|
async isAuthenticatedAsync(token) {
|
|
756
336
|
return this.validateToken(token);
|
|
757
337
|
}
|
|
758
|
-
/**
|
|
759
|
-
* Get environment token (browser-side)
|
|
760
|
-
* Checks localStorage cache first, then calls backend endpoint if needed
|
|
761
|
-
* Uses clientTokenUri from config or defaults to /api/v1/auth/client-token
|
|
762
|
-
*
|
|
763
|
-
* @returns Client token string
|
|
764
|
-
* @throws Error if token fetch fails
|
|
765
|
-
*/
|
|
766
338
|
async getEnvironmentToken() {
|
|
767
339
|
return (0, data_client_auth_1.getEnvironmentToken)(this.config, this.misoClient);
|
|
768
340
|
}
|
|
769
|
-
/**
|
|
770
|
-
* Get client token information (browser-side)
|
|
771
|
-
* Extracts application and environment info from client token
|
|
772
|
-
*
|
|
773
|
-
* @returns Client token info or null if token not available
|
|
774
|
-
*/
|
|
775
341
|
getClientTokenInfo() {
|
|
776
342
|
return (0, data_client_auth_1.getClientTokenInfo)(this.config.misoConfig);
|
|
777
343
|
}
|
|
778
344
|
}
|
|
779
345
|
exports.DataClient = DataClient;
|
|
780
|
-
|
|
781
|
-
* Singleton instance factory
|
|
782
|
-
*/
|
|
346
|
+
// ==================== SINGLETON FACTORY ====================
|
|
783
347
|
let defaultDataClient = null;
|
|
784
|
-
/**
|
|
785
|
-
* Get or create default DataClient instance
|
|
786
|
-
*/
|
|
787
348
|
function dataClient(config) {
|
|
788
349
|
if (!defaultDataClient && config) {
|
|
789
350
|
defaultDataClient = new DataClient(config);
|