monkey-front-core 22.0.0 → 22.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,24 +1,21 @@
1
- # MonkeyStyleGuideV2
1
+ # monkey-front-core
2
2
 
3
- This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 17.3.0.
3
+ Shared Angular core library for Monkey Exchange front-end applications.
4
4
 
5
- ## Code scaffolding
5
+ > **Internal use only.** This package is published to npm for distribution across Monkey Exchange projects. It is not intended for public or third-party use, and no support or API stability is offered outside those projects.
6
6
 
7
- Run `ng generate component component-name --project monkey-front-core` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project monkey-front-core`.
8
- > Note: Don't forget to add `--project monkey-front-core` or else it will be added to the default project in your `angular.json` file.
7
+ ## What it provides
9
8
 
10
- ## Build
9
+ Cross-cutting building blocks reused by Monkey front-end apps:
11
10
 
12
- Run `ng build monkey-front-core` to build the project. The build artifacts will be stored in the `dist/` directory.
11
+ - **Services** — configuration, locale, feature toggles, Datadog, caching, scheduling, validation, session handling
12
+ - **State** — NgRx store setup, actions, selectors and effects
13
+ - **HTTP** — interceptors and base resolvers
14
+ - **Routing** — guards and route discovery helpers
15
+ - **Storage** — cookie and token storage
16
+ - **Angular primitives** — directives, pipes, decorators, injectors, form validators
17
+ - **Types** — shared interfaces, enums and models
13
18
 
14
- ## Publishing
19
+ ## License
15
20
 
16
- After building your library with `ng build monkey-front-core`, go to the dist folder `cd dist/monkey-front-core` and run `npm publish`.
17
-
18
- ## Running unit tests
19
-
20
- Run `ng test monkey-front-core` to execute the unit tests via [Karma](https://karma-runner.github.io).
21
-
22
- ## Further help
23
-
24
- To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
21
+ MIT © Monkey Exchange
@@ -5,7 +5,7 @@ import { inject, InjectionToken, Injectable, LOCALE_ID, DestroyRef, DOCUMENT, In
5
5
  import * as i2 from '@angular/router';
6
6
  import { Router, NavigationStart } from '@angular/router';
7
7
  import queryString from 'query-string';
8
- import { BehaviorSubject, of, map, firstValueFrom, merge, fromEvent, interval, ReplaySubject, Subject, tap, catchError, throwError, finalize, switchMap, take, filter, Subscription, from, debounceTime } from 'rxjs';
8
+ import { BehaviorSubject, of, map, firstValueFrom, combineLatest, distinctUntilChanged, filter, merge, fromEvent, interval, ReplaySubject, Subject, tap, catchError, throwError, finalize, switchMap, take, Subscription, from, debounceTime } from 'rxjs';
9
9
  import * as i1 from 'ngx-cookie-service';
10
10
  import * as i1$1 from '@ngrx/store';
11
11
  import { createAction, props, INIT, createReducer, on, createFeatureSelector, createSelector, provideStore, provideState } from '@ngrx/store';
@@ -25,11 +25,6 @@ import { DomSanitizer } from '@angular/platform-browser';
25
25
  import { NgModel, TouchedChangeEvent, ValueChangeEvent, StatusChangeEvent } from '@angular/forms';
26
26
  import { map as map$1, catchError as catchError$1, finalize as finalize$1 } from 'rxjs/operators';
27
27
 
28
- /** ************************
29
- * Copyright Monkey Exchange. All Rights Reserved
30
- * This style guide was developed by Monkey Exchange Team
31
- * MIT Licence
32
- ************************* */
33
28
  function injectTokenWithWarning(token, name) {
34
29
  const value = inject(token, { optional: true });
35
30
  if (!value) {
@@ -88,6 +83,20 @@ const MECX_REFRESH_TOKEN_STRATEGY = new InjectionToken('MECX_REFRESH_TOKEN_STRAT
88
83
  const MECX_REDIRECT_LOGIN_WELCOMEBACK_STRATEGY = new InjectionToken('MECX_REDIRECT_LOGIN_WELCOMEBACK_STRATEGY');
89
84
  const MECX_I18N_PATH = new InjectionToken('MECX_I18N_PATH');
90
85
  const MECX_I18N_ALIAS = new InjectionToken('MECX_I18N_ALIAS');
86
+ /**
87
+ * The native federation instance resolved by `initFederation` in the shell `main.ts`.
88
+ * Used by `MonkeyEcxFederationService` to register and load the remotes of `federationSettings`.
89
+ *
90
+ * ### Example
91
+ * ```
92
+ * // main.ts
93
+ * initFederation({}).then((federation) => import('./bootstrap').then((m) => m.bootstrap(federation)));
94
+ *
95
+ * // bootstrap.ts
96
+ * providers: [...appConfig.providers, provideMonkeyEcxFederation(federation)]
97
+ * ```
98
+ */
99
+ const MECX_FEDERATION = new InjectionToken('MECX_FEDERATION');
91
100
 
92
101
  /** ************************
93
102
  * Copyright Monkey Exchange. All Rights Reserved
@@ -1308,19 +1317,7 @@ class MonkeyEcxConfigsService {
1308
1317
  this._styleGuide$.next(data);
1309
1318
  }
1310
1319
  federationSettings(key) {
1311
- try {
1312
- const { value } = this._bootstrap$;
1313
- if (value) {
1314
- const { federationSettings } = value;
1315
- if (key in federationSettings || {}) {
1316
- return federationSettings[key];
1317
- }
1318
- }
1319
- }
1320
- catch (e) {
1321
- // not to do
1322
- }
1323
- return null;
1320
+ return this._bootstrap$.value?.federationSettings?.[key] ?? null;
1324
1321
  }
1325
1322
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: MonkeyEcxConfigsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1326
1323
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: MonkeyEcxConfigsService, providedIn: 'root' }); }
@@ -2016,6 +2013,141 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImpor
2016
2013
  }]
2017
2014
  }] });
2018
2015
 
2016
+ /** ************************
2017
+ * Copyright Monkey Exchange. All Rights Reserved
2018
+ * This style guide was developed by Monkey Exchange Team
2019
+ * MIT Licence
2020
+ ************************* */
2021
+ const DEFAULT_REMOTE_ENTRY = 'remoteEntry.json';
2022
+ const DEFAULT_EXPOSED_MODULE = './Routes';
2023
+ class MonkeyEcxFederationService {
2024
+ constructor() {
2025
+ this._configsService = inject(MonkeyEcxConfigsService);
2026
+ this._errorService = inject(MonkeyEcxErrorService);
2027
+ this._federation = injectTokenWithWarning(MECX_FEDERATION, 'MECX_FEDERATION');
2028
+ this._remotes$ = new BehaviorSubject({});
2029
+ this._initialized$ = new BehaviorSubject(false);
2030
+ this._loading = new Map();
2031
+ this._errorApplied = false;
2032
+ }
2033
+ get remotes$() {
2034
+ return this._remotes$.asObservable();
2035
+ }
2036
+ get allLoaded$() {
2037
+ return this.watchHoldSplash(['loaded']);
2038
+ }
2039
+ get allSettled$() {
2040
+ return this.watchHoldSplash(['loaded', 'error']);
2041
+ }
2042
+ watchHoldSplash(statuses) {
2043
+ return combineLatest([this._initialized$, this._remotes$]).pipe(map(([initialized, remotes]) => {
2044
+ return this.isHoldSplashIn(initialized, remotes, statuses);
2045
+ }), distinctUntilChanged());
2046
+ }
2047
+ isHoldSplashIn(initialized, remotes, statuses) {
2048
+ if (!initialized)
2049
+ return false;
2050
+ return Object.values(remotes)
2051
+ .filter(({ setting }) => {
2052
+ return setting.holdSplash;
2053
+ })
2054
+ .every(({ status }) => {
2055
+ return statuses.includes(status);
2056
+ });
2057
+ }
2058
+ updateRemote(name, data) {
2059
+ const remotes = this._remotes$.value;
2060
+ this._remotes$.next({
2061
+ ...remotes,
2062
+ [name]: { ...remotes[name], ...data }
2063
+ });
2064
+ }
2065
+ async handleLoad(name) {
2066
+ const setting = this._configsService.federationSettings(name);
2067
+ if (!setting) {
2068
+ throw new Error(`MECXFederation -> Remote "${name}" not found in federationSettings`);
2069
+ }
2070
+ this.updateRemote(name, { name, setting, status: 'loading', error: undefined });
2071
+ try {
2072
+ if (!this._federation) {
2073
+ throw new Error(`MECXFederation -> Remote "${name}" could not be loaded`);
2074
+ }
2075
+ const { host, remoteEntry = DEFAULT_REMOTE_ENTRY, exposedModule = DEFAULT_EXPOSED_MODULE } = setting;
2076
+ const url = `${host.replace(/\/+$/, '')}/${remoteEntry.replace(/^\/+/, '')}`;
2077
+ this._federation = await this._federation.initRemoteEntry(url, name);
2078
+ const module = await this._federation.loadRemoteModule(name, exposedModule);
2079
+ this.updateRemote(name, { status: 'loaded', module });
2080
+ return module;
2081
+ }
2082
+ catch (e) {
2083
+ console.error(`MECXFederation -> Remote "${name}" failed to load: `, e);
2084
+ this.updateRemote(name, { status: 'error', error: e });
2085
+ throw e;
2086
+ }
2087
+ }
2088
+ handleStartupError(name, setting, e) {
2089
+ if (!setting.holdSplash || this._errorApplied)
2090
+ return;
2091
+ this._errorApplied = true;
2092
+ this._errorService.apply(`Remote "${name}" | ${setting.host} | ${e?.message || e}`);
2093
+ }
2094
+ apply() {
2095
+ const federationSettings = this._configsService.bootstrap?.federationSettings || {};
2096
+ const current = this._remotes$.value;
2097
+ const remotes = Object.entries(federationSettings).reduce((acc, [name, setting]) => {
2098
+ acc[name] = current[name] || { name, setting, status: 'idle' };
2099
+ return acc;
2100
+ }, {});
2101
+ this._remotes$.next(remotes);
2102
+ this._initialized$.next(true);
2103
+ Object.entries(federationSettings)
2104
+ .filter(([, setting]) => {
2105
+ return setting.preload || setting.holdSplash;
2106
+ })
2107
+ .forEach(([name, setting]) => {
2108
+ this.load(name).catch((e) => {
2109
+ this.handleStartupError(name, setting, e);
2110
+ });
2111
+ });
2112
+ }
2113
+ skip() {
2114
+ this._initialized$.next(true);
2115
+ }
2116
+ load(name) {
2117
+ let promise = this._loading.get(name);
2118
+ if (!promise) {
2119
+ promise = this.handleLoad(name).catch((e) => {
2120
+ this._loading.delete(name);
2121
+ throw e;
2122
+ });
2123
+ this._loading.set(name, promise);
2124
+ }
2125
+ return promise;
2126
+ }
2127
+ async loadRoutes(name) {
2128
+ const module = await this.load(name);
2129
+ return module.routes;
2130
+ }
2131
+ status(name) {
2132
+ return this._remotes$.value[name] || null;
2133
+ }
2134
+ isAllLoaded() {
2135
+ return this.isHoldSplashIn(this._initialized$.value, this._remotes$.value, ['loaded']);
2136
+ }
2137
+ isAllSettled() {
2138
+ return this.isHoldSplashIn(this._initialized$.value, this._remotes$.value, ['loaded', 'error']);
2139
+ }
2140
+ async whenAllSettled() {
2141
+ await firstValueFrom(this.allSettled$.pipe(filter(Boolean)));
2142
+ }
2143
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: MonkeyEcxFederationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2144
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: MonkeyEcxFederationService, providedIn: 'root' }); }
2145
+ }
2146
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: MonkeyEcxFederationService, decorators: [{
2147
+ type: Injectable,
2148
+ args: [{ providedIn: 'root' }]
2149
+ }] });
2150
+
2019
2151
  /** ************************
2020
2152
  * Copyright Monkey Exchange. All Rights Reserved
2021
2153
  * This style guide was developed by Monkey Exchange Team
@@ -3075,6 +3207,7 @@ class MonkeyEcxInitService {
3075
3207
  this._maintenanceService = inject(MonkeyEcxMaintenanceService);
3076
3208
  this._localeService = inject(MonkeyEcxLocaleService);
3077
3209
  this._connectionService = inject(MonkeyEcxConnectionService);
3210
+ this._federationService = inject(MonkeyEcxFederationService);
3078
3211
  this._bootstrapService = injectTokenWithWarning(MECX_BOOTSTRAP_SERVICE, 'MECX_BOOTSTRAP_SERVICE');
3079
3212
  // not to do
3080
3213
  }
@@ -3107,9 +3240,11 @@ class MonkeyEcxInitService {
3107
3240
  async handleSettings(response, code) {
3108
3241
  this._updateService.apply();
3109
3242
  if (response.maintenance.closed) {
3243
+ this._federationService.skip();
3110
3244
  this._maintenanceService.apply();
3111
3245
  }
3112
3246
  else {
3247
+ this._federationService.apply();
3113
3248
  await this.handleWhiteLabel(code);
3114
3249
  await this._featureToggleService.apply();
3115
3250
  await this.handleStyleGuide(code);
@@ -3121,6 +3256,7 @@ class MonkeyEcxInitService {
3121
3256
  async performValidation(response, code) {
3122
3257
  this._configsService.bootstrap = response;
3123
3258
  if (!code) {
3259
+ this._federationService.skip();
3124
3260
  this._errorService.apply();
3125
3261
  return;
3126
3262
  }
@@ -3142,6 +3278,7 @@ class MonkeyEcxInitService {
3142
3278
  }
3143
3279
  catch (e) {
3144
3280
  console.error('🤯 MECXInit -> Monkey app initialization failed: ', e);
3281
+ this._federationService.skip();
3145
3282
  this._errorService.apply(e);
3146
3283
  }
3147
3284
  }
@@ -5646,7 +5783,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImpor
5646
5783
  * MIT Licence
5647
5784
  ************************* */
5648
5785
 
5649
- function provideDomainServiceWorker(workerUrl, scope = '/') {
5786
+ function provideMonkeyEcxFederation(federation) {
5787
+ return [{ provide: MECX_FEDERATION, useValue: federation }];
5788
+ }
5789
+
5790
+ function provideMonkeyEcxDomainServiceWorker(workerUrl, scope = '/') {
5650
5791
  return provideServiceWorker(workerUrl, {
5651
5792
  enabled: true,
5652
5793
  scope,
@@ -5881,5 +6022,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImpor
5881
6022
  * Generated bundle index. Do not edit.
5882
6023
  */
5883
6024
 
5884
- export { CACHE_LOCALE_EXPIRATION_MS, CountryMasks, LService, Link, MECX_ALPHA, MECX_BETA, MECX_BOOTSTRAP_SERVICE, MECX_CORE_I18N_WRAPPER, MECX_COUNTRY, MECX_DATE_FORMAT, MECX_I18N_ALIAS, MECX_I18N_PATH, MECX_REDIRECT_LOGIN_WELCOMEBACK_STRATEGY, MECX_REFRESH_TOKEN_STRATEGY, MECX_REQUEST_ID, MECX_TIMEZONEOFFSET, MonkeyEcxAuthGuard, MonkeyEcxAuthGuardByRole, MonkeyEcxAuthGuardCompany, MonkeyEcxAuthGuardLogin, MonkeyEcxBaseResolver, MonkeyEcxBlobSecurePipe, MonkeyEcxCommonsActions, MonkeyEcxCommonsSelectors, MonkeyEcxCommonsStoreService, MonkeyEcxConfigsService, MonkeyEcxCookieStorageService, MonkeyEcxCoreModule, MonkeyEcxCoreService, MonkeyEcxCurrencyCodePipe, MonkeyEcxDatadogService, MonkeyEcxDiscoveryParamsService, MonkeyEcxDisplayFirstNamePipe, MonkeyEcxDisplayInitialsPipe, MonkeyEcxErrorMessageDirective, MonkeyEcxFeatureByProgramDirective, MonkeyEcxFeatureDirective, MonkeyEcxFeatureToggleService, MonkeyEcxFileCacheService, MonkeyEcxFormValidationService, MonkeyEcxFormatAddressPipe, MonkeyEcxFormatBeaufityJSONPipe, MonkeyEcxFormatCurrencyPipe, MonkeyEcxFormatDatePipe, MonkeyEcxFormatDocumentPipe, MonkeyEcxFormatDocumentTypePipe, MonkeyEcxFormatNumberPipe, MonkeyEcxFormatPhonePipe, MonkeyEcxFormatSizePipe, MonkeyEcxFormatTaxPipe, MonkeyEcxFormatValue, MonkeyEcxFormatZipCodePipe, MonkeyEcxI18nResolver, MonkeyEcxLinksModel, MonkeyEcxLoadingDirective, MonkeyEcxLocaleService, MonkeyEcxLoggedHandleService, MonkeyEcxLogs, MonkeyEcxModel, MonkeyEcxPipesModule, MonkeyEcxScheduleService, MonkeyEcxSecurityDirective, MonkeyEcxService, MonkeyEcxTextTruncatePipe, MonkeyEcxTokenStorageService, MonkeyEcxTruncateQtdPipe, MonkeyEcxUtils, MonkeyValidators, comboValidator, containsNumber, dateRangeValidator, dateStartEndValidator, dateValidator, differentFromZero, documentValidator, documentValidatorByType, emailValidator, injectTokenWithWarning, minYearsValidator, monkeyEcxHttpConfigInterceptor, passwordConfirmValidator, provideDomainServiceWorker, registerValidator, requiredWithTrimValidator, index as storage, index$1 as store, trueValidator, urlValidator, validateFullName, valueGreaterThanZero, zipCodeValidator };
6025
+ export { CACHE_LOCALE_EXPIRATION_MS, CountryMasks, LService, Link, MECX_ALPHA, MECX_BETA, MECX_BOOTSTRAP_SERVICE, MECX_CORE_I18N_WRAPPER, MECX_COUNTRY, MECX_DATE_FORMAT, MECX_FEDERATION, MECX_I18N_ALIAS, MECX_I18N_PATH, MECX_REDIRECT_LOGIN_WELCOMEBACK_STRATEGY, MECX_REFRESH_TOKEN_STRATEGY, MECX_REQUEST_ID, MECX_TIMEZONEOFFSET, MonkeyEcxAuthGuard, MonkeyEcxAuthGuardByRole, MonkeyEcxAuthGuardCompany, MonkeyEcxAuthGuardLogin, MonkeyEcxBaseResolver, MonkeyEcxBlobSecurePipe, MonkeyEcxCommonsActions, MonkeyEcxCommonsSelectors, MonkeyEcxCommonsStoreService, MonkeyEcxConfigsService, MonkeyEcxCookieStorageService, MonkeyEcxCoreModule, MonkeyEcxCoreService, MonkeyEcxCurrencyCodePipe, MonkeyEcxDatadogService, MonkeyEcxDiscoveryParamsService, MonkeyEcxDisplayFirstNamePipe, MonkeyEcxDisplayInitialsPipe, MonkeyEcxErrorMessageDirective, MonkeyEcxFeatureByProgramDirective, MonkeyEcxFeatureDirective, MonkeyEcxFeatureToggleService, MonkeyEcxFederationService, MonkeyEcxFileCacheService, MonkeyEcxFormValidationService, MonkeyEcxFormatAddressPipe, MonkeyEcxFormatBeaufityJSONPipe, MonkeyEcxFormatCurrencyPipe, MonkeyEcxFormatDatePipe, MonkeyEcxFormatDocumentPipe, MonkeyEcxFormatDocumentTypePipe, MonkeyEcxFormatNumberPipe, MonkeyEcxFormatPhonePipe, MonkeyEcxFormatSizePipe, MonkeyEcxFormatTaxPipe, MonkeyEcxFormatValue, MonkeyEcxFormatZipCodePipe, MonkeyEcxI18nResolver, MonkeyEcxLinksModel, MonkeyEcxLoadingDirective, MonkeyEcxLocaleService, MonkeyEcxLoggedHandleService, MonkeyEcxLogs, MonkeyEcxModel, MonkeyEcxPipesModule, MonkeyEcxScheduleService, MonkeyEcxSecurityDirective, MonkeyEcxService, MonkeyEcxTextTruncatePipe, MonkeyEcxTokenStorageService, MonkeyEcxTruncateQtdPipe, MonkeyEcxUtils, MonkeyValidators, comboValidator, containsNumber, dateRangeValidator, dateStartEndValidator, dateValidator, differentFromZero, documentValidator, documentValidatorByType, emailValidator, injectTokenWithWarning, minYearsValidator, monkeyEcxHttpConfigInterceptor, passwordConfirmValidator, provideMonkeyEcxDomainServiceWorker, provideMonkeyEcxFederation, registerValidator, requiredWithTrimValidator, index as storage, index$1 as store, trueValidator, urlValidator, validateFullName, valueGreaterThanZero, zipCodeValidator };
5885
6026
  //# sourceMappingURL=monkey-front-core.mjs.map