diff --git a/docs/en/Multi-Tenancy.md b/docs/en/Multi-Tenancy.md index 77ca49961b..901a5c5cff 100644 --- a/docs/en/Multi-Tenancy.md +++ b/docs/en/Multi-Tenancy.md @@ -355,7 +355,7 @@ namespace MyCompany.MyProject } ```` -{0} is the the placeholder to determine current tenant's unique name. +{0} is the placeholder to determine current tenant's unique name. Instead of ``options.TenantResolvers.Insert(1, new DomainTenantResolveContributor("{0}.mydomain.com"));`` you can use this shortcut: diff --git a/docs/en/UI/Angular/Multi-Tenancy.md b/docs/en/UI/Angular/Multi-Tenancy.md new file mode 100644 index 0000000000..94b3954a03 --- /dev/null +++ b/docs/en/UI/Angular/Multi-Tenancy.md @@ -0,0 +1,135 @@ +# Multi Tenancy in Angular UI + +ABP Angular UI supports the multi-tenancy. The following features related to multi-tenancy are available in the startup templates. + + +![Tenants Page](./images/tenants-page.png) +

Tenants page

+ +On the page above, you can; + +- See the all tenants. +- Create a new tenant. +- Edit an existing tenant. +- Delete a tenant. + + +![Tenant Switching Component](./images/tenant-switching-box.png) +

Tenant Switching Component

+ +You can switch between existing tenants by using the tenant switching component in the child pages of the `AccountLayoutComponent` (like Login page). Angular UI sends the selected tenant id sends to the backend as `__tenant` header on each request. + + +## Domain Tenant Resolver + +Angular UI can get the tenant name from the app running URL. You can determine the current tenant by subdomain (like mytenant1.mydomain.com) or by the whole domain (like mytenant.com). To do this, you need to set the `application.baseUrl` property in the environment: + +Subdomain resolver: + +```js +// environment.prod.ts + +export const environment = { + //... + application: { + baseUrl: 'https://{0}.mydomain.com/' + }, + //... +} +``` + +**{0}** is the placeholder to determine current tenant's unique name. + +After the configuration above, if your app runs on the `mytenant1.mydomain.com`, the app will get the tenant name as **mytenant1**. Then, the app will call the `/api/abp/multi-tenancy/tenants/by-name/mytenant1` endpoint to check if the tenant exists. If the tenant (mytenant1) exists, the app will keep this tenant data and send its `id` as `__tenant` header to the backend on each request. If the tenant does not exist, the app will not send `__tenant` header to the backend. + +> **Important Note:** If you define the `baseUrl` with the placeholder (**{0}**), the tenant switching component in the child pages of the `AccountLayoutComponent` (like Login page) will be hidden. + + +Domain resolver: + +```js +// environment.prod.ts + +export const environment = { + //... + application: { + baseUrl: 'https://{0}.com/' + }, + //... +} +``` + +After the configuration above, if your app runs on the `mytenant.com`, the app will get the tenant name as **mytenant**. + +### Tenant Specific Remote Endpoints + +The **{0}** placeholder can be put to the API URLs in the environment to determine tenant specific endpoints. + +```js +// environment.prod.ts + +export const environment = { + //... + application: { + baseUrl: 'https://{0}.mydomain.com/', + //... + }, + oAuthConfig: { + issuer: 'https://{0}.ids.mydomain.com', + //... + }, + apis: { + default: { + url: 'https://{0}.api.mydomain.com', + }, + AbpIdentity: { + url: 'https://{0}.identity.mydomain.com', + }, + }, +} +``` + +> **Important Note:** The `application.baseUrl` and the `{0}` placeholder in the value of the `baseUrl` property are required to be able to get tenant from running URL. Other placeholders in API URLs are optional. + +After the configuration above, if your app runs on the `mytenant1.mydomain.com`, the app will get tenant name as **mytenant1** and replace the environment object in `ConfigState` on app initialization as follows: + + +```js +// environment object in ConfigState + +{ + //... + application: { + baseUrl: 'https://mytenant1.mydomain.com/', + //... + }, + oAuthConfig: { + issuer: 'https://mytenant1.ids.mydomain.com', + //... + }, + apis: { + default: { + url: 'https://mytenant1.api.mydomain.com', + }, + AbpIdentity: { + url: 'https://mytenant1.identity.mydomain.com', + }, + }, +} +``` + +After this replacement, the app will use the following URLs: + +- `https://mytenant1.ids.mydomain.com` as IdentityServer URL. +- `https://mytenant1.api.mydomain.com` as default URL. +- `https://mytenant1.identity.mydomain.com` as `AbpIdentity` remote endpoint URL. + +The app sends the `__tenant` header that contains the current tenant id on each request. + +## See Also + +* [Multi Tenancy in ABP](../../Multi-Tenancy.md) + +## What's Next? + +- [Confirmation Popup](./Confirmation-Service.md) diff --git a/docs/en/UI/Angular/Permission-Management.md b/docs/en/UI/Angular/Permission-Management.md index 61169c85b8..8cc7325afd 100644 --- a/docs/en/UI/Angular/Permission-Management.md +++ b/docs/en/UI/Angular/Permission-Management.md @@ -78,4 +78,4 @@ Granted Policies are stored in the `auth` property of `ConfigState`. ## What's Next? -- [Confirmation Popup](./Confirmation-Service.md) \ No newline at end of file +* [Multi Tenancy](./Multi-Tenancy.md) \ No newline at end of file diff --git a/docs/en/UI/Angular/images/tenant-switching-box.png b/docs/en/UI/Angular/images/tenant-switching-box.png new file mode 100644 index 0000000000..ed4d299c55 Binary files /dev/null and b/docs/en/UI/Angular/images/tenant-switching-box.png differ diff --git a/docs/en/UI/Angular/images/tenants-page.png b/docs/en/UI/Angular/images/tenants-page.png new file mode 100644 index 0000000000..8882d58d2f Binary files /dev/null and b/docs/en/UI/Angular/images/tenants-page.png differ diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index b586f3aff4..90d4192dce 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -262,7 +262,7 @@ "path": "Blob-Storing-Custom-Provider.md" } ] - } + } ] }, { @@ -435,6 +435,10 @@ "text": "Permission Management", "path": "UI/Angular/Permission-Management.md" }, + { + "text": "Multi Tenancy", + "path": "UI/Angular/Multi-Tenancy.md" + }, { "text": "Confirmation Popup", "path": "UI/Angular/Confirmation-Service.md" diff --git a/npm/ng-packs/apps/dev-app/src/environments/environment.prod.ts b/npm/ng-packs/apps/dev-app/src/environments/environment.prod.ts index ae0e6aba2c..21e1302773 100644 --- a/npm/ng-packs/apps/dev-app/src/environments/environment.prod.ts +++ b/npm/ng-packs/apps/dev-app/src/environments/environment.prod.ts @@ -1,7 +1,10 @@ +import { Config } from '@abp/ng.core'; + export const environment = { production: true, hmr: false, application: { + baseUrl: 'http://localhost:4200/', name: 'MyProjectName', logoUrl: '', }, @@ -10,7 +13,6 @@ export const environment = { clientId: 'MyProjectName_App', dummyClientSecret: '1q2w3e*', scope: 'MyProjectName', - showDebugInformation: true, oidc: false, requireHttps: true, }, @@ -19,4 +21,4 @@ export const environment = { url: 'https://localhost:44305', }, }, -}; +} as Config.Environment; diff --git a/npm/ng-packs/apps/dev-app/src/environments/environment.ts b/npm/ng-packs/apps/dev-app/src/environments/environment.ts index e678b55a74..8cae243d46 100644 --- a/npm/ng-packs/apps/dev-app/src/environments/environment.ts +++ b/npm/ng-packs/apps/dev-app/src/environments/environment.ts @@ -1,7 +1,10 @@ +import { Config } from '@abp/ng.core'; + export const environment = { production: false, hmr: false, application: { + baseUrl: 'http://localhost:4200/', name: 'MyProjectName', logoUrl: '', }, @@ -10,7 +13,6 @@ export const environment = { clientId: 'MyProjectName_App', dummyClientSecret: '1q2w3e*', scope: 'MyProjectName', - showDebugInformation: true, oidc: false, requireHttps: true, }, @@ -19,4 +21,4 @@ export const environment = { url: 'https://localhost:44305', }, }, -}; +} as Config.Environment; diff --git a/npm/ng-packs/packages/account/src/lib/components/auth-wrapper/auth-wrapper.component.html b/npm/ng-packs/packages/account/src/lib/components/auth-wrapper/auth-wrapper.component.html index 3377b74a88..f57643f7b2 100644 --- a/npm/ng-packs/packages/account/src/lib/components/auth-wrapper/auth-wrapper.component.html +++ b/npm/ng-packs/packages/account/src/lib/components/auth-wrapper/auth-wrapper.component.html @@ -1,6 +1,6 @@
- + diff --git a/npm/ng-packs/packages/account/src/lib/components/auth-wrapper/auth-wrapper.component.ts b/npm/ng-packs/packages/account/src/lib/components/auth-wrapper/auth-wrapper.component.ts index be35672862..e7b398cc3d 100644 --- a/npm/ng-packs/packages/account/src/lib/components/auth-wrapper/auth-wrapper.component.ts +++ b/npm/ng-packs/packages/account/src/lib/components/auth-wrapper/auth-wrapper.component.ts @@ -1,4 +1,4 @@ -import { ConfigState, SubscriptionService } from '@abp/ng.core'; +import { ConfigState, SubscriptionService, MultiTenancyService } from '@abp/ng.core'; import { Component, Input, OnInit, TemplateRef } from '@angular/core'; import { Select, Store } from '@ngxs/store'; import { Observable } from 'rxjs'; @@ -26,7 +26,11 @@ export class AuthWrapperComponent tenantBoxKey = eAccountComponents.TenantBox; - constructor(private store: Store, private subscription: SubscriptionService) {} + constructor( + public readonly multiTenancy: MultiTenancyService, + private store: Store, + private subscription: SubscriptionService, + ) {} ngOnInit() { this.subscription.addOne( diff --git a/npm/ng-packs/packages/core/src/lib/core.module.ts b/npm/ng-packs/packages/core/src/lib/core.module.ts index 3fd29fec53..85cf87297f 100644 --- a/npm/ng-packs/packages/core/src/lib/core.module.ts +++ b/npm/ng-packs/packages/core/src/lib/core.module.ts @@ -21,6 +21,7 @@ import { PermissionDirective } from './directives/permission.directive'; import { ReplaceableTemplateDirective } from './directives/replaceable-template.directive'; import { StopPropagationDirective } from './directives/stop-propagation.directive'; import { VisibilityDirective } from './directives/visibility.directive'; +import { OAuthConfigurationHandler } from './handlers/oauth-configuration.handler'; import { RoutesHandler } from './handlers/routes.handler'; import { ApiInterceptor } from './interceptors/api.interceptor'; import { LocalizationModule } from './localization.module'; @@ -34,10 +35,10 @@ import { ConfigState } from './states/config.state'; import { ProfileState } from './states/profile.state'; import { ReplaceableComponentsState } from './states/replaceable-components.state'; import { SessionState } from './states/session.state'; -import { CORE_OPTIONS, coreOptionsFactory } from './tokens/options.token'; +import { coreOptionsFactory, CORE_OPTIONS } from './tokens/options.token'; import { noop } from './utils/common-utils'; import './utils/date-extensions'; -import { getInitialData, localeInitializer, configureOAuth } from './utils/initial-utils'; +import { getInitialData, localeInitializer } from './utils/initial-utils'; export function storageFactory(): OAuthStorage { return localStorage; @@ -187,8 +188,8 @@ export class CoreModule { { provide: APP_INITIALIZER, multi: true, - deps: [Injector, NGXS_CONFIG_PLUGIN_OPTIONS], - useFactory: configureOAuth, + deps: [OAuthConfigurationHandler], + useFactory: noop, }, { provide: APP_INITIALIZER, diff --git a/npm/ng-packs/packages/core/src/lib/handlers/index.ts b/npm/ng-packs/packages/core/src/lib/handlers/index.ts index b666218d93..e11b317f45 100644 --- a/npm/ng-packs/packages/core/src/lib/handlers/index.ts +++ b/npm/ng-packs/packages/core/src/lib/handlers/index.ts @@ -1 +1,2 @@ +export * from './oauth-configuration.handler'; export * from './routes.handler'; diff --git a/npm/ng-packs/packages/core/src/lib/handlers/oauth-configuration.handler.ts b/npm/ng-packs/packages/core/src/lib/handlers/oauth-configuration.handler.ts new file mode 100644 index 0000000000..d9c6806900 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/handlers/oauth-configuration.handler.ts @@ -0,0 +1,35 @@ +import { Inject, Injectable } from '@angular/core'; +import { Actions, ofActionSuccessful } from '@ngxs/store'; +import { OAuthService } from 'angular-oauth2-oidc'; +import compare from 'just-compare'; +import { filter, map } from 'rxjs/operators'; +import { SetEnvironment } from '../actions/config.actions'; +import { ABP } from '../models/common'; +import { CORE_OPTIONS } from '../tokens/options.token'; + +@Injectable({ + providedIn: 'root', +}) +export class OAuthConfigurationHandler { + constructor( + private actions: Actions, + private oAuthService: OAuthService, + @Inject(CORE_OPTIONS) private options: ABP.Root, + ) { + this.oAuthService.configure(this.options.environment.oAuthConfig); + + this.listenToSetEnvironment(); + } + + private listenToSetEnvironment() { + this.actions + .pipe(ofActionSuccessful(SetEnvironment)) + .pipe( + map(({ environment }: SetEnvironment) => environment.oAuthConfig), + filter(config => !compare(config, this.options.environment.oAuthConfig)), + ) + .subscribe(config => { + this.oAuthService.configure(config); + }); + } +} diff --git a/npm/ng-packs/packages/core/src/lib/models/config.ts b/npm/ng-packs/packages/core/src/lib/models/config.ts index d328cfe5b5..682e49e94e 100644 --- a/npm/ng-packs/packages/core/src/lib/models/config.ts +++ b/npm/ng-packs/packages/core/src/lib/models/config.ts @@ -17,6 +17,7 @@ export namespace Config { export interface Application { name: string; + baseUrl?: string; logoUrl?: string; } diff --git a/npm/ng-packs/packages/core/src/lib/models/find-tenant-result-dto.ts b/npm/ng-packs/packages/core/src/lib/models/find-tenant-result-dto.ts new file mode 100644 index 0000000000..9b1b0cc4b6 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/models/find-tenant-result-dto.ts @@ -0,0 +1,14 @@ + +export class FindTenantResultDto { + success: boolean; + tenantId?: string; + name: string; + + constructor(initialValues: Partial = {}) { + for (const key in initialValues) { + if (initialValues.hasOwnProperty(key)) { + this[key] = initialValues[key]; + } + } + } +} diff --git a/npm/ng-packs/packages/core/src/lib/models/index.ts b/npm/ng-packs/packages/core/src/lib/models/index.ts index c0950c3dee..e5776a682e 100644 --- a/npm/ng-packs/packages/core/src/lib/models/index.ts +++ b/npm/ng-packs/packages/core/src/lib/models/index.ts @@ -2,6 +2,7 @@ export * from './application-configuration'; export * from './common'; export * from './config'; export * from './dtos'; +export * from './find-tenant-result-dto'; export * from './profile'; export * from './replaceable-components'; export * from './rest'; diff --git a/npm/ng-packs/packages/core/src/lib/services/index.ts b/npm/ng-packs/packages/core/src/lib/services/index.ts index e5e5286710..c084fd4808 100644 --- a/npm/ng-packs/packages/core/src/lib/services/index.ts +++ b/npm/ng-packs/packages/core/src/lib/services/index.ts @@ -6,6 +6,7 @@ export * from './dom-insertion.service'; export * from './lazy-load.service'; export * from './list.service'; export * from './localization.service'; +export * from './multi-tenancy.service'; export * from './profile-state.service'; export * from './profile.service'; export * from './rest.service'; diff --git a/npm/ng-packs/packages/core/src/lib/services/multi-tenancy.service.ts b/npm/ng-packs/packages/core/src/lib/services/multi-tenancy.service.ts new file mode 100644 index 0000000000..3a66a99311 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/services/multi-tenancy.service.ts @@ -0,0 +1,45 @@ +import { Injectable } from '@angular/core'; +import { Store } from '@ngxs/store'; +import { Observable } from 'rxjs'; +import { SetTenant } from '../actions/session.actions'; +import { ABP } from '../models/common'; +import { FindTenantResultDto } from '../models/find-tenant-result-dto'; +import { RestService } from './rest.service'; + +@Injectable({ providedIn: 'root' }) +export class MultiTenancyService { + private _domainTenant: ABP.BasicItem = null; + + set domainTenant(value: ABP.BasicItem) { + this._domainTenant = value; + this.store.dispatch(new SetTenant(value)); + } + + get domainTenant() { + return this._domainTenant; + } + + isTenantBoxVisible = true; + + apiName = 'abp'; + + constructor(private restService: RestService, private store: Store) {} + + findTenantByName(name: string, headers: ABP.Dictionary): Observable { + return this.restService.request( + { + url: `/api/abp/multi-tenancy/tenants/by-name/${name}`, + method: 'GET', + headers, + }, + { apiName: this.apiName }, + ); + } + + findTenantById(id: string, headers: ABP.Dictionary): Observable { + return this.restService.request( + { url: `/api/abp/multi-tenancy/tenants/by-id/${id}`, method: 'GET', headers }, + { apiName: this.apiName }, + ); + } +} diff --git a/npm/ng-packs/packages/core/src/lib/states/config.state.ts b/npm/ng-packs/packages/core/src/lib/states/config.state.ts index 713eb336e1..2aaf7a3bc2 100644 --- a/npm/ng-packs/packages/core/src/lib/states/config.state.ts +++ b/npm/ng-packs/packages/core/src/lib/states/config.state.ts @@ -233,8 +233,6 @@ export class ConfigState { @Action(SetEnvironment) setEnvironment({ patchState }: StateContext, { environment }: SetEnvironment) { - return patchState({ - environment, - }); + return patchState({ environment }); } } diff --git a/npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts index 9a4166e7cc..ae9ce94650 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts @@ -1,10 +1,12 @@ import { Component, Injector } from '@angular/core'; import { createComponentFactory, Spectator } from '@ngneat/spectator/jest'; import { Store } from '@ngxs/store'; +import { OAuthService } from 'angular-oauth2-oidc'; import { of } from 'rxjs'; import { GetAppConfiguration } from '../actions'; -import { getInitialData, localeInitializer, configureOAuth } from '../utils'; -import { OAuthService } from 'angular-oauth2-oidc'; +import { CORE_OPTIONS } from '../tokens/options.token'; +import { checkAccessToken, getInitialData, localeInitializer } from '../utils'; +import * as multiTenancyUtils from '../utils/multi-tenancy-utils'; @Component({ selector: 'abp-dummy', @@ -17,30 +19,21 @@ describe('InitialUtils', () => { const createComponent = createComponentFactory({ component: DummyComponent, mocks: [Store, OAuthService], + providers: [ + { provide: CORE_OPTIONS, useValue: { environment: { oAuthConfig: { issuer: 'test' } } } }, + ], }); beforeEach(() => (spectator = createComponent())); - describe('#configureOAuth', () => { - test('should be called the the configure method of OAuthService', async () => { - const injector = spectator.inject(Injector); - const injectorSpy = jest.spyOn(injector, 'get'); - const oAuth = spectator.inject(OAuthService); - const configureSpy = jest.spyOn(oAuth, 'configure'); - - injectorSpy.mockReturnValueOnce(oAuth); - - await configureOAuth(injector, { environment: { oAuthConfig: { issuer: 'test' } } })(); - expect(configureSpy).toHaveBeenCalledWith({ issuer: 'test' }); - }); - }); - describe('#getInitialData', () => { test('should dispatch GetAppConfiguration and return', async () => { const injector = spectator.inject(Injector); const injectorSpy = jest.spyOn(injector, 'get'); const store = spectator.inject(Store); const dispatchSpy = jest.spyOn(store, 'dispatch'); + const parseTenantFromUrlSpy = jest.spyOn(multiTenancyUtils, 'parseTenantFromUrl'); + parseTenantFromUrlSpy.mockReturnValue(Promise.resolve()); injectorSpy.mockReturnValueOnce(store); injectorSpy.mockReturnValueOnce({ skipGetAppConfiguration: false }); @@ -57,16 +50,16 @@ describe('InitialUtils', () => { test('should call logOut fn of OAuthService when token is valid and current user not found', async () => { const injector = spectator.inject(Injector); const injectorSpy = jest.spyOn(injector, 'get'); - const store = spectator.inject(Store); - const dispatchSpy = jest.spyOn(store, 'dispatch'); const logOutFn = jest.fn(); - injectorSpy.mockReturnValueOnce(store); - injectorSpy.mockReturnValueOnce({ skipGetAppConfiguration: false }); - injectorSpy.mockReturnValueOnce({ hasValidAccessToken: () => true, logOut: logOutFn }); - dispatchSpy.mockReturnValue(of({ currentUser: { id: null } })); + injectorSpy.mockReturnValue({ hasValidAccessToken: () => true, logOut: logOutFn }); - getInitialData(injector)(); + checkAccessToken( + { + selectSnapshot: () => false, + } as any, + injector, + ); expect(logOutFn).toHaveBeenCalled(); }); }); diff --git a/npm/ng-packs/packages/core/src/lib/tests/multi-tenancy-utils.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/multi-tenancy-utils.spec.ts new file mode 100644 index 0000000000..f802e22371 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/tests/multi-tenancy-utils.spec.ts @@ -0,0 +1,103 @@ +import { Component, Injector } from '@angular/core'; +import { createComponentFactory, Spectator } from '@ngneat/spectator/jest'; +import { Store } from '@ngxs/store'; +import clone from 'just-clone'; +import { BehaviorSubject } from 'rxjs'; +import { FindTenantResultDto } from '../models/find-tenant-result-dto'; +import { MultiTenancyService } from '../services/multi-tenancy.service'; +import { parseTenantFromUrl } from '../utils'; + +const environment = { + production: false, + hmr: false, + application: { + baseUrl: 'https://{0}.volosoft.com', + name: 'MyProjectName', + logoUrl: '', + }, + oAuthConfig: { + issuer: 'https://{0}.api.volosoft.com', + clientId: 'MyProjectName_App', + dummyClientSecret: '1q2w3e*', + scope: 'MyProjectName', + oidc: false, + requireHttps: true, + }, + apis: { + default: { + url: 'https://{0}.api.volosoft.com', + }, + abp: { + url: 'https://api.volosoft.com/{0}', + }, + }, +}; + +const setHref = url => { + global.window = Object.create(window); + delete window.location; + Object.defineProperty(window, 'location', { + value: { + href: url, + }, + }); +}; + +@Component({ + selector: 'abp-dummy', + template: '', +}) +export class DummyComponent {} + +describe('MultiTenancyUtils', () => { + let spectator: Spectator; + const createComponent = createComponentFactory({ + component: DummyComponent, + mocks: [Store, MultiTenancyService], + }); + + beforeEach(() => (spectator = createComponent())); + + describe('#parseTenantFromUrl', () => { + test('should get the tenancyName, set replaced environment and call the findTenantByName method of MultiTenancyService', async () => { + const injector = spectator.inject(Injector); + const injectorSpy = jest.spyOn(injector, 'get'); + const store = spectator.inject(Store); + const selectSnapshotSpy = jest.spyOn(store, 'selectSnapshot'); + const dispatchSpy = jest.spyOn(store, 'dispatch'); + const multiTenancyService = spectator.inject(MultiTenancyService); + const findTenantByNameSpy = jest.spyOn(multiTenancyService, 'findTenantByName'); + + injectorSpy.mockReturnValueOnce(spectator.inject(Store)); + injectorSpy.mockReturnValueOnce(multiTenancyService); + selectSnapshotSpy.mockReturnValue(clone(environment)); + + setHref('https://abp.volosoft.com/'); + + dispatchSpy.mockReturnValue(new BehaviorSubject(true)); + findTenantByNameSpy.mockReturnValue( + new BehaviorSubject({ name: 'abp', tenantId: '1', success: true } as FindTenantResultDto), + ); + + parseTenantFromUrl(injector); + + const replacedEnv = { + ...environment, + application: { ...environment.application, baseUrl: 'https://abp.volosoft.com' }, + oAuthConfig: { ...environment.oAuthConfig, issuer: 'https://abp.api.volosoft.com' }, + apis: { + default: { + url: 'https://abp.api.volosoft.com', + }, + abp: { + url: 'https://api.volosoft.com/abp', + }, + }, + }; + + expect(dispatchSpy).toHaveBeenCalledWith({ environment: replacedEnv }); + expect(findTenantByNameSpy).toHaveBeenCalledWith('abp', { __tenant: '' }); + expect(multiTenancyService.domainTenant).toEqual({ id: '1', name: 'abp' }); + }); + }); +}); diff --git a/npm/ng-packs/packages/core/src/lib/tests/rest.service.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/rest.service.spec.ts index 601c9dd6d2..ee9f07f5a8 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/rest.service.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/rest.service.spec.ts @@ -6,6 +6,7 @@ import { Rest } from '../models'; import { RestService } from '../services/rest.service'; import { ConfigState } from '../states/config.state'; import { CORE_OPTIONS } from '../tokens'; +import { OAuthService } from 'angular-oauth2-oidc'; describe('HttpClient testing', () => { let spectator: SpectatorHttp; @@ -16,6 +17,7 @@ describe('HttpClient testing', () => { dataService: RestService, imports: [NgxsModule.forRoot([ConfigState])], providers: [{ provide: CORE_OPTIONS, useValue: { environment: {} } }], + mocks: [OAuthService], }); beforeEach(() => { diff --git a/npm/ng-packs/packages/core/src/lib/tests/string-utils.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/string-utils.spec.ts new file mode 100644 index 0000000000..a0642e43ee --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/tests/string-utils.spec.ts @@ -0,0 +1,22 @@ +import { createTokenParser } from '../utils/string-utils'; + +describe('String Utils', () => { + describe('#createTokenParser', () => { + const parseTokens = createTokenParser('{subDomain}.{domain}.{gtld}|{domain}.{gtld}'); + + test.each` + url | subDomain | domain | gtld + ${'www.example.com'} | ${'www'} | ${'example'} | ${'com'} + ${'test.sub.example.com'} | ${'test.sub'} | ${'example'} | ${'com'} + ${'example.com'} | ${undefined} | ${'example'} | ${'com'} + `( + 'should return subDomain as $subDomain, domain as $domain, and gtld as $gtld when url is $url', + ({ url, subDomain, domain, gtld }) => { + const parsed = parseTokens(url); + expect(parsed.subDomain[0]).toBe(subDomain); + expect(parsed.domain[0]).toBe(domain); + expect(parsed.gtld[0]).toBe(gtld); + }, + ); + }); +}); diff --git a/npm/ng-packs/packages/core/src/lib/utils/index.ts b/npm/ng-packs/packages/core/src/lib/utils/index.ts index 6f6136b195..9949fa9f26 100644 --- a/npm/ng-packs/packages/core/src/lib/utils/index.ts +++ b/npm/ng-packs/packages/core/src/lib/utils/index.ts @@ -6,7 +6,9 @@ export * from './generator-utils'; export * from './initial-utils'; export * from './lazy-load-utils'; export * from './localization-utils'; +export * from './multi-tenancy-utils'; export * from './number-utils'; export * from './route-utils'; export * from './rxjs-utils'; +export * from './string-utils'; export * from './tree-utils'; diff --git a/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts b/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts index 78677b7ca4..b0adfd4980 100644 --- a/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts +++ b/npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts @@ -7,22 +7,15 @@ import { GetAppConfiguration } from '../actions/config.actions'; import { ABP } from '../models/common'; import { ConfigState } from '../states/config.state'; import { CORE_OPTIONS } from '../tokens/options.token'; - -export function configureOAuth(injector: Injector, options: ABP.Root) { - const fn = () => { - const oAuth = injector.get(OAuthService); - oAuth.configure(options.environment.oAuthConfig); - return Promise.resolve(); - }; - - return fn; -} +import { parseTenantFromUrl } from './multi-tenancy-utils'; export function getInitialData(injector: Injector) { - const fn = () => { + const fn = async () => { const store: Store = injector.get(Store); const { skipGetAppConfiguration } = injector.get(CORE_OPTIONS) as ABP.Root; + await parseTenantFromUrl(injector); + if (skipGetAppConfiguration) return; return store @@ -34,7 +27,7 @@ export function getInitialData(injector: Injector) { return fn; } -function checkAccessToken(store: Store, injector: Injector) { +export function checkAccessToken(store: Store, injector: Injector) { const oAuth = injector.get(OAuthService); if (oAuth.hasValidAccessToken() && !store.selectSnapshot(ConfigState.getDeep('currentUser.id'))) { oAuth.logOut(); diff --git a/npm/ng-packs/packages/core/src/lib/utils/multi-tenancy-utils.ts b/npm/ng-packs/packages/core/src/lib/utils/multi-tenancy-utils.ts new file mode 100644 index 0000000000..6ba6c9e683 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/utils/multi-tenancy-utils.ts @@ -0,0 +1,74 @@ +import { Injector } from '@angular/core'; +import { Store } from '@ngxs/store'; +import clone from 'just-clone'; +import { switchMap, tap } from 'rxjs/operators'; +import { SetEnvironment } from '../actions'; +import { Config } from '../models/config'; +import { MultiTenancyService } from '../services/multi-tenancy.service'; +import { ConfigState } from '../states/config.state'; +import { createTokenParser } from './string-utils'; + +const tenancyPlaceholder = '{0}'; + +function getCurrentTenancyName(appBaseUrl: string): string { + if (appBaseUrl.charAt(appBaseUrl.length - 1) !== '/') appBaseUrl += '/'; + + const parseTokens = createTokenParser(appBaseUrl); + const token = tenancyPlaceholder.replace(/[}{]/g, ''); + return parseTokens(window.location.href)[token][0]; +} + +export async function parseTenantFromUrl(injector: Injector) { + const store: Store = injector.get(Store); + const multiTenancyService = injector.get(MultiTenancyService); + const environment = store.selectSnapshot(ConfigState.getOne('environment')) as Config.Environment; + + const { baseUrl = '' } = environment.application; + const tenancyName = getCurrentTenancyName(baseUrl); + + if (tenancyName) { + multiTenancyService.isTenantBoxVisible = false; + + return setEnvironment(store, tenancyName) + .pipe( + switchMap(() => multiTenancyService.findTenantByName(tenancyName, { __tenant: '' })), + tap(res => { + multiTenancyService.domainTenant = res.success + ? { id: res.tenantId, name: res.name } + : null; + }), + ) + .toPromise(); + } + + return Promise.resolve(); +} + +function setEnvironment(store: Store, tenancyName: string) { + const environment = clone( + store.selectSnapshot(ConfigState.getOne('environment')), + ) as Config.Environment; + + if (environment.application.baseUrl) { + environment.application.baseUrl = environment.application.baseUrl.replace( + tenancyPlaceholder, + tenancyName, + ); + } + + environment.oAuthConfig.issuer = environment.oAuthConfig.issuer.replace( + tenancyPlaceholder, + tenancyName, + ); + + Object.keys(environment.apis).forEach(api => { + Object.keys(environment.apis[api]).forEach(key => { + environment.apis[api][key] = environment.apis[api][key].replace( + tenancyPlaceholder, + tenancyName, + ); + }); + }); + + return store.dispatch(new SetEnvironment(environment)); +} diff --git a/npm/ng-packs/packages/core/src/lib/utils/string-utils.ts b/npm/ng-packs/packages/core/src/lib/utils/string-utils.ts new file mode 100644 index 0000000000..00db697325 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/utils/string-utils.ts @@ -0,0 +1,17 @@ +export function createTokenParser(format: string) { + return (string: string) => { + const tokens: string[] = []; + const regex = format.replace(/\./g, '\\.').replace(/\{\s?([0-9a-zA-Z]+)\s?\}/g, (_, token) => { + tokens.push(token); + return '(.+)'; + }); + + const matches = (string.match(regex) || []).slice(1); + + return matches.reduce((acc, v, i) => { + const key = tokens[i]; + acc[key] = [...(acc[key] || []), v].filter(Boolean); + return acc; + }, {} as Record); + }; +} diff --git a/npm/ng-packs/packages/theme-shared/extensions/src/tests/state.util.spec.ts b/npm/ng-packs/packages/theme-shared/extensions/src/tests/state.util.spec.ts index 9592d4c9c1..86060b8597 100644 --- a/npm/ng-packs/packages/theme-shared/extensions/src/tests/state.util.spec.ts +++ b/npm/ng-packs/packages/theme-shared/extensions/src/tests/state.util.spec.ts @@ -13,6 +13,7 @@ import { getObjectExtensionEntitiesFromStore, mapEntitiesToContributors, } from '../lib/utils/state.util'; +import { OAuthService } from 'angular-oauth2-oidc'; describe('State Utils', () => { let spectator: SpectatorService; @@ -21,7 +22,7 @@ describe('State Utils', () => { const createService = createServiceFactory({ service: Store, imports: [NgxsModule.forRoot([ConfigState])], - mocks: [HttpClient], + mocks: [HttpClient, OAuthService], }); beforeEach(() => { diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/validation-utils.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/validation-utils.spec.ts index 35a46e1ae9..22f445c36c 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/validation-utils.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/validation-utils.spec.ts @@ -6,6 +6,7 @@ import { NgxsModule, Store } from '@ngxs/store'; import { HttpClient } from '@angular/common/http'; import { getPasswordValidators } from '../utils'; import { Validators } from '@angular/forms'; +import { OAuthService } from 'angular-oauth2-oidc'; @Component({ template: '', selector: 'abp-dummy' }) class DummyComponent {} @@ -15,7 +16,7 @@ describe('ValidationUtils', () => { const createComponent = createComponentFactory({ component: DummyComponent, imports: [NgxsModule.forRoot([ConfigState]), NgxValidateCoreModule.forRoot()], - mocks: [HttpClient], + mocks: [HttpClient, OAuthService], }); beforeEach(() => (spectator = createComponent())); diff --git a/npm/ng-packs/yarn.lock b/npm/ng-packs/yarn.lock index c00ccb0da6..5f274d1935 100644 --- a/npm/ng-packs/yarn.lock +++ b/npm/ng-packs/yarn.lock @@ -2,20 +2,20 @@ # yarn lockfile v1 -"@abp/ng.account@~3.0.4": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@abp/ng.account/-/ng.account-3.0.4.tgz#5c75a30c912294b40cbc43f218d61cbe67a58355" - integrity sha512-a+ZjFoaNlJAYW3Hd+hEhq/TCVENc3x9D4Grf5/zr8h1WcETdgjx8rvRxhj6l6i/Ry/mAgPHOKuObSbb+pxVo6w== +"@abp/ng.account@~3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@abp/ng.account/-/ng.account-3.0.5.tgz#3f359e07be021c5743f42f32abc8371f93552df1" + integrity sha512-isG8VmENHookDJoq73dJfPbAdLxmzPGAJMDvg5Yn124yfHVkZQONszLGZxDNUFWti0S07Xose5dripNzcK2Clg== dependencies: - "@abp/ng.theme.shared" "~3.0.4" + "@abp/ng.theme.shared" "~3.0.5" tslib "^2.0.0" -"@abp/ng.core@~3.0.4": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@abp/ng.core/-/ng.core-3.0.4.tgz#ef86082c13d1ccbf0c48fb2b0ccd5a059e44215b" - integrity sha512-dBHCtcM4dVOvHJ88p8d71qpYpOvTjrvu78e6LO6qK7CsSoJq5B8EkYZgkV6MO2Kq5/p3mLHTtwuP3mkQSUfLJw== +"@abp/ng.core@~3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@abp/ng.core/-/ng.core-3.0.5.tgz#8956c4e27689e80d981bae66e173524c79ca8678" + integrity sha512-PTluEXyea1d5oPtvkNx/SbmX3kBaHtdiJyN88vJoZXbdd5/OIZeeR5cL4Q58+kYG5xf1z6xkq7wNSAzRjTG7VA== dependencies: - "@abp/utils" "^3.0.3" + "@abp/utils" "^3.0.4" "@angular/localize" "~9.1.11" "@ngxs/router-plugin" "^3.6.2" "@ngxs/storage-plugin" "^3.6.2" @@ -27,81 +27,74 @@ ts-toolbelt "^6.9.9" tslib "^2.0.0" -"@abp/ng.feature-management@~3.0.4": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@abp/ng.feature-management/-/ng.feature-management-3.0.4.tgz#127a81c9f8b045c38bc41de4ab49d29acaa14f70" - integrity sha512-TVNmjLhhg0VbaUlaXeDUsgpz5BX26aMzAY0dahsXhyM/dti2slIlEyyTKf673a1ve84nUuigrDJiAhi6WntUbw== +"@abp/ng.feature-management@~3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@abp/ng.feature-management/-/ng.feature-management-3.0.5.tgz#d947f9f05e9edd7c972c42ea903bf05d89efe8da" + integrity sha512-TUrKF5U2hjQ92/Ocig7uULNCew++dfIpCyoHdXrcWZHdhLiFcuuNLc0UElPjFe7WrIuPkka/28MEWHylKFAk4Q== dependencies: - "@abp/ng.theme.shared" "~3.0.4" + "@abp/ng.theme.shared" "~3.0.5" tslib "^2.0.0" -"@abp/ng.identity@~3.0.4": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@abp/ng.identity/-/ng.identity-3.0.4.tgz#321ab33db22d32013d2ea635616f6402717ebc40" - integrity sha512-ZJVh77gZVPKyexfLxo613NeiKWYSk/7q6QrMEzkeDM21R9VLyw5jGg00pw7hkmUldy5bObW/5VVCxJlCzSTwdg== +"@abp/ng.identity@~3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@abp/ng.identity/-/ng.identity-3.0.5.tgz#474119e9d3ce2529f0b03a3241d41ed1d49faa65" + integrity sha512-v6hxUniSyIknOidXYuYFvV2edNksDIBgiB7LvqY/csmddH+fHJhct0W0bdk//83aj5N/Fy3FO5BvkeiGYSFMRg== dependencies: - "@abp/ng.permission-management" "~3.0.4" - "@abp/ng.theme.shared" "~3.0.4" + "@abp/ng.permission-management" "~3.0.5" + "@abp/ng.theme.shared" "~3.0.5" tslib "^2.0.0" -"@abp/ng.permission-management@~3.0.4": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@abp/ng.permission-management/-/ng.permission-management-3.0.4.tgz#511226c1c0e1445a453015d8d85b013e7a009f96" - integrity sha512-hIiUdQh9XVvfmLc5B+eQpj36PxCcBzOCRRaBuGhd2+lecEVUV12EgpWq0fzW1laL9FV1REmqIKP5uzKUeUw4Dw== +"@abp/ng.permission-management@~3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@abp/ng.permission-management/-/ng.permission-management-3.0.5.tgz#2d496872be5af52e8f50022a5c36b3db989c9bc4" + integrity sha512-ukXX/v/ECU0R4SNKNwwdLG1+bbbS8r2GabaefX8IHYxq084VWXWlM7gTgStDIsvgC3Trh8Itoi7uVJHCU6bb0Q== dependencies: - "@abp/ng.theme.shared" "~3.0.4" + "@abp/ng.theme.shared" "~3.0.5" tslib "^2.0.0" -"@abp/ng.setting-management@~3.0.4": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@abp/ng.setting-management/-/ng.setting-management-3.0.4.tgz#880a8999e6f77a46bebb5c3ec2e53e652cb6b289" - integrity sha512-mnjxofTqE+n9C6x5nZkb0DQK/s0cZLwCFrhFoJdiQmfIewHU4AVbs7cT6L7FNewYwojPsCsppiR+y0cUaXDlMQ== +"@abp/ng.setting-management@~3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@abp/ng.setting-management/-/ng.setting-management-3.0.5.tgz#57cc71d3357b73fe4f8890c077916c616301ee97" + integrity sha512-Cd6hTXS9XfIVmzwStICijEzaELDn4++xVUmVncWLJn9dWW5T9Mau+kkn7SeElzmv6U/iSEZH8/UHshktCvJ3Tg== dependencies: - "@abp/ng.theme.shared" "~3.0.4" + "@abp/ng.theme.shared" "~3.0.5" tslib "^2.0.0" -"@abp/ng.tenant-management@~3.0.4": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@abp/ng.tenant-management/-/ng.tenant-management-3.0.4.tgz#3e4edcb94b11b190451ef08115409f59cf164088" - integrity sha512-3lcq80Isa+gTZOKOyzQBd/6t4pe+mOakjZFWOBOpi4gmy4Mmun1KqbfaFoMW+v0wacQPGiznStdln0AeOXXj7g== +"@abp/ng.tenant-management@~3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@abp/ng.tenant-management/-/ng.tenant-management-3.0.5.tgz#ade0e26b26dcea5445842a21f5a1f675705dfa50" + integrity sha512-2etqlpCB2iXCXSTX1D/YSl5WIXgTvPMFUaOQ8r1CFVxdOhsmWgS/8JZEEZMO5oJDKMyw/jibqtY9WeqgdsnJQg== dependencies: - "@abp/ng.feature-management" "~3.0.4" - "@abp/ng.theme.shared" "~3.0.4" + "@abp/ng.feature-management" "~3.0.5" + "@abp/ng.theme.shared" "~3.0.5" tslib "^2.0.0" -"@abp/ng.theme.basic@~3.0.4": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@abp/ng.theme.basic/-/ng.theme.basic-3.0.4.tgz#655e4388f6dd91eea10bdf14f313d92bbec3cf49" - integrity sha512-bSIYntH0gF/HJVYOvuguZfKkkmA6zALSVj6OYQPNo3HW7+N++loawnbMyEbiBSd0V8JolkFHeX/xvOGlY12jnw== +"@abp/ng.theme.basic@~3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@abp/ng.theme.basic/-/ng.theme.basic-3.0.5.tgz#13d3da2547fde92a66eb5fc9f9798892226e63b2" + integrity sha512-COeCirRKpLcY2OE4cs9CrKObA1XRRaHXbRcKnMovPUcxC4xb47tQ5snZ4n4C9VYkRnlpSh8p2w51a8SQuxQjMg== dependencies: - "@abp/ng.theme.shared" "~3.0.4" + "@abp/ng.theme.shared" "~3.0.5" tslib "^2.0.0" -"@abp/ng.theme.shared@~3.0.4": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@abp/ng.theme.shared/-/ng.theme.shared-3.0.4.tgz#d12f560b7e90d91a659c1227bd4e8c25b4f8cd3e" - integrity sha512-0Z37zIiNU0ZVK7F5nP/7uS6ppPGlltUUvlf/l6RdOKi4aUbUtSRqDVoAbTl29AV14A8gicWkSFYKK+2wxoN09Q== +"@abp/ng.theme.shared@~3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@abp/ng.theme.shared/-/ng.theme.shared-3.0.5.tgz#7d0187621d5e27bcc171d21d8ab0e5f7241edef4" + integrity sha512-LAokCastVsEIMH+HfQjkkt6OotKNrIFMCMlDs7Y7i74sXGGhhe+v4hHsWlAT4yQ0EydNYr1W10XoI7B3pzH1MQ== dependencies: - "@abp/ng.core" "~3.0.4" + "@abp/ng.core" "~3.0.5" "@fortawesome/fontawesome-free" "^5.13.1" "@ng-bootstrap/ng-bootstrap" "^6.1.0" - "@ngx-validate/core" "^0.0.9" + "@ngx-validate/core" "^0.0.10" "@swimlane/ngx-datatable" "^17.0.0" bootstrap "^4.5.0" chart.js "^2.9.3" tslib "^2.0.0" -"@abp/utils@^3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-3.0.3.tgz#563aa062882ca82227b749d90458adafa46ae73b" - integrity sha512-eV4cl605j1IbuIbnTTO5JW+O3mpUUVxp+AG2xqIeqrRSnyTGhTG0q30XjsDGlTdcUfwxpZORptD4pu8NfCGUpg== - dependencies: - just-compare "^1.3.0" - -"@abp/utils@^3.0.4": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-3.0.4.tgz#38068fa8f735e1889cf2f226128366825948814d" - integrity sha512-TnXRZIZcxv5+EctEPsZEi2cyRXbpl3A679wzQa6BACv+pM45cjGO1JR8P0VswKN4TVL0aQRMv26N6U/uie8sEQ== +"@abp/utils@^3.0.4", "@abp/utils@^3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-3.0.5.tgz#66b3da953500e73ff1f23d1b41168cde8216ce49" + integrity sha512-X9V1xLIEazItaf93nFSA4p94WT6QK3yA4eIyvU7GyyEkkOQdaakNwPbRwy930sd+I+/oXnIqM1vDsJu9QDhgvg== dependencies: just-compare "^1.3.0" @@ -115,12 +108,12 @@ jest-preset-angular "^8.1.2" lodash "^4.17.10" -"@angular-devkit/architect@0.1000.4": - version "0.1000.4" - resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1000.4.tgz#2effe58361bea2a77d11671743568ab4d50b1554" - integrity sha512-n0DXdrecxXupxKf37sv5Oky5QpQXOHPgLDAmyAwevr31yLEwyZ3OQoVxaC68AMQJFYMlHYYMwi6gdIcFmL6W0g== +"@angular-devkit/architect@0.1000.5": + version "0.1000.5" + resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1000.5.tgz#39488b92a366e49d50dda0af4eee3b0bb9425ec4" + integrity sha512-BhNqB7fmmrDQwxoJ3zdw5FslFD+nYGgMTiC48ERVYJVuN3BK6xtt2OGA7vho3eJ13OE5cPGUi8crQDRROgxxQg== dependencies: - "@angular-devkit/core" "10.0.4" + "@angular-devkit/core" "10.0.5" rxjs "6.5.5" "@angular-devkit/architect@>=0.900.0 < 0.1000.0": @@ -132,14 +125,14 @@ rxjs "6.5.4" "@angular-devkit/build-angular@~0.1000.0": - version "0.1000.4" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-0.1000.4.tgz#447ebfc16afaa7638099e2f183144ebdc0e2a1a4" - integrity sha512-jAl2xsj1g4RdQ4MBLSZ8Dsj3MUKjYKK+e73DxVHSTo0166T1p/7gdgSehLHWVlavJLDVM+fjYdt4kP12Z7FBjQ== - dependencies: - "@angular-devkit/architect" "0.1000.4" - "@angular-devkit/build-optimizer" "0.1000.4" - "@angular-devkit/build-webpack" "0.1000.4" - "@angular-devkit/core" "10.0.4" + version "0.1000.5" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-0.1000.5.tgz#9be7c63d96d3adf7d6929a09618df9c57d61f76e" + integrity sha512-YOlYdOksFsirCV7l2S0T/k9phRtT5eR+Pk3uWHXGfrkCBzFlAHw1EqOlJLOOSuN+stGHHYnKES2WUVJRJXLlCQ== + dependencies: + "@angular-devkit/architect" "0.1000.5" + "@angular-devkit/build-optimizer" "0.1000.5" + "@angular-devkit/build-webpack" "0.1000.5" + "@angular-devkit/core" "10.0.5" "@babel/core" "7.9.6" "@babel/generator" "7.9.6" "@babel/plugin-transform-runtime" "7.9.6" @@ -147,7 +140,7 @@ "@babel/runtime" "7.9.6" "@babel/template" "7.8.6" "@jsdevtools/coverage-istanbul-loader" "3.0.3" - "@ngtools/webpack" "10.0.4" + "@ngtools/webpack" "10.0.5" ajv "6.12.3" autoprefixer "9.8.0" babel-loader "8.1.0" @@ -203,36 +196,36 @@ worker-plugin "4.0.3" "@angular-devkit/build-ng-packagr@~0.1000.0": - version "0.1000.4" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-ng-packagr/-/build-ng-packagr-0.1000.4.tgz#a449169210b994491cf6048d07b246daf74eb1c7" - integrity sha512-YcqXv0+mNEAUtFI2XtoabXNxlTfgIsFobeoGwdfe1tVn4b465FIgqFDiNFEgaZ4UZbdbLuk0yrVHpk/f8X/wzw== + version "0.1000.5" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-ng-packagr/-/build-ng-packagr-0.1000.5.tgz#681774fa8982bf092e7ee33a19842e531a36a4dc" + integrity sha512-MiYwlyz6LOQONEBZMiaN3U7/CpsttNKmphdMmsBZyIPBnlHIHeHgekUEjYSMJDI9C/31HsstVR2DIJjOD2nJmw== dependencies: - "@angular-devkit/architect" "0.1000.4" + "@angular-devkit/architect" "0.1000.5" rxjs "6.5.5" -"@angular-devkit/build-optimizer@0.1000.4": - version "0.1000.4" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.1000.4.tgz#bdeb610b042533dbbc3c14c52f81f2f67bfb6513" - integrity sha512-usscQipxIU2yJVmBdyIDPmJZ+ltOjsX4VbMkGM2IdJHCIi9uEk2E3+YLxzyU5Xl5tXEK61AQt4YWUimt8Kg0GA== +"@angular-devkit/build-optimizer@0.1000.5": + version "0.1000.5" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.1000.5.tgz#dc1e6fa38b7ede190ab1f31867011e624fde83ed" + integrity sha512-H6jTF7TOYq909HR6M3Bu8lScqrG1qznK2XMefK3m1I1jBJ+WO4bL7hrhTp/CIY3d+47txep+XqhitDWD/6ikpg== dependencies: loader-utils "2.0.0" source-map "0.7.3" tslib "2.0.0" webpack-sources "1.4.3" -"@angular-devkit/build-webpack@0.1000.4": - version "0.1000.4" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.1000.4.tgz#781e7d67dbc80932e933010fea96339e10a7eec8" - integrity sha512-ZPXrm1+UyKbMZtnU+b5jdtZPFDYs8Pu5lHhJDzX6bk0TxtuXws+nwaeUs6WkfwXft8cksxK2WwGr57XX3OT7nw== +"@angular-devkit/build-webpack@0.1000.5": + version "0.1000.5" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.1000.5.tgz#040f58661cb81e545d2e2872ebb0b55ab695e27d" + integrity sha512-233EbW+6IKJEV20IG9Qzlz8MdDedzoTheB+lx9tTPn21m0ph2vmpTsNOsmMWwvdBBgXbv3pW3SMbJiqDCh7u4w== dependencies: - "@angular-devkit/architect" "0.1000.4" - "@angular-devkit/core" "10.0.4" + "@angular-devkit/architect" "0.1000.5" + "@angular-devkit/core" "10.0.5" rxjs "6.5.5" -"@angular-devkit/core@10.0.4": - version "10.0.4" - resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-10.0.4.tgz#105df3e7a7df56005f3637121ef010dd3849f5eb" - integrity sha512-Pe60BJCcAVtOkhXn2c+ql1NfyMCu421jWmKwl1KsW1DXclpGB+UIa560ICBgEwla6DyltMKEN/lX+P4WOskpkQ== +"@angular-devkit/core@10.0.5": + version "10.0.5" + resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-10.0.5.tgz#ad747edbf3344a87f86acb71bdeaac0380538c04" + integrity sha512-ZaF1EYniIo+yRLvvaKnLrjYCdKeg2U3YtbA932M2AIfjgfFv/9mnAbH4jmZsBZhCstxZPz+ItwJesdR20h4Z1Q== dependencies: ajv "6.12.3" fast-json-stable-stringify "2.1.0" @@ -262,12 +255,12 @@ rxjs "6.5.4" source-map "0.7.3" -"@angular-devkit/schematics@10.0.4": - version "10.0.4" - resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-10.0.4.tgz#73e0021b01e4c35d3bf54111824793527c5ec6e5" - integrity sha512-k9b73XkKQK8yFbq+dQqJnxAMG3mm/YR1KQlsQzOEVdw8cqqEALLoUXg/73hT5eUnSsNWmyDLBzEAyNtemmmI4w== +"@angular-devkit/schematics@10.0.5": + version "10.0.5" + resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-10.0.5.tgz#a9365e06a433c89f0cf7e0a0937ab17816206b1e" + integrity sha512-UeeV8O0IydxCKj2oejygs80oIAQXPYrJHo0PQ/fa0RH6rtV3wZwirdy+yqq/BDGhtV/5VQSVCvu6uyAtGGMgNg== dependencies: - "@angular-devkit/core" "10.0.4" + "@angular-devkit/core" "10.0.5" ora "4.0.4" rxjs "6.5.5" @@ -280,9 +273,9 @@ rxjs "6.4.0" "@angular/animations@~10.0.0": - version "10.0.5" - resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-10.0.5.tgz#41c1419f5233cf8adc2139461a552969e1f938c1" - integrity sha512-vHWn7NJiiDAok36GSBJ0y/nqjd4UFl9WGIEsvydUqnyBJ0scuqJa+hADrWwqkK7b/xVW9ARVG00NXmemEPUVGA== + version "10.0.7" + resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-10.0.7.tgz#1896b76bee50abb5a199b335d447f9fcb195ab1b" + integrity sha512-lTF7wuhx16fc3WahmqcYE3Q6sHB5sUQZ6m4dKg38wuf49Hr9x8uQpOMypnOAp9qfKG06ZZ2arRs53JeHpzkMPw== dependencies: tslib "^2.0.0" @@ -294,15 +287,15 @@ parse5 "^5.0.0" "@angular/cli@~10.0.0": - version "10.0.4" - resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-10.0.4.tgz#5c13500f3135e43b9e6e53534fdfbc283abb83cc" - integrity sha512-hmr1fXT8+6wOoh7abIg154wdP9QCMPHMShWPEYHks6ARmlRfX5k+BykQMzgI8H6tMNLoR+DAlO5+pPouJEyilQ== - dependencies: - "@angular-devkit/architect" "0.1000.4" - "@angular-devkit/core" "10.0.4" - "@angular-devkit/schematics" "10.0.4" - "@schematics/angular" "10.0.4" - "@schematics/update" "0.1000.4" + version "10.0.5" + resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-10.0.5.tgz#04628246ee6e5428c124ea14656fb1b40f819408" + integrity sha512-Qsa90IGPApJS9HL6Ih7Z8S8mIdriWYEintsT9cfI0WMVYyjvSNZQBf1SvnNU3IEboV4RFnpfXJNmQz1Q4KsRFQ== + dependencies: + "@angular-devkit/architect" "0.1000.5" + "@angular-devkit/core" "10.0.5" + "@angular-devkit/schematics" "10.0.5" + "@schematics/angular" "10.0.5" + "@schematics/update" "0.1000.5" "@yarnpkg/lockfile" "1.1.0" ansi-colors "4.1.1" debug "4.1.1" @@ -320,9 +313,9 @@ uuid "8.1.0" "@angular/common@~10.0.0": - version "10.0.5" - resolved "https://registry.yarnpkg.com/@angular/common/-/common-10.0.5.tgz#f1c1b8671dbacc263d5d4f63606a82bc968644ff" - integrity sha512-AKmD/X13q3zzo5uTV/M4dWpAqJ136187rL4VweRc6b5t/oZ3VGcejjElZebgtoyGTye8luIP6fZ/LMb580lBlQ== + version "10.0.7" + resolved "https://registry.yarnpkg.com/@angular/common/-/common-10.0.7.tgz#16dc489ea2e53563fb972581e3b3de46ebd194b1" + integrity sha512-CPjmbjylbMG0eFLWz7TCaxONDcwuldcvEheEwaBGS3RloHVsa+ry/8r6/7YilQkscdNPUazhX8pIzzrxIf9cBQ== dependencies: tslib "^2.0.0" @@ -353,28 +346,28 @@ tslib "^2.0.0" "@angular/core@~10.0.0": - version "10.0.5" - resolved "https://registry.yarnpkg.com/@angular/core/-/core-10.0.5.tgz#52a11d1b6ce065f6c26d919ab3bea233f51902be" - integrity sha512-zoIxIi/UaRImeC1uD+eIKrdcihvQR/zfbqKgK67IPy/tghijxge1Tbl8FWIAT0ncAj0XH/JHsWnVdUV/TUI+CA== + version "10.0.7" + resolved "https://registry.yarnpkg.com/@angular/core/-/core-10.0.7.tgz#297392ea4cf0764de28ac8efc7b4f041db507efc" + integrity sha512-h8R/2TCIFkagrFl6zmPN34gS5ZtQ1soYDI8dDeLj0+oQ+qH8HncoRgzYl+1+agFvUeYQ2pkwc5i635j/LwC++Q== dependencies: tslib "^2.0.0" "@angular/forms@~10.0.0": - version "10.0.5" - resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-10.0.5.tgz#c1e3d7218770e56ab0060b28dbf33d76a481a1c5" - integrity sha512-Bv+KEPjqd+ndl/Z0w1uWsBmvb8Je1JObHRjbKAcW7c4r1CVobm+QJv6r6MDL+FOs78lnrm8baekGLQyHH1uO7g== + version "10.0.7" + resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-10.0.7.tgz#571cbdc5ed213e10aedfdb9d660f4d55c71687a2" + integrity sha512-xSGPhidaUWLop3j9zPy4ZeO+/rwnusNWvwrDNey4W68lS068AExRXqf3yTuzobqBGdV2swDJaRabzgD7NS8yag== dependencies: tslib "^2.0.0" "@angular/language-service@~10.0.0": - version "10.0.5" - resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-10.0.5.tgz#2e4b24f7440257d3038ad717b19c5c0065684937" - integrity sha512-WJz5+XxOb0ORUERwNEUsX+0L7V4Tm7tz6i/mKAcz5SbE5eVfi+ywT+Zg7xMVRhyEpwDycqLXHK4piBOuGIjk+g== + version "10.0.7" + resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-10.0.7.tgz#22a10d4ee4458b946aae376cf8d502c78b956a20" + integrity sha512-iD1It0GjQyn+1KKVh0IMTtrRw/HI0cXq69KYju2LXckngzSK0GXg+yvPP4sizwSBhJW2xeepV8qGkpGo9M+Wyw== "@angular/localize@~10.0.0": - version "10.0.5" - resolved "https://registry.yarnpkg.com/@angular/localize/-/localize-10.0.5.tgz#cc51976e0ad3cdd05df0ce8448b85d1f2b9ff492" - integrity sha512-iyZ58H7+WBm9J1K2OLKgFFHno33KOu1FMQKaGdj/XCZaG1PphanOUivNxvxXo/6r71UW6uX/U17Rk//F8M0zPA== + version "10.0.7" + resolved "https://registry.yarnpkg.com/@angular/localize/-/localize-10.0.7.tgz#ea99439ad94420cad73b23930f6d091c2e470c13" + integrity sha512-20PciUxCyVdIAkvopzGhmU5LA0bFRXmPFpfDqBccUn9tFv27PAOjNf70HbscdUKzEQW79kLjdV5qcbzXZqPnCg== dependencies: "@babel/core" "7.8.3" glob "7.1.2" @@ -390,23 +383,23 @@ yargs "15.3.0" "@angular/platform-browser-dynamic@~10.0.0": - version "10.0.5" - resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-10.0.5.tgz#bf0e6af90677e08c38747b1d1b9bacb2463872e0" - integrity sha512-Qa6RM9aJuuw5E7BeGBG9/kCOtssI6Wyzbb/8awzZFF6Fjqom1kef185nwx7SgQs2cdrhqRAgjt0eDJqTfSVb+Q== + version "10.0.7" + resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-10.0.7.tgz#e419f25da20bdee5ac7c7c3b1907f4301cd7a363" + integrity sha512-ESn1hssKmgFbSSU8tI3KcP6QFEMKaxTvoKElkwULhAnCNkeXAhZaIkTdeqaa/vkO8s9nRbRwqcLuhw/mIQJbpQ== dependencies: tslib "^2.0.0" "@angular/platform-browser@~10.0.0": - version "10.0.5" - resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-10.0.5.tgz#0b90263a3858385cfb3ab440358d19eb9e8e91d3" - integrity sha512-bmknyK18yMv+iLCqcrfcpq3/2Ls9mRA1lOe7YhSGpHxM969Rb6Av8vJNW+uv0y7+gTvxacmpiQO8iryr/xvzRg== + version "10.0.7" + resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-10.0.7.tgz#c2328f2f5dad78da79c35fc8eb2bb6bacad81171" + integrity sha512-iACZDApTWTID+Dgpv9ztAlmP4OBIyCnqfmSrVWIpN30O/2pgalYS4hKS+jFXXjqG3IXrG6IpOAbFT9UubOWXKg== dependencies: tslib "^2.0.0" "@angular/router@~10.0.0": - version "10.0.5" - resolved "https://registry.yarnpkg.com/@angular/router/-/router-10.0.5.tgz#3e5f8be439b827b1d7bc980d673dec216a2f0769" - integrity sha512-hUGffVOjkdaN5IN9fSipm5ED+XGyfc9yOr5hYr/6YA3H4xaQzXZGlzrrDhAVltTyYalD2LJeXhzlvp59lXgcjg== + version "10.0.7" + resolved "https://registry.yarnpkg.com/@angular/router/-/router-10.0.7.tgz#8fe294f1054214a8aff9a3d982756a4b4dcf6284" + integrity sha512-uZAUTSQNuDvpkWGqF2qTkqr+btrNwg9USRB08lzhkWH351Myt1S/7ECVYOWNek6b/NmlAA+e3Kcyb94uDwMEew== dependencies: tslib "^2.0.0" @@ -432,9 +425,9 @@ "@babel/highlight" "^7.10.4" "@babel/compat-data@^7.10.4", "@babel/compat-data@^7.9.6": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.10.5.tgz#d38425e67ea96b1480a3f50404d1bf85676301a6" - integrity sha512-mPVoWNzIpYJHbWje0if7Ck36bpbtTvIxOi9+6WSK9wjGEXearAqlwBoTQvVjsAY2VIwgcs8V940geY3okzRCEw== + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.11.0.tgz#e9f73efe09af1355b723a7f39b11bad637d7c99c" + integrity sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ== dependencies: browserslist "^4.12.0" invariant "^2.2.4" @@ -484,18 +477,18 @@ source-map "^0.5.0" "@babel/core@^7.1.0", "@babel/core@^7.7.5": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.5.tgz#1f15e2cca8ad9a1d78a38ddba612f5e7cdbbd330" - integrity sha512-O34LQooYVDXPl7QWCdW9p4NR+QlzOr7xShPPJz8GsuCU3/8ua/wqTr7gmnxXv+WBESiGU/G5s16i6tUvHkNb+w== + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.0.tgz#73b9c33f1658506887f767c26dae07798b30df76" + integrity sha512-mkLq8nwaXmDtFmRkQ8ED/eA2CnVw4zr7dCztKalZXBvdK5EeNUAesrrwUqjQEzFgomJssayzB0aqlOsP1vGLqg== dependencies: "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.10.5" - "@babel/helper-module-transforms" "^7.10.5" + "@babel/generator" "^7.11.0" + "@babel/helper-module-transforms" "^7.11.0" "@babel/helpers" "^7.10.4" - "@babel/parser" "^7.10.5" + "@babel/parser" "^7.11.0" "@babel/template" "^7.10.4" - "@babel/traverse" "^7.10.5" - "@babel/types" "^7.10.5" + "@babel/traverse" "^7.11.0" + "@babel/types" "^7.11.0" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.1" @@ -515,12 +508,12 @@ lodash "^4.17.13" source-map "^0.5.0" -"@babel/generator@^7.10.5", "@babel/generator@^7.8.3", "@babel/generator@^7.9.6": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.5.tgz#1b903554bc8c583ee8d25f1e8969732e6b829a69" - integrity sha512-3vXxr3FEW7E7lJZiWQ3bM4+v/Vyr9C+hpolQ8BGFr9Y8Ri2tFLWTixmwKBafDujO1WVah4fhZBeU1bieKdghig== +"@babel/generator@^7.11.0", "@babel/generator@^7.8.3", "@babel/generator@^7.9.6": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.0.tgz#4b90c78d8c12825024568cbe83ee6c9af193585c" + integrity sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ== dependencies: - "@babel/types" "^7.10.5" + "@babel/types" "^7.11.0" jsesc "^2.5.1" source-map "^0.5.0" @@ -600,11 +593,11 @@ "@babel/types" "^7.10.4" "@babel/helper-member-expression-to-functions@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.5.tgz#172f56e7a63e78112f3a04055f24365af702e7ee" - integrity sha512-HiqJpYD5+WopCXIAbQDG0zye5XYVvcO9w/DHp5GsaGkRUaamLj2bEtu6i8rnGGprAhHM3qidCMgp71HF4endhA== + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz#ae69c83d84ee82f4b42f96e2a09410935a8f26df" + integrity sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q== dependencies: - "@babel/types" "^7.10.5" + "@babel/types" "^7.11.0" "@babel/helper-module-imports@^7.10.4", "@babel/helper-module-imports@^7.8.3": version "7.10.4" @@ -613,17 +606,17 @@ dependencies: "@babel/types" "^7.10.4" -"@babel/helper-module-transforms@^7.10.4", "@babel/helper-module-transforms@^7.10.5", "@babel/helper-module-transforms@^7.9.0": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.10.5.tgz#120c271c0b3353673fcdfd8c053db3c544a260d6" - integrity sha512-4P+CWMJ6/j1W915ITJaUkadLObmCRRSC234uctJfn/vHrsLNxsR8dwlcXv9ZhJWzl77awf+mWXSZEKt5t0OnlA== +"@babel/helper-module-transforms@^7.10.4", "@babel/helper-module-transforms@^7.10.5", "@babel/helper-module-transforms@^7.11.0", "@babel/helper-module-transforms@^7.9.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz#b16f250229e47211abdd84b34b64737c2ab2d359" + integrity sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg== dependencies: "@babel/helper-module-imports" "^7.10.4" "@babel/helper-replace-supers" "^7.10.4" "@babel/helper-simple-access" "^7.10.4" - "@babel/helper-split-export-declaration" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" "@babel/template" "^7.10.4" - "@babel/types" "^7.10.5" + "@babel/types" "^7.11.0" lodash "^4.17.19" "@babel/helper-optimise-call-expression@^7.10.4": @@ -674,12 +667,19 @@ "@babel/template" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helper-split-export-declaration@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz#2c70576eaa3b5609b24cb99db2888cc3fc4251d1" - integrity sha512-pySBTeoUff56fL5CBU2hWm9TesA4r/rOkI9DyJLvvgz09MB9YtfIYe3iBriVaYNaPe+Alua0vBIOVOLs2buWhg== +"@babel/helper-skip-transparent-expression-wrappers@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz#eec162f112c2f58d3af0af125e3bb57665146729" + integrity sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q== dependencies: - "@babel/types" "^7.10.4" + "@babel/types" "^7.11.0" + +"@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" + integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== + dependencies: + "@babel/types" "^7.11.0" "@babel/helper-validator-identifier@^7.10.4": version "7.10.4" @@ -714,10 +714,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.10.4", "@babel/parser@^7.10.5", "@babel/parser@^7.8.3", "@babel/parser@^7.8.6", "@babel/parser@^7.9.6": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.5.tgz#e7c6bf5a7deff957cec9f04b551e2762909d826b" - integrity sha512-wfryxy4bE1UivvQKSQDU4/X6dr+i8bctjUjj8Zyt3DQy7NtPizJXT8M52nqpNKL+nq2PW8lxk4ZqLj0fD4B4hQ== +"@babel/parser@^7.1.0", "@babel/parser@^7.10.4", "@babel/parser@^7.11.0", "@babel/parser@^7.8.3", "@babel/parser@^7.8.6", "@babel/parser@^7.9.6": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.0.tgz#a9d7e11aead25d3b422d17b2c6502c8dddef6a5d" + integrity sha512-qvRvi4oI8xii8NllyEc4MDJjuZiNaRzyb7Y7lup1NqJV8TZHF4O27CcP+72WPn/k1zkgJ6WJfnIbk4jTsVAZHw== "@babel/plugin-proposal-async-generator-functions@^7.8.3": version "7.10.5" @@ -761,9 +761,9 @@ "@babel/plugin-syntax-numeric-separator" "^7.10.4" "@babel/plugin-proposal-object-rest-spread@^7.9.6": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.10.4.tgz#50129ac216b9a6a55b3853fdd923e74bf553a4c0" - integrity sha512-6vh4SqRuLLarjgeOf4EaROJAHjvu9Gl+/346PbDH9yWbJyfnJ/ah3jmYKYtswEyCoWZiidvVHjHshd4WgjB9BA== + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz#bd81f95a1f746760ea43b6c2d3d62b11790ad0af" + integrity sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-object-rest-spread" "^7.8.0" @@ -778,11 +778,12 @@ "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" "@babel/plugin-proposal-optional-chaining@^7.9.0": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.10.4.tgz#750f1255e930a1f82d8cdde45031f81a0d0adff7" - integrity sha512-ZIhQIEeavTgouyMSdZRap4VPPHqJJ3NEs2cuHs5p0erH+iz6khB0qfgU8g7UuJkG88+fBMy23ZiU+nuHvekJeQ== + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz#de5866d0646f6afdaab8a566382fe3a221755076" + integrity sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" "@babel/plugin-syntax-optional-chaining" "^7.8.0" "@babel/plugin-proposal-unicode-property-regex@^7.4.4", "@babel/plugin-proposal-unicode-property-regex@^7.8.3": @@ -1100,11 +1101,12 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-spread@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.10.4.tgz#4e2c85ea0d6abaee1b24dcfbbae426fe8d674cff" - integrity sha512-1e/51G/Ni+7uH5gktbWv+eCED9pP8ZpRhZB3jOaI3mmzfvJTWHkuyYTv0Z5PYtyM+Tr2Ccr9kUdQxn60fI5WuQ== + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz#fa84d300f5e4f57752fe41a6d1b3c554f13f17cc" + integrity sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" "@babel/plugin-transform-sticky-regex@^7.8.3": version "7.10.4" @@ -1222,9 +1224,9 @@ regenerator-runtime "^0.13.4" "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.5.tgz#303d8bd440ecd5a491eae6117fd3367698674c5c" - integrity sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg== + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.0.tgz#f10245877042a815e07f7e693faff0ae9d3a2aac" + integrity sha512-qArkXsjJq7H+T86WrIFV0Fnu/tNOkZ4cgXmjkzAu3b/58D5mFIO8JH/y77t7C9q0OdDRdh9s7Ue5GasYssxtXw== dependencies: regenerator-runtime "^0.13.4" @@ -1246,25 +1248,25 @@ "@babel/parser" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.10.5", "@babel/traverse@^7.8.3", "@babel/traverse@^7.9.6": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.5.tgz#77ce464f5b258be265af618d8fddf0536f20b564" - integrity sha512-yc/fyv2gUjPqzTz0WHeRJH2pv7jA9kA7mBX2tXl/x5iOE81uaVPuGPtaYk7wmkx4b67mQ7NqI8rmT2pF47KYKQ== +"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.11.0", "@babel/traverse@^7.8.3", "@babel/traverse@^7.9.6": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.0.tgz#9b996ce1b98f53f7c3e4175115605d56ed07dd24" + integrity sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg== dependencies: "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.10.5" + "@babel/generator" "^7.11.0" "@babel/helper-function-name" "^7.10.4" - "@babel/helper-split-export-declaration" "^7.10.4" - "@babel/parser" "^7.10.5" - "@babel/types" "^7.10.5" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/parser" "^7.11.0" + "@babel/types" "^7.11.0" debug "^4.1.0" globals "^11.1.0" lodash "^4.17.19" -"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.6": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.5.tgz#d88ae7e2fde86bfbfe851d4d81afa70a997b5d15" - integrity sha512-ixV66KWfCI6GKoA/2H9v6bQdbfXEwwpOdQ8cRvb4F+eyvhlaHxWFMQB4+3d9QFJXZsiiiqVrewNV0DFEQpyT4Q== +"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.6": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.0.tgz#2ae6bf1ba9ae8c3c43824e5861269871b206e90d" + integrity sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA== dependencies: "@babel/helper-validator-identifier" "^7.10.4" lodash "^4.17.19" @@ -1588,13 +1590,14 @@ "@types/yargs" "^15.0.0" chalk "^3.0.0" -"@jest/types@^26.1.0": - version "26.1.0" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.1.0.tgz#f8afaaaeeb23b5cad49dd1f7779689941dcb6057" - integrity sha512-GXigDDsp6ZlNMhXQDeuy/iYCDsRIHJabWtDzvnn36+aqFfG14JmFV0e/iXxY4SP9vbXSiPNOWdehU5MeqrYHBQ== +"@jest/types@^26.2.0": + version "26.2.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.2.0.tgz#b28ca1fb517a4eb48c0addea7fcd9edc4ab45721" + integrity sha512-lvm3rJvctxd7+wxKSxxbzpDbr4FXDLaC57WEKdUIZ2cjTYuxYSc0zlyD7Z4Uqr5VdKxRUrtwIkiqBuvgf8uKJA== dependencies: "@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-reports" "^1.1.1" + "@types/node" "*" "@types/yargs" "^15.0.0" chalk "^4.0.0" @@ -2308,20 +2311,20 @@ integrity sha512-wqwhnJFyEwvzWQJjXrEt+7oBTSvu2qPbdYvUFYhDVzOJLWB5M7YEhDAkMrfHQJ0pZNBMGr580FqYue+XiURY0Q== "@ngneat/spectator@^5.11.0": - version "5.12.0" - resolved "https://registry.yarnpkg.com/@ngneat/spectator/-/spectator-5.12.0.tgz#fe4752b75febb5797b7d3e2ba8167921b7adc756" - integrity sha512-q8F2eIp7uygnfBzn+2syGnYf4u9vDNT/WQSHAk+IffyPbQfM5EiPxPTY0vIccXg51zuZBPZVFtXMoFqN8zyglg== + version "5.13.0" + resolved "https://registry.yarnpkg.com/@ngneat/spectator/-/spectator-5.13.0.tgz#0a9720c3d3b60571c3619054f9831856997acf67" + integrity sha512-BlCmmgHMPtrdJECwctFmziRhHzSF3xxRnKiR/qJIerCd4csgpwGbhtEEh/2jnFEyLP6yLo4T4nCslwq3dHdFrQ== dependencies: "@testing-library/dom" "6.1.0" jquery "3.5.0" replace-in-file "^4.1.3" -"@ngtools/webpack@10.0.4": - version "10.0.4" - resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-10.0.4.tgz#25c0a932319f8a26cbc849f4d13587f179fdc494" - integrity sha512-qzWkmVUUvr+2kiCtVLyopRwaBbExWtsGrgNVnJoAhtKKDflT4W33FpyJZJvxHwL6nfGGdb261Gfw7teIlCGjog== +"@ngtools/webpack@10.0.5": + version "10.0.5" + resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-10.0.5.tgz#8123647aa73463e586ac5792d16751a36d5caaaa" + integrity sha512-jMHfLXFzmgRlZbHgS71BEIKDyHbkfKrJL1sWEs3Ylox+TEIYzJiGfnem5ZGpr8wplz8HMMJ+xngtABePvc3/0w== dependencies: - "@angular-devkit/core" "10.0.4" + "@angular-devkit/core" "10.0.5" enhanced-resolve "4.1.1" rxjs "6.5.5" webpack-sources "1.4.3" @@ -2333,13 +2336,6 @@ dependencies: tslib "^1.9.0" -"@ngx-validate/core@^0.0.8", "@ngx-validate/core@^0.0.9": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@ngx-validate/core/-/core-0.0.8.tgz#8577405eb1af0f5002cdda7a86fbcda56280f116" - integrity sha512-caIG5ao76Xhf7T+pNA8crnpAwK0yqj3i0OAUGZRUq1W+kNgz+ZnrSd4F9an/W4g+38u/8gfUVvsfsm07ju6qYA== - dependencies: - tslib "^1.9.0" - "@ngxs/devtools-plugin@^3.6.2": version "3.6.2" resolved "https://registry.yarnpkg.com/@ngxs/devtools-plugin/-/devtools-plugin-3.6.2.tgz#aa0a4835f90fb905951d7712dc3ce508cbc15a2c" @@ -2559,21 +2555,21 @@ estree-walker "^1.0.1" picomatch "^2.2.2" -"@schematics/angular@10.0.4": - version "10.0.4" - resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-10.0.4.tgz#5a84fe6f4e8d8e4e7e2925c05b7689f70dab597f" - integrity sha512-wTpuVfPKALOcOHfD7Y222r/IfqJgpqASyoXdkzf7dZVrLXjNy/XrKuc2Vfn85Ce9lnme0xT5ww+KjbSRc0cSUw== +"@schematics/angular@10.0.5": + version "10.0.5" + resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-10.0.5.tgz#905f7c58547fdf9847fb004c1689bc0af7a09a7a" + integrity sha512-zg8QxgW3uLva/MSKMRYfV7dzj00SUki4nxYN4j1rw42VlwNPnFrPtzFVEilL6N7wFgoHP/6cZRgm4bfXYvLBvg== dependencies: - "@angular-devkit/core" "10.0.4" - "@angular-devkit/schematics" "10.0.4" + "@angular-devkit/core" "10.0.5" + "@angular-devkit/schematics" "10.0.5" -"@schematics/update@0.1000.4": - version "0.1000.4" - resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.1000.4.tgz#e0780c5313ee90480f8a26b66c0104f664df64a4" - integrity sha512-NkIUsqnEqG6jhW6b1xXYmgW02WYAN9/IoswnZnaQrbGzxroNVQKURiV4AP22sZLCr7gQ9NJwjXxO5rxbzbY8wg== +"@schematics/update@0.1000.5": + version "0.1000.5" + resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.1000.5.tgz#7ce1012ee0b5fb88b149f84294eb49b911b01a3f" + integrity sha512-xodvq3X4B90u8myMEp9ESPnD2aC4YtNXj1FOcJ+BnguRA7q9rq9EL9Xqdef8sx3PObbSiKC0OFLyxgw76WuC3Q== dependencies: - "@angular-devkit/core" "10.0.4" - "@angular-devkit/schematics" "10.0.4" + "@angular-devkit/core" "10.0.5" + "@angular-devkit/schematics" "10.0.5" "@yarnpkg/lockfile" "1.1.0" ini "1.3.5" npm-package-arg "^8.0.0" @@ -2707,9 +2703,9 @@ "@types/istanbul-lib-report" "*" "@types/jasmine@^3.3.9": - version "3.5.11" - resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-3.5.11.tgz#ba8e80639dffbe277f49c708b45373a320d158e2" - integrity sha512-fg1rOd/DehQTIJTifGqGVY6q92lDgnLfs7C6t1ccSwQrMyoTGSoH6wWzhJDZb6ezhsdwAX4EIBLe8w5fXWmEng== + version "3.5.12" + resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-3.5.12.tgz#5c378c1545cdc7cb339cff5578f854b6d1e0a17d" + integrity sha512-vJaQ58oceFao+NzpKNqLOWwHPsqA7YEhKv+mOXvYU4/qh+BfVWIxaBtL0Ck5iCS67yOkNwGkDCrzepnzIWF+7g== "@types/jest@^25.2.3": version "25.2.3" @@ -2735,9 +2731,9 @@ integrity sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY= "@types/node@*", "@types/node@>= 8": - version "14.0.26" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.26.tgz#22a3b8a46510da8944b67bfc27df02c34a35331c" - integrity sha512-W+fpe5s91FBGE0pEa0lnqGLL4USgpLgs4nokw16SrBBco/gQxuua7KnArSEOd5iaMqbbSHV10vUDkJYJJqpXKA== + version "14.0.27" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.27.tgz#a151873af5a5e851b51b3b065c9e63390a9e0eb1" + integrity sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g== "@types/node@^12.11.1": version "12.12.53" @@ -3009,9 +3005,9 @@ JSONStream@^1.0.4, JSONStream@^1.3.4: through ">=2.2.7 <3" abab@^2.0.0, abab@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a" - integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg== + version "2.0.4" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.4.tgz#6dfa57b417ca06d21b2478f0e638302f99c2405c" + integrity sha512-Eu9ELJWCz/c1e9gTiCY+FceWxcqzjYEbqMgtndnuSqZSUCOL73TWNK2mHfIj4Cw2E/ongOp+JISVNCmovt2KYQ== abbrev@1: version "1.1.1" @@ -3045,9 +3041,9 @@ acorn@^6.0.1, acorn@^6.4.1: integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== acorn@^7.1.0: - version "7.3.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.3.1.tgz#85010754db53c3fbaf3b9ea3e083aa5c5d147ffd" - integrity sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA== + version "7.4.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.0.tgz#e1ad486e6c54501634c6c397c5c121daa383607c" + integrity sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w== add-stream@^1.0.0: version "1.0.0" @@ -3109,7 +3105,7 @@ ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv@6.12.3, ajv@^6.1.0, ajv@^6.10.2, ajv@^6.12.2, ajv@^6.12.3, ajv@^6.5.5: +ajv@6.12.3, ajv@^6.1.0, ajv@^6.10.2, ajv@^6.12.2, ajv@^6.12.3: version "6.12.3" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.3.tgz#18c5af38a111ddeb4f2697bd78d68abc1cabd706" integrity sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA== @@ -3458,13 +3454,13 @@ autoprefixer@9.8.0: postcss-value-parser "^4.1.0" autoprefixer@^9.6.5: - version "9.8.5" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.5.tgz#2c225de229ddafe1d1424c02791d0c3e10ccccaa" - integrity sha512-C2p5KkumJlsTHoNv9w31NrBRgXhf6eCMteJuHZi2xhkgC+5Vm40MEtCKPhc0qdgAOhox0YPy1SQHTAky05UoKg== + version "9.8.6" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.6.tgz#3b73594ca1bf9266320c5acf1588d74dea74210f" + integrity sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg== dependencies: browserslist "^4.12.0" - caniuse-lite "^1.0.30001097" - colorette "^1.2.0" + caniuse-lite "^1.0.30001109" + colorette "^1.2.1" normalize-range "^0.1.2" num2fraction "^1.2.2" postcss "^7.0.32" @@ -4099,10 +4095,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001032, caniuse-lite@^1.0.30001061, caniuse-lite@^1.0.30001093, caniuse-lite@^1.0.30001097: - version "1.0.30001107" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001107.tgz#809360df7a5b3458f627aa46b0f6ed6d5239da9a" - integrity sha512-86rCH+G8onCmdN4VZzJet5uPELII59cUzDphko3thQFgAQG1RNa+sVLDoALIhRYmflo5iSIzWY3vu1XTWtNMQQ== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001032, caniuse-lite@^1.0.30001061, caniuse-lite@^1.0.30001093, caniuse-lite@^1.0.30001109: + version "1.0.30001110" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001110.tgz#9003e3c7f5a43ea6f1193d4d5acba0bfb152c71a" + integrity sha512-KqJWeat4rhSHF0ito4yz9q/JuZHkvn71SsBnxge4azjPDbowIjOUnS8i1xpKGxZxU6BFiPqO2hSV2eiCpFQVRw== canonical-path@1.0.0: version "1.0.0" @@ -4439,7 +4435,7 @@ color@^3.0.0: color-convert "^1.9.1" color-string "^1.5.2" -colorette@^1.2.0: +colorette@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b" integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw== @@ -5680,9 +5676,9 @@ ee-first@1.1.1: integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= electron-to-chromium@^1.3.488: - version "1.3.510" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.510.tgz#dee781ff8b595c0deb60172b75d50b6889757eda" - integrity sha512-sLtGB0znXdmo6lM8hy5wTVo+fLqvIuO8hEpgc0DvPmFZqvBu/WB7AarEwhxVKjf3rVbws/rC8Xf+AlsOb36lJQ== + version "1.3.518" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.518.tgz#c54ee9cf1a7bafd6e482a1a6cceac86448d941e8" + integrity sha512-IspiwXYDKZMxo+qc3Vof4WtwbG9BMDbJfati8PYj7uS4DJmJ67pwjCKZxlTBSAuCZSMcbRnj2Xz2H14uiKT7bQ== elliptic@^6.0.0, elliptic@^6.5.2: version "6.5.3" @@ -6830,11 +6826,11 @@ har-schema@^2.0.0: integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= har-validator@~5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" - integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== dependencies: - ajv "^6.5.5" + ajv "^6.12.3" har-schema "^2.0.0" hard-rejection@^2.1.0: @@ -7543,9 +7539,9 @@ is-directory@^0.3.1: integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= is-docker@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.0.0.tgz#2cb0df0e75e2d064fe1864c37cdeacb7b2dcf25b" - integrity sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ== + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.1.0.tgz#25dc043e4fdc3cf969d622735e05a86ba9952e2b" + integrity sha512-mB2WygGsSeoXtLKpSYzP6sa0Z9DyU9ZyKlnvuZWxCociaI0qsF8u12sR72DFTX236g1u6oWSWYFuUk09nGQEjg== is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" @@ -7718,9 +7714,9 @@ is-reference@^1.1.2: "@types/estree" "*" is-regex@^1.0.4, is-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.0.tgz#ece38e389e490df0dc21caea2bd596f987f767ff" - integrity sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw== + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" + integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg== dependencies: has-symbols "^1.0.1" @@ -8228,11 +8224,12 @@ jest-snapshot@^25.5.1: semver "^6.3.0" jest-util@26.x: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.1.0.tgz#80e85d4ba820decacf41a691c2042d5276e5d8d8" - integrity sha512-rNMOwFQevljfNGvbzNQAxdmXQ+NawW/J72dmddsK0E8vgxXCMtwQ/EH0BiWEIxh0hhMcTsxwAxINt7Lh46Uzbg== + version "26.2.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.2.0.tgz#0597d2a27c559340957609f106c408c17c1d88ac" + integrity sha512-YmDwJxLZ1kFxpxPfhSJ0rIkiZOM0PQbRcfH0TzJOhqCisCAsI1WcmoQqO83My9xeVA2k4n+rzg2UuexVKzPpig== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" + "@types/node" "*" chalk "^4.0.0" graceful-fs "^4.2.4" is-ci "^2.0.0" @@ -8290,10 +8287,11 @@ jest-worker@^25.5.0: supports-color "^7.0.0" jest-worker@^26.0.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.1.0.tgz#65d5641af74e08ccd561c240e7db61284f82f33d" - integrity sha512-Z9P5pZ6UC+kakMbNJn+tA2RdVdNX5WH1x+5UCBZ9MxIK24pjYtFt96fK+UwBTrjLYm232g1xz0L3eTh51OW+yQ== + version "26.2.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.2.1.tgz#5d630ab93f666b53f911615bc13e662b382bd513" + integrity sha512-+XcGMMJDTeEGncRb5M5Zq9P7K4sQ1sirhjdOxsN1462h6lFo9w59bl2LVQmdGEEeU3m+maZCkS2Tcc9SfCHO4A== dependencies: + "@types/node" "*" merge-stream "^2.0.0" supports-color "^7.0.0" @@ -9202,9 +9200,9 @@ minipass-flush@^1.0.5: minipass "^3.0.0" minipass-pipeline@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.3.tgz#55f7839307d74859d6e8ada9c3ebe72cec216a34" - integrity sha512-cFOknTvng5vqnwOpDsZTWhNll6Jf8o2x+/diplafmxpuIymAjzoOolZG0VvQf3V2HgqzJNhnuKHYp2BqDgz8IQ== + version "1.2.4" + resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" + integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== dependencies: minipass "^3.0.0" @@ -9274,7 +9272,7 @@ mkdirp@*, mkdirp@1.x, mkdirp@^1.0.3, mkdirp@^1.0.4, mkdirp@~1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@~0.5.1, mkdirp@~0.5.x: +mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1, mkdirp@~0.5.x: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -9893,9 +9891,9 @@ onetime@^2.0.0: mimic-fn "^1.0.0" onetime@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" - integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== + version "5.1.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.1.tgz#5c8016847b0d67fcedb7eef254751cfcdc7e9418" + integrity sha512-ZpZpjcJeugQfWsfyQlshVoowIIQ1qBGSVll4rfDq6JJVO//fesjoX808hXWfBjY+ROZgpKDI5TRSRBSoJiZ8eg== dependencies: mimic-fn "^2.1.0" @@ -10436,13 +10434,13 @@ pnp-webpack-plugin@1.6.4: ts-pnp "^1.1.6" portfinder@^1.0.26: - version "1.0.27" - resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.27.tgz#a41333c116b5e5f3d380f9745ac2f35084c4c758" - integrity sha512-bJ3U3MThKnyJ9Dx1Idtm5pQmxXqw08+XOHhi/Lie8OF1OlhVaBFhsntAIhkZYjfDcCzszSr0w1yCbccThhzgxQ== + version "1.0.28" + resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" + integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA== dependencies: async "^2.6.2" debug "^3.1.1" - mkdirp "^0.5.1" + mkdirp "^0.5.5" posix-character-classes@^0.1.0: version "0.1.1" @@ -10864,11 +10862,11 @@ pretty-format@^25.2.1, pretty-format@^25.5.0: react-is "^16.12.0" pretty-format@^26.0.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.1.0.tgz#272b9cd1f1a924ab5d443dc224899d7a65cb96ec" - integrity sha512-GmeO1PEYdM+non4BKCj+XsPJjFOJIPnsLewqhDVoqY1xo0yNmDas7tC2XwpMrRAHR3MaE2hPo37deX5OisJ2Wg== + version "26.2.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.2.0.tgz#83ecc8d7de676ff224225055e72bd64821cec4f1" + integrity sha512-qi/8IuBu2clY9G7qCXgCdD1Bf9w+sXakdHTRToknzMtVy0g7c4MBWaZy7MfB7ndKZovRO6XRwJiAYqq+MC7SDA== dependencies: - "@jest/types" "^26.1.0" + "@jest/types" "^26.2.0" ansi-regex "^5.0.0" ansi-styles "^4.0.0" react-is "^16.12.0" @@ -11741,9 +11739,9 @@ rxjs@6.5.5, rxjs@~6.5.4: tslib "^1.9.0" rxjs@^6.4.0, rxjs@^6.5.0, rxjs@^6.5.2, rxjs@^6.5.3: - version "6.6.0" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.0.tgz#af2901eedf02e3a83ffa7f886240ff9018bbec84" - integrity sha512-3HMA8z/Oz61DUHe+SdOiQyzIf4tOx5oQHmMir7IZEu6TMqCLHT4LRcmNaUS0NwOz8VLvmmBduMsoaUvMaIiqzg== + version "6.6.2" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.2.tgz#8096a7ac03f2cc4fe5860ef6e572810d9e01c0d2" + integrity sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg== dependencies: tslib "^1.9.0" @@ -13094,9 +13092,9 @@ ts-pnp@^1.1.6: integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw== ts-toolbelt@^6.9.9: - version "6.13.34" - resolved "https://registry.yarnpkg.com/ts-toolbelt/-/ts-toolbelt-6.13.34.tgz#3bd6e1e333a75c5ddab584d293f35494cb8c9222" - integrity sha512-ikZwSUPO+fW+OUnyER1KCG58khTi51Di3+iVdhkK7UshqkL0Ir749B2TQ44o/khkKvDSOMzF8NuVkQLycDXnsg== + version "6.13.39" + resolved "https://registry.yarnpkg.com/ts-toolbelt/-/ts-toolbelt-6.13.39.tgz#80541ce39b595a42be5ddd04e3e6df65597774f8" + integrity sha512-VD/rJ6+NGFA7AK2KWmGzLifrqA060M9o7+R2BxJtLBlwmfEaGdqGeyUPRDKhMZPMgpT/JMQ6+X+/ppaZNzuhvw== tsickle@^0.38.1: version "0.38.1" @@ -13108,15 +13106,15 @@ tslib@2.0.0, tslib@^2.0.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.0.tgz#18d13fc2dce04051e20f074cc8387fd8089ce4f3" integrity sha512-lTqkx847PI7xEDYJntxZH89L2/aXInsyF2luSafe/+0fHOMjlBNXdH6th7f70qxLDhul7KZK0zC8V5ZIyHl0/g== -tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: +tslib@^1.10.0, tslib@^1.13.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.13.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== tslint@~6.1.0: - version "6.1.2" - resolved "https://registry.yarnpkg.com/tslint/-/tslint-6.1.2.tgz#2433c248512cc5a7b2ab88ad44a6b1b34c6911cf" - integrity sha512-UyNrLdK3E0fQG/xWNqAFAC5ugtFyPO4JJR1KyyfQAyzR8W0fTRrC91A8Wej4BntFzcvETdCSDa/4PnNYJQLYiA== + version "6.1.3" + resolved "https://registry.yarnpkg.com/tslint/-/tslint-6.1.3.tgz#5c23b2eccc32487d5523bd3a470e9aa31789d904" + integrity sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg== dependencies: "@babel/code-frame" "^7.0.0" builtin-modules "^1.1.1" @@ -13129,7 +13127,7 @@ tslint@~6.1.0: mkdirp "^0.5.3" resolve "^1.3.2" semver "^5.3.0" - tslib "^1.10.0" + tslib "^1.13.0" tsutils "^2.29.0" tsutils@^2.29.0: @@ -13229,9 +13227,9 @@ typescript@^3.5.2, typescript@~3.9.5: integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw== uglify-js@^3.1.4: - version "3.10.0" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.10.0.tgz#397a7e6e31ce820bfd1cb55b804ee140c587a9e7" - integrity sha512-Esj5HG5WAyrLIdYU74Z3JdG2PxdIusvj6IWHMtlyESxc7kcDz7zYlYjpnSokn1UbpV0d/QX9fan7gkCNd/9BQA== + version "3.10.1" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.10.1.tgz#dd14767eb7150de97f2573a5ff210db14fffe4ad" + integrity sha512-RjxApKkrPJB6kjJxQS3iZlf///REXWYxYJxO/MpmlQzVkDWVI3PSnCBWezMecmTU/TRkNxrl8bmsfFQCp+LO+Q== uid-number@0.0.6: version "0.0.6" diff --git a/templates/app/angular/src/environments/environment.prod.ts b/templates/app/angular/src/environments/environment.prod.ts index 53f0ecdf89..cfe0401dee 100644 --- a/templates/app/angular/src/environments/environment.prod.ts +++ b/templates/app/angular/src/environments/environment.prod.ts @@ -1,6 +1,9 @@ +import { Config } from '@abp/ng.core'; + export const environment = { production: true, application: { + baseUrl: 'http://localhost:4200/', name: 'MyProjectName', logoUrl: '', }, @@ -9,7 +12,6 @@ export const environment = { clientId: 'MyProjectName_App', dummyClientSecret: '1q2w3e*', scope: 'MyProjectName', - showDebugInformation: true, oidc: false, requireHttps: true, }, @@ -21,4 +23,4 @@ export const environment = { localization: { defaultResourceName: 'MyProjectName', }, -}; +} as Config.Environment; diff --git a/templates/app/angular/src/environments/environment.ts b/templates/app/angular/src/environments/environment.ts index d5d0dff39e..2039e8a2dc 100644 --- a/templates/app/angular/src/environments/environment.ts +++ b/templates/app/angular/src/environments/environment.ts @@ -1,6 +1,9 @@ +import { Config } from '@abp/ng.core'; + export const environment = { production: false, application: { + baseUrl: 'http://localhost:4200/', name: 'MyProjectName', logoUrl: '', }, @@ -21,4 +24,4 @@ export const environment = { localization: { defaultResourceName: 'MyProjectName', }, -}; +} as Config.Environment; diff --git a/templates/module/angular/projects/dev-app/src/environments/environment.prod.ts b/templates/module/angular/projects/dev-app/src/environments/environment.prod.ts index 9171185a9e..e7750a4873 100644 --- a/templates/module/angular/projects/dev-app/src/environments/environment.prod.ts +++ b/templates/module/angular/projects/dev-app/src/environments/environment.prod.ts @@ -1,6 +1,9 @@ +import { Config } from '@abp/ng.core'; + export const environment = { production: true, application: { + baseUrl: 'http://localhost:4200/', name: 'MyProjectName', logoUrl: '', }, @@ -9,7 +12,6 @@ export const environment = { clientId: 'MyProjectName_ConsoleTestApp', dummyClientSecret: '1q2w3e*', scope: 'MyProjectName', - showDebugInformation: true, oidc: false, requireHttps: true, }, @@ -21,4 +23,4 @@ export const environment = { url: 'https://localhost:44300', }, }, -}; +} as Config.Environment; diff --git a/templates/module/angular/projects/dev-app/src/environments/environment.ts b/templates/module/angular/projects/dev-app/src/environments/environment.ts index 452b154f4a..780fa891d9 100644 --- a/templates/module/angular/projects/dev-app/src/environments/environment.ts +++ b/templates/module/angular/projects/dev-app/src/environments/environment.ts @@ -1,6 +1,9 @@ +import { Config } from '@abp/ng.core'; + export const environment = { production: false, application: { + baseUrl: 'http://localhost:4200/', name: 'MyProjectName', logoUrl: '', }, @@ -9,7 +12,6 @@ export const environment = { clientId: 'MyProjectName_ConsoleTestApp', dummyClientSecret: '1q2w3e*', scope: 'MyProjectName', - showDebugInformation: true, oidc: false, requireHttps: true, }, @@ -21,4 +23,4 @@ export const environment = { url: 'https://localhost:44300', }, }, -}; +} as Config.Environment;