monkey-front-core 22.0.0 → 22.2.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/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,133 @@ 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._federation = injectTokenWithWarning(MECX_FEDERATION, 'MECX_FEDERATION');
2027
+ this._remotes$ = new BehaviorSubject({});
2028
+ this._initialized$ = new BehaviorSubject(false);
2029
+ this._loading = new Map();
2030
+ }
2031
+ get remotes$() {
2032
+ return this._remotes$.asObservable();
2033
+ }
2034
+ get allLoaded$() {
2035
+ return this.watchHoldSplash(['loaded']);
2036
+ }
2037
+ get allSettled$() {
2038
+ return this.watchHoldSplash(['loaded', 'error']);
2039
+ }
2040
+ watchHoldSplash(statuses) {
2041
+ return combineLatest([this._initialized$, this._remotes$]).pipe(map(([initialized, remotes]) => {
2042
+ return this.isHoldSplashIn(initialized, remotes, statuses);
2043
+ }), distinctUntilChanged());
2044
+ }
2045
+ isHoldSplashIn(initialized, remotes, statuses) {
2046
+ if (!initialized)
2047
+ return false;
2048
+ return Object.values(remotes)
2049
+ .filter(({ setting }) => {
2050
+ return setting.holdSplash;
2051
+ })
2052
+ .every(({ status }) => {
2053
+ return statuses.includes(status);
2054
+ });
2055
+ }
2056
+ updateRemote(name, data) {
2057
+ const remotes = this._remotes$.value;
2058
+ this._remotes$.next({
2059
+ ...remotes,
2060
+ [name]: { ...remotes[name], ...data }
2061
+ });
2062
+ }
2063
+ async handleLoad(name) {
2064
+ const setting = this._configsService.federationSettings(name);
2065
+ if (!setting) {
2066
+ throw new Error(`MECXFederation -> Remote "${name}" not found in federationSettings`);
2067
+ }
2068
+ this.updateRemote(name, { name, setting, status: 'loading', error: undefined });
2069
+ try {
2070
+ if (!this._federation) {
2071
+ throw new Error(`MECXFederation -> Remote "${name}" could not be loaded`);
2072
+ }
2073
+ const { host, remoteEntry = DEFAULT_REMOTE_ENTRY, exposedModule = DEFAULT_EXPOSED_MODULE } = setting;
2074
+ const url = `${host.replace(/\/+$/, '')}/${remoteEntry.replace(/^\/+/, '')}`;
2075
+ this._federation = await this._federation.initRemoteEntry(url, name);
2076
+ const module = await this._federation.loadRemoteModule(name, exposedModule);
2077
+ this.updateRemote(name, { status: 'loaded', module });
2078
+ return module;
2079
+ }
2080
+ catch (e) {
2081
+ console.error(`MECXFederation -> Remote "${name}" failed to load: `, e);
2082
+ this.updateRemote(name, { status: 'error', error: e });
2083
+ throw e;
2084
+ }
2085
+ }
2086
+ apply() {
2087
+ const federationSettings = this._configsService.bootstrap?.federationSettings || {};
2088
+ const current = this._remotes$.value;
2089
+ const remotes = Object.entries(federationSettings).reduce((acc, [name, setting]) => {
2090
+ acc[name] = current[name] || { name, setting, status: 'idle' };
2091
+ return acc;
2092
+ }, {});
2093
+ this._remotes$.next(remotes);
2094
+ this._initialized$.next(true);
2095
+ Object.entries(federationSettings)
2096
+ .filter(([, setting]) => {
2097
+ return setting.preload || setting.holdSplash;
2098
+ })
2099
+ .forEach(([name]) => {
2100
+ this.load(name).catch(() => {
2101
+ // not to do
2102
+ });
2103
+ });
2104
+ }
2105
+ skip() {
2106
+ this._initialized$.next(true);
2107
+ }
2108
+ load(name) {
2109
+ let promise = this._loading.get(name);
2110
+ if (!promise) {
2111
+ promise = this.handleLoad(name).catch((e) => {
2112
+ this._loading.delete(name);
2113
+ throw e;
2114
+ });
2115
+ this._loading.set(name, promise);
2116
+ }
2117
+ return promise;
2118
+ }
2119
+ async loadRoutes(name) {
2120
+ const module = await this.load(name);
2121
+ return module.routes;
2122
+ }
2123
+ status(name) {
2124
+ return this._remotes$.value[name] || null;
2125
+ }
2126
+ isAllLoaded() {
2127
+ return this.isHoldSplashIn(this._initialized$.value, this._remotes$.value, ['loaded']);
2128
+ }
2129
+ isAllSettled() {
2130
+ return this.isHoldSplashIn(this._initialized$.value, this._remotes$.value, ['loaded', 'error']);
2131
+ }
2132
+ async whenAllSettled() {
2133
+ await firstValueFrom(this.allSettled$.pipe(filter(Boolean)));
2134
+ }
2135
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: MonkeyEcxFederationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2136
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: MonkeyEcxFederationService, providedIn: 'root' }); }
2137
+ }
2138
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: MonkeyEcxFederationService, decorators: [{
2139
+ type: Injectable,
2140
+ args: [{ providedIn: 'root' }]
2141
+ }] });
2142
+
2019
2143
  /** ************************
2020
2144
  * Copyright Monkey Exchange. All Rights Reserved
2021
2145
  * This style guide was developed by Monkey Exchange Team
@@ -3075,6 +3199,7 @@ class MonkeyEcxInitService {
3075
3199
  this._maintenanceService = inject(MonkeyEcxMaintenanceService);
3076
3200
  this._localeService = inject(MonkeyEcxLocaleService);
3077
3201
  this._connectionService = inject(MonkeyEcxConnectionService);
3202
+ this._federationService = inject(MonkeyEcxFederationService);
3078
3203
  this._bootstrapService = injectTokenWithWarning(MECX_BOOTSTRAP_SERVICE, 'MECX_BOOTSTRAP_SERVICE');
3079
3204
  // not to do
3080
3205
  }
@@ -3107,9 +3232,11 @@ class MonkeyEcxInitService {
3107
3232
  async handleSettings(response, code) {
3108
3233
  this._updateService.apply();
3109
3234
  if (response.maintenance.closed) {
3235
+ this._federationService.skip();
3110
3236
  this._maintenanceService.apply();
3111
3237
  }
3112
3238
  else {
3239
+ this._federationService.apply();
3113
3240
  await this.handleWhiteLabel(code);
3114
3241
  await this._featureToggleService.apply();
3115
3242
  await this.handleStyleGuide(code);
@@ -3121,6 +3248,7 @@ class MonkeyEcxInitService {
3121
3248
  async performValidation(response, code) {
3122
3249
  this._configsService.bootstrap = response;
3123
3250
  if (!code) {
3251
+ this._federationService.skip();
3124
3252
  this._errorService.apply();
3125
3253
  return;
3126
3254
  }
@@ -3142,6 +3270,7 @@ class MonkeyEcxInitService {
3142
3270
  }
3143
3271
  catch (e) {
3144
3272
  console.error('🤯 MECXInit -> Monkey app initialization failed: ', e);
3273
+ this._federationService.skip();
3145
3274
  this._errorService.apply(e);
3146
3275
  }
3147
3276
  }
@@ -5646,7 +5775,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImpor
5646
5775
  * MIT Licence
5647
5776
  ************************* */
5648
5777
 
5649
- function provideDomainServiceWorker(workerUrl, scope = '/') {
5778
+ function provideMonkeyEcxFederation(federation) {
5779
+ return [{ provide: MECX_FEDERATION, useValue: federation }];
5780
+ }
5781
+
5782
+ function provideMonkeyEcxDomainServiceWorker(workerUrl, scope = '/') {
5650
5783
  return provideServiceWorker(workerUrl, {
5651
5784
  enabled: true,
5652
5785
  scope,
@@ -5881,5 +6014,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImpor
5881
6014
  * Generated bundle index. Do not edit.
5882
6015
  */
5883
6016
 
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 };
6017
+ 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
6018
  //# sourceMappingURL=monkey-front-core.mjs.map