@aakash58/chatbot 1.1.34 → 1.1.35
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/fesm2022/aakash58-chatbot.mjs +197 -186
- package/fesm2022/aakash58-chatbot.mjs.map +1 -1
- package/index.d.ts +26 -3
- package/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { isDevMode, InjectionToken, signal, Optional, Inject, Injectable, inject, effect, EventEmitter, Output, Input, Component, Pipe, ViewChild, HostListener, Directive, computed, ChangeDetectionStrategy, ElementRef, ViewEncapsulation, makeEnvironmentProviders } from '@angular/core';
|
|
3
|
-
import { delay, retry, map, catchError, of,
|
|
3
|
+
import { BehaviorSubject, delay, retry, map, catchError, of, firstValueFrom, throwError, tap, Observable, Subject, lastValueFrom, switchMap, filter, take } from 'rxjs';
|
|
4
4
|
import { JwtHelperService } from '@auth0/angular-jwt';
|
|
5
5
|
import * as i1 from '@angular/common/http';
|
|
6
|
-
import { HttpHeaders, HttpEventType,
|
|
6
|
+
import { HttpHeaders, HttpEventType, HttpErrorResponse, HTTP_INTERCEPTORS } from '@angular/common/http';
|
|
7
7
|
import * as CryptoJS from 'crypto-js';
|
|
8
8
|
import * as i4 from '@angular/router';
|
|
9
9
|
import * as i1$1 from '@angular/cdk/overlay';
|
|
@@ -178,13 +178,12 @@ const DEFAULT_DOOHBOT_CONFIG = {
|
|
|
178
178
|
retryAttempts: 2,
|
|
179
179
|
retryDelay: 1000,
|
|
180
180
|
apiSegment: 'api/',
|
|
181
|
-
secretKey:
|
|
181
|
+
secretKey: undefined,
|
|
182
182
|
storageKey: 'doohbot_storage',
|
|
183
|
-
authToken: '',
|
|
184
|
-
companyCode: '',
|
|
185
|
-
tenancyName: '',
|
|
186
|
-
licenseKey: '',
|
|
187
|
-
licenseFilePath: '',
|
|
183
|
+
authToken: 'doohbot_storage',
|
|
184
|
+
companyCode: 'doohbot_storage',
|
|
185
|
+
tenancyName: 'doohbot_storage',
|
|
186
|
+
licenseKey: 'doohbot_storage',
|
|
188
187
|
rememberMe: false,
|
|
189
188
|
useStandardApi: false,
|
|
190
189
|
enableDrag: false,
|
|
@@ -198,58 +197,72 @@ const DEFAULT_DOOHBOT_CONFIG = {
|
|
|
198
197
|
*/
|
|
199
198
|
const DOOHBOT_CONFIG = new InjectionToken('DOOHBOT_CONFIG');
|
|
200
199
|
|
|
201
|
-
|
|
202
|
-
|
|
200
|
+
/**
|
|
201
|
+
* Centralized service for managing Doohbot configuration.
|
|
202
|
+
* Provides reactive access and runtime updates.
|
|
203
|
+
* Singleton via providedIn: 'root'.
|
|
204
|
+
*/
|
|
205
|
+
class DoohbotConfigService {
|
|
206
|
+
/** Current configuration snapshot */
|
|
207
|
+
get config() {
|
|
208
|
+
return this.configSignal();
|
|
209
|
+
}
|
|
203
210
|
constructor(injectedConfig = {}) {
|
|
204
|
-
// Use DoohbotConfig for type-safe signal
|
|
205
|
-
this.configSignal = signal({
|
|
206
|
-
...DEFAULT_DOOHBOT_CONFIG,
|
|
207
|
-
}, ...(ngDevMode ? [{ debugName: "configSignal" }] : []));
|
|
208
|
-
this.config$ = this.configSignal.asReadonly();
|
|
209
211
|
// Merge injected config with defaults
|
|
210
|
-
|
|
212
|
+
const mergedConfig = {
|
|
211
213
|
...DEFAULT_DOOHBOT_CONFIG,
|
|
212
214
|
...injectedConfig,
|
|
213
215
|
};
|
|
214
|
-
|
|
215
|
-
|
|
216
|
+
this.validateConfig(mergedConfig);
|
|
217
|
+
// Initialize state
|
|
218
|
+
this.configSignal = signal(mergedConfig, ...(ngDevMode ? [{ debugName: "configSignal" }] : []));
|
|
219
|
+
this.configSubject = new BehaviorSubject(mergedConfig);
|
|
220
|
+
this.config$ = this.configSubject.asObservable();
|
|
216
221
|
}
|
|
217
222
|
/**
|
|
218
|
-
* Updates the global library configuration
|
|
223
|
+
* Updates the global library configuration from dynamic runtime fields
|
|
219
224
|
*/
|
|
220
|
-
|
|
225
|
+
updateRuntimeInput(input) {
|
|
221
226
|
if (!input)
|
|
222
227
|
return;
|
|
223
|
-
|
|
228
|
+
const current = this.configSignal();
|
|
224
229
|
const updatedConfig = {
|
|
225
|
-
...
|
|
226
|
-
authToken: input.authToken ??
|
|
230
|
+
...current,
|
|
231
|
+
authToken: input.authToken ?? current.authToken,
|
|
232
|
+
licenseKey: input.licenseKey ?? current.licenseKey,
|
|
233
|
+
licenseFilePath: input.licenseFilePath ?? current.licenseFilePath,
|
|
227
234
|
};
|
|
228
|
-
this.
|
|
235
|
+
this.updateConfig(updatedConfig);
|
|
229
236
|
}
|
|
230
237
|
/**
|
|
231
238
|
* Update configuration at runtime.
|
|
232
239
|
* @param updates Partial config updates
|
|
233
240
|
*/
|
|
234
|
-
|
|
241
|
+
updateConfig(updates) {
|
|
235
242
|
const newConfig = { ...this.configSignal(), ...updates };
|
|
243
|
+
this.validateConfig(newConfig);
|
|
236
244
|
this.configSignal.set(newConfig);
|
|
245
|
+
this.configSubject.next(newConfig);
|
|
246
|
+
}
|
|
247
|
+
validateConfig(config) {
|
|
248
|
+
if (config.timeout < 0)
|
|
249
|
+
throw new Error('timeout must be >= 0');
|
|
250
|
+
if (config.maxHistoryMessages < 0)
|
|
251
|
+
throw new Error('maxHistoryMessages must be >= 0');
|
|
252
|
+
if (config.retryAttempts < 0)
|
|
253
|
+
throw new Error('retryAttempts must be >= 0');
|
|
254
|
+
if (config.retryDelay < 0)
|
|
255
|
+
throw new Error('retryDelay must be >= 0');
|
|
237
256
|
}
|
|
238
257
|
/**
|
|
239
258
|
* Dynamic getters for common config properties
|
|
240
259
|
*/
|
|
241
260
|
get apiUrl() {
|
|
242
261
|
const config = this.configSignal();
|
|
243
|
-
|
|
244
|
-
return `${config.apiBaseUrl}${config.apiSegment || ''}`;
|
|
245
|
-
}
|
|
246
|
-
// Fallback to AppConst
|
|
247
|
-
const appBase = this.config?.apiBaseUrl || '';
|
|
248
|
-
const appSegment = this.config?.apiSegment || '';
|
|
249
|
-
return `${appBase}${appSegment}`;
|
|
262
|
+
return `${config.apiBaseUrl}${config.apiSegment || ''}`;
|
|
250
263
|
}
|
|
251
264
|
get storageKey() {
|
|
252
|
-
return this.configSignal().storageKey || '';
|
|
265
|
+
return this.configSignal().storageKey || 'doohbot_storage';
|
|
253
266
|
}
|
|
254
267
|
get secretKey() {
|
|
255
268
|
return this.configSignal().secretKey || '';
|
|
@@ -267,7 +280,7 @@ class CoreConfigService {
|
|
|
267
280
|
return this.configSignal().licenseFilePath || '';
|
|
268
281
|
}
|
|
269
282
|
get rememberMe() {
|
|
270
|
-
return this.configSignal().rememberMe
|
|
283
|
+
return !!this.configSignal().rememberMe;
|
|
271
284
|
}
|
|
272
285
|
get useStandardApi() {
|
|
273
286
|
return !!this.configSignal().useStandardApi;
|
|
@@ -279,20 +292,21 @@ class CoreConfigService {
|
|
|
279
292
|
return !!this.configSignal().enableResize;
|
|
280
293
|
}
|
|
281
294
|
get apiConfig() {
|
|
282
|
-
// Use specialized type if needed
|
|
283
295
|
return this.configSignal().apiConfig;
|
|
284
296
|
}
|
|
285
297
|
get themeConfig() {
|
|
286
|
-
// Use specialized type if needed
|
|
287
298
|
return this.configSignal().themeConfig;
|
|
288
299
|
}
|
|
289
300
|
get buttonStyle() {
|
|
290
301
|
return this.configSignal().buttonStyle || 'fab';
|
|
291
302
|
}
|
|
292
|
-
|
|
293
|
-
|
|
303
|
+
ngOnDestroy() {
|
|
304
|
+
this.configSubject.complete();
|
|
305
|
+
}
|
|
306
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: DoohbotConfigService, deps: [{ token: DOOHBOT_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
307
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: DoohbotConfigService, providedIn: 'root' }); }
|
|
294
308
|
}
|
|
295
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type:
|
|
309
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: DoohbotConfigService, decorators: [{
|
|
296
310
|
type: Injectable,
|
|
297
311
|
args: [{
|
|
298
312
|
providedIn: 'root',
|
|
@@ -306,13 +320,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImpo
|
|
|
306
320
|
|
|
307
321
|
class StorageService {
|
|
308
322
|
get storageKey() {
|
|
309
|
-
return this.
|
|
323
|
+
return this.configService.storageKey;
|
|
310
324
|
}
|
|
311
325
|
get secretKey() {
|
|
312
|
-
return this.
|
|
326
|
+
return this.configService.secretKey;
|
|
313
327
|
}
|
|
314
|
-
constructor(
|
|
315
|
-
this.
|
|
328
|
+
constructor(configService) {
|
|
329
|
+
this.configService = configService;
|
|
316
330
|
// Determine initial storage
|
|
317
331
|
// If session storage has data, use it (implies remember me was false)
|
|
318
332
|
// Otherwise default/fallback to local storage
|
|
@@ -399,7 +413,7 @@ class StorageService {
|
|
|
399
413
|
return null;
|
|
400
414
|
}
|
|
401
415
|
}
|
|
402
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: StorageService, deps: [{ token:
|
|
416
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: StorageService, deps: [{ token: DoohbotConfigService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
403
417
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: StorageService, providedIn: 'root' }); }
|
|
404
418
|
}
|
|
405
419
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: StorageService, decorators: [{
|
|
@@ -407,17 +421,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImpo
|
|
|
407
421
|
args: [{
|
|
408
422
|
providedIn: 'root',
|
|
409
423
|
}]
|
|
410
|
-
}], ctorParameters: () => [{ type:
|
|
424
|
+
}], ctorParameters: () => [{ type: DoohbotConfigService }] });
|
|
411
425
|
|
|
412
426
|
class HttpService {
|
|
413
427
|
// @BlockUI() blockUI!: NgBlockUI;
|
|
414
428
|
get apiUrl() {
|
|
415
|
-
return this.
|
|
429
|
+
return this.configService.apiUrl;
|
|
416
430
|
}
|
|
417
|
-
constructor(http, tokenStorage,
|
|
431
|
+
constructor(http, tokenStorage, configService) {
|
|
418
432
|
this.http = http;
|
|
419
433
|
this.tokenStorage = tokenStorage;
|
|
420
|
-
this.
|
|
434
|
+
this.configService = configService;
|
|
421
435
|
Logger.log('HttpService: Initialized');
|
|
422
436
|
}
|
|
423
437
|
get(url, param, nestedParam = false, showLoader = false, refresh = true, headers) {
|
|
@@ -495,7 +509,7 @@ class HttpService {
|
|
|
495
509
|
// }
|
|
496
510
|
return value;
|
|
497
511
|
}
|
|
498
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: HttpService, deps: [{ token: i1.HttpClient }, { token: StorageService }, { token:
|
|
512
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: HttpService, deps: [{ token: i1.HttpClient }, { token: StorageService }, { token: DoohbotConfigService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
499
513
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: HttpService, providedIn: 'root' }); }
|
|
500
514
|
}
|
|
501
515
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: HttpService, decorators: [{
|
|
@@ -503,7 +517,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImpo
|
|
|
503
517
|
args: [{
|
|
504
518
|
providedIn: 'root',
|
|
505
519
|
}]
|
|
506
|
-
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: StorageService }, { type:
|
|
520
|
+
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: StorageService }, { type: DoohbotConfigService }] });
|
|
507
521
|
|
|
508
522
|
class AccountService {
|
|
509
523
|
constructor(http, tokenStorage) {
|
|
@@ -592,23 +606,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImpo
|
|
|
592
606
|
|
|
593
607
|
class AuthService {
|
|
594
608
|
get apiUrl() {
|
|
595
|
-
return this.
|
|
609
|
+
return this.configService.apiUrl;
|
|
596
610
|
}
|
|
597
611
|
get storageKey() {
|
|
598
|
-
return this.
|
|
612
|
+
return this.configService.storageKey;
|
|
599
613
|
}
|
|
600
614
|
get secretKey() {
|
|
601
|
-
return this.
|
|
615
|
+
return this.configService.secretKey;
|
|
602
616
|
}
|
|
603
617
|
get companyCode() {
|
|
604
|
-
return this.
|
|
618
|
+
return this.configService.companyCode;
|
|
605
619
|
}
|
|
606
|
-
constructor(accountService, cryptoHelper, tokenStorage, router,
|
|
620
|
+
constructor(accountService, cryptoHelper, tokenStorage, router, configService) {
|
|
607
621
|
this.accountService = accountService;
|
|
608
622
|
this.cryptoHelper = cryptoHelper;
|
|
609
623
|
this.tokenStorage = tokenStorage;
|
|
610
624
|
this.router = router;
|
|
611
|
-
this.
|
|
625
|
+
this.configService = configService;
|
|
612
626
|
this.jwtHelper = new JwtHelperService();
|
|
613
627
|
this.advancedConfig = inject(DOOHBOT_ADVANCED_CONFIG, { optional: true });
|
|
614
628
|
// Reactive Authentication State
|
|
@@ -624,7 +638,7 @@ class AuthService {
|
|
|
624
638
|
* Updates the service configuration from the component input
|
|
625
639
|
*/
|
|
626
640
|
updateConfig(config) {
|
|
627
|
-
this.
|
|
641
|
+
this.configService.updateRuntimeInput(config);
|
|
628
642
|
}
|
|
629
643
|
getLoggedInUserName() {
|
|
630
644
|
const username = this.tokenStorage.get('username');
|
|
@@ -649,7 +663,7 @@ class AuthService {
|
|
|
649
663
|
* Resolves a federated token from browser storage
|
|
650
664
|
*/
|
|
651
665
|
resolveSilentToken() {
|
|
652
|
-
const config = this.
|
|
666
|
+
const config = this.configService.config;
|
|
653
667
|
const commonKeys = ['access_token', 'id_token', 'token', 'authToken'];
|
|
654
668
|
// 1. Try explicit authToken from config (Highest Priority)
|
|
655
669
|
if (config.authToken) {
|
|
@@ -916,7 +930,7 @@ class AuthService {
|
|
|
916
930
|
};
|
|
917
931
|
}
|
|
918
932
|
get licenseKey() {
|
|
919
|
-
return this.tokenStorage.get('license_key') || this.
|
|
933
|
+
return this.tokenStorage.get('license_key') || this.configService.licenseKey || '';
|
|
920
934
|
}
|
|
921
935
|
get isFederated() {
|
|
922
936
|
return this.licenseKey.startsWith('doohbot_lic_');
|
|
@@ -955,7 +969,7 @@ class AuthService {
|
|
|
955
969
|
clearCache() {
|
|
956
970
|
// this.cacheService.clear();
|
|
957
971
|
}
|
|
958
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: AuthService, deps: [{ token: AccountService }, { token: CryptoHelperService }, { token: StorageService }, { token: i4.Router }, { token:
|
|
972
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: AuthService, deps: [{ token: AccountService }, { token: CryptoHelperService }, { token: StorageService }, { token: i4.Router }, { token: DoohbotConfigService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
959
973
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: AuthService, providedIn: 'root' }); }
|
|
960
974
|
}
|
|
961
975
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: AuthService, decorators: [{
|
|
@@ -963,7 +977,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImpo
|
|
|
963
977
|
args: [{
|
|
964
978
|
providedIn: 'root',
|
|
965
979
|
}]
|
|
966
|
-
}], ctorParameters: () => [{ type: AccountService }, { type: CryptoHelperService }, { type: StorageService }, { type: i4.Router }, { type:
|
|
980
|
+
}], ctorParameters: () => [{ type: AccountService }, { type: CryptoHelperService }, { type: StorageService }, { type: i4.Router }, { type: DoohbotConfigService }] });
|
|
967
981
|
|
|
968
982
|
const BASE_STORAGE_KEY = 'app.personalization.v1';
|
|
969
983
|
const DEFAULT_SETTINGS = {
|
|
@@ -2877,7 +2891,7 @@ class ChatService {
|
|
|
2877
2891
|
// Dependencies
|
|
2878
2892
|
this.apiService = inject(ChatApiService);
|
|
2879
2893
|
this.authService = inject(AuthService);
|
|
2880
|
-
this.
|
|
2894
|
+
this.configService = inject(DoohbotConfigService);
|
|
2881
2895
|
this.audioService = inject(ChatAudioService);
|
|
2882
2896
|
this.config = inject(DOOHBOT_ADVANCED_CONFIG, { optional: true });
|
|
2883
2897
|
this.chatHistoryService = inject(ChatHistoryService);
|
|
@@ -2904,7 +2918,7 @@ class ChatService {
|
|
|
2904
2918
|
this.isBotTyping = signal(false, ...(ngDevMode ? [{ debugName: "isBotTyping" }] : []));
|
|
2905
2919
|
this.promptMode = signal('markdown', ...(ngDevMode ? [{ debugName: "promptMode" }] : []));
|
|
2906
2920
|
//! Controls whether to use Streaming API (default) or Standard API
|
|
2907
|
-
this.isStreaming = computed(() => !this.
|
|
2921
|
+
this.isStreaming = computed(() => !this.configService.useStandardApi, ...(ngDevMode ? [{ debugName: "isStreaming" }] : []));
|
|
2908
2922
|
this.messagesStream = [];
|
|
2909
2923
|
this.currentResponse = '';
|
|
2910
2924
|
this.cancelSubject = new Subject();
|
|
@@ -4429,68 +4443,136 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImpo
|
|
|
4429
4443
|
}] } });
|
|
4430
4444
|
|
|
4431
4445
|
class LicenseService {
|
|
4432
|
-
constructor() {
|
|
4433
|
-
this.
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
this.registry = signal(
|
|
4446
|
+
constructor(http) {
|
|
4447
|
+
this.http = http;
|
|
4448
|
+
// private http = inject(HttpClient);
|
|
4449
|
+
this.configService = inject(DoohbotConfigService);
|
|
4450
|
+
this.registry = signal(null, ...(ngDevMode ? [{ debugName: "registry" }] : []));
|
|
4437
4451
|
}
|
|
4438
4452
|
/**
|
|
4439
4453
|
* Load the license configuration from a JSON file.
|
|
4440
|
-
*
|
|
4454
|
+
* Supports both Hierarchical (entitlements) and Flat-map (package:key) formats.
|
|
4455
|
+
* @param filePath Path to the license JSON file
|
|
4441
4456
|
*/
|
|
4442
4457
|
async loadLicenseFile(filePath) {
|
|
4443
4458
|
try {
|
|
4444
|
-
const finalPath = filePath || this.
|
|
4445
|
-
if (!finalPath) {
|
|
4446
|
-
Logger.debug('[LicenseService] No license file path provided.');
|
|
4447
|
-
return;
|
|
4448
|
-
}
|
|
4449
|
-
Logger.log(`[LicenseService] Loading flat-map license file: ${finalPath}`);
|
|
4459
|
+
const finalPath = filePath || this.configService.licenseFilePath;
|
|
4450
4460
|
const data = await firstValueFrom(this.http.get(finalPath));
|
|
4451
|
-
if (data) {
|
|
4452
|
-
|
|
4453
|
-
|
|
4454
|
-
|
|
4461
|
+
if (!data) {
|
|
4462
|
+
throw new Error('Empty license file');
|
|
4463
|
+
}
|
|
4464
|
+
// Detection: Hierarchical Format (subjectId/licenses array)
|
|
4465
|
+
if (data.licenses && Array.isArray(data.licenses)) {
|
|
4466
|
+
this.processHierarchicalLicense(data);
|
|
4467
|
+
}
|
|
4468
|
+
// Detection: Flat Map Format (packageId: key)
|
|
4469
|
+
else {
|
|
4470
|
+
this.processFlatMapLicense(data);
|
|
4455
4471
|
}
|
|
4456
4472
|
}
|
|
4457
4473
|
catch (error) {
|
|
4458
|
-
|
|
4459
|
-
|
|
4474
|
+
// Industry pattern: Silent loading for optional registry files
|
|
4475
|
+
Logger.log('[LicenseService] No external license file found or failed to load. Falling back to AppConst.');
|
|
4476
|
+
this.registry.set(null);
|
|
4460
4477
|
}
|
|
4461
4478
|
}
|
|
4479
|
+
processHierarchicalLicense(data) {
|
|
4480
|
+
const subjectMap = new Map();
|
|
4481
|
+
data.licenses.forEach((license) => {
|
|
4482
|
+
const key = `${license.subjectType}:${license.subjectId}`;
|
|
4483
|
+
subjectMap.set(key, license.packages);
|
|
4484
|
+
});
|
|
4485
|
+
this.registry.set({
|
|
4486
|
+
accountId: data.accountId,
|
|
4487
|
+
subjectLicenses: subjectMap,
|
|
4488
|
+
});
|
|
4489
|
+
Logger.log(`[LicenseService] Hierarchical Registry loaded for account: ${data.accountId}`);
|
|
4490
|
+
}
|
|
4491
|
+
processFlatMapLicense(data) {
|
|
4492
|
+
// Flat-map format: { "tenantName": "license_key" }
|
|
4493
|
+
// Convert each entry to: tenant:tenantName -> { doohbot: license_key }
|
|
4494
|
+
const subjectMap = new Map();
|
|
4495
|
+
Object.entries(data).forEach(([tenantName, licenseKey]) => {
|
|
4496
|
+
const tenantKey = `tenant:${tenantName}`;
|
|
4497
|
+
subjectMap.set(tenantKey, {
|
|
4498
|
+
doohbot: licenseKey,
|
|
4499
|
+
});
|
|
4500
|
+
});
|
|
4501
|
+
this.registry.set({
|
|
4502
|
+
accountId: 'FLAT_MAP_REGISTRY',
|
|
4503
|
+
subjectLicenses: subjectMap,
|
|
4504
|
+
});
|
|
4505
|
+
Logger.log(`[LicenseService] Flat-map registry loaded with ${subjectMap.size} tenant(s)`);
|
|
4506
|
+
}
|
|
4462
4507
|
/**
|
|
4463
|
-
*
|
|
4464
|
-
* @param
|
|
4508
|
+
* Resolve the correct license key based on context and requested package
|
|
4509
|
+
* @param context The current licensing context (tenant, user, roles)
|
|
4510
|
+
* @param packageId The ID of the package requesting a license
|
|
4511
|
+
* @returns The resolved license key, or null if unauthorized
|
|
4465
4512
|
*/
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4513
|
+
resolveLicenseKey(context, packageId) {
|
|
4514
|
+
// Hierarchical Registry (Most Specific)
|
|
4515
|
+
const keyFromRegistry = this.resolveFromRegistry(context, packageId);
|
|
4516
|
+
if (keyFromRegistry)
|
|
4517
|
+
return keyFromRegistry;
|
|
4518
|
+
Logger.warn(`[LicenseService] No license found for package: ${packageId} and user: ${context.principalId}`);
|
|
4519
|
+
return null;
|
|
4520
|
+
}
|
|
4521
|
+
resolveFromRegistry(context, packageId) {
|
|
4522
|
+
const reg = this.registry();
|
|
4523
|
+
if (!reg)
|
|
4524
|
+
return null;
|
|
4525
|
+
// Strict Account Check
|
|
4526
|
+
if (reg.accountId !== 'EXTERNAL_OVERRIDE' && reg.accountId !== context.tenantId) {
|
|
4527
|
+
Logger.error(`[LicenseService] Account mismatch! Registry: ${reg.accountId}, Context: ${context.tenantId}`);
|
|
4470
4528
|
return null;
|
|
4471
4529
|
}
|
|
4472
|
-
const
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4530
|
+
const subjectsToSearch = [
|
|
4531
|
+
`user:${context.principalId}`,
|
|
4532
|
+
...(context.roles?.map((r) => `role:${r}`) || []),
|
|
4533
|
+
`tenant:${context.tenantId}`,
|
|
4534
|
+
'tenant:default', // Fallback for flat-map external files
|
|
4535
|
+
];
|
|
4536
|
+
for (const subjectKey of subjectsToSearch) {
|
|
4537
|
+
const packages = reg.subjectLicenses.get(subjectKey);
|
|
4538
|
+
if (packages && packages[packageId]) {
|
|
4539
|
+
Logger.debug(`[LicenseService] Resolved key for ${packageId} via Registry (${subjectKey})`);
|
|
4540
|
+
return packages[packageId];
|
|
4541
|
+
}
|
|
4476
4542
|
}
|
|
4477
|
-
Logger.warn(`[LicenseService] No license key found in registry for tenant: ${name}`);
|
|
4478
4543
|
return null;
|
|
4479
4544
|
}
|
|
4480
4545
|
/**
|
|
4481
|
-
*
|
|
4546
|
+
* Resolves the license key for the current tenant.
|
|
4482
4547
|
*/
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4548
|
+
resolveTenantLicenseKey(tenancyName) {
|
|
4549
|
+
const activeTenancy = tenancyName || this.configService.tenancyName;
|
|
4550
|
+
if (!activeTenancy) {
|
|
4551
|
+
Logger.warn('[LicenseService] No tenancy name found.');
|
|
4552
|
+
return null;
|
|
4553
|
+
}
|
|
4554
|
+
const reg = this.registry();
|
|
4555
|
+
if (!reg) {
|
|
4556
|
+
Logger.error('[LicenseService] License registry not loaded.');
|
|
4557
|
+
return null;
|
|
4558
|
+
}
|
|
4559
|
+
const tenantLicenses = reg.subjectLicenses.get(`tenant:${activeTenancy}`);
|
|
4560
|
+
const licenseKey = tenantLicenses?.['doohbot'] || null;
|
|
4561
|
+
if (licenseKey) {
|
|
4562
|
+
Logger.info(`[LicenseService] Resolved Doohbot license for: ${activeTenancy}`);
|
|
4563
|
+
}
|
|
4564
|
+
else {
|
|
4565
|
+
Logger.warn(`[LicenseService] No license key found for tenant: ${activeTenancy}`);
|
|
4566
|
+
}
|
|
4567
|
+
return licenseKey;
|
|
4486
4568
|
}
|
|
4487
4569
|
/**
|
|
4488
4570
|
* Check if a registry is currently loaded
|
|
4489
4571
|
*/
|
|
4490
4572
|
isRegistryLoaded() {
|
|
4491
|
-
return this.registry()
|
|
4573
|
+
return this.registry() !== null;
|
|
4492
4574
|
}
|
|
4493
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: LicenseService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4575
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: LicenseService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4494
4576
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: LicenseService, providedIn: 'root' }); }
|
|
4495
4577
|
}
|
|
4496
4578
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: LicenseService, decorators: [{
|
|
@@ -4498,7 +4580,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImpo
|
|
|
4498
4580
|
args: [{
|
|
4499
4581
|
providedIn: 'root',
|
|
4500
4582
|
}]
|
|
4501
|
-
}] });
|
|
4583
|
+
}], ctorParameters: () => [{ type: i1.HttpClient }] });
|
|
4502
4584
|
|
|
4503
4585
|
/**
|
|
4504
4586
|
* Doohbot Main Component
|
|
@@ -4507,10 +4589,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImpo
|
|
|
4507
4589
|
class DoohbotComponent {
|
|
4508
4590
|
// Configuration exposure for template
|
|
4509
4591
|
get enableDrag() {
|
|
4510
|
-
return this.
|
|
4592
|
+
return this.configService?.enableDrag ?? false;
|
|
4511
4593
|
}
|
|
4512
4594
|
get enableResize() {
|
|
4513
|
-
return this.
|
|
4595
|
+
return this.configService?.enableResize ?? false;
|
|
4514
4596
|
}
|
|
4515
4597
|
//! ======================= CONSTRUCTOR ========================
|
|
4516
4598
|
constructor(elementRef, renderer, dialogService, snackbarService) {
|
|
@@ -4531,7 +4613,7 @@ class DoohbotComponent {
|
|
|
4531
4613
|
// private snackbarService = inject(SnackbarService);
|
|
4532
4614
|
this.personalization = inject(PersonalizationService);
|
|
4533
4615
|
this.licenseService = inject(LicenseService);
|
|
4534
|
-
this.
|
|
4616
|
+
this.configService = inject(DoohbotConfigService);
|
|
4535
4617
|
//! ========================= EXPOSED STATE FROM SERVICES ============================
|
|
4536
4618
|
// UI State signals
|
|
4537
4619
|
this.isChatOpen = this.uiState.isChatOpen;
|
|
@@ -4576,7 +4658,7 @@ class DoohbotComponent {
|
|
|
4576
4658
|
this.renderer.removeClass(host, 'dark-theme');
|
|
4577
4659
|
this.renderer.addClass(host, activeTheme);
|
|
4578
4660
|
// Apply theme configuration from global config
|
|
4579
|
-
const themeConfig = this.
|
|
4661
|
+
const themeConfig = this.configService?.themeConfig;
|
|
4580
4662
|
if (themeConfig) {
|
|
4581
4663
|
this.themeService.setThemeConfig(themeConfig, host);
|
|
4582
4664
|
if (themeConfig.primaryColor) {
|
|
@@ -4589,11 +4671,7 @@ class DoohbotComponent {
|
|
|
4589
4671
|
// Corrected structural integrity.
|
|
4590
4672
|
async ngOnInit() {
|
|
4591
4673
|
Logger.log('Initializing Doohbot component...');
|
|
4592
|
-
const path = this.
|
|
4593
|
-
const licenseKey = this.coreConfig.licenseKey;
|
|
4594
|
-
if (licenseKey) {
|
|
4595
|
-
this.authService.setLicenseKey(licenseKey);
|
|
4596
|
-
}
|
|
4674
|
+
const path = this.configService.licenseFilePath;
|
|
4597
4675
|
// Load license registry from file and wait for it to complete
|
|
4598
4676
|
if (path) {
|
|
4599
4677
|
await this.licenseService.loadLicenseFile(path);
|
|
@@ -4630,14 +4708,14 @@ class DoohbotComponent {
|
|
|
4630
4708
|
}
|
|
4631
4709
|
canAttemptFederatedLogin() {
|
|
4632
4710
|
const hasAuthToken = !!this.config?.authToken;
|
|
4633
|
-
const hasDirectLicenseKey = !!this.
|
|
4634
|
-
const hasTenantLicenseLookup = !!this.
|
|
4711
|
+
const hasDirectLicenseKey = !!this.configService?.licenseKey;
|
|
4712
|
+
const hasTenantLicenseLookup = !!this.configService?.tenancyName && !!this.configService?.licenseFilePath;
|
|
4635
4713
|
const hasValidLicenseContext = hasDirectLicenseKey || hasTenantLicenseLookup;
|
|
4636
4714
|
return hasAuthToken && hasValidLicenseContext;
|
|
4637
4715
|
}
|
|
4638
4716
|
initializeUI() {
|
|
4639
4717
|
// Apply theme from global configuration
|
|
4640
|
-
const themeConfig = this.
|
|
4718
|
+
const themeConfig = this.configService?.themeConfig;
|
|
4641
4719
|
if (themeConfig) {
|
|
4642
4720
|
this.themeService.setThemeConfig(themeConfig, this.elementRef.nativeElement);
|
|
4643
4721
|
}
|
|
@@ -4665,13 +4743,13 @@ class DoohbotComponent {
|
|
|
4665
4743
|
this.authService.updateConfig(this.config);
|
|
4666
4744
|
this.userAvatarUrl();
|
|
4667
4745
|
this.updateUserName();
|
|
4668
|
-
if (this.
|
|
4669
|
-
this.authService.setLicenseKey(this.
|
|
4746
|
+
if (this.configService?.licenseKey) {
|
|
4747
|
+
this.authService.setLicenseKey(this.configService.licenseKey);
|
|
4670
4748
|
}
|
|
4671
4749
|
// Sync button style from global config to personalization
|
|
4672
|
-
if (this.
|
|
4750
|
+
if (this.configService?.buttonStyle) {
|
|
4673
4751
|
this.personalization.setDeveloperDefaults({
|
|
4674
|
-
buttonStyle: this.
|
|
4752
|
+
buttonStyle: this.configService.buttonStyle,
|
|
4675
4753
|
});
|
|
4676
4754
|
}
|
|
4677
4755
|
// Handle dynamic config updates for authentication
|
|
@@ -4688,7 +4766,7 @@ class DoohbotComponent {
|
|
|
4688
4766
|
// Logic moved to ChatFacadeService.initialize()
|
|
4689
4767
|
onNormalLogin(credentials) {
|
|
4690
4768
|
// Use Tenancy Name from Global Config
|
|
4691
|
-
let tenancy = this.
|
|
4769
|
+
let tenancy = this.configService?.tenancyName;
|
|
4692
4770
|
//! fallback: Try to resolve from global utility (Auto-detect)
|
|
4693
4771
|
// if (!tenancy) {
|
|
4694
4772
|
// tenancy = window.AppPreBootstrap?.resolveTenancyName(window.AppConsts?.appBaseUrl);
|
|
@@ -4708,14 +4786,14 @@ class DoohbotComponent {
|
|
|
4708
4786
|
let autoKey = this.licenseService.resolveTenantLicenseKey();
|
|
4709
4787
|
// Fallback to Global Config
|
|
4710
4788
|
if (!autoKey) {
|
|
4711
|
-
autoKey = this.
|
|
4789
|
+
autoKey = this.configService?.licenseKey || '';
|
|
4712
4790
|
}
|
|
4713
4791
|
if (autoKey) {
|
|
4714
4792
|
this.authService.setLicenseKey(autoKey);
|
|
4715
4793
|
}
|
|
4716
4794
|
const request = {
|
|
4717
4795
|
accessToken: token,
|
|
4718
|
-
rememberMe: this.
|
|
4796
|
+
rememberMe: this.configService?.rememberMe,
|
|
4719
4797
|
license: autoKey || '',
|
|
4720
4798
|
};
|
|
4721
4799
|
// Await the federated login result
|
|
@@ -4851,7 +4929,7 @@ class DoohbotComponent {
|
|
|
4851
4929
|
}
|
|
4852
4930
|
const loggedInName = this.authService.getLoggedInUserName();
|
|
4853
4931
|
// const contextName = this.userContext?.userName;
|
|
4854
|
-
const configName = this.
|
|
4932
|
+
const configName = this.configService?.config.authToken ? 'User' : ''; // simplified username logic
|
|
4855
4933
|
if (configName) {
|
|
4856
4934
|
this.userName = configName;
|
|
4857
4935
|
}
|
|
@@ -5082,7 +5160,6 @@ function provideDoohbot(config = {}) {
|
|
|
5082
5160
|
useClass: LicenseInterceptor,
|
|
5083
5161
|
multi: true,
|
|
5084
5162
|
},
|
|
5085
|
-
CoreConfigService,
|
|
5086
5163
|
DoohbotConfigService,
|
|
5087
5164
|
]);
|
|
5088
5165
|
}
|
|
@@ -5124,72 +5201,6 @@ function provideDoohbotMinimal(config = {}) {
|
|
|
5124
5201
|
]);
|
|
5125
5202
|
}
|
|
5126
5203
|
|
|
5127
|
-
/**
|
|
5128
|
-
* Centralized service for managing Doohbot configuration.
|
|
5129
|
-
* Provides reactive access and runtime updates.
|
|
5130
|
-
* Singleton via providedIn: 'root'.
|
|
5131
|
-
*/
|
|
5132
|
-
class DoohbotConfigService {
|
|
5133
|
-
/** Current configuration snapshot */
|
|
5134
|
-
get config() {
|
|
5135
|
-
return this.configSubject.value;
|
|
5136
|
-
}
|
|
5137
|
-
constructor(userConfig) {
|
|
5138
|
-
const mergedConfig = {
|
|
5139
|
-
...DEFAULT_DOOHBOT_CONFIG,
|
|
5140
|
-
...userConfig,
|
|
5141
|
-
};
|
|
5142
|
-
this.validateConfig(mergedConfig);
|
|
5143
|
-
this.configSubject = new BehaviorSubject(mergedConfig);
|
|
5144
|
-
this.config$ = this.configSubject.asObservable();
|
|
5145
|
-
}
|
|
5146
|
-
/**
|
|
5147
|
-
* Update configuration at runtime.
|
|
5148
|
-
* @param updates Partial config updates
|
|
5149
|
-
*/
|
|
5150
|
-
updateConfig(updates) {
|
|
5151
|
-
const newConfig = { ...this.config, ...updates };
|
|
5152
|
-
this.validateConfig(newConfig);
|
|
5153
|
-
this.configSubject.next(newConfig);
|
|
5154
|
-
}
|
|
5155
|
-
validateConfig(config) {
|
|
5156
|
-
if (config.timeout < 0)
|
|
5157
|
-
throw new Error('timeout must be >= 0');
|
|
5158
|
-
if (config.maxHistoryMessages < 0)
|
|
5159
|
-
throw new Error('maxHistoryMessages must be >= 0');
|
|
5160
|
-
if (config.retryAttempts < 0)
|
|
5161
|
-
throw new Error('retryAttempts must be >= 0');
|
|
5162
|
-
if (config.retryDelay < 0)
|
|
5163
|
-
throw new Error('retryDelay must be >= 0');
|
|
5164
|
-
if (config.environment === 'production' && !this.isValidUrl(config.apiBaseUrl)) {
|
|
5165
|
-
console.warn('DoohbotConfig: apiBaseUrl may be invalid in production');
|
|
5166
|
-
}
|
|
5167
|
-
}
|
|
5168
|
-
isValidUrl(url) {
|
|
5169
|
-
try {
|
|
5170
|
-
new URL(url);
|
|
5171
|
-
return true;
|
|
5172
|
-
}
|
|
5173
|
-
catch {
|
|
5174
|
-
return false;
|
|
5175
|
-
}
|
|
5176
|
-
}
|
|
5177
|
-
ngOnDestroy() {
|
|
5178
|
-
this.configSubject.complete();
|
|
5179
|
-
}
|
|
5180
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: DoohbotConfigService, deps: [{ token: DOOHBOT_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
5181
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: DoohbotConfigService, providedIn: 'root' }); }
|
|
5182
|
-
}
|
|
5183
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: DoohbotConfigService, decorators: [{
|
|
5184
|
-
type: Injectable,
|
|
5185
|
-
args: [{ providedIn: 'root' }]
|
|
5186
|
-
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
5187
|
-
type: Optional
|
|
5188
|
-
}, {
|
|
5189
|
-
type: Inject,
|
|
5190
|
-
args: [DOOHBOT_CONFIG]
|
|
5191
|
-
}] }] });
|
|
5192
|
-
|
|
5193
5204
|
/**
|
|
5194
5205
|
* public-api.ts
|
|
5195
5206
|
* Main public API surface of the Doohbot library.
|