diff --git a/apps/sample-blog/src/app/about/about.component.ts b/apps/sample-blog/src/app/about/about.component.ts index b22ff3df3..9b495610d 100644 --- a/apps/sample-blog/src/app/about/about.component.ts +++ b/apps/sample-blog/src/app/about/about.component.ts @@ -1,6 +1,6 @@ import { Component, OnInit } from '@angular/core'; import { ScullyRoutesService } from '@scullyio/ng-lib'; -import { take } from 'rxjs/operators'; +import { firstValueFrom } from 'rxjs'; @Component({ selector: 'app-about', @@ -11,10 +11,7 @@ export class AboutComponent implements OnInit { constructor(private srs: ScullyRoutesService) {} async ngOnInit() { - const cur = await this.srs - .getCurrent() - .pipe(take(1)) - .toPromise(); + const cur = await firstValueFrom(this.srs.getCurrent()) console.log(cur); } } diff --git a/apps/sample-blog/src/app/app.module.ts b/apps/sample-blog/src/app/app.module.ts index d543e5104..b204a2164 100644 --- a/apps/sample-blog/src/app/app.module.ts +++ b/apps/sample-blog/src/app/app.module.ts @@ -11,8 +11,10 @@ import { AppComponent } from './app.component'; BrowserModule, HttpClientModule, AppRoutingModule, - ScullyLibModule.forRoot({ useTransferState: true, alwaysMonitor: true }) + ScullyLibModule + .forRoot({ useTransferState: true, alwaysMonitor: true }) ], bootstrap: [AppComponent] }) -export class AppModule {} +export class AppModule { } + diff --git a/apps/sample-blog/src/app/app.universal.module.ts b/apps/sample-blog/src/app/app.universal.module.ts new file mode 100644 index 000000000..1c54dc707 --- /dev/null +++ b/apps/sample-blog/src/app/app.universal.module.ts @@ -0,0 +1,14 @@ +import { NgModule } from '@angular/core'; +import { ServerModule } from '@angular/platform-server'; +import { AppComponent } from './app.component'; +import { AppModule } from './app.module'; + + +@NgModule({ + imports: [ + AppModule, + ServerModule, + ], + bootstrap: [AppComponent], +}) +export class AppUniversalModule {} diff --git a/apps/sample-blog/src/app/blog/blog-holder.component.ts b/apps/sample-blog/src/app/blog/blog-holder.component.ts index 6a4b8246b..2b8b469e0 100644 --- a/apps/sample-blog/src/app/blog/blog-holder.component.ts +++ b/apps/sample-blog/src/app/blog/blog-holder.component.ts @@ -1,6 +1,6 @@ import { Component } from '@angular/core'; import { ScullyRoute, ScullyRoutesService, TransferStateService } from '@scullyio/ng-lib'; -import { map } from 'rxjs/operators'; +import { map } from 'rxjs'; @Component({ selector: 'app-blog-holder', diff --git a/apps/sample-blog/src/app/blog/blog-list/blog-list.component.ts b/apps/sample-blog/src/app/blog/blog-list/blog-list.component.ts index 201218fcf..f4bf341ef 100644 --- a/apps/sample-blog/src/app/blog/blog-list/blog-list.component.ts +++ b/apps/sample-blog/src/app/blog/blog-list/blog-list.component.ts @@ -1,6 +1,6 @@ import { Component, OnInit } from '@angular/core'; import { ScullyRoute, ScullyRoutesService } from '@scullyio/ng-lib'; -import { map } from 'rxjs/operators'; +import { map } from 'rxjs'; @Component({ selector: 'app-blog-list', diff --git a/apps/sample-blog/src/app/demo/demo.component.ts b/apps/sample-blog/src/app/demo/demo.component.ts index f3eeb3e96..ceff1200f 100644 --- a/apps/sample-blog/src/app/demo/demo.component.ts +++ b/apps/sample-blog/src/app/demo/demo.component.ts @@ -1,6 +1,6 @@ import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, ActivatedRouteSnapshot } from '@angular/router'; -import { pluck, tap } from 'rxjs/operators'; +import { pluck, tap } from 'rxjs'; @Component({ selector: 'app-demo', diff --git a/apps/sample-blog/src/app/noscript/noscript.module.ts b/apps/sample-blog/src/app/noscript/noscript.module.ts index 9ed2e78f8..3c7e37a02 100644 --- a/apps/sample-blog/src/app/noscript/noscript.module.ts +++ b/apps/sample-blog/src/app/noscript/noscript.module.ts @@ -3,7 +3,7 @@ import { HttpClient } from '@angular/common/http'; import { Component, NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { ScullyLibModule, TransferStateService } from '@scullyio/ng-lib'; -import { map } from 'rxjs/operators'; +import { map } from 'rxjs'; import { User } from '../user/user.component'; @Component({ diff --git a/apps/sample-blog/src/app/slow/slow.component.ts b/apps/sample-blog/src/app/slow/slow.component.ts index 92e64a90a..e67e34e02 100644 --- a/apps/sample-blog/src/app/slow/slow.component.ts +++ b/apps/sample-blog/src/app/slow/slow.component.ts @@ -1,7 +1,7 @@ import { HttpClient } from '@angular/common/http'; import { Component } from '@angular/core'; import { isScullyGenerated } from '@scullyio/ng-lib'; -import { first } from 'rxjs/operators'; +import { first } from 'rxjs'; @Component({ selector: 'app-slow', diff --git a/apps/sample-blog/src/app/static/static.component.ts b/apps/sample-blog/src/app/static/static.component.ts index a2002888c..74e59fa06 100644 --- a/apps/sample-blog/src/app/static/static.component.ts +++ b/apps/sample-blog/src/app/static/static.component.ts @@ -2,7 +2,7 @@ import { Component, OnInit } from '@angular/core'; import { Title } from '@angular/platform-browser'; import { ActivatedRoute } from '@angular/router'; import { ScullyRoutesService } from '@scullyio/ng-lib'; -import { map, tap } from 'rxjs/operators'; +import { map, tap } from 'rxjs'; @Component({ selector: 'app-static', diff --git a/apps/sample-blog/src/app/user/post/post.component.ts b/apps/sample-blog/src/app/user/post/post.component.ts index f29f62fbc..f03d49e49 100644 --- a/apps/sample-blog/src/app/user/post/post.component.ts +++ b/apps/sample-blog/src/app/user/post/post.component.ts @@ -8,7 +8,7 @@ import { tap, filter, map, -} from 'rxjs/operators'; +} from 'rxjs'; import { Post } from '../posts/posts.component'; import { isScullyGenerated, TransferStateService } from '@scullyio/ng-lib'; import { ActivatedRoute } from '@angular/router'; diff --git a/apps/sample-blog/src/app/user/posts/posts.component.ts b/apps/sample-blog/src/app/user/posts/posts.component.ts index 4baf4d077..26f5d4377 100644 --- a/apps/sample-blog/src/app/user/posts/posts.component.ts +++ b/apps/sample-blog/src/app/user/posts/posts.component.ts @@ -11,7 +11,7 @@ import { shareReplay, switchMap, tap, -} from 'rxjs/operators'; +} from 'rxjs'; export interface Post { userId: number; @@ -37,10 +37,10 @@ export class PostsComponent implements OnInit { switchMap((id) => this.http.get(`/api/posts?userId=${id}`).pipe( catchError(() => - of({ + of([{ id, title: 'not found', - } as Post) + }] as Post[]) ) ) ), @@ -48,7 +48,7 @@ export class PostsComponent implements OnInit { ); // This is an example of using TransferState - posts$ = isScullyGenerated() + posts$:Observable = isScullyGenerated() ? this.transferState.getState('posts') : this.apiPosts$.pipe( tap((posts) => this.transferState.setState('posts', posts)) diff --git a/apps/sample-blog/src/app/user/user.component.ts b/apps/sample-blog/src/app/user/user.component.ts index e3853b9d0..a7d29946c 100644 --- a/apps/sample-blog/src/app/user/user.component.ts +++ b/apps/sample-blog/src/app/user/user.component.ts @@ -11,7 +11,7 @@ import { map, shareReplay, tap, -} from 'rxjs/operators'; +} from 'rxjs'; @Component({ selector: 'app-user', diff --git a/apps/sample-blog/src/app/user/users/users.component.html b/apps/sample-blog/src/app/user/users/users.component.html index 8ef3ba054..9f51c919b 100644 --- a/apps/sample-blog/src/app/user/users/users.component.html +++ b/apps/sample-blog/src/app/user/users/users.component.html @@ -10,7 +10,7 @@

Users

{{ user.id }} - + {{ user.name }} diff --git a/apps/sample-blog/src/app/user/users/users.component.ts b/apps/sample-blog/src/app/user/users/users.component.ts index 18b4b4669..7c4b9a74b 100644 --- a/apps/sample-blog/src/app/user/users/users.component.ts +++ b/apps/sample-blog/src/app/user/users/users.component.ts @@ -2,7 +2,7 @@ import { HttpClient } from '@angular/common/http'; import { Component, OnInit } from '@angular/core'; import { isScullyGenerated, TransferStateService } from '@scullyio/ng-lib'; import { of } from 'rxjs'; -import { catchError, map, shareReplay, tap } from 'rxjs/operators'; +import { catchError, map, shareReplay, tap } from 'rxjs'; import { User } from '../user.component'; @Component({ diff --git a/apps/sample-blog/src/main.universal.ts b/apps/sample-blog/src/main.universal.ts new file mode 100644 index 000000000..027c9f02a --- /dev/null +++ b/apps/sample-blog/src/main.universal.ts @@ -0,0 +1,10 @@ +import { enableProdMode } from '@angular/core'; +import { environment } from './environments/environment'; + + +if (environment.production) { + enableProdMode(); +} +export { renderModule, renderModuleFactory } from '@angular/platform-server'; +export { AppUniversalModule } from './app/app.universal.module'; + diff --git a/apps/scully-docs/src/app/components/lang-select/component/lang-select/lang-select.component.ts b/apps/scully-docs/src/app/components/lang-select/component/lang-select/lang-select.component.ts index ff74a14cf..181682130 100644 --- a/apps/scully-docs/src/app/components/lang-select/component/lang-select/lang-select.component.ts +++ b/apps/scully-docs/src/app/components/lang-select/component/lang-select/lang-select.component.ts @@ -1,7 +1,7 @@ import { Component, ViewEncapsulation } from '@angular/core'; import { NavListService } from '../../../nav-list/nav-list.service'; import { ScullyRoutesService } from '@scullyio/ng-lib'; -import { pluck, take } from 'rxjs/operators'; +import { pluck, take } from 'rxjs'; const langs = { es: { diff --git a/apps/scully-docs/src/app/components/nav-list/nav-list.service.ts b/apps/scully-docs/src/app/components/nav-list/nav-list.service.ts index b5fb74ee7..c273dfd3b 100644 --- a/apps/scully-docs/src/app/components/nav-list/nav-list.service.ts +++ b/apps/scully-docs/src/app/components/nav-list/nav-list.service.ts @@ -1,7 +1,7 @@ import { DoCheck, Injectable } from '@angular/core'; import { ScullyRoute, ScullyRoutesService } from '@scullyio/ng-lib'; import { combineLatest, EMPTY, forkJoin, Observable, throwError } from 'rxjs'; -import { catchError, map, take, tap } from 'rxjs/operators'; +import { catchError, map, take, tap } from 'rxjs'; export interface DocTree { _route: ScullyRoute; diff --git a/apps/scully-docs/src/app/pages/docs/page/docs.page.component.ts b/apps/scully-docs/src/app/pages/docs/page/docs.page.component.ts index 0bb0bcf26..6eba3b4cc 100644 --- a/apps/scully-docs/src/app/pages/docs/page/docs.page.component.ts +++ b/apps/scully-docs/src/app/pages/docs/page/docs.page.component.ts @@ -1,7 +1,7 @@ import { Component, ViewEncapsulation } from '@angular/core'; import { Title } from '@angular/platform-browser'; import { EMPTY } from 'rxjs'; -import { catchError, map, tap } from 'rxjs/operators'; +import { catchError, map, tap } from 'rxjs'; import { NavListService } from '../../../components/nav-list/nav-list.service'; @Component({ diff --git a/apps/universal-sample-e2e/.eslintrc.json b/apps/universal-sample-e2e/.eslintrc.json new file mode 100644 index 000000000..0c26e120e --- /dev/null +++ b/apps/universal-sample-e2e/.eslintrc.json @@ -0,0 +1,20 @@ +{ + "extends": ["plugin:cypress/recommended", "../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "parserOptions": { + "project": "apps/universal-sample-e2e/tsconfig.*?.json" + }, + "rules": {} + }, + { + "files": ["src/plugins/index.js"], + "rules": { + "@typescript-eslint/no-var-requires": "off", + "no-undef": "off" + } + } + ] +} diff --git a/apps/universal-sample-e2e/cypress.json b/apps/universal-sample-e2e/cypress.json new file mode 100644 index 000000000..7e95dd8ff --- /dev/null +++ b/apps/universal-sample-e2e/cypress.json @@ -0,0 +1,12 @@ +{ + "fileServerFolder": ".", + "fixturesFolder": "./src/fixtures", + "integrationFolder": "./src/integration", + "modifyObstructiveCode": false, + "pluginsFile": "./src/plugins/index", + "supportFile": "./src/support/index.ts", + "video": true, + "videosFolder": "../../dist/cypress/apps/universal-sample-e2e/videos", + "screenshotsFolder": "../../dist/cypress/apps/universal-sample-e2e/screenshots", + "chromeWebSecurity": false +} diff --git a/apps/universal-sample-e2e/src/fixtures/example.json b/apps/universal-sample-e2e/src/fixtures/example.json new file mode 100644 index 000000000..294cbed6c --- /dev/null +++ b/apps/universal-sample-e2e/src/fixtures/example.json @@ -0,0 +1,4 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io" +} diff --git a/apps/universal-sample-e2e/src/integration/app.spec.ts b/apps/universal-sample-e2e/src/integration/app.spec.ts new file mode 100644 index 000000000..28a4218bb --- /dev/null +++ b/apps/universal-sample-e2e/src/integration/app.spec.ts @@ -0,0 +1,13 @@ +import { getGreeting } from '../support/app.po'; + +describe('universal-sample', () => { + beforeEach(() => cy.visit('/')); + + it('should display welcome message', () => { + // Custom command example, see `../support/commands.ts` file + cy.login('my-email@something.com', 'myPassword'); + + // Function helper example, see `../support/app.po.ts` file + getGreeting().contains('Welcome to universal-sample!'); + }); +}); diff --git a/apps/universal-sample-e2e/src/plugins/index.js b/apps/universal-sample-e2e/src/plugins/index.js new file mode 100644 index 000000000..9067e75a2 --- /dev/null +++ b/apps/universal-sample-e2e/src/plugins/index.js @@ -0,0 +1,22 @@ +// *********************************************************** +// This example plugins/index.js can be used to load plugins +// +// You can change the location of this file or turn off loading +// the plugins file with the 'pluginsFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/plugins-guide +// *********************************************************** + +// This function is called when a project is opened or re-opened (e.g. due to +// the project's config changing) + +const { preprocessTypescript } = require('@nrwl/cypress/plugins/preprocessor'); + +module.exports = (on, config) => { + // `on` is used to hook into various events Cypress emits + // `config` is the resolved Cypress config + + // Preprocess Typescript file using Nx helper + on('file:preprocessor', preprocessTypescript(config)); +}; diff --git a/apps/universal-sample-e2e/src/support/app.po.ts b/apps/universal-sample-e2e/src/support/app.po.ts new file mode 100644 index 000000000..329342469 --- /dev/null +++ b/apps/universal-sample-e2e/src/support/app.po.ts @@ -0,0 +1 @@ +export const getGreeting = () => cy.get('h1'); diff --git a/apps/universal-sample-e2e/src/support/commands.ts b/apps/universal-sample-e2e/src/support/commands.ts new file mode 100644 index 000000000..310f1fa0e --- /dev/null +++ b/apps/universal-sample-e2e/src/support/commands.ts @@ -0,0 +1,33 @@ +// *********************************************** +// This example commands.js shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** + +// eslint-disable-next-line @typescript-eslint/no-namespace +declare namespace Cypress { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + interface Chainable { + login(email: string, password: string): void; + } +} +// +// -- This is a parent command -- +Cypress.Commands.add('login', (email, password) => { + console.log('Custom command example: Login', email, password); +}); +// +// -- This is a child command -- +// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) diff --git a/apps/universal-sample-e2e/src/support/index.ts b/apps/universal-sample-e2e/src/support/index.ts new file mode 100644 index 000000000..3d469a6b6 --- /dev/null +++ b/apps/universal-sample-e2e/src/support/index.ts @@ -0,0 +1,17 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands'; diff --git a/apps/universal-sample-e2e/tsconfig.e2e.json b/apps/universal-sample-e2e/tsconfig.e2e.json new file mode 100644 index 000000000..8ed2e0c4a --- /dev/null +++ b/apps/universal-sample-e2e/tsconfig.e2e.json @@ -0,0 +1,18 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "sourceMap": false, + "outDir": "../../dist/out-tsc", + "allowJs": true, + "types": ["cypress", "node"], + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src/**/*.ts", "src/**/*.js"], + "angularCompilerOptions": { + "strictInjectionParameters": true, + "strictTemplates": true + } +} diff --git a/apps/universal-sample-e2e/tsconfig.json b/apps/universal-sample-e2e/tsconfig.json new file mode 100644 index 000000000..08841a7f5 --- /dev/null +++ b/apps/universal-sample-e2e/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.e2e.json" + } + ] +} diff --git a/apps/universal-sample/.browserslistrc b/apps/universal-sample/.browserslistrc new file mode 100644 index 000000000..427441dc9 --- /dev/null +++ b/apps/universal-sample/.browserslistrc @@ -0,0 +1,17 @@ +# This file is used by the build system to adjust CSS and JS output to support the specified browsers below. +# For additional information regarding the format and rule options, please see: +# https://github.com/browserslist/browserslist#queries + +# For the full list of supported browsers by the Angular framework, please see: +# https://angular.io/guide/browser-support + +# You can see what browsers were selected by your queries by running: +# npx browserslist + +last 1 Chrome version +last 1 Firefox version +last 2 Edge major versions +last 2 Safari major versions +last 2 iOS major versions +Firefox ESR +not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line. diff --git a/apps/universal-sample/.eslintrc.json b/apps/universal-sample/.eslintrc.json new file mode 100644 index 000000000..ab0f21586 --- /dev/null +++ b/apps/universal-sample/.eslintrc.json @@ -0,0 +1,39 @@ +{ + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nrwl/nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "parserOptions": { + "project": ["apps/universal-sample/tsconfig.*?.json"] + }, + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "scullyio", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "scullyio", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nrwl/nx/angular-template"], + "rules": {} + } + ] +} diff --git a/apps/universal-sample/jest.config.js b/apps/universal-sample/jest.config.js new file mode 100644 index 000000000..188d1fef7 --- /dev/null +++ b/apps/universal-sample/jest.config.js @@ -0,0 +1,23 @@ +module.exports = { + displayName: 'universal-sample', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + globals: { + 'ts-jest': { + tsConfig: '/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + astTransformers: { + before: [ + 'jest-preset-angular/build/InlineFilesTransformer', + 'jest-preset-angular/build/StripStylesTransformer', + ], + }, + }, + }, + coverageDirectory: '../../coverage/apps/universal-sample', + snapshotSerializers: [ + 'jest-preset-angular/build/AngularNoNgAttributesSnapshotSerializer.js', + 'jest-preset-angular/build/AngularSnapshotSerializer.js', + 'jest-preset-angular/build/HTMLCommentSerializer.js', + ], +}; diff --git a/apps/universal-sample/src/app/about/about-routing.module.ts b/apps/universal-sample/src/app/about/about-routing.module.ts new file mode 100644 index 000000000..4a61313de --- /dev/null +++ b/apps/universal-sample/src/app/about/about-routing.module.ts @@ -0,0 +1,11 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { AboutComponent } from './about.component'; + +const routes: Routes = [{ path: '', component: AboutComponent }]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class AboutRoutingModule { } diff --git a/apps/universal-sample/src/app/about/about.component.css b/apps/universal-sample/src/app/about/about.component.css new file mode 100644 index 000000000..e69de29bb diff --git a/apps/universal-sample/src/app/about/about.component.html b/apps/universal-sample/src/app/about/about.component.html new file mode 100644 index 000000000..6094aa9f5 --- /dev/null +++ b/apps/universal-sample/src/app/about/about.component.html @@ -0,0 +1 @@ +

about works!

diff --git a/apps/universal-sample/src/app/about/about.component.spec.ts b/apps/universal-sample/src/app/about/about.component.spec.ts new file mode 100644 index 000000000..0e0d812f0 --- /dev/null +++ b/apps/universal-sample/src/app/about/about.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AboutComponent } from './about.component'; + +describe('AboutComponent', () => { + let component: AboutComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AboutComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AboutComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/apps/universal-sample/src/app/about/about.component.ts b/apps/universal-sample/src/app/about/about.component.ts new file mode 100644 index 000000000..e9f997f30 --- /dev/null +++ b/apps/universal-sample/src/app/about/about.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'scullyio-about', + templateUrl: './about.component.html', + styleUrls: ['./about.component.css'] +}) +export class AboutComponent implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/apps/universal-sample/src/app/about/about.module.ts b/apps/universal-sample/src/app/about/about.module.ts new file mode 100644 index 000000000..131a0d511 --- /dev/null +++ b/apps/universal-sample/src/app/about/about.module.ts @@ -0,0 +1,20 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { Routes, RouterModule } from '@angular/router'; + +import { AboutRoutingModule } from './about-routing.module'; +import { AboutComponent } from './about.component'; + +const routes: Routes = [ + { path: '', component: AboutComponent } +]; + +@NgModule({ + declarations: [AboutComponent], + imports: [ + CommonModule, + AboutRoutingModule, + RouterModule.forChild(routes) + ] +}) +export class AboutModule { } diff --git a/apps/universal-sample/src/app/app.component.ts b/apps/universal-sample/src/app/app.component.ts new file mode 100644 index 000000000..266a76060 --- /dev/null +++ b/apps/universal-sample/src/app/app.component.ts @@ -0,0 +1,25 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'scullyio-root', + template: ` + + + + `, + + styles: [``], +}) +export class AppComponent { + title = 'universal-sample'; +} diff --git a/apps/universal-sample/src/app/app.module.ts b/apps/universal-sample/src/app/app.module.ts new file mode 100644 index 000000000..815a415ab --- /dev/null +++ b/apps/universal-sample/src/app/app.module.ts @@ -0,0 +1,27 @@ +import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { AppComponent } from './app.component'; +import { RouterModule } from '@angular/router'; +import { HttpClientModule } from '@angular/common/http'; +import { ScullyLibModule } from '@scullyio/ng-lib'; + +@NgModule({ + declarations: [AppComponent], + imports: [ + BrowserModule.withServerTransition({appId:'universalSample'}), + HttpClientModule, + ScullyLibModule, + RouterModule.forRoot( + [ + { path: 'demo/:id', loadChildren: () => import('./demo/demo.module').then((m) => m.DemoModule) }, + { path: 'about', loadChildren: () => import('./about/about.module').then((m) => m.AboutModule) }, + { path: 'home', loadChildren: () => import('./home/home.module').then((m) => m.HomeModule) }, + { path: 'user/:id', loadChildren: () => import('./user/user.module').then((m) => m.UserModule) }, + ], + ), + ], + providers: [], + bootstrap: [AppComponent], +}) +export class AppModule {} diff --git a/apps/universal-sample/src/app/app.universal.module.ts b/apps/universal-sample/src/app/app.universal.module.ts new file mode 100644 index 000000000..d5e0b0430 --- /dev/null +++ b/apps/universal-sample/src/app/app.universal.module.ts @@ -0,0 +1,12 @@ +import { NgModule } from '@angular/core'; +import { ServerModule } from '@angular/platform-server'; +import { AppComponent } from './app.component'; +import { AppModule } from './app.module'; +import { ScullyUniversalModule } from '@scullyio/universal' + + +@NgModule({ + imports: [AppModule, ServerModule, ScullyUniversalModule], + bootstrap: [AppComponent], +}) +export class AppUniversalModule {} diff --git a/apps/universal-sample/src/app/demo/demo-routing.module.ts b/apps/universal-sample/src/app/demo/demo-routing.module.ts new file mode 100644 index 000000000..098f52161 --- /dev/null +++ b/apps/universal-sample/src/app/demo/demo-routing.module.ts @@ -0,0 +1,11 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { DemoComponent } from './demo.component'; + +const routes: Routes = [{ path: '', component: DemoComponent }]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class DemoRoutingModule { } diff --git a/apps/universal-sample/src/app/demo/demo.component.ts b/apps/universal-sample/src/app/demo/demo.component.ts new file mode 100644 index 000000000..59bbdb42b --- /dev/null +++ b/apps/universal-sample/src/app/demo/demo.component.ts @@ -0,0 +1,36 @@ +import { HttpClient } from '@angular/common/http'; +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { combineLatest, Observable, of, throwError } from 'rxjs'; +import { catchError, map, pluck, switchMap, tap } from 'rxjs'; + +@Component({ + selector: 'app-demo', + template: `

{{ pageId$ | async }}

+
{{ userName$ | async }}
+ prev +   + next`, + styles: [], +}) +export class DemoComponent implements OnInit { + pageId = this.route.snapshot.params.id; + pageId$ = this.route.params.pipe( + pluck('id'), + map((id) => +id) + // tap(id => (this.pageId = id)) + ); + + userList$ = this.http.get(`http://localhost:8200/users/?delay=100`); + userName$ = combineLatest([this.pageId$, this.userList$]).pipe( + map(([id, users]) => { + const _id = +id % users.length + return users[_id]['name']; + }), + tap((r) => console.log('username', r)) + ); + + constructor(private route: ActivatedRoute, private http: HttpClient) {} + + ngOnInit(): void {} +} diff --git a/apps/universal-sample/src/app/demo/demo.module.ts b/apps/universal-sample/src/app/demo/demo.module.ts new file mode 100644 index 000000000..21c868c35 --- /dev/null +++ b/apps/universal-sample/src/app/demo/demo.module.ts @@ -0,0 +1,20 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { Routes, RouterModule } from '@angular/router'; + +import { DemoRoutingModule } from './demo-routing.module'; +import { DemoComponent } from './demo.component'; + +const routes: Routes = [ + { path: '', component: DemoComponent } +]; + +@NgModule({ + declarations: [DemoComponent], + imports: [ + CommonModule, + DemoRoutingModule, + RouterModule.forChild(routes) + ] +}) +export class DemoModule { } diff --git a/apps/universal-sample/src/app/home/home-routing.module.ts b/apps/universal-sample/src/app/home/home-routing.module.ts new file mode 100644 index 000000000..b570b4927 --- /dev/null +++ b/apps/universal-sample/src/app/home/home-routing.module.ts @@ -0,0 +1,11 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { HomeComponent } from './home.component'; + +const routes: Routes = [{ path: '', component: HomeComponent }]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class HomeRoutingModule { } diff --git a/apps/universal-sample/src/app/home/home.component.css b/apps/universal-sample/src/app/home/home.component.css new file mode 100644 index 000000000..e69de29bb diff --git a/apps/universal-sample/src/app/home/home.component.html b/apps/universal-sample/src/app/home/home.component.html new file mode 100644 index 000000000..5f2c53ffd --- /dev/null +++ b/apps/universal-sample/src/app/home/home.component.html @@ -0,0 +1 @@ +

home works!

diff --git a/apps/universal-sample/src/app/home/home.component.spec.ts b/apps/universal-sample/src/app/home/home.component.spec.ts new file mode 100644 index 000000000..2c5a17268 --- /dev/null +++ b/apps/universal-sample/src/app/home/home.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { HomeComponent } from './home.component'; + +describe('HomeComponent', () => { + let component: HomeComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ HomeComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(HomeComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/apps/universal-sample/src/app/home/home.component.ts b/apps/universal-sample/src/app/home/home.component.ts new file mode 100644 index 000000000..7803ca1b3 --- /dev/null +++ b/apps/universal-sample/src/app/home/home.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'scullyio-home', + templateUrl: './home.component.html', + styleUrls: ['./home.component.css'] +}) +export class HomeComponent implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/apps/universal-sample/src/app/home/home.module.ts b/apps/universal-sample/src/app/home/home.module.ts new file mode 100644 index 000000000..43ed85c95 --- /dev/null +++ b/apps/universal-sample/src/app/home/home.module.ts @@ -0,0 +1,20 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { Routes, RouterModule } from '@angular/router'; + +import { HomeRoutingModule } from './home-routing.module'; +import { HomeComponent } from './home.component'; + +const routes: Routes = [ + { path: '', component: HomeComponent } +]; + +@NgModule({ + declarations: [HomeComponent], + imports: [ + CommonModule, + HomeRoutingModule, + RouterModule.forChild(routes) + ] +}) +export class HomeModule { } diff --git a/apps/universal-sample/src/app/user/user-routing.module.ts b/apps/universal-sample/src/app/user/user-routing.module.ts new file mode 100644 index 000000000..3a55d86e2 --- /dev/null +++ b/apps/universal-sample/src/app/user/user-routing.module.ts @@ -0,0 +1,11 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { UserComponent } from './user.component'; + +const routes: Routes = [{ path: '', component: UserComponent }]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class UserRoutingModule { } diff --git a/apps/universal-sample/src/app/user/user.component.spec.ts b/apps/universal-sample/src/app/user/user.component.spec.ts new file mode 100644 index 000000000..e6bf59698 --- /dev/null +++ b/apps/universal-sample/src/app/user/user.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { UserComponent } from './user.component'; + +describe('UserComponent', () => { + let component: UserComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ UserComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(UserComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/apps/universal-sample/src/app/user/user.component.ts b/apps/universal-sample/src/app/user/user.component.ts new file mode 100644 index 000000000..1d178f8db --- /dev/null +++ b/apps/universal-sample/src/app/user/user.component.ts @@ -0,0 +1,41 @@ +import { HttpClient } from '@angular/common/http'; +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { TransferStateService } from '@scullyio/ng-lib'; +import { Observable, of } from 'rxjs'; +import { catchError, filter, map, pluck, shareReplay, switchMap, tap } from 'rxjs'; + +@Component({ + selector: 'app-user', + template: ` +

user {{ userId$ | async }} works!

+

{{ user.name }}

+ prev +   + next + `, + styles: [], +}) +export class UserComponent implements OnInit { + userId$: Observable = this.route.params.pipe( + pluck('id'), + filter((val) => ![undefined, null].includes(val)), + map((val) => parseInt(val, 10)), + // tap(r => console.log(r)), + shareReplay(1) + ); + + userList$ = this.http.get(`http://localhost:8200/users/?delay=100`); + + apiUser$ = this.userId$.pipe( + switchMap((id) => + this.sts.useScullyTransferState(`user-${id}`, this.userList$.pipe(map((list) => list.find((user) => user.id === id)))) + ), + // tap(r => console.log(r)), + shareReplay(1) + ); + + constructor(private route: ActivatedRoute, private http: HttpClient, private sts: TransferStateService) {} + + ngOnInit(): void {} +} diff --git a/apps/universal-sample/src/app/user/user.module.ts b/apps/universal-sample/src/app/user/user.module.ts new file mode 100644 index 000000000..b7b7fe981 --- /dev/null +++ b/apps/universal-sample/src/app/user/user.module.ts @@ -0,0 +1,20 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { Routes, RouterModule } from '@angular/router'; + +import { UserRoutingModule } from './user-routing.module'; +import { UserComponent } from './user.component'; + +const routes: Routes = [ + { path: '', component: UserComponent } +]; + +@NgModule({ + declarations: [UserComponent], + imports: [ + CommonModule, + UserRoutingModule, + RouterModule.forChild(routes) + ] +}) +export class UserModule { } diff --git a/apps/universal-sample/src/assets/.gitkeep b/apps/universal-sample/src/assets/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/universal-sample/src/environments/environment.prod.ts b/apps/universal-sample/src/environments/environment.prod.ts new file mode 100644 index 000000000..c9669790b --- /dev/null +++ b/apps/universal-sample/src/environments/environment.prod.ts @@ -0,0 +1,3 @@ +export const environment = { + production: true, +}; diff --git a/apps/universal-sample/src/environments/environment.ts b/apps/universal-sample/src/environments/environment.ts new file mode 100644 index 000000000..31cb7855f --- /dev/null +++ b/apps/universal-sample/src/environments/environment.ts @@ -0,0 +1,16 @@ +// This file can be replaced during build by using the `fileReplacements` array. +// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. +// The list of file replacements can be found in `angular.json`. + +export const environment = { + production: false, +}; + +/* + * For easier debugging in development mode, you can import the following file + * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. + * + * This import should be commented out in production mode because it will have a negative impact + * on performance if an error is thrown. + */ +// import 'zone.js/plugins/zone-error'; // Included with Angular CLI. diff --git a/apps/universal-sample/src/favicon.ico b/apps/universal-sample/src/favicon.ico new file mode 100644 index 000000000..317ebcb23 Binary files /dev/null and b/apps/universal-sample/src/favicon.ico differ diff --git a/apps/universal-sample/src/index.html b/apps/universal-sample/src/index.html new file mode 100644 index 000000000..37c163ac2 --- /dev/null +++ b/apps/universal-sample/src/index.html @@ -0,0 +1,13 @@ + + + + + UniversalSample + + + + + + + + diff --git a/apps/universal-sample/src/main.ts b/apps/universal-sample/src/main.ts new file mode 100644 index 000000000..d9a2e7e4a --- /dev/null +++ b/apps/universal-sample/src/main.ts @@ -0,0 +1,13 @@ +import { enableProdMode } from '@angular/core'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from './app/app.module'; +import { environment } from './environments/environment'; + +if (environment.production) { + enableProdMode(); +} + +platformBrowserDynamic() + .bootstrapModule(AppModule) + .catch((err) => console.error(err)); diff --git a/apps/universal-sample/src/main.universal.ts b/apps/universal-sample/src/main.universal.ts new file mode 100644 index 000000000..10fc3440f --- /dev/null +++ b/apps/universal-sample/src/main.universal.ts @@ -0,0 +1,11 @@ +import { enableProdMode } from '@angular/core'; + +import { environment } from './environments/environment'; + +if (environment.production) { +} +enableProdMode(); + + +export { AppUniversalModule } from './app/app.universal.module'; +export { renderModule, renderModuleFactory } from '@angular/platform-server'; diff --git a/apps/universal-sample/src/polyfills.ts b/apps/universal-sample/src/polyfills.ts new file mode 100644 index 000000000..d1bde133b --- /dev/null +++ b/apps/universal-sample/src/polyfills.ts @@ -0,0 +1,66 @@ +/** + * This file includes polyfills needed by Angular and is loaded before the app. + * You can add your own extra polyfills to this file. + * + * This file is divided into 2 sections: + * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. + * 2. Application imports. Files imported after ZoneJS that should be loaded before your main + * file. + * + * The current setup is for so-called "evergreen" browsers; the last versions of browsers that + * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), + * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. + * + * Learn more in https://angular.io/guide/browser-support + */ + +/*************************************************************************************************** + * BROWSER POLYFILLS + */ + +/** + * IE11 requires the following for NgClass support on SVG elements + */ +// import 'classlist.js'; // Run `npm install --save classlist.js`. + +/** + * Web Animations `@angular/platform-browser/animations` + * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. + * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). + */ +// import 'web-animations-js'; // Run `npm install --save web-animations-js`. + +/** + * By default, zone.js will patch all possible macroTask and DomEvents + * user can disable parts of macroTask/DomEvents patch by setting following flags + * because those flags need to be set before `zone.js` being loaded, and webpack + * will put import in the top of bundle, so user need to create a separate file + * in this directory (for example: zone-flags.ts), and put the following flags + * into that file, and then add the following code before importing zone.js. + * import './zone-flags'; + * + * The flags allowed in zone-flags.ts are listed here. + * + * The following flags will work for all browsers. + * + * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame + * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick + * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames + * + * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js + * with the following flag, it will bypass `zone.js` patch for IE/Edge + * + * (window as any).__Zone_enable_cross_context_check = true; + * + */ + +/*************************************************************************************************** + * Zone JS is required by default for Angular itself. + */ +import 'zone.js'; // Included with Angular CLI. +// tslint:disable-next-line: ordered-imports +import 'zone.js/dist/task-tracking'; + +/*************************************************************************************************** + * APPLICATION IMPORTS + */ diff --git a/apps/universal-sample/src/styles.css b/apps/universal-sample/src/styles.css new file mode 100644 index 000000000..90d4ee007 --- /dev/null +++ b/apps/universal-sample/src/styles.css @@ -0,0 +1 @@ +/* You can add global styles to this file, and also import other style files */ diff --git a/apps/universal-sample/src/test-setup.ts b/apps/universal-sample/src/test-setup.ts new file mode 100644 index 000000000..035d640f7 --- /dev/null +++ b/apps/universal-sample/src/test-setup.ts @@ -0,0 +1,2 @@ +// import 'jest-preset-angular'; +import 'jest-preset-angular/setup-jest'; diff --git a/apps/universal-sample/tsconfig.app.json b/apps/universal-sample/tsconfig.app.json new file mode 100644 index 000000000..e9fa6dfd9 --- /dev/null +++ b/apps/universal-sample/tsconfig.app.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "types": [] + }, + "files": ["src/main.ts", "src/polyfills.ts"] +} diff --git a/apps/universal-sample/tsconfig.editor.json b/apps/universal-sample/tsconfig.editor.json new file mode 100644 index 000000000..20c4afdbf --- /dev/null +++ b/apps/universal-sample/tsconfig.editor.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "include": ["**/*.ts"], + "compilerOptions": { + "types": ["jest", "node"] + } +} diff --git a/apps/universal-sample/tsconfig.json b/apps/universal-sample/tsconfig.json new file mode 100644 index 000000000..7766f8f1f --- /dev/null +++ b/apps/universal-sample/tsconfig.json @@ -0,0 +1,26 @@ +{ + "extends": "../../tsconfig.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.spec.json" + }, + { + "path": "./tsconfig.editor.json" + } + ], + "compilerOptions": { + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "angularCompilerOptions": { + "strictInjectionParameters": true, + "strictTemplates": true + } +} diff --git a/apps/universal-sample/tsconfig.spec.json b/apps/universal-sample/tsconfig.spec.json new file mode 100644 index 000000000..cfff29a54 --- /dev/null +++ b/apps/universal-sample/tsconfig.spec.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts"] +} diff --git a/libs/ng-lib/ng-package.json b/libs/ng-lib/ng-package.json index f63071afb..073412c1b 100644 --- a/libs/ng-lib/ng-package.json +++ b/libs/ng-lib/ng-package.json @@ -3,5 +3,8 @@ "dest": "../../dist/libs/ng-lib", "lib": { "entryFile": "src/public-api.ts" - } + }, + "allowedNonPeerDependencies": [ + "rxjs" + ] } diff --git a/libs/ng-lib/package.json b/libs/ng-lib/package.json index f977bc464..27c8e7b89 100644 --- a/libs/ng-lib/package.json +++ b/libs/ng-lib/package.json @@ -5,12 +5,14 @@ "type": "GIT", "url": "https://github.com/scullyio/scully/tree/main/libs/ng-lib" }, + "dependencies": { + "rxjs": "7.x.x" + }, "peerDependencies": { "@angular/router": "12.x.x", "@angular/platform-browser-dynamic": "12.x.x", "@angular/common": "12.x.x", - "@angular/core": "12.x.x", - "rxjs": "6.x.x || 7.x.x" + "@angular/core": "12.x.x" }, "keywords": [ "angular", @@ -19,4 +21,4 @@ "scully-plugin", "plugin" ] -} \ No newline at end of file +} diff --git a/libs/ng-lib/src/lib/idleMonitor/idle-monitor.service.ts b/libs/ng-lib/src/lib/idleMonitor/idle-monitor.service.ts index e5ddafafb..17f1a643b 100644 --- a/libs/ng-lib/src/lib/idleMonitor/idle-monitor.service.ts +++ b/libs/ng-lib/src/lib/idleMonitor/idle-monitor.service.ts @@ -1,8 +1,8 @@ +import { DOCUMENT } from '@angular/common'; import { Inject, Injectable, NgZone } from '@angular/core'; import { NavigationEnd, Router } from '@angular/router'; -import { BehaviorSubject } from 'rxjs'; -import { filter, pluck, take, tap } from 'rxjs/operators'; -import { ScullyLibConfig, SCULLY_LIB_CONFIG, ScullyDefaultSettings } from '../config/scully-config'; +import { BehaviorSubject, filter, firstValueFrom, pluck, tap } from 'rxjs'; +import { ScullyDefaultSettings, ScullyLibConfig, SCULLY_LIB_CONFIG } from '../config/scully-config'; import { TransferStateService } from '../transfer-state/transfer-state.service'; import { isScullyRunning } from '../utils/isScully'; @@ -31,6 +31,9 @@ declare global { // }); // } +// Adding this dynamic comment to suppress ngc error around Document as a DI token. +// https://github.com/angular/angular/issues/20351#issuecomment-344009887 +/** @dynamic */ @Injectable({ providedIn: 'root', }) @@ -61,6 +64,7 @@ export class IdleMonitorService { private zone: NgZone, private router: Router, @Inject(SCULLY_LIB_CONFIG) conf: ScullyLibConfig, + @Inject(DOCUMENT) private document: Document, tss: TransferStateService ) { /** provide the default for missing conf paramter */ @@ -69,7 +73,7 @@ export class IdleMonitorService { const manualIdle = !!exposed.manualIdle; if (!this.scullyLibConfig.manualIdle && window && (this.scullyLibConfig.alwaysMonitor || isScullyRunning())) { - window.dispatchEvent(this.initApp); + this.document.dispatchEvent(this.initApp); this.router.events .pipe( filter((ev) => ev instanceof NavigationEnd && ev.urlAfterRedirects !== undefined), @@ -81,7 +85,7 @@ export class IdleMonitorService { } if (this.scullyLibConfig.manualIdle) { /** we still need the init event. */ - window.dispatchEvent(this.initApp); + this.document.dispatchEvent(this.initApp); } if (this.scullyLibConfig.useTransferState) { /** don't start monitoring if people don't use the transferState */ @@ -90,11 +94,11 @@ export class IdleMonitorService { } public async fireManualMyAppReadyEvent() { - return window.dispatchEvent(this.appReady); + return this.document.dispatchEvent(this.appReady); } - public async init() { - return this.idle$.pipe(take(1)).toPromise(); + public init() { + return firstValueFrom(this.idle$); } private async zoneIdleCheck() { @@ -118,13 +122,13 @@ export class IdleMonitorService { // console.table(taskTrackingZone.macroTasks); if (Date.now() - startTime > 30 * 1000) { /** bail out after 30 seconds. */ - window.dispatchEvent(this.appTimeout); + this.document.dispatchEvent(this.appTimeout); return; } if ( (taskTrackingZone.macroTasks.length > 0 && taskTrackingZone.macroTasks.find((z: { source: string | string[] }) => z.source.includes('XMLHttpRequest')) !== - undefined) || + undefined) || count < 1 // make sure it runs at least once! ) { tCancel = setTimeout(() => { @@ -136,7 +140,7 @@ export class IdleMonitorService { this.zone.run(() => { /** run this inside the zone, and give the app 250Ms to wrap up, before scraping starts */ setTimeout(() => { - window.dispatchEvent(this.appReady); + this.document.dispatchEvent(this.appReady); this.setState('idle', true); }, 250); }); @@ -149,7 +153,7 @@ export class IdleMonitorService { /** zone not available, use a timeout instead. */ console.warn('Scully is using timeouts, add the needed polyfills instead!'); await new Promise((r) => setTimeout(r, this.imState.value.timeOut)); - window.dispatchEvent(this.appReady); + this.document.dispatchEvent(this.appReady); } public setPupeteerTimeoutValue(milliseconds: number) { diff --git a/libs/ng-lib/src/lib/route-service/scully-routes.service.ts b/libs/ng-lib/src/lib/route-service/scully-routes.service.ts index 286748fdb..cde254e8d 100644 --- a/libs/ng-lib/src/lib/route-service/scully-routes.service.ts +++ b/libs/ng-lib/src/lib/route-service/scully-routes.service.ts @@ -1,15 +1,11 @@ import { Injectable } from '@angular/core'; -import { Observable, of, ReplaySubject, merge } from 'rxjs'; +import { NavigationEnd, Router } from '@angular/router'; import { - catchError, - map, - shareReplay, - switchMap, - filter, -} from 'rxjs/operators'; -import { fetchHttp } from '../utils/fetchHttp'; -import { Router, NavigationEnd, NavigationStart } from '@angular/router'; + catchError, filter, map, merge, Observable, of, ReplaySubject, shareReplay, + switchMap +} from 'rxjs'; import { basePathOnly } from '../utils/basePathOnly'; +import { fetchHttp } from '../utils/fetchHttp'; export interface ScullyRoute { route: string; diff --git a/libs/ng-lib/src/lib/scully-content/scully-content.component.ts b/libs/ng-lib/src/lib/scully-content/scully-content.component.ts index 6702ef8aa..9c0fd2c45 100644 --- a/libs/ng-lib/src/lib/scully-content/scully-content.component.ts +++ b/libs/ng-lib/src/lib/scully-content/scully-content.component.ts @@ -1,4 +1,4 @@ -import { Location } from '@angular/common'; +import { DOCUMENT, Location } from '@angular/common'; import { ChangeDetectionStrategy, Component, @@ -7,10 +7,10 @@ import { isDevMode, OnDestroy, OnInit, - ViewEncapsulation, + ViewEncapsulation } from '@angular/core'; import { NavigationEnd, Router } from '@angular/router'; -import { filter, take, tap } from 'rxjs/operators'; +import { filter, firstValueFrom, tap } from 'rxjs'; import { ScullyDefaultSettings, ScullyLibConfig, SCULLY_LIB_CONFIG } from '../config/scully-config'; import { ScullyRoutesService } from '../route-service/scully-routes.service'; import { basePathOnly } from '../utils/basePathOnly'; @@ -33,6 +33,9 @@ const scullyEnd = ''; /** use the module's closure to keep a system-wide check for the last handled URL. */ let lastHandled: String; +// Adding this dynamic comment to suppress ngc error around Document as a DI token. +// https://github.com/angular/angular/issues/20351#issuecomment-344009887 +/** @dynamic */ @Component({ // tslint:disable-next-line: component-selector selector: 'scully-content', @@ -55,7 +58,7 @@ export class ScullyContentComponent implements OnDestroy, OnInit { baseUrl = this.conf.useTransferState || ScullyDefaultSettings.useTransferState; elm = this.elmRef.nativeElement as HTMLElement; /** pull in all available routes into an eager promise */ - routes = this.srs.allRoutes$.pipe(take(1)).toPromise(); + routes = firstValueFrom(this.srs.allRoutes$); /** monitor the router, so we can update while navigating in the same 'page' see #311 */ routeUpdates$ = this.router.events.pipe( filter((ev) => ev instanceof NavigationEnd), @@ -71,6 +74,7 @@ export class ScullyContentComponent implements OnDestroy, OnInit { private srs: ScullyRoutesService, private router: Router, private location: Location, + @Inject(DOCUMENT) private document: Document, @Inject(SCULLY_LIB_CONFIG) private conf: ScullyLibConfig ) { /** do this from constructor, so it runs ASAP */ @@ -99,7 +103,7 @@ export class ScullyContentComponent implements OnDestroy, OnInit { return; } lastHandled = curPage; - const template = document.createElement('template'); + const template = this.document.createElement('template'); const currentCssId = this.getCSSId(this.elm); if (window.scullyContent) { /** upgrade existing static content */ @@ -150,14 +154,14 @@ export class ScullyContentComponent implements OnDestroy, OnInit { }); } /** insert the whole thing just before the `` element */ - const parent = this.elm.parentElement || document.body; - const begin = document.createComment('scullyContent-begin'); - const end = document.createComment('scullyContent-end'); + const parent = this.elm.parentElement || this.document.body; + const begin = this.document.createComment('scullyContent-begin'); + const end = this.document.createComment('scullyContent-end'); parent.insertBefore(begin, this.elm); parent.insertBefore(template.content, this.elm); parent.insertBefore(end, this.elm); /** upgrade all hrefs to simulated routelinks (in next microtask) */ - setTimeout(() => document.querySelectorAll('[href]').forEach(this.upgradeToRoutelink.bind(this)), 10); + setTimeout(() => this.document.querySelectorAll('[href]').forEach(this.upgradeToRoutelink.bind(this)), 10); // document.querySelectorAll('[href]').forEach(this.upgradeToRoutelink.bind(this)); } diff --git a/libs/ng-lib/src/lib/scully-lib.module.ts b/libs/ng-lib/src/lib/scully-lib.module.ts index 5ff9e1875..25b2d01cc 100644 --- a/libs/ng-lib/src/lib/scully-lib.module.ts +++ b/libs/ng-lib/src/lib/scully-lib.module.ts @@ -13,9 +13,8 @@ export class ScullyLibModule { * First, we separate out the component in a separate module to prevent a circulair injection * second we create a constuctor that activates the IdleMonitorService. as that is provided for 'root' * there will be only 1 instance in our app. - * We don't need forRoot, as we are not configuring anything in here. */ - static forRoot(config: ScullyLibConfig = ScullyDefaultSettings): ModuleWithProviders { + static forRoot(config: ScullyLibConfig = ScullyDefaultSettings): ModuleWithProviders { config = Object.assign({}, ScullyDefaultSettings, config); return { ngModule: ScullyLibModule, diff --git a/libs/ng-lib/src/lib/transfer-state/transfer-state.service.ts b/libs/ng-lib/src/lib/transfer-state/transfer-state.service.ts index 991aa4206..cb76c6d6a 100644 --- a/libs/ng-lib/src/lib/transfer-state/transfer-state.service.ts +++ b/libs/ng-lib/src/lib/transfer-state/transfer-state.service.ts @@ -1,8 +1,7 @@ import { DOCUMENT } from '@angular/common'; import { Inject, Injectable } from '@angular/core'; import { NavigationEnd, NavigationStart, Router } from '@angular/router'; -import { BehaviorSubject, NEVER, Observable, of } from 'rxjs'; -import { catchError, filter, first, map, pluck, shareReplay, switchMap, take, takeWhile, tap } from 'rxjs/operators'; +import { BehaviorSubject, catchError, filter, first, firstValueFrom, map, NEVER, Observable, of, pluck, shareReplay, switchMap, takeWhile, tap } from 'rxjs'; import { basePathOnly } from '../utils/basePathOnly'; import { fetchHttp } from '../utils/fetchHttp'; import { isScullyGenerated, isScullyRunning } from '../utils/isScully'; @@ -66,7 +65,7 @@ export class TransferStateService { shareReplay(1) ); - constructor(@Inject(DOCUMENT) private document: Document, private router: Router) {} + constructor(@Inject(DOCUMENT) private document: Document, private router: Router) { } startMonitoring() { if (window && window['ScullyIO-injected'] && window['ScullyIO-injected'].inlineStateOnly) { @@ -97,11 +96,16 @@ export class TransferStateService { private injectScript() { this.script = this.document.createElement('script'); this.script.setAttribute('id', SCULLY_SCRIPT_ID); - let last = document.body.lastChild; + let last = this.document.body.lastChild; while (last.previousSibling.nodeName === 'SCRIPT') { last = last.previousSibling as ChildNode; } - document.body.insertBefore(this.script, last); + // console.log(` + // -------------------------------------------------- + // Welp! ${this.script} + // -------------------------------------------------- + // `) + this.document.body.insertBefore(this.script, last) } /** @@ -192,7 +196,7 @@ export class TransferStateService { /** put this in the next event cycle so the correct route can be read */ await new Promise((r) => setTimeout(r, 0)); /** get the current url */ - const currentUrl = await this.nextUrl.pipe(take(1)).toPromise(); + const currentUrl = await firstValueFrom(this.nextUrl); const baseUrl = base(currentUrl); if (this.currentBaseUrl === baseUrl) { /** already monitoring, don't tho a thing */ diff --git a/libs/ng-lib/tsconfig.lib.json b/libs/ng-lib/tsconfig.lib.json index 488107ac3..43a64df82 100644 --- a/libs/ng-lib/tsconfig.lib.json +++ b/libs/ng-lib/tsconfig.lib.json @@ -23,7 +23,8 @@ "fullTemplateTypeCheck": true, "strictInjectionParameters": true, "enableResourceInlining": true, - "enableIvy": false + "enableIvy": true, + "compilationMode": "partial" }, "exclude": ["src/test.ts", "**/*.spec.ts"] } diff --git a/libs/plugins/scully-plugin-critical-css/tsconfig.json b/libs/plugins/scully-plugin-critical-css/tsconfig.json index 72391d467..04ed177f8 100644 --- a/libs/plugins/scully-plugin-critical-css/tsconfig.json +++ b/libs/plugins/scully-plugin-critical-css/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../../../tsconfig.base.json", + "extends": "../../../tsconfig.json", "compilerOptions": { "esModuleInterop": true, "allowSyntheticDefaultImports": true diff --git a/libs/plugins/scully-plugin-local-cache/src/lib/handlePuppeteerRequest.ts b/libs/plugins/scully-plugin-local-cache/src/lib/handlePuppeteerRequest.ts index 30dab7401..46c87c536 100644 --- a/libs/plugins/scully-plugin-local-cache/src/lib/handlePuppeteerRequest.ts +++ b/libs/plugins/scully-plugin-local-cache/src/lib/handlePuppeteerRequest.ts @@ -1,12 +1,12 @@ /* eslint-disable no-prototype-builtins */ -import { HTTPRequest as Request } from 'puppeteer'; +import { HTTPRequest } from 'puppeteer'; import { config } from './config'; import { generateId } from './generateId'; import { del, get } from './ldb'; import { CacheItem } from './local-cache.interface'; import { usageStatistics } from './usageStatistics'; -export async function handlePuppeteerRequest(request: Request) { +export async function handlePuppeteerRequest(request: HTTPRequest) { const url = request.url(); const id = generateId(); const { referer, ...headers } = request.headers(); diff --git a/libs/plugins/scully-plugin-local-cache/src/lib/local-cache.interface.ts b/libs/plugins/scully-plugin-local-cache/src/lib/local-cache.interface.ts index 1e7a64c77..940bcf9d0 100644 --- a/libs/plugins/scully-plugin-local-cache/src/lib/local-cache.interface.ts +++ b/libs/plugins/scully-plugin-local-cache/src/lib/local-cache.interface.ts @@ -26,7 +26,7 @@ export interface CacheItem { TTL: number; /** the response from the server */ response: { - /** esponse headers form server */ + /** response headers form server */ headers: Headers; /** contentTYpe provided by server, extracted form above headers */ contentType: string; diff --git a/libs/plugins/scully-plugin-local-cache/tsconfig.json b/libs/plugins/scully-plugin-local-cache/tsconfig.json index f4023e39f..42882af48 100644 --- a/libs/plugins/scully-plugin-local-cache/tsconfig.json +++ b/libs/plugins/scully-plugin-local-cache/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../../../tsconfig.base.json", + "extends": "../../../tsconfig.json", "files": [], "include": [], "references": [ diff --git a/libs/scully/src/index.ts b/libs/scully/src/index.ts index a3d55af20..7e9a396ec 100644 --- a/libs/scully/src/index.ts +++ b/libs/scully/src/index.ts @@ -26,35 +26,38 @@ import { routeSplit } from './lib/utils/routeSplit'; import { staticServer } from './lib/utils/serverstuff/staticServer'; import { getHandledRoutes } from './lib/utils/services/routeStorage'; import { startScully } from './lib/utils/startup'; +import { universalRender } from './lib/systemPlugins/universalRender'; export * from './lib/utils/log'; +export * from './lib/utils/procesmanager'; export { configValidator, ContentMetaData, - HandledRoute, ContentTextRoute, + createFolderFor, + findPlugin, + getHandledRoutes, + getPluginConfig, + HandledRoute, httpGetJson, registerPlugin, replaceFirstRouteParamWithVal, + RouteConfig, routeSplit, RouteTypes, scullyConfig, ScullyConfig, + setPluginConfig, startScully, + universalRender, updateScullyConfig, - getHandledRoutes, - setPluginConfig, - getPluginConfig, - findPlugin, - createFolderFor, - RouteConfig, /** WIP part, those might be remove again in near future. */ - staticServer, - loadConfig, handleTravesal, + launchedBrowser$, + loadConfig, + renderRoute, routeDiscovery, + staticServer, WriteToStorage, - renderRoute, - launchedBrowser$, /** end WIP */ getConfig as getMyConfig, setConfig as setMyConfig, diff --git a/libs/scully/src/lib/pluginManagement/pluginRepository.ts b/libs/scully/src/lib/pluginManagement/pluginRepository.ts index f03ffa86f..50da183a9 100644 --- a/libs/scully/src/lib/pluginManagement/pluginRepository.ts +++ b/libs/scully/src/lib/pluginManagement/pluginRepository.ts @@ -39,7 +39,6 @@ export const pluginTypes = [ ] as const; /** type helpers for registerPlugin */ - export const registerPlugin = ( type: T, name: string | symbol, diff --git a/libs/scully/src/lib/renderPlugins/launchedBrowser.ts b/libs/scully/src/lib/renderPlugins/launchedBrowser.ts index c641b97d6..18ec409c1 100644 --- a/libs/scully/src/lib/renderPlugins/launchedBrowser.ts +++ b/libs/scully/src/lib/renderPlugins/launchedBrowser.ts @@ -1,6 +1,6 @@ import { Browser, launch, LaunchOptions, BrowserLaunchArgumentOptions } from 'puppeteer'; import { BehaviorSubject, from, interval, merge, Observable, of, timer } from 'rxjs'; -import { catchError, delayWhen, filter, shareReplay, switchMap, take, throttleTime } from 'rxjs/operators'; +import { catchError, delayWhen, filter, shareReplay, switchMap, take, throttleTime } from 'rxjs'; import { captureException } from '../utils/captureMessage'; import { showBrowser, serverTimeout } from '../utils/cli-options'; import { loadConfig, scullyConfig } from '../utils/config'; diff --git a/libs/scully/src/lib/renderPlugins/puppeteerRenderPlugin.ts b/libs/scully/src/lib/renderPlugins/puppeteerRenderPlugin.ts index 15cddcbb3..40b3b671d 100644 --- a/libs/scully/src/lib/renderPlugins/puppeteerRenderPlugin.ts +++ b/libs/scully/src/lib/renderPlugins/puppeteerRenderPlugin.ts @@ -5,7 +5,7 @@ import { jsonc } from 'jsonc'; import { join } from 'path'; import { Browser, Page, Serializable } from 'puppeteer'; import { interval, Subject } from 'rxjs'; -import { filter, switchMap, take } from 'rxjs/operators'; +import { filter, switchMap, take } from 'rxjs'; import { registerPlugin, scullySystem } from '../pluginManagement'; import { HandledRoute } from '../routerPlugins/handledRoute.interface'; import { createFolderFor } from '../utils'; diff --git a/libs/scully/src/lib/systemPlugins/universalRender.ts b/libs/scully/src/lib/systemPlugins/universalRender.ts new file mode 100644 index 000000000..f46a90134 --- /dev/null +++ b/libs/scully/src/lib/systemPlugins/universalRender.ts @@ -0,0 +1,128 @@ +import { existsSync } from 'fs'; +import { performance } from 'perf_hooks'; +import { findPlugin, registerPlugin } from '../pluginManagement'; +import { HandledRoute } from '../routerPlugins'; +import { + baseFilter, + determineConfigFilePath, + generateAll, + getJsName, + getPool, + handleAllDone, + handleJobs, + handleRouteDiscoveryDone, + handleTravesal, + Job, + loadConfig, + log, + yellow, + logError, + moveDistAngular, + orange, + performanceIds, + printProgress, + removeStaticDist, + routeDiscovery, + scullyConfig, + startScully +} from '../utils'; +import { installExitHandler } from '../utils/exitHandler'; +import { processRoutes } from '../utils/handlers/processRoutes'; + +let workerPath: string; +// const poolSize = 64; + +installExitHandler(); + +export const universalRender = Symbol('universalRender'); +registerPlugin('scullySystem', universalRender, universalPlugin); + +async function universalPlugin(path) { + performance.mark('startplugin-UniversalWarmUp'); + performanceIds.add('plugin-UniversalWarmUp'); + if (!existsSync(path)) { + throw new Error(` + ================================================================ + the worker for the Universal render is not found + Please provide a fully qualified path to the plugin + + The file "${orange(path)}" is not found. + ================================================================ + + `); + } + workerPath = path; + /** replace the generate-all to be able to optimize building with universal */ + registerPlugin('scullySystem', generateAll, generateWithUniversal, undefined, { replaceExistingPlugin: true }); + printProgress(undefined, 'Warming up.'); + /** compile the config, so the .js version is available for workers */ + await loadConfig(); + /** get the full path of the config.js file */ + const configPath = getJsName(determineConfigFilePath()); + + /** start prepping the workers */ + const pool = getPool(workerPath, scullyConfig.maxRenderThreads); + const initJobs = pool.map(() => new Job('init', configPath)); + const initDone = handleJobs(initJobs, pool); + + /** copy in current build artifacts */ + printProgress(undefined, 'Copying distribution files'); + await moveDistAngular(scullyConfig.distFolder, scullyConfig.outDir, { + removeStaticDist: removeStaticDist, + reset: false, + }); + + /** wait until all workers are up and running */ + await initDone; + performance.mark('stopplugin-UniversalWarmUp'); + /** run full scully */ + await startScully(); + + /** clean up worker pool */ + await Promise.all(pool.map((p) => p.kill())); + // process.exit(0); +} + +async function generateWithUniversal(localBaseFilter = baseFilter): Promise { + await loadConfig(); + try { + // maintain progress ui + /** handleTravesal execute the guessParser and create a list of route.routes */ + const unhandledRoutes = await findPlugin(handleTravesal)(); + + /** RouteDiscovery is the place for create the list of handler routes & add the plugins to the route */ + const handledRoutes = await routeDiscovery(unhandledRoutes, localBaseFilter); + + /** handle routeProcess plugins (this is the place to change handle routes) */ + const processedRoutes = await findPlugin(processRoutes)(handledRoutes); + + /** handleRouteDiscoveryDone run the discoverydone plugins */ + const discoveryDone = handleRouteDiscoveryDone(processedRoutes); + + /** update user on progress */ + printProgress(false, 'Start universal rendering'); + + /** start handling each route, works in chunked parallel mode */ + await renderParallel(processedRoutes); + /** wait for routeDiscoveryDone plugins to be ready. they can still be running. */ + await discoveryDone; + /** fire off the allDone plugins */ + await handleAllDone(processedRoutes); + + // stop progress ui + return processedRoutes; + } catch (e) { + // TODO: add better error handling + logError(e); + } + return []; +} + +async function renderParallel(routes: HandledRoute[]) { + const jobs = routes.map((r, i) => { + // log(`generating ${yellow(r.route)}`); + return new Job('render', r); + }); + // .filter((_, i) => i < 2); + await handleJobs(jobs, getPool(workerPath)); +} diff --git a/libs/scully/src/lib/utils/compileConfig.ts b/libs/scully/src/lib/utils/compileConfig.ts index ff22ea22e..924941956 100644 --- a/libs/scully/src/lib/utils/compileConfig.ts +++ b/libs/scully/src/lib/utils/compileConfig.ts @@ -24,18 +24,12 @@ const angularConfig = readAngularJson(); const defaultProjectName = angularConfig.defaultProject; const createConfigName = (name = defaultProjectName) => `scully.${name}.config.ts`; -const getJsName = (name: string) => name.replace('.ts', '.js'); +export const getJsName = (name: string) => name.replace('.ts', '.js'); export const compileConfig = async (): Promise => { let path: string; try { - path = join(angularRoot, createConfigName()); - if (configFileName) { - path = join(angularRoot, configFileName); - } - if (project) { - path = join(angularRoot, createConfigName(project)); - } + path = determineConfigFilePath(); if (!(await pathExists(path))) { /** no js config, nothing to do. */ logWarn(` @@ -83,6 +77,17 @@ export const compileConfig = async (): Promise => { } }; +export function determineConfigFilePath() { + let path = join(angularRoot, createConfigName()); + if (configFileName) { + path = join(angularRoot, configFileName); + } + if (project) { + path = join(angularRoot, createConfigName(project)); + } + return path; +} + async function compileUserPluginsAndConfig() { const persistentFolder = readDotProperty('pluginFolder'); let folder = persistentFolder || pluginFolder; diff --git a/libs/scully/src/lib/utils/exitHandler.ts b/libs/scully/src/lib/utils/exitHandler.ts index bf2b002dc..1c0a0bb8a 100644 --- a/libs/scully/src/lib/utils/exitHandler.ts +++ b/libs/scully/src/lib/utils/exitHandler.ts @@ -3,8 +3,13 @@ import { browser } from '../renderPlugins/launchedBrowser'; type ExitHandler = () => void; const exitHandlers: ExitHandler[] = []; +let alreadyInstalled = false; export function installExitHandler(): void { + if (alreadyInstalled) { + return; + } + alreadyInstalled = true; /** * The following code is to make sure puppeteer will be closed properly. * Future additions on cleanup might to be handled here too. @@ -17,34 +22,39 @@ export function installExitHandler(): void { * without it, we have no proper way to wind down the browser or puppeteer. */ process.stdin.resume(); // so the program will not close. - function exitHandler(options, exitCode) { - for (const handler of exitHandlers) { - try { - handler(); - } catch (e) { - logWarn(`Error while closing Scully ${e.toString()}`) + try { + for (const handler of exitHandlers) { + try { + handler(); + } catch (e) { + logWarn(`Error while closing Scully ${e.toString()}`) + } } - } - if (exitCode || exitCode === 0) { - if (typeof exitCode !== 'number') { - /** not a 'clean' exit log to console */ - console.log(exitCode); + if (exitCode || exitCode === 0) { + if (typeof exitCode !== 'number') { + /** not a 'clean' exit log to console */ + console.log(exitCode); + } } - } - // TODO: kill the server here. (but only if started from scully, not when started from another process) - if (options.exit) { - if (browser) { - /** add a timeout, so if the browser/puppeteer is stalled, we still exit */ - Promise.race([ - browser.close(), - new Promise(resolve => setTimeout(resolve, 3000)) - ]).finally(() => process.exit(exitCode)); - } else { - process.exit(exitCode); + // TODO: kill the server here. (but only if started from scully, not when started from another process) + if (options.exit) { + if (browser) { + /** add a timeout, so if the browser/puppeteer is stalled, we still exit */ + Promise.race([ + browser.close(), + new Promise(resolve => setTimeout(resolve, 3000)) + ]).finally(() => process.exit(exitCode)); + } else { + process.exit(exitCode); + } } + } catch (e) { + console.error(e); + process.exit(15); } } + // do something when app is closing process.on('exit', exitHandler.bind(null, { exit: true })); // catches ctrl+c event diff --git a/libs/scully/src/lib/utils/fsAngular.ts b/libs/scully/src/lib/utils/fsAngular.ts index b40febe07..fa4072274 100644 --- a/libs/scully/src/lib/utils/fsAngular.ts +++ b/libs/scully/src/lib/utils/fsAngular.ts @@ -2,7 +2,7 @@ import { watch } from 'chokidar'; import { copy, remove } from 'fs-extra'; import { join } from 'path'; import { Observable } from 'rxjs'; -import { debounceTime, filter, tap } from 'rxjs/operators'; +import { debounceTime, filter, tap } from 'rxjs'; import { restartStaticServer, startScullyWatchMode } from '../watchMode'; import { baseFilter } from './cli-options'; import { scullyConfig } from './config'; diff --git a/libs/scully/src/lib/utils/fsFolder.ts b/libs/scully/src/lib/utils/fsFolder.ts index ac7f1c23a..516d84ce1 100644 --- a/libs/scully/src/lib/utils/fsFolder.ts +++ b/libs/scully/src/lib/utils/fsFolder.ts @@ -1,7 +1,7 @@ import { existsSync, watch } from 'fs'; import { join } from 'path'; import { Observable } from 'rxjs'; -import { throttleTime } from 'rxjs/operators'; +import { throttleTime } from 'rxjs'; import { startScullyWatchMode } from '../watchMode'; import { scullyConfig } from './config'; import { log, red } from './log'; diff --git a/libs/scully/src/lib/utils/index.ts b/libs/scully/src/lib/utils/index.ts index ec66b94e4..4cb4b3b7f 100644 --- a/libs/scully/src/lib/utils/index.ts +++ b/libs/scully/src/lib/utils/index.ts @@ -26,3 +26,4 @@ export * from './restart'; export * from './routeSplit'; export * from './startup'; export * from './validateConfig'; +export * from './procesmanager' diff --git a/libs/scully/src/lib/utils/interfacesandenums.ts b/libs/scully/src/lib/utils/interfacesandenums.ts index e3c064146..6f6a102dc 100644 --- a/libs/scully/src/lib/utils/interfacesandenums.ts +++ b/libs/scully/src/lib/utils/interfacesandenums.ts @@ -1,4 +1,4 @@ -import { LaunchOptions, ResourceType } from 'puppeteer'; +import { LaunchOptions } from 'puppeteer'; import { LogSeverity } from './log'; export enum RouteTypes { @@ -55,7 +55,7 @@ export interface ScullyConfig { /** the maximum of concurrent puppeteer tabs open. defaults to the available amounts of cores */ maxRenderThreads?: number; /** the resource types to ignore when generating pages via Puppeteer */ - ignoreResourceTypes?: ResourceType[]; + ignoreResourceTypes?: string[]; /** how to handle 404 in Scully server */ handle404?: string; /** specify the project target propery, defaults to 'architect' */ diff --git a/libs/scully/src/lib/utils/log.ts b/libs/scully/src/lib/utils/log.ts index cdcea2a4d..0c86706af 100644 --- a/libs/scully/src/lib/utils/log.ts +++ b/libs/scully/src/lib/utils/log.ts @@ -4,7 +4,7 @@ import { appendFile } from 'fs'; import { join } from 'path'; import * as readline from 'readline'; import { interval } from 'rxjs'; -import { tap } from 'rxjs/operators'; +import { tap } from 'rxjs'; import { captureMessage } from './captureMessage'; import { logSeverity, noLog } from './cli-options'; import { findAngularJsonPath } from './findAngularJsonPath'; diff --git a/libs/scully/src/lib/utils/nodeFsFolder.ts b/libs/scully/src/lib/utils/nodeFsFolder.ts index 7f9fc6971..5a2cb9485 100644 --- a/libs/scully/src/lib/utils/nodeFsFolder.ts +++ b/libs/scully/src/lib/utils/nodeFsFolder.ts @@ -6,7 +6,7 @@ import { existsSync, watch } from 'fs'; import { join } from 'path'; import { Observable } from 'rxjs'; -import { throttleTime } from 'rxjs/operators'; +import { throttleTime } from 'rxjs'; import { log, red } from './log'; // tslint:disable-next-line:no-shadowed-variable diff --git a/libs/scully/src/lib/utils/procesmanager/TaskWorker.ts b/libs/scully/src/lib/utils/procesmanager/TaskWorker.ts new file mode 100644 index 000000000..97cd64f68 --- /dev/null +++ b/libs/scully/src/lib/utils/procesmanager/TaskWorker.ts @@ -0,0 +1,102 @@ +import { ChildProcess, fork } from 'child_process'; +import { existsSync } from 'fs'; +import { join } from 'path'; +import { filter, map, Observable, Subject, take } from 'rxjs'; + + +/** + * taksWorker, starts a script in its own process + */ +export class TaskWorker { + #messages = new Subject(); + /** + * if a worker dies due to error on anything else unexpected 3 times in a row + * it becomes false and can't start a new task anymore. the sub-process is killed + */ + active = true; + ready: Promise | unknown; + #errCount = 0; + #lastTask: string; + /** messages from the sub-process */ + messages$:Observable<{worker:TaskWorker,msg:any}> = this.#messages.pipe( + /** filter out "system" messages, for now its only ready */ + filter((msg) => !(typeof msg === 'string' && ['ready'].includes(msg))), + map((msg) => ({ worker: this, msg })) + ); + #lastSend: { type: string | undefined; msg: any; } = { type: undefined, msg: undefined }; + #worker: ChildProcess = undefined!; + constructor(task: string) { + if (typeof task !== 'string' || !existsSync(task)) { + throw new Error(`Worker task needs to be a string path to an existing JS file, not: ${task}`); + } + this.#init(task); + } + get id() { + return this.#worker !== undefined && this.#worker.pid; + } + + async send(type: string, msg?: any) { + if (!this.active) { + throw new Error(`Trying to send to an inactive job`); + } + // console.log('got',type,msg) + await this.ready; + // console.log('sending to worker') + this.#worker.send([type, msg]); + if (this.#lastSend.type !== type || this.#lastSend.msg !== msg) { + this.#lastSend = { type, msg }; + this.#errCount = 0; + } + } + + #init = (task = this.#lastTask) => { + this.#lastTask = task; + const handleFault = (source: string) => (msg: any) => this.#clean({ source, msg }); + this.active = true; + this.#errCount = 0; + this.#worker = fork(join(task)); + this.ready = this.#messages.pipe(take(1)).toPromise(); + this.#worker.on('message', (msg) => this.#messages.next(msg)); + this.#worker.on('error', handleFault('error')); + this.#worker.on('close', handleFault('close')); + this.#worker.on('disconnect', handleFault('disconnect')); + this.#worker.on('exit', handleFault('exit')); + }; + + async kill() { + if (this.active) { + this.#messages.error(new Error('Task killed by calling TaskWorker.kill()')); + await this.send('kill'); + this.active = false; + this.#worker = undefined!; + } + } + + #debounceClean: NodeJS.Timeout | undefined; + #clean = ({ source, msg }: { source: string; msg: any; }) => { + /** when something happens, it usually doesn't come alone */ + if (this.#debounceClean) { + clearTimeout(this.#debounceClean); + } + /** that why we debounce for 25ms. */ + this.#debounceClean = setTimeout(async () => { + this.#errCount += 1; + try { + /** clean up possible dangling task */ + this.#worker.kill(); + } catch { } + if (this.#errCount > 3) { + console.error(`Can't recover worker, failed 3 times in a row. worker is inactive now`); + this.active = false; + this.#worker = undefined!; + } else if (this.active) { + /** restart and resend last msg */ + this.#init(); + if (this.#lastSend && this.#lastSend.type) { + this.send(this.#lastSend.type, this.#lastSend.msg); + } + } + this.#debounceClean = undefined; + }, 25); + }; +} diff --git a/libs/scully/src/lib/utils/procesmanager/handleJobs.ts b/libs/scully/src/lib/utils/procesmanager/handleJobs.ts new file mode 100644 index 000000000..977d09d09 --- /dev/null +++ b/libs/scully/src/lib/utils/procesmanager/handleJobs.ts @@ -0,0 +1,29 @@ +import { Job } from './job'; +import { TaskWorker } from './TaskWorker'; + + +export async function handleJobs(jobs: Job[], pool: TaskWorker[]) { + // const pool = getPool(scriptFile, poolSize); + let tasks = []; + + /** start max amount of initial jobs */ + const x = Math.min(pool.length, jobs.length); + for (let i = 0; i < x; i += 1) { + jobs[i].startWithWorker(pool[i]); + tasks.push(jobs[i].done.then(() => jobs[i])); + } + + let limit = tasks.length; + while (jobs.some((j) => j.pending)) { + const jobDone = await Promise.race(tasks); + const nextJob = jobs.find((row) => row.pending && !row.started); + if (nextJob) { + nextJob.startWithWorker(jobDone.worker!); + jobDone.worker = undefined; + } + tasks = jobs.filter((row) => row.pending && row.started).map((task) => task.done.then(() => task)); + } + + await Promise.all(tasks); + return Promise.all(jobs.map((j) => j.done)); +} diff --git a/libs/scully/src/lib/utils/procesmanager/index.ts b/libs/scully/src/lib/utils/procesmanager/index.ts new file mode 100644 index 000000000..aa0daaac6 --- /dev/null +++ b/libs/scully/src/lib/utils/procesmanager/index.ts @@ -0,0 +1,6 @@ +export {Job} from './job' +export {handleJobs} from './handleJobs' +export {TaskWorker} from './TaskWorker' +export {startWorkerListener, workerMessages$, addWorkerTask} from './startWorkerListener' +export {getPool} from './taskPool' +export {Tasks} from './tasks.interface' diff --git a/libs/scully/src/lib/utils/procesmanager/job.ts b/libs/scully/src/lib/utils/procesmanager/job.ts new file mode 100644 index 000000000..e57fdacc3 --- /dev/null +++ b/libs/scully/src/lib/utils/procesmanager/job.ts @@ -0,0 +1,45 @@ +import { catchError, filter, map, take, throwError } from 'rxjs'; +import { TaskWorker } from './TaskWorker'; + + +export class Job { + pending = true; + started = false; + allowedTime = .2 * 60 * 1000; + #done: (value: unknown) => void = undefined!; + #fail: (reason?: any) => void = undefined!; + worker: TaskWorker | undefined; + /** default timeout time, job wil fail if not done whitin this time */ + done = new Promise((resolve, reject) => ((this.#done = resolve), (this.#fail = reject))); + constructor(public taskName: string, public taskValue?: any, public trigger?: String) { + this.trigger = this.trigger ?? `${this.taskName}Done`; + } + + startWithWorker(worker: TaskWorker) { + this.started = true; + let cancelTimout; + Promise.race([ + new Promise((_, reject) => { + cancelTimout = setTimeout(() => reject(), this.allowedTime); + }), + worker.messages$ + .pipe( + catchError((e) => (console.log('Error', e), throwError(e))), + filter((m) => (Array.isArray(m.msg) ? m.msg[0] === this.trigger : m.msg === this.trigger)), + map(({ msg }) => msg), + map(([trigger, payload]) => payload), + take(1) + ) + .toPromise() + .catch((e) => console.error(e)), + ]) + .then((r) => this.#done(r)) + .catch((e) => this.#fail(e)); + this.worker = worker; + worker.send(this.taskName, this.taskValue); + this.done.finally(() => { + this.pending = false; + clearTimeout(cancelTimout); + }); + } +} diff --git a/libs/scully/src/lib/utils/procesmanager/startWorkerListener.ts b/libs/scully/src/lib/utils/procesmanager/startWorkerListener.ts new file mode 100644 index 000000000..c364a9f05 --- /dev/null +++ b/libs/scully/src/lib/utils/procesmanager/startWorkerListener.ts @@ -0,0 +1,46 @@ +import { Subject } from 'rxjs'; +import { logError } from '../log'; +import { Tasks } from './tasks.interface'; + +const masterTaskList: Tasks = { + kill: () => process.exit(0), +}; +const workerMessages = new Subject<{ type: string; msg: any }>(); +export const workerMessages$ = workerMessages.asObservable(); + +export const addWorkerTask = (key: string, fn: (...msg: any[]) => any | Promise) => { + if (masterTaskList.hasOwnProperty(key)) { + console.log(`Task ${key} already defined, skipped assignment`); + return; + } + masterTaskList[key] = fn; +}; + +export function startWorkerListener(tasks: Tasks) { + /** check if I'm running in an forked task, will be undefined otherwise */ + if (process.send) { + /** add tasks to master task list. */ + Object.entries(tasks).forEach(([key, task]) => addWorkerTask(key, task)); + + process.on('message', async ([type, msg]: [string, any]) => { + // console.log('got msg',type,msg) + if (masterTaskList.hasOwnProperty(type)) { + try { + const result = await masterTaskList[type](msg); + process.send([`${type}Done`, result]); + } catch (e) { + console.error(e); + process.exit(15); + } + } else { + logError(`No worker task found for ${type}`); + workerMessages.next({ type, msg }); + } + }); + + process.send('ready'); + return; + } + logError('Trying to start a worker process as main'); + process.exit(15); +} diff --git a/libs/scully/src/lib/utils/procesmanager/taskPool.ts b/libs/scully/src/lib/utils/procesmanager/taskPool.ts new file mode 100644 index 000000000..3cf4190c6 --- /dev/null +++ b/libs/scully/src/lib/utils/procesmanager/taskPool.ts @@ -0,0 +1,18 @@ +import { scullyConfig } from '..'; +import { TaskWorker } from './TaskWorker'; + +const taskPools = {} as { + [taskPath: string]: TaskWorker[]; +}; +export function getPool(taskPath: string, poolSize: number = scullyConfig.maxRenderThreads) { + if (!taskPools[taskPath]) { + taskPools[taskPath] = [] as TaskWorker[]; + } + const _pool = taskPools[taskPath]; + while (poolSize > _pool.length) { + _pool.push(new TaskWorker(taskPath)); + } + return _pool; +} + + diff --git a/libs/scully/src/lib/utils/procesmanager/tasks.interface.ts b/libs/scully/src/lib/utils/procesmanager/tasks.interface.ts new file mode 100644 index 000000000..20fe12356 --- /dev/null +++ b/libs/scully/src/lib/utils/procesmanager/tasks.interface.ts @@ -0,0 +1,5 @@ +/** helpers for inside the actual worker */ + +export interface Tasks { + [x: string]: (...msg: any[]) => any | Promise; +} diff --git a/libs/scully/src/lib/utils/startup.ts b/libs/scully/src/lib/utils/startup.ts index e2b17fabc..69e0175ac 100644 --- a/libs/scully/src/lib/utils/startup.ts +++ b/libs/scully/src/lib/utils/startup.ts @@ -128,6 +128,8 @@ function totalPluginTimes(durations: { [x: string]: number }) { } else { t[prop] += dur; } + } else { + t[name] = (t[name] || 0) + dur; } return t; }, {} as { [x: string]: number }); diff --git a/libs/universal/.eslintrc.json b/libs/universal/.eslintrc.json new file mode 100644 index 000000000..7b8a67dda --- /dev/null +++ b/libs/universal/.eslintrc.json @@ -0,0 +1,39 @@ +{ + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nrwl/nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "parserOptions": { + "project": ["libs/universal/tsconfig.*?.json"] + }, + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "scullyio", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "scullyio", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nrwl/nx/angular-template"], + "rules": {} + } + ] +} diff --git a/libs/universal/README.md b/libs/universal/README.md new file mode 100644 index 000000000..92f569abf --- /dev/null +++ b/libs/universal/README.md @@ -0,0 +1,5 @@ +# @scullyio/universal + +Helpers for rendering Angular aps with scully and universal + + diff --git a/libs/universal/jest.config.js b/libs/universal/jest.config.js new file mode 100644 index 000000000..844540641 --- /dev/null +++ b/libs/universal/jest.config.js @@ -0,0 +1,23 @@ +module.exports = { + displayName: 'universal', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + globals: { + 'ts-jest': { + tsConfig: '/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + astTransformers: { + before: [ + 'jest-preset-angular/build/InlineFilesTransformer', + 'jest-preset-angular/build/StripStylesTransformer', + ], + }, + }, + }, + coverageDirectory: '../../coverage/libs/universal', + snapshotSerializers: [ + 'jest-preset-angular/build/AngularNoNgAttributesSnapshotSerializer.js', + 'jest-preset-angular/build/AngularSnapshotSerializer.js', + 'jest-preset-angular/build/HTMLCommentSerializer.js', + ], +}; diff --git a/libs/universal/ng-package.json b/libs/universal/ng-package.json new file mode 100644 index 000000000..2a8f7082e --- /dev/null +++ b/libs/universal/ng-package.json @@ -0,0 +1,12 @@ +{ + "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", + "dest": "../../dist/libs/universal", + "lib": { + "entryFile": "src/index.ts", + "umdModuleIds": { + "@scullyio/scully": "@scullyio/scully", + "@scullyio/ng-lib": "@scullyio/ng-lib", + "crypto": "crypto" + } + } +} diff --git a/libs/universal/package-lock.json b/libs/universal/package-lock.json new file mode 100644 index 000000000..c2c176f82 --- /dev/null +++ b/libs/universal/package-lock.json @@ -0,0 +1,14 @@ +{ + "name": "@scullyio/universal", + "version": "0.0.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/node": { + "version": "14.14.37", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.37.tgz", + "integrity": "sha512-XYmBiy+ohOR4Lh5jE379fV2IU+6Jn4g5qASinhitfyO71b/sCo6MKsMLF5tc7Zf2CE8hViVQyYSobJNke8OvUw==", + "dev": true + } + } +} diff --git a/libs/universal/package.json b/libs/universal/package.json new file mode 100644 index 000000000..7028246c9 --- /dev/null +++ b/libs/universal/package.json @@ -0,0 +1,14 @@ +{ + "name": "@scullyio/universal", + "version": "0.0.1", + "peerDependencies": { + "@angular/common": "^11.2.5", + "@angular/core": "^11.2.5" + }, + "dependencies": { + "tslib": "^2.0.0" + }, + "devDependencies": { + "@types/node": "^14.14.37" + } +} diff --git a/libs/universal/src/index.ts b/libs/universal/src/index.ts new file mode 100644 index 000000000..54c6b3930 --- /dev/null +++ b/libs/universal/src/index.ts @@ -0,0 +1 @@ +export * from './lib/universal.module'; diff --git a/libs/universal/src/lib/ScullyXhr.ts b/libs/universal/src/lib/ScullyXhr.ts new file mode 100644 index 000000000..d3482f7e4 --- /dev/null +++ b/libs/universal/src/lib/ScullyXhr.ts @@ -0,0 +1,118 @@ +import { HttpClient, HttpHandler, HttpHeaders, HttpParams, HttpRequest } from '@angular/common/http'; +import { Injectable, NgZone } from '@angular/core'; +import { workerMessages$ } from '@scullyio/scully'; +import { createHash } from 'crypto'; +import { Observable, of, throwError } from 'rxjs'; +import { catchError, filter, map, mergeMap, take, tap } from 'rxjs'; +const testCache = new Map(); + +interface HttpRequestOptions { + body?: any; + headers?: + | HttpHeaders + | { + [header: string]: string | string[]; + }; + context?: Map; + observe?: 'body' | 'events' | 'response'; + params?: + | HttpParams + | { + [param: string]: string | number | boolean | ReadonlyArray; + }; + reportProgress?: boolean; + responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; + withCredentials?: boolean; +} + +@Injectable() +export class ScullyHttpClient extends HttpClient { + constructor(handler: HttpHandler, private zone: NgZone) { + super(handler); + } + + // @ts-ignore: + request(first: string | HttpRequest, url?: string, options: HttpRequestOptions = {}) { + let method: string = first as string; + const simple = typeof first === 'string'; + /** extract the values we need to create an caching Id */ + if (first instanceof HttpRequest) { + url = first.url; + options.headers = first.headers; + method = first.method; + } + if (!(options.headers instanceof HttpHeaders)) { + options.headers = new HttpHeaders(options.headers); + } + const headerString = + options.headers.keys().reduce((s, key) => { + const val = options.headers!.getAll ?? key; + s += key; + s += ':'; + /** its ok to add undefined or null in the id string */ + s += Array.isArray(val) ? val.join(', ') : val; + return s; + }, '') || 'No headers'; + const id = createKey(url!, headerString, method.toLowerCase()); + // @ts-ignore + const resp: Observable = simple ? super.request(first, url, options) : super.request(first); + + return cacheHas(id, this.zone).pipe( + take(1), + mergeMap((result) => + result !== false ? of(result) : resp.pipe(tap((response) => process.send!(['cacheSet', { id, response }]))) + ), + // tap((p) => console.log('progr', p)), + catchError((e) => { + console.log(e); + return throwError(e); + }) + ); + } +} + +function createKey(...args: string[]) { + const hash = createHash('md5'); + args.forEach((part) => hash.update(part)); + return hash.digest('hex'); +} + +declare var Zone: any; + +function cacheHas(id: string, zone: any) { + return new Observable((obs) => { + const tsk = Zone.current.scheduleMacroTask( + 'Scully.XMLHttpRequest', + (r: any) => { + obs.next(r); + }, + { id }, + (task: any) => { + task.data.sub = workerMessages$ + .pipe( + filter(({ type }) => type === 'cacheResult'), + map(({ msg }) => msg), + take(1) + ) + .subscribe({ + next(r) { + task.invoke(r); + }, + complete() { + obs.complete(); + }, + error(e) { + obs.error(e); + }, + }); + process.send!(['cacheHas', task.data.id]); + }, + (task: any) => task.data.sub.unsubscribe() + ); + return () => { + if (tsk && tsk.data && tsk.data.sub) { + tsk.data.sub.unsubscribe() + } + } + }); +} diff --git a/libs/universal/src/lib/universal.module.ts b/libs/universal/src/lib/universal.module.ts new file mode 100644 index 000000000..95394115e --- /dev/null +++ b/libs/universal/src/lib/universal.module.ts @@ -0,0 +1,29 @@ +import { DOCUMENT } from '@angular/common'; +import { HttpClient } from '@angular/common/http'; +import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { BEFORE_APP_SERIALIZED, ServerModule } from '@angular/platform-server'; +import { IdleMonitorService } from '@scullyio/ng-lib'; +import { ScullyHttpClient } from './ScullyXhr'; +import { domContentLoadedFactory } from './unversalWorker'; + +@NgModule({ + imports: [ServerModule], + providers: [ + // { provide: HttpClient, useClass: ScullyHttpClient }, + { provide: APP_INITIALIZER, multi: true, useFactory: domContentLoadedFactory, deps: [DOCUMENT] }, + + { + provide: BEFORE_APP_SERIALIZED, + useFactory: (i: IdleMonitorService) => () => i.init(), + deps: [IdleMonitorService], + multi: true, + }, + ], +}) +export class ScullyUniversalModule { + constructor() { + if (!process.version) { + console.warn('the ScullyUniversalModule seems to be loaded in a browsers context. This might lead to unpredictable results') + } + } +} diff --git a/libs/universal/src/lib/unversalWorker.ts b/libs/universal/src/lib/unversalWorker.ts new file mode 100644 index 000000000..f6dc11f98 --- /dev/null +++ b/libs/universal/src/lib/unversalWorker.ts @@ -0,0 +1,50 @@ +import { DOCUMENT } from '@angular/common'; +import { ResourceLoader } from '@angular/compiler'; +import { APP_INITIALIZER, Compiler, CompilerFactory, NgModuleFactory, StaticProvider, Type } from '@angular/core'; +import { platformDynamicServer, renderModuleFactory } from '@angular/platform-server'; +import { readFile } from 'fs'; + +export function domContentLoadedFactory(doc: Document): () => Promise { + return () => + new Promise((resolve, _reject) => { + if (doc.readyState === 'complete' || doc.readyState === 'interactive') { + resolve(); + + return; + } + + const contentLoaded = () => { + doc.removeEventListener('DOMContentLoaded', contentLoaded); + resolve(); + }; + + doc.addEventListener('DOMContentLoaded', contentLoaded); + }); +} + +const factoryCacheMap = new Map, NgModuleFactory<{}>>(); +export async function getFactory(moduleOrFactory: Type<{}> | NgModuleFactory<{}>): Promise> { + // If module has been compiled AoT + if (moduleOrFactory instanceof NgModuleFactory) { + return moduleOrFactory; + } else { + // we're in JIT mode + if (!factoryCacheMap.has(moduleOrFactory)) { + // Compile the module and cache it + const module = await getCompiler().compileModuleAsync(moduleOrFactory).catch(e => { console.log(e); process.exit(15) }) + factoryCacheMap.set(moduleOrFactory, module); + } + return factoryCacheMap.get(moduleOrFactory); + } +} + +export function getCompiler(): Compiler { + const compilerFactory: CompilerFactory = platformDynamicServer().injector.get(CompilerFactory); + return compilerFactory.createCompiler([{ providers: [{ provide: ResourceLoader, useClass: FileLoader, deps: [] }] }]); +} + +export class FileLoader implements ResourceLoader { + get(url: string): Promise { + return new Promise((resolve, reject) => readFile(url, { encoding: 'utf-8' }, (err, data) => err ? reject(err) : resolve(data))); + } +} diff --git a/libs/universal/src/test-setup.ts b/libs/universal/src/test-setup.ts new file mode 100644 index 000000000..8d88704e8 --- /dev/null +++ b/libs/universal/src/test-setup.ts @@ -0,0 +1 @@ +import 'jest-preset-angular'; diff --git a/libs/universal/tsconfig.json b/libs/universal/tsconfig.json new file mode 100644 index 000000000..0bcf008a0 --- /dev/null +++ b/libs/universal/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.lib.prod.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/libs/universal/tsconfig.lib.json b/libs/universal/tsconfig.lib.json new file mode 100644 index 000000000..53846c5dc --- /dev/null +++ b/libs/universal/tsconfig.lib.json @@ -0,0 +1,21 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "allowJs": true, + "allowSyntheticDefaultImports": true, + "experimentalDecorators": true, + "types": ["node"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": false, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts"], + "include": ["**/*.ts"] +} diff --git a/libs/universal/tsconfig.lib.prod.json b/libs/universal/tsconfig.lib.prod.json new file mode 100644 index 000000000..61c7592e7 --- /dev/null +++ b/libs/universal/tsconfig.lib.prod.json @@ -0,0 +1,10 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "extends": "./tsconfig.lib.json", + "compilerOptions": { + "declarationMap": false + }, + "angularCompilerOptions": { + "enableIvy": true + } +} diff --git a/libs/universal/tsconfig.spec.json b/libs/universal/tsconfig.spec.json new file mode 100644 index 000000000..cfff29a54 --- /dev/null +++ b/libs/universal/tsconfig.spec.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts"] +} diff --git a/nx.json b/nx.json index 26c7e66a9..0835f8f4e 100644 --- a/nx.json +++ b/nx.json @@ -67,6 +67,16 @@ "scully": { "tags": [] }, + "universal-sample": { + "tags": [] + }, + "universal-sample-e2e": { + "tags": [], + "implicitDependencies": ["universal-sample"] + }, + "universal": { + "tags": [] + }, "scully-docs": { "tags": [] }, diff --git a/package-lock.json b/package-lock.json index eb75b18e4..06fee1d8e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1130,6 +1130,16 @@ "tslib": "^2.2.0" } }, + "@angular/platform-server": { + "version": "12.2.10", + "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-12.2.10.tgz", + "integrity": "sha512-g2m2/+e+6mxbvMYICe+1zDP/KGMwmf9gu/fz+I9UFpGuAx4S7eBL/GCII2gnrrbavZ2vxczY0Ff4JU7AEBrGug==", + "requires": { + "domino": "^2.1.2", + "tslib": "^2.2.0", + "xhr2": "^0.2.0" + } + }, "@angular/router": { "version": "12.2.6", "resolved": "https://registry.npmjs.org/@angular/router/-/router-12.2.6.tgz", @@ -6319,6 +6329,42 @@ "yargs-parser": "20.0.0" }, "dependencies": { + "@nrwl/workspace": { + "version": "12.9.0", + "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-12.9.0.tgz", + "integrity": "sha512-P8jab7DebwU1fMnpA9A+7oBXNLxVYPqdGPIusOsvpRaJ9tjzhXhVM4OCYu3ZnmcpHboskmSwUMcIvOARRcwWLg==", + "dev": true, + "requires": { + "@nrwl/cli": "12.9.0", + "@nrwl/devkit": "12.9.0", + "@nrwl/jest": "12.9.0", + "@nrwl/linter": "12.9.0", + "chalk": "4.1.0", + "chokidar": "^3.5.1", + "cosmiconfig": "^4.0.0", + "dotenv": "~10.0.0", + "enquirer": "~2.3.6", + "flat": "^5.0.2", + "fs-extra": "^9.1.0", + "glob": "7.1.4", + "ignore": "^5.0.4", + "minimatch": "3.0.4", + "npm-run-all": "^4.1.5", + "open": "^7.4.2", + "rxjs": "^6.5.4", + "semver": "7.3.4", + "tmp": "~0.2.1", + "tslib": "^2.0.0", + "yargs": "15.4.1", + "yargs-parser": "20.0.0" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, "chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -6329,6 +6375,125 @@ "supports-color": "^7.1.0" } }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "cosmiconfig": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz", + "integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==", + "dev": true, + "requires": { + "is-directory": "^0.3.1", + "js-yaml": "^3.9.0", + "parse-json": "^4.0.0", + "require-from-string": "^2.0.1" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "dev": true, + "requires": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, "rxjs": { "version": "6.6.7", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", @@ -6346,6 +6511,86 @@ } } }, + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "requires": { + "rimraf": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "dependencies": { + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, "yargs-parser": { "version": "20.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.0.0.tgz", @@ -6410,6 +6655,47 @@ "tsconfig-paths": "^3.9.0" }, "dependencies": { + "@nrwl/workspace": { + "version": "12.9.0", + "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-12.9.0.tgz", + "integrity": "sha512-P8jab7DebwU1fMnpA9A+7oBXNLxVYPqdGPIusOsvpRaJ9tjzhXhVM4OCYu3ZnmcpHboskmSwUMcIvOARRcwWLg==", + "dev": true, + "requires": { + "@nrwl/cli": "12.9.0", + "@nrwl/devkit": "12.9.0", + "@nrwl/jest": "12.9.0", + "@nrwl/linter": "12.9.0", + "chalk": "4.1.0", + "chokidar": "^3.5.1", + "cosmiconfig": "^4.0.0", + "dotenv": "~10.0.0", + "enquirer": "~2.3.6", + "flat": "^5.0.2", + "fs-extra": "^9.1.0", + "glob": "7.1.4", + "ignore": "^5.0.4", + "minimatch": "3.0.4", + "npm-run-all": "^4.1.5", + "open": "^7.4.2", + "rxjs": "^6.5.4", + "semver": "7.3.4", + "tmp": "~0.2.1", + "tslib": "^2.0.0", + "yargs": "15.4.1", + "yargs-parser": "20.0.0" + }, + "dependencies": { + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, "@typescript-eslint/experimental-utils": { "version": "4.28.5", "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.5.tgz", @@ -6465,6 +6751,45 @@ "eslint-visitor-keys": "^2.0.0" } }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "cosmiconfig": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz", + "integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==", + "dev": true, + "requires": { + "is-directory": "^0.3.1", + "js-yaml": "^3.9.0", + "parse-json": "^4.0.0", + "require-from-string": "^2.0.1" + } + }, "eslint-utils": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", @@ -6474,95 +6799,16 @@ "eslint-visitor-keys": "^2.0.0" } }, - "ts-node": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", - "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", - "dev": true, - "requires": { - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "source-map-support": "^0.5.17", - "yn": "3.1.1" - } - } - } - }, - "@nrwl/express": { - "version": "12.9.0", - "resolved": "https://registry.npmjs.org/@nrwl/express/-/express-12.9.0.tgz", - "integrity": "sha512-idACvnMwoAWjKMoEzDfrJfij1hWzqqwxTgGmMR9KitEoRPnAUdCzk4iR13u5YNHqOGhdgVRKAhvlOt2knYYzhA==", - "dev": true, - "requires": { - "@nrwl/devkit": "12.9.0", - "@nrwl/jest": "12.9.0", - "@nrwl/node": "12.9.0", - "@nrwl/workspace": "12.9.0" - } - }, - "@nrwl/jest": { - "version": "12.9.0", - "resolved": "https://registry.npmjs.org/@nrwl/jest/-/jest-12.9.0.tgz", - "integrity": "sha512-PHPG6DlwNgrT4+uplJqM814k+gqNV/m85FIes6JkzRO8XMK9jmqF0hwJvyymCZHDmGXMqwa0muoxkjoJs2CI/A==", - "dev": true, - "requires": { - "@jest/reporters": "27.0.6", - "@jest/test-result": "27.0.6", - "@nrwl/devkit": "12.9.0", - "chalk": "4.1.0", - "identity-obj-proxy": "3.0.0", - "jest-config": "27.0.6", - "jest-resolve": "27.0.6", - "jest-util": "27.0.6", - "rxjs": "^6.5.4", - "tslib": "^2.0.0" - }, - "dependencies": { - "chalk": { + "find-up": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - } - } - }, - "@nrwl/linter": { - "version": "12.9.0", - "resolved": "https://registry.npmjs.org/@nrwl/linter/-/linter-12.9.0.tgz", - "integrity": "sha512-8acZTT0nkwi914uJ6fMhZT6fZMMKOUGGjEWhvw9D3Lhe0aACsnXXSB+hJh+E8qchcGMYliqXuSi3X4Liq/fUFw==", - "dev": true, - "requires": { - "@nrwl/devkit": "12.9.0", - "@nrwl/jest": "12.9.0", - "glob": "7.1.4", - "minimatch": "3.0.4", - "tmp": "~0.2.1", - "tslib": "^2.0.0" - }, - "dependencies": { "glob": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", @@ -6577,346 +6823,277 @@ "path-is-absolute": "^1.0.0" } }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "requires": { - "glob": "^7.1.3" + "argparse": "^1.0.7", + "esprima": "^4.0.0" } }, - "tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "requires": { - "rimraf": "^3.0.0" + "p-locate": "^4.1.0" } - } - } - }, - "@nrwl/node": { - "version": "12.9.0", - "resolved": "https://registry.npmjs.org/@nrwl/node/-/node-12.9.0.tgz", - "integrity": "sha512-AluoSQVMKMCPMvlPZbBxTNlVQTx6/nFOZZMOYCrNLWgWuyfX29jrghCw3WSDAW41B9+ruhxPLxzmER/T58FfuQ==", - "dev": true, - "requires": { - "@nrwl/devkit": "12.9.0", - "@nrwl/jest": "12.9.0", - "@nrwl/linter": "12.9.0", - "@nrwl/workspace": "12.9.0", - "chalk": "4.1.0", - "circular-dependency-plugin": "5.2.0", - "copy-webpack-plugin": "6.4.1", - "fork-ts-checker-webpack-plugin": "6.2.10", - "fs-extra": "^9.1.0", - "glob": "7.1.4", - "license-webpack-plugin": "2.3.15", - "rxjs": "^6.5.4", - "rxjs-for-await": "0.0.2", - "source-map-support": "0.5.19", - "tree-kill": "1.2.2", - "ts-loader": "5.4.5", - "tsconfig-paths-webpack-plugin": "3.4.1", - "tslib": "^2.0.0", - "webpack": "4.46.0", - "webpack-merge": "4.2.1", - "webpack-node-externals": "1.7.2" - }, - "dependencies": { - "@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", - "dev": true }, - "@webassemblyjs/ast": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", - "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", "dev": true, "requires": { - "@webassemblyjs/helper-module-context": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0" + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" } }, - "@webassemblyjs/helper-api-error": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", - "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", - "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", - "dev": true - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", - "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", - "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0" + "p-try": "^2.0.0" } }, - "@webassemblyjs/ieee754": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", - "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "requires": { - "@xtuc/ieee754": "^1.2.0" + "p-limit": "^2.2.0" } }, - "@webassemblyjs/leb128": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", - "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "dev": true, "requires": { - "@xtuc/long": "4.2.2" + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" } }, - "@webassemblyjs/utf8": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", - "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", - "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/helper-wasm-section": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0", - "@webassemblyjs/wasm-opt": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0", - "@webassemblyjs/wast-printer": "1.9.0" + "glob": "^7.1.3" } }, - "@webassemblyjs/wasm-gen": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", - "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/ieee754": "1.9.0", - "@webassemblyjs/leb128": "1.9.0", - "@webassemblyjs/utf8": "1.9.0" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", - "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0" + "tslib": "^1.9.0" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } } }, - "@webassemblyjs/wasm-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", - "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-api-error": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/ieee754": "1.9.0", - "@webassemblyjs/leb128": "1.9.0", - "@webassemblyjs/utf8": "1.9.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" } }, - "@webassemblyjs/wast-printer": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", - "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0", - "@xtuc/long": "4.2.2" + "ansi-regex": "^5.0.1" } }, - "acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", - "dev": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", "dev": true, "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "rimraf": "^3.0.0" } }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "ts-node": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", + "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" } }, - "circular-dependency-plugin": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/circular-dependency-plugin/-/circular-dependency-plugin-5.2.0.tgz", - "integrity": "sha512-7p4Kn/gffhQaavNfyDFg7LS5S/UT1JAjyGd4UqR2+jzoYF02eDkj0Ec3+48TsIa4zghjLY87nQHIh/ecK9qLdw==", - "dev": true - }, - "copy-webpack-plugin": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.4.1.tgz", - "integrity": "sha512-MXyPCjdPVx5iiWyl40Va3JGh27bKzOTNY3NjUTrosD2q7dR/cLD0013uqJ3BpFbUjyONINjb6qI7nDIJujrMbA==", + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, "requires": { - "cacache": "^15.0.5", - "fast-glob": "^3.2.4", - "find-cache-dir": "^3.3.1", - "glob-parent": "^5.1.1", - "globby": "^11.0.1", - "loader-utils": "^2.0.0", - "normalize-path": "^3.0.0", - "p-limit": "^3.0.2", - "schema-utils": "^3.0.0", - "serialize-javascript": "^5.0.1", - "webpack-sources": "^1.4.3" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" } }, - "enhanced-resolve": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", - "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.5.0", - "tapable": "^1.0.0" + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" }, "dependencies": { - "memory-fs": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", - "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } }, - "errno": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", - "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", - "dev": true, - "requires": { - "prr": "~1.0.1" + "yargs-parser": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.0.0.tgz", + "integrity": "sha512-8eblPHTL7ZWRkyjIZJjnGf+TijiKJSwA24svzLRVvtgoi/RZiKa9fFQTrlx0OKLnyHSdt/enrdadji6WFfESVA==", + "dev": true + } + } + }, + "@nrwl/express": { + "version": "12.9.0", + "resolved": "https://registry.npmjs.org/@nrwl/express/-/express-12.9.0.tgz", + "integrity": "sha512-idACvnMwoAWjKMoEzDfrJfij1hWzqqwxTgGmMR9KitEoRPnAUdCzk4iR13u5YNHqOGhdgVRKAhvlOt2knYYzhA==", + "dev": true, + "requires": { + "@nrwl/devkit": "12.9.0", + "@nrwl/jest": "12.9.0", + "@nrwl/node": "12.9.0", + "@nrwl/workspace": "12.9.0" + }, + "dependencies": { + "@nrwl/workspace": { + "version": "12.9.0", + "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-12.9.0.tgz", + "integrity": "sha512-P8jab7DebwU1fMnpA9A+7oBXNLxVYPqdGPIusOsvpRaJ9tjzhXhVM4OCYu3ZnmcpHboskmSwUMcIvOARRcwWLg==", + "dev": true, + "requires": { + "@nrwl/cli": "12.9.0", + "@nrwl/devkit": "12.9.0", + "@nrwl/jest": "12.9.0", + "@nrwl/linter": "12.9.0", + "chalk": "4.1.0", + "chokidar": "^3.5.1", + "cosmiconfig": "^4.0.0", + "dotenv": "~10.0.0", + "enquirer": "~2.3.6", + "flat": "^5.0.2", + "fs-extra": "^9.1.0", + "glob": "7.1.4", + "ignore": "^5.0.4", + "minimatch": "3.0.4", + "npm-run-all": "^4.1.5", + "open": "^7.4.2", + "rxjs": "^6.5.4", + "semver": "7.3.4", + "tmp": "~0.2.1", + "tslib": "^2.0.0", + "yargs": "15.4.1", + "yargs-parser": "20.0.0" } }, - "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", "dev": true, "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" } }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "cosmiconfig": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz", + "integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==", "dev": true, "requires": { - "locate-path": "^3.0.0" + "is-directory": "^0.3.1", + "js-yaml": "^3.9.0", + "parse-json": "^4.0.0", + "require-from-string": "^2.0.1" } }, - "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, "glob": { @@ -6933,177 +7110,76 @@ "path-is-absolute": "^1.0.0" } }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-number": { + "is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "license-webpack-plugin": { - "version": "2.3.15", - "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-2.3.15.tgz", - "integrity": "sha512-reA0yvwvkkFMRsyqVikTcLGFXmgWKPVXrFaR3tRvAnFoZozM4zvwlNNQxuB5Il6fgTtS7nGkrIPm9xS2KZtu7g==", + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "requires": { - "@types/webpack-sources": "^0.1.5", - "webpack-sources": "^1.2.0" + "argparse": "^1.0.7", + "esprima": "^4.0.0" } }, - "loader-runner": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", - "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", - "dev": true - }, "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "requires": { - "yallist": "^3.0.2" + "p-locate": "^4.1.0" } }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", "dev": true, "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" } }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "p-try": "^2.0.0" } }, "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "requires": { - "p-limit": "^2.0.0" - }, - "dependencies": { - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - } + "p-limit": "^2.2.0" } }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "dev": true, "requires": { - "find-up": "^3.0.0" + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" } }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "glob": "^7.1.3" } }, "rxjs": { @@ -7123,373 +7199,167 @@ } } }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", "dev": true, "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" + "lru-cache": "^6.0.0" } }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "requires": { - "randombytes": "^2.1.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" } }, - "ssri": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", - "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "figgy-pudding": "^3.5.1" + "ansi-regex": "^5.0.1" } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "rimraf": "^3.0.0" } }, - "tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "dev": true - }, - "terser": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", - "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, "requires": { - "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" } }, - "terser-webpack-plugin": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", - "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, "requires": { - "cacache": "^12.0.2", - "find-cache-dir": "^2.1.0", - "is-wsl": "^1.1.0", - "schema-utils": "^1.0.0", - "serialize-javascript": "^4.0.0", - "source-map": "^0.6.1", - "terser": "^4.1.2", - "webpack-sources": "^1.4.0", - "worker-farm": "^1.7.0" - }, - "dependencies": { - "cacache": { - "version": "12.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", - "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", - "dev": true, - "requires": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", - "figgy-pudding": "^3.5.1", - "glob": "^7.1.4", - "graceful-fs": "^4.1.15", - "infer-owner": "^1.0.3", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" - } - }, - "find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - } - }, - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - }, - "serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - } - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - }, - "watchpack": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", - "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", - "dev": true, - "requires": { - "chokidar": "^3.4.1", - "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0", - "watchpack-chokidar2": "^2.0.1" - } - }, - "webpack": { - "version": "4.46.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", - "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-module-context": "1.9.0", - "@webassemblyjs/wasm-edit": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0", - "acorn": "^6.4.1", - "ajv": "^6.10.2", - "ajv-keywords": "^3.4.1", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^4.5.0", - "eslint-scope": "^4.0.3", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^2.4.0", - "loader-utils": "^1.2.3", - "memory-fs": "^0.4.1", - "micromatch": "^3.1.10", - "mkdirp": "^0.5.3", - "neo-async": "^2.6.1", - "node-libs-browser": "^2.2.1", - "schema-utils": "^1.0.0", - "tapable": "^1.1.3", - "terser-webpack-plugin": "^1.4.3", - "watchpack": "^1.7.4", - "webpack-sources": "^1.4.1" + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" }, "dependencies": { - "loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - } - }, - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } }, - "webpack-merge": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.1.tgz", - "integrity": "sha512-4p8WQyS98bUJcCvFMbdGZyZmsKuWjWVnVHnAS3FFg0HDaRVrPbkivx2RYCre8UiemD67RsiFFLfn4JhLAin8Vw==", - "dev": true, - "requires": { - "lodash": "^4.17.5" - } - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "yargs-parser": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.0.0.tgz", + "integrity": "sha512-8eblPHTL7ZWRkyjIZJjnGf+TijiKJSwA24svzLRVvtgoi/RZiKa9fFQTrlx0OKLnyHSdt/enrdadji6WFfESVA==", "dev": true } } }, - "@nrwl/nx-cloud": { - "version": "12.3.10", - "resolved": "https://registry.npmjs.org/@nrwl/nx-cloud/-/nx-cloud-12.3.10.tgz", - "integrity": "sha512-5ZychlcrcDrPEdpPOsH1/UcakunK9PzhgCQmrFA+fHXRxzRbLE4K/Mz8dyIs+1aloXhMoYPncHsnRRwxyLhjXQ==", + "@nrwl/jest": { + "version": "12.9.0", + "resolved": "https://registry.npmjs.org/@nrwl/jest/-/jest-12.9.0.tgz", + "integrity": "sha512-PHPG6DlwNgrT4+uplJqM814k+gqNV/m85FIes6JkzRO8XMK9jmqF0hwJvyymCZHDmGXMqwa0muoxkjoJs2CI/A==", + "dev": true, "requires": { - "axios": "^0.21.1", + "@jest/reporters": "27.0.6", + "@jest/test-result": "27.0.6", + "@nrwl/devkit": "12.9.0", "chalk": "4.1.0", - "node-machine-id": "^1.1.12", - "rxjs": "6.5.5", - "strip-json-comments": "^3.1.1", - "tar": "5.0.7" + "identity-obj-proxy": "3.0.0", + "jest-config": "27.0.6", + "jest-resolve": "27.0.6", + "jest-util": "27.0.6", + "rxjs": "^6.5.4", + "tslib": "^2.0.0" }, "dependencies": { "chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "rxjs": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz", - "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==", + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, "requires": { "tslib": "^1.9.0" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" } } }, - "@nrwl/storybook": { + "@nrwl/linter": { "version": "12.9.0", - "resolved": "https://registry.npmjs.org/@nrwl/storybook/-/storybook-12.9.0.tgz", - "integrity": "sha512-J6hAfPVh3WK97qvs7vI2xTYx2Afn3hxFkew19Z4HQeJjsKpJ0xVz9OFPVmWnAmL9A3NpYzfIvE7aRwNAKlA8oQ==", + "resolved": "https://registry.npmjs.org/@nrwl/linter/-/linter-12.9.0.tgz", + "integrity": "sha512-8acZTT0nkwi914uJ6fMhZT6fZMMKOUGGjEWhvw9D3Lhe0aACsnXXSB+hJh+E8qchcGMYliqXuSi3X4Liq/fUFw==", "dev": true, "requires": { - "@nrwl/cypress": "12.9.0", "@nrwl/devkit": "12.9.0", - "@nrwl/linter": "12.9.0", - "@nrwl/workspace": "12.9.0", - "core-js": "^3.6.5", - "semver": "7.3.4", - "ts-loader": "5.4.5", - "tsconfig-paths-webpack-plugin": "3.4.1" + "@nrwl/jest": "12.9.0", + "glob": "7.1.4", + "minimatch": "3.0.4", + "tmp": "~0.2.1", + "tslib": "^2.0.0" }, "dependencies": { - "semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", "dev": true, "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "@nrwl/tao": { - "version": "12.9.0", - "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-12.9.0.tgz", - "integrity": "sha512-a97JYoLohhBRthnWAGMh3++8Ri/yvCQUG/INBAYxW6sWAk2owJ6DIEIERP4yhIW29HPdqZ/fA2k9iqU6EgIAew==", - "dev": true, - "requires": { - "chalk": "4.1.0", - "enquirer": "~2.3.6", - "fs-extra": "^9.1.0", - "jsonc-parser": "3.0.0", - "nx": "12.9.0", - "rxjs": "^6.5.4", - "rxjs-for-await": "0.0.2", - "semver": "7.3.4", - "tmp": "~0.2.1", - "tslib": "^2.0.0", - "yargs-parser": "20.0.0" - }, - "dependencies": { - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "nx": { - "version": "12.9.0", - "resolved": "https://registry.npmjs.org/nx/-/nx-12.9.0.tgz", - "integrity": "sha512-AOyMJPpioeMtY1UJ2Zgxyjfsc6rg31uztqiCZIQEOLwXoYIYiPuz54IhTngW7c1MjtxDl8B62G8xCjlRv2zjhw==", - "dev": true, - "requires": { - "@nrwl/cli": "*" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "rimraf": { @@ -7501,32 +7371,6 @@ "glob": "^7.1.3" } }, - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, "tmp": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", @@ -7535,132 +7379,2918 @@ "requires": { "rimraf": "^3.0.0" } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - }, - "yargs-parser": { - "version": "20.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.0.0.tgz", - "integrity": "sha512-8eblPHTL7ZWRkyjIZJjnGf+TijiKJSwA24svzLRVvtgoi/RZiKa9fFQTrlx0OKLnyHSdt/enrdadji6WFfESVA==", - "dev": true } } }, - "@nrwl/workspace": { + "@nrwl/node": { "version": "12.9.0", - "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-12.9.0.tgz", - "integrity": "sha512-P8jab7DebwU1fMnpA9A+7oBXNLxVYPqdGPIusOsvpRaJ9tjzhXhVM4OCYu3ZnmcpHboskmSwUMcIvOARRcwWLg==", + "resolved": "https://registry.npmjs.org/@nrwl/node/-/node-12.9.0.tgz", + "integrity": "sha512-AluoSQVMKMCPMvlPZbBxTNlVQTx6/nFOZZMOYCrNLWgWuyfX29jrghCw3WSDAW41B9+ruhxPLxzmER/T58FfuQ==", "dev": true, "requires": { - "@nrwl/cli": "12.9.0", "@nrwl/devkit": "12.9.0", "@nrwl/jest": "12.9.0", "@nrwl/linter": "12.9.0", + "@nrwl/workspace": "12.9.0", "chalk": "4.1.0", - "chokidar": "^3.5.1", - "cosmiconfig": "^4.0.0", - "dotenv": "~10.0.0", - "enquirer": "~2.3.6", - "flat": "^5.0.2", + "circular-dependency-plugin": "5.2.0", + "copy-webpack-plugin": "6.4.1", + "fork-ts-checker-webpack-plugin": "6.2.10", "fs-extra": "^9.1.0", "glob": "7.1.4", - "ignore": "^5.0.4", - "minimatch": "3.0.4", - "npm-run-all": "^4.1.5", - "open": "^7.4.2", + "license-webpack-plugin": "2.3.15", "rxjs": "^6.5.4", - "semver": "7.3.4", - "tmp": "~0.2.1", + "rxjs-for-await": "0.0.2", + "source-map-support": "0.5.19", + "tree-kill": "1.2.2", + "ts-loader": "5.4.5", + "tsconfig-paths-webpack-plugin": "3.4.1", "tslib": "^2.0.0", - "yargs": "15.4.1", - "yargs-parser": "20.0.0" + "webpack": "4.46.0", + "webpack-merge": "4.2.1", + "webpack-node-externals": "1.7.2" }, "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "@nrwl/workspace": { + "version": "12.9.0", + "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-12.9.0.tgz", + "integrity": "sha512-P8jab7DebwU1fMnpA9A+7oBXNLxVYPqdGPIusOsvpRaJ9tjzhXhVM4OCYu3ZnmcpHboskmSwUMcIvOARRcwWLg==", + "dev": true, + "requires": { + "@nrwl/cli": "12.9.0", + "@nrwl/devkit": "12.9.0", + "@nrwl/jest": "12.9.0", + "@nrwl/linter": "12.9.0", + "chalk": "4.1.0", + "chokidar": "^3.5.1", + "cosmiconfig": "^4.0.0", + "dotenv": "~10.0.0", + "enquirer": "~2.3.6", + "flat": "^5.0.2", + "fs-extra": "^9.1.0", + "glob": "7.1.4", + "ignore": "^5.0.4", + "minimatch": "3.0.4", + "npm-run-all": "^4.1.5", + "open": "^7.4.2", + "rxjs": "^6.5.4", + "semver": "7.3.4", + "tmp": "~0.2.1", + "tslib": "^2.0.0", + "yargs": "15.4.1", + "yargs-parser": "20.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "@types/json-schema": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", "dev": true }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" } }, - "cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", "dev": true, "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" } }, - "cosmiconfig": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz", - "integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==", + "@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", "dev": true, "requires": { - "is-directory": "^0.3.1", - "js-yaml": "^3.9.0", - "parse-json": "^4.0.0", - "require-from-string": "^2.0.1" + "@xtuc/ieee754": "^1.2.0" } }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "circular-dependency-plugin": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/circular-dependency-plugin/-/circular-dependency-plugin-5.2.0.tgz", + "integrity": "sha512-7p4Kn/gffhQaavNfyDFg7LS5S/UT1JAjyGd4UqR2+jzoYF02eDkj0Ec3+48TsIa4zghjLY87nQHIh/ecK9qLdw==", + "dev": true + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "copy-webpack-plugin": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.4.1.tgz", + "integrity": "sha512-MXyPCjdPVx5iiWyl40Va3JGh27bKzOTNY3NjUTrosD2q7dR/cLD0013uqJ3BpFbUjyONINjb6qI7nDIJujrMbA==", + "dev": true, + "requires": { + "cacache": "^15.0.5", + "fast-glob": "^3.2.4", + "find-cache-dir": "^3.3.1", + "glob-parent": "^5.1.1", + "globby": "^11.0.1", + "loader-utils": "^2.0.0", + "normalize-path": "^3.0.0", + "p-limit": "^3.0.2", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1", + "webpack-sources": "^1.4.3" + } + }, + "cosmiconfig": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz", + "integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==", + "dev": true, + "requires": { + "is-directory": "^0.3.1", + "js-yaml": "^3.9.0", + "parse-json": "^4.0.0", + "require-from-string": "^2.0.1" + } + }, + "enhanced-resolve": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", + "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + } + } + }, + "errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "requires": { + "prr": "~1.0.1" + } + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "license-webpack-plugin": { + "version": "2.3.15", + "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-2.3.15.tgz", + "integrity": "sha512-reA0yvwvkkFMRsyqVikTcLGFXmgWKPVXrFaR3tRvAnFoZozM4zvwlNNQxuB5Il6fgTtS7nGkrIPm9xS2KZtu7g==", + "dev": true, + "requires": { + "@types/webpack-sources": "^0.1.5", + "webpack-sources": "^1.2.0" + } + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "dev": true, + "requires": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "dependencies": { + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } + } + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + }, + "dependencies": { + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + } + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true + }, + "terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + }, + "terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + } + } + }, + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "requires": { + "rimraf": "^3.0.0" + }, + "dependencies": { + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + }, + "watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "dev": true, + "requires": { + "chokidar": "^3.4.1", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.1" + } + }, + "webpack": { + "version": "4.46.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", + "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.5.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "webpack-merge": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.1.tgz", + "integrity": "sha512-4p8WQyS98bUJcCvFMbdGZyZmsKuWjWVnVHnAS3FFg0HDaRVrPbkivx2RYCre8UiemD67RsiFFLfn4JhLAin8Vw==", + "dev": true, + "requires": { + "lodash": "^4.17.5" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "yargs-parser": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.0.0.tgz", + "integrity": "sha512-8eblPHTL7ZWRkyjIZJjnGf+TijiKJSwA24svzLRVvtgoi/RZiKa9fFQTrlx0OKLnyHSdt/enrdadji6WFfESVA==", + "dev": true + } + } + }, + "@nrwl/nx-cloud": { + "version": "12.3.13", + "resolved": "https://registry.npmjs.org/@nrwl/nx-cloud/-/nx-cloud-12.3.13.tgz", + "integrity": "sha512-t+msfqNhhIvYMSdsh5WMcgpggHjX+RkORboNyGZS1KA6iL9mFABYxroiOeB9JxwGiA4HMjejyOVu0CzKfB8pyw==", + "requires": { + "axios": "^0.21.1", + "chalk": "4.1.0", + "node-machine-id": "^1.1.12", + "rxjs": "6.5.5", + "strip-json-comments": "^3.1.1", + "tar": "6.1.11" + }, + "dependencies": { + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "rxjs": { + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz", + "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==", + "requires": { + "tslib": "^1.9.0" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, + "@nrwl/storybook": { + "version": "12.9.0", + "resolved": "https://registry.npmjs.org/@nrwl/storybook/-/storybook-12.9.0.tgz", + "integrity": "sha512-J6hAfPVh3WK97qvs7vI2xTYx2Afn3hxFkew19Z4HQeJjsKpJ0xVz9OFPVmWnAmL9A3NpYzfIvE7aRwNAKlA8oQ==", + "dev": true, + "requires": { + "@nrwl/cypress": "12.9.0", + "@nrwl/devkit": "12.9.0", + "@nrwl/linter": "12.9.0", + "@nrwl/workspace": "12.9.0", + "core-js": "^3.6.5", + "semver": "7.3.4", + "ts-loader": "5.4.5", + "tsconfig-paths-webpack-plugin": "3.4.1" + }, + "dependencies": { + "@nrwl/workspace": { + "version": "12.9.0", + "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-12.9.0.tgz", + "integrity": "sha512-P8jab7DebwU1fMnpA9A+7oBXNLxVYPqdGPIusOsvpRaJ9tjzhXhVM4OCYu3ZnmcpHboskmSwUMcIvOARRcwWLg==", + "dev": true, + "requires": { + "@nrwl/cli": "12.9.0", + "@nrwl/devkit": "12.9.0", + "@nrwl/jest": "12.9.0", + "@nrwl/linter": "12.9.0", + "chalk": "4.1.0", + "chokidar": "^3.5.1", + "cosmiconfig": "^4.0.0", + "dotenv": "~10.0.0", + "enquirer": "~2.3.6", + "flat": "^5.0.2", + "fs-extra": "^9.1.0", + "glob": "7.1.4", + "ignore": "^5.0.4", + "minimatch": "3.0.4", + "npm-run-all": "^4.1.5", + "open": "^7.4.2", + "rxjs": "^6.5.4", + "semver": "7.3.4", + "tmp": "~0.2.1", + "tslib": "^2.0.0", + "yargs": "15.4.1", + "yargs-parser": "20.0.0" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "cosmiconfig": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz", + "integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==", + "dev": true, + "requires": { + "is-directory": "^0.3.1", + "js-yaml": "^3.9.0", + "parse-json": "^4.0.0", + "require-from-string": "^2.0.1" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "dev": true, + "requires": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "requires": { + "rimraf": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "dependencies": { + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "yargs-parser": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.0.0.tgz", + "integrity": "sha512-8eblPHTL7ZWRkyjIZJjnGf+TijiKJSwA24svzLRVvtgoi/RZiKa9fFQTrlx0OKLnyHSdt/enrdadji6WFfESVA==", + "dev": true + } + } + }, + "@nrwl/tao": { + "version": "12.9.0", + "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-12.9.0.tgz", + "integrity": "sha512-a97JYoLohhBRthnWAGMh3++8Ri/yvCQUG/INBAYxW6sWAk2owJ6DIEIERP4yhIW29HPdqZ/fA2k9iqU6EgIAew==", + "dev": true, + "requires": { + "chalk": "4.1.0", + "enquirer": "~2.3.6", + "fs-extra": "^9.1.0", + "jsonc-parser": "3.0.0", + "nx": "12.9.0", + "rxjs": "^6.5.4", + "rxjs-for-await": "0.0.2", + "semver": "7.3.4", + "tmp": "~0.2.1", + "tslib": "^2.0.0", + "yargs-parser": "20.0.0" + }, + "dependencies": { + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "nx": { + "version": "12.9.0", + "resolved": "https://registry.npmjs.org/nx/-/nx-12.9.0.tgz", + "integrity": "sha512-AOyMJPpioeMtY1UJ2Zgxyjfsc6rg31uztqiCZIQEOLwXoYIYiPuz54IhTngW7c1MjtxDl8B62G8xCjlRv2zjhw==", + "dev": true, + "requires": { + "@nrwl/cli": "*" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "requires": { + "rimraf": "^3.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + }, + "yargs-parser": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.0.0.tgz", + "integrity": "sha512-8eblPHTL7ZWRkyjIZJjnGf+TijiKJSwA24svzLRVvtgoi/RZiKa9fFQTrlx0OKLnyHSdt/enrdadji6WFfESVA==", + "dev": true + } + } + }, + "@nrwl/workspace": { + "version": "12.10.0", + "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-12.10.0.tgz", + "integrity": "sha512-3efkh/0DEOmQXnA2SlBcEk21QiM0vPaJt73CiYnocm1oy7/ngZDyhxYFxOJkVtsfRvR69Etj2JLonbIWa4Za5w==", + "dev": true, + "requires": { + "@nrwl/cli": "12.10.0", + "@nrwl/devkit": "12.10.0", + "@nrwl/jest": "12.10.0", + "@nrwl/linter": "12.10.0", + "@parcel/watcher": "2.0.0-alpha.11", + "chalk": "4.1.0", + "chokidar": "^3.5.1", + "cosmiconfig": "^4.0.0", + "dotenv": "~10.0.0", + "enquirer": "~2.3.6", + "flat": "^5.0.2", + "fs-extra": "^9.1.0", + "glob": "7.1.4", + "ignore": "^5.0.4", + "minimatch": "3.0.4", + "npm-run-all": "^4.1.5", + "npm-run-path": "^4.0.1", + "open": "^7.4.2", + "rxjs": "^6.5.4", + "semver": "7.3.4", + "strip-ansi": "6.0.0", + "tmp": "~0.2.1", + "tslib": "^2.0.0", + "yargs": "15.4.1", + "yargs-parser": "20.0.0" + }, + "dependencies": { + "@jest/console": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.2.5.tgz", + "integrity": "sha512-smtlRF9vNKorRMCUtJ+yllIoiY8oFmfFG7xlzsAE76nKEwXNhjPOJIsc7Dv+AUitVt76t+KjIpUP9m98Crn2LQ==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.2.5", + "jest-util": "^27.2.5", + "slash": "^3.0.0" + }, + "dependencies": { + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "jest-util": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.2.5.tgz", + "integrity": "sha512-QRhDC6XxISntMzFRd/OQ6TGsjbzA5ONO0tlAj2ElHs155x1aEr0rkYJBEysG6H/gZVH3oGFzCdAB/GA8leh8NQ==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "@types/node": "*", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^3.0.0", + "picomatch": "^2.2.3" + } + } + } + }, + "@jest/environment": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.2.5.tgz", + "integrity": "sha512-XvUW3q6OUF+54SYFCgbbfCd/BKTwm5b2MGLoc2jINXQLKQDTCS2P2IrpPOtQ08WWZDGzbhAzVhOYta3J2arubg==", + "dev": true, + "requires": { + "@jest/fake-timers": "^27.2.5", + "@jest/types": "^27.2.5", + "@types/node": "*", + "jest-mock": "^27.2.5" + }, + "dependencies": { + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + } + } + }, + "@jest/fake-timers": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.2.5.tgz", + "integrity": "sha512-ZGUb6jg7BgwY+nmO0TW10bc7z7Hl2G/UTAvmxEyZ/GgNFoa31tY9/cgXmqcxnnZ7o5Xs7RAOz3G1SKIj8IVDlg==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.2.5", + "jest-mock": "^27.2.5", + "jest-util": "^27.2.5" + }, + "dependencies": { + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "jest-util": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.2.5.tgz", + "integrity": "sha512-QRhDC6XxISntMzFRd/OQ6TGsjbzA5ONO0tlAj2ElHs155x1aEr0rkYJBEysG6H/gZVH3oGFzCdAB/GA8leh8NQ==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "@types/node": "*", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^3.0.0", + "picomatch": "^2.2.3" + } + } + } + }, + "@jest/globals": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.2.5.tgz", + "integrity": "sha512-naRI537GM+enFVJQs6DcwGYPn/0vgJNb06zGVbzXfDfe/epDPV73hP1vqO37PqSKDeOXM2KInr6ymYbL1HTP7g==", + "dev": true, + "requires": { + "@jest/environment": "^27.2.5", + "@jest/types": "^27.2.5", + "expect": "^27.2.5" + }, + "dependencies": { + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + } + } + }, + "@jest/reporters": { + "version": "27.2.2", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.2.2.tgz", + "integrity": "sha512-ufwZ8XoLChEfPffDeVGroYbhbcYPom3zKDiv4Flhe97rr/o2IfUXoWkDUDoyJ3/V36RFIMjokSu0IJ/pbFtbHg==", + "dev": true, + "requires": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^27.2.2", + "@jest/test-result": "^27.2.2", + "@jest/transform": "^27.2.2", + "@jest/types": "^27.1.1", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.2", + "graceful-fs": "^4.2.4", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^4.0.3", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.2", + "jest-haste-map": "^27.2.2", + "jest-resolve": "^27.2.2", + "jest-util": "^27.2.0", + "jest-worker": "^27.2.2", + "slash": "^3.0.0", + "source-map": "^0.6.0", + "string-length": "^4.0.1", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^8.0.0" + } + }, + "@jest/test-result": { + "version": "27.2.2", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.2.2.tgz", + "integrity": "sha512-yENoDEoWlEFI7l5z7UYyJb/y5Q8RqbPd4neAVhKr6l+vVaQOPKf8V/IseSMJI9+urDUIxgssA7RGNyCRhGjZvw==", + "dev": true, + "requires": { + "@jest/console": "^27.2.2", + "@jest/types": "^27.1.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/test-sequencer": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.2.5.tgz", + "integrity": "sha512-8j8fHZRfnjbbdMitMAGFKaBZ6YqvFRFJlMJzcy3v75edTOqc7RY65S9JpMY6wT260zAcL2sTQRga/P4PglCu3Q==", + "dev": true, + "requires": { + "@jest/test-result": "^27.2.5", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^27.2.5", + "jest-runtime": "^27.2.5" + }, + "dependencies": { + "@jest/test-result": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.2.5.tgz", + "integrity": "sha512-ub7j3BrddxZ0BdSnM5JCF6cRZJ/7j3wgdX0+Dtwhw2Po+HKsELCiXUTvh+mgS4/89mpnU1CPhZxe2mTvuLPJJg==", + "dev": true, + "requires": { + "@jest/console": "^27.2.5", + "@jest/types": "^27.2.5", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + } + } + }, + "@jest/transform": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.2.5.tgz", + "integrity": "sha512-29lRtAHHYGALbZOx343v0zKmdOg4Sb0rsA1uSv0818bvwRhs3TyElOmTVXlrw0v1ZTqXJCAH/cmoDXimBhQOJQ==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.2.5", + "babel-plugin-istanbul": "^6.0.0", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^27.2.5", + "jest-regex-util": "^27.0.6", + "jest-util": "^27.2.5", + "micromatch": "^4.0.4", + "pirates": "^4.0.1", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + }, + "dependencies": { + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "jest-util": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.2.5.tgz", + "integrity": "sha512-QRhDC6XxISntMzFRd/OQ6TGsjbzA5ONO0tlAj2ElHs155x1aEr0rkYJBEysG6H/gZVH3oGFzCdAB/GA8leh8NQ==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "@types/node": "*", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^3.0.0", + "picomatch": "^2.2.3" + } + } + } + }, + "@nrwl/cli": { + "version": "12.10.0", + "resolved": "https://registry.npmjs.org/@nrwl/cli/-/cli-12.10.0.tgz", + "integrity": "sha512-T8HY7OpY5ygwUZcgt1W2mKYvSsiJ2AMDv7PDGQMCfauYd37FeK8ae93mqdbAXZRJKLrAuaoy51TWOQxwv4vzsA==", + "dev": true, + "requires": { + "@nrwl/tao": "12.10.0", + "chalk": "4.1.0", + "v8-compile-cache": "2.3.0", + "yargs": "15.4.1", + "yargs-parser": "20.0.0" + } + }, + "@nrwl/devkit": { + "version": "12.10.0", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-12.10.0.tgz", + "integrity": "sha512-we0K5Hn48BXh77SV5GVSPfRJeIHNCVFSn+feLbnKz3G60Tk3wFEEFhDABA8cCfTKDxMESSjZoWBy4ZcVg0EX0g==", + "dev": true, + "requires": { + "@nrwl/tao": "12.10.0", + "ejs": "^3.1.5", + "ignore": "^5.0.4", + "rxjs": "^6.5.4", + "semver": "7.3.4", + "tslib": "^2.0.0" + } + }, + "@nrwl/jest": { + "version": "12.10.0", + "resolved": "https://registry.npmjs.org/@nrwl/jest/-/jest-12.10.0.tgz", + "integrity": "sha512-Tqrl/d6y+fGWV9j8bCReLhhfnioAA8yPC9Y6EUevxPuuuW0AUwRZp8slhx7mCiWNh9nLCkMO7PcwD+4L39kzjQ==", + "dev": true, + "requires": { + "@jest/reporters": "27.2.2", + "@jest/test-result": "27.2.2", + "@nrwl/devkit": "12.10.0", + "chalk": "4.1.0", + "identity-obj-proxy": "3.0.0", + "jest-config": "27.2.2", + "jest-resolve": "27.2.2", + "jest-util": "27.2.0", + "rxjs": "^6.5.4", + "tslib": "^2.0.0" + } + }, + "@nrwl/linter": { + "version": "12.10.0", + "resolved": "https://registry.npmjs.org/@nrwl/linter/-/linter-12.10.0.tgz", + "integrity": "sha512-GULnMm3vMh1QEq6QUzZWV+AYB2NlZnov0Pj6tdtqXTjS+mOXkLYP/k8Vfb4ZEPVNSwHyjRZY08A5sbeRnurD2w==", + "dev": true, + "requires": { + "@nrwl/devkit": "12.10.0", + "@nrwl/jest": "12.10.0", + "glob": "7.1.4", + "minimatch": "3.0.4", + "tmp": "~0.2.1", + "tslib": "^2.0.0" + } + }, + "@nrwl/tao": { + "version": "12.10.0", + "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-12.10.0.tgz", + "integrity": "sha512-YkdgTJJsDQlItVj25vW8zEen7BAra6i41Udd0v3CuxTSEXjJJnBD2KzEOGUxXS0gMg7+ILuw2rl9aOKu43TmVA==", + "dev": true, + "requires": { + "chalk": "4.1.0", + "enquirer": "~2.3.6", + "fs-extra": "^9.1.0", + "jsonc-parser": "3.0.0", + "nx": "12.10.0", + "rxjs": "^6.5.4", + "rxjs-for-await": "0.0.2", + "semver": "7.3.4", + "tmp": "~0.2.1", + "tslib": "^2.0.0", + "yargs-parser": "20.0.0" + }, + "dependencies": { + "nx": { + "version": "12.10.0", + "resolved": "https://registry.npmjs.org/nx/-/nx-12.10.0.tgz", + "integrity": "sha512-LpCfZCWsVEtmD2SI1j2KRaw1uIyn4DJ3eRzsjnDYitbq38aORpkvYO+L0zVMZRNDSYSRGTsuj0nHCS3OOxK/Cg==", + "dev": true, + "requires": { + "@nrwl/cli": "*" + } + } + } + }, + "@sinonjs/fake-timers": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.0.1.tgz", + "integrity": "sha512-AU7kwFxreVd6OAXcAFlKSmZquiRUU0FvYm44k1Y1QbK7Co4m0aqfGMhjykIeQp/H6rcl+nFmj0zfdUcGVs9Dew==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "babel-jest": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.2.5.tgz", + "integrity": "sha512-GC9pWCcitBhSuF7H3zl0mftoKizlswaF0E3qi+rPL417wKkCB0d+Sjjb0OfXvxj7gWiBf497ldgRMii68Xz+2g==", + "dev": true, + "requires": { + "@jest/transform": "^27.2.5", + "@jest/types": "^27.2.5", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.0.0", + "babel-preset-jest": "^27.2.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "slash": "^3.0.0" + }, + "dependencies": { + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + } + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "cosmiconfig": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz", + "integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==", + "dev": true, + "requires": { + "is-directory": "^0.3.1", + "js-yaml": "^3.9.0", + "parse-json": "^4.0.0", + "require-from-string": "^2.0.1" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "expect": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.2.5.tgz", + "integrity": "sha512-ZrO0w7bo8BgGoP/bLz+HDCI+0Hfei9jUSZs5yI/Wyn9VkG9w8oJ7rHRgYj+MA7yqqFa0IwHA3flJzZtYugShJA==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "ansi-styles": "^5.0.0", + "jest-get-type": "^27.0.6", + "jest-matcher-utils": "^27.2.5", + "jest-message-util": "^27.2.5", + "jest-regex-util": "^27.0.6" + }, + "dependencies": { + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "jest-circus": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.2.5.tgz", + "integrity": "sha512-eyL9IcrAxm3Saq3rmajFCwpaxaRMGJ1KJs+7hlTDinXpJmeR3P02bheM3CYohE7UfwOBmrFMJHjgo/WPcLTM+Q==", + "dev": true, + "requires": { + "@jest/environment": "^27.2.5", + "@jest/test-result": "^27.2.5", + "@jest/types": "^27.2.5", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "expect": "^27.2.5", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.2.5", + "jest-matcher-utils": "^27.2.5", + "jest-message-util": "^27.2.5", + "jest-runtime": "^27.2.5", + "jest-snapshot": "^27.2.5", + "jest-util": "^27.2.5", + "pretty-format": "^27.2.5", + "slash": "^3.0.0", + "stack-utils": "^2.0.3", + "throat": "^6.0.1" + }, + "dependencies": { + "@jest/test-result": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.2.5.tgz", + "integrity": "sha512-ub7j3BrddxZ0BdSnM5JCF6cRZJ/7j3wgdX0+Dtwhw2Po+HKsELCiXUTvh+mgS4/89mpnU1CPhZxe2mTvuLPJJg==", + "dev": true, + "requires": { + "@jest/console": "^27.2.5", + "@jest/types": "^27.2.5", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "jest-util": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.2.5.tgz", + "integrity": "sha512-QRhDC6XxISntMzFRd/OQ6TGsjbzA5ONO0tlAj2ElHs155x1aEr0rkYJBEysG6H/gZVH3oGFzCdAB/GA8leh8NQ==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "@types/node": "*", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^3.0.0", + "picomatch": "^2.2.3" + } + } + } + }, + "jest-config": { + "version": "27.2.2", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.2.2.tgz", + "integrity": "sha512-2nhms3lp52ZpU0636bB6zIFHjDVtYxzFQIOHZjBFUeXcb6b41sEkWojbHaJ4FEIO44UbccTLa7tvNpiFCgPE7w==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^27.2.2", + "@jest/types": "^27.1.1", + "babel-jest": "^27.2.2", + "chalk": "^4.0.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.1", + "graceful-fs": "^4.2.4", + "is-ci": "^3.0.0", + "jest-circus": "^27.2.2", + "jest-environment-jsdom": "^27.2.2", + "jest-environment-node": "^27.2.2", + "jest-get-type": "^27.0.6", + "jest-jasmine2": "^27.2.2", + "jest-regex-util": "^27.0.6", + "jest-resolve": "^27.2.2", + "jest-runner": "^27.2.2", + "jest-util": "^27.2.0", + "jest-validate": "^27.2.2", + "micromatch": "^4.0.4", + "pretty-format": "^27.2.2" + } + }, + "jest-diff": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.2.5.tgz", + "integrity": "sha512-7gfwwyYkeslOOVQY4tVq5TaQa92mWfC9COsVYMNVYyJTOYAqbIkoD3twi5A+h+tAPtAelRxkqY6/xu+jwTr0dA==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^27.0.6", + "jest-get-type": "^27.0.6", + "pretty-format": "^27.2.5" + } + }, + "jest-each": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.2.5.tgz", + "integrity": "sha512-HUPWIbJT0bXarRwKu/m7lYzqxR4GM5EhKOsu0z3t0SKtbFN6skQhpAUADM4qFShBXb9zoOuag5lcrR1x/WM+Ag==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "chalk": "^4.0.0", + "jest-get-type": "^27.0.6", + "jest-util": "^27.2.5", + "pretty-format": "^27.2.5" + }, + "dependencies": { + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "jest-util": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.2.5.tgz", + "integrity": "sha512-QRhDC6XxISntMzFRd/OQ6TGsjbzA5ONO0tlAj2ElHs155x1aEr0rkYJBEysG6H/gZVH3oGFzCdAB/GA8leh8NQ==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "@types/node": "*", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^3.0.0", + "picomatch": "^2.2.3" + } + } + } + }, + "jest-environment-jsdom": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.2.5.tgz", + "integrity": "sha512-QtRpOh/RQKuXniaWcoFE2ElwP6tQcyxHu0hlk32880g0KczdonCs5P1sk5+weu/OVzh5V4Bt1rXuQthI01mBLg==", + "dev": true, + "requires": { + "@jest/environment": "^27.2.5", + "@jest/fake-timers": "^27.2.5", + "@jest/types": "^27.2.5", + "@types/node": "*", + "jest-mock": "^27.2.5", + "jest-util": "^27.2.5", + "jsdom": "^16.6.0" + }, + "dependencies": { + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "jest-util": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.2.5.tgz", + "integrity": "sha512-QRhDC6XxISntMzFRd/OQ6TGsjbzA5ONO0tlAj2ElHs155x1aEr0rkYJBEysG6H/gZVH3oGFzCdAB/GA8leh8NQ==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "@types/node": "*", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^3.0.0", + "picomatch": "^2.2.3" + } + } + } + }, + "jest-environment-node": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.2.5.tgz", + "integrity": "sha512-0o1LT4grm7iwrS8fIoLtwJxb/hoa3GsH7pP10P02Jpj7Mi4BXy65u46m89vEM2WfD1uFJQ2+dfDiWZNA2e6bJg==", + "dev": true, + "requires": { + "@jest/environment": "^27.2.5", + "@jest/fake-timers": "^27.2.5", + "@jest/types": "^27.2.5", + "@types/node": "*", + "jest-mock": "^27.2.5", + "jest-util": "^27.2.5" + }, + "dependencies": { + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "jest-util": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.2.5.tgz", + "integrity": "sha512-QRhDC6XxISntMzFRd/OQ6TGsjbzA5ONO0tlAj2ElHs155x1aEr0rkYJBEysG6H/gZVH3oGFzCdAB/GA8leh8NQ==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "@types/node": "*", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^3.0.0", + "picomatch": "^2.2.3" + } + } + } + }, + "jest-haste-map": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.2.5.tgz", + "integrity": "sha512-pzO+Gw2WLponaSi0ilpzYBE0kuVJstoXBX8YWyUebR8VaXuX4tzzn0Zp23c/WaETo7XYTGv2e8KdnpiskAFMhQ==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.4", + "jest-regex-util": "^27.0.6", + "jest-serializer": "^27.0.6", + "jest-util": "^27.2.5", + "jest-worker": "^27.2.5", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + }, + "dependencies": { + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "jest-util": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.2.5.tgz", + "integrity": "sha512-QRhDC6XxISntMzFRd/OQ6TGsjbzA5ONO0tlAj2ElHs155x1aEr0rkYJBEysG6H/gZVH3oGFzCdAB/GA8leh8NQ==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "@types/node": "*", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^3.0.0", + "picomatch": "^2.2.3" + } + } + } + }, + "jest-jasmine2": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.2.5.tgz", + "integrity": "sha512-hdxY9Cm/CjLqu2tXeAoQHPgA4vcqlweVXYOg1+S9FeFdznB9Rti+eEBKDDkmOy9iqr4Xfbq95OkC4NFbXXPCAQ==", + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@jest/environment": "^27.2.5", + "@jest/source-map": "^27.0.6", + "@jest/test-result": "^27.2.5", + "@jest/types": "^27.2.5", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^27.2.5", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.2.5", + "jest-matcher-utils": "^27.2.5", + "jest-message-util": "^27.2.5", + "jest-runtime": "^27.2.5", + "jest-snapshot": "^27.2.5", + "jest-util": "^27.2.5", + "pretty-format": "^27.2.5", + "throat": "^6.0.1" + }, + "dependencies": { + "@jest/test-result": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.2.5.tgz", + "integrity": "sha512-ub7j3BrddxZ0BdSnM5JCF6cRZJ/7j3wgdX0+Dtwhw2Po+HKsELCiXUTvh+mgS4/89mpnU1CPhZxe2mTvuLPJJg==", + "dev": true, + "requires": { + "@jest/console": "^27.2.5", + "@jest/types": "^27.2.5", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "jest-util": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.2.5.tgz", + "integrity": "sha512-QRhDC6XxISntMzFRd/OQ6TGsjbzA5ONO0tlAj2ElHs155x1aEr0rkYJBEysG6H/gZVH3oGFzCdAB/GA8leh8NQ==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "@types/node": "*", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^3.0.0", + "picomatch": "^2.2.3" + } + } + } + }, + "jest-leak-detector": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.2.5.tgz", + "integrity": "sha512-HYsi3GUR72bYhOGB5C5saF9sPdxGzSjX7soSQS+BqDRysc7sPeBwPbhbuT8DnOpijnKjgwWQ8JqvbmReYnt3aQ==", + "dev": true, + "requires": { + "jest-get-type": "^27.0.6", + "pretty-format": "^27.2.5" + } + }, + "jest-matcher-utils": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.2.5.tgz", + "integrity": "sha512-qNR/kh6bz0Dyv3m68Ck2g1fLW5KlSOUNcFQh87VXHZwWc/gY6XwnKofx76Qytz3x5LDWT09/2+yXndTkaG4aWg==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^27.2.5", + "jest-get-type": "^27.0.6", + "pretty-format": "^27.2.5" + } + }, + "jest-message-util": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.2.5.tgz", + "integrity": "sha512-ggXSLoPfIYcbmZ8glgEJZ8b+e0Msw/iddRmgkoO7lDAr9SmI65IIfv7VnvTnV4FGnIIUIjzM+fHRHO5RBvyAbQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.2.5", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.4", + "pretty-format": "^27.2.5", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "dependencies": { + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + } + } + }, + "jest-mock": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.2.5.tgz", + "integrity": "sha512-HiMB3LqE9RzmeMzZARi2Bz3NoymxyP0gCid4y42ca1djffNtYFKgI220aC1VP1mUZ8rbpqZbHZOJ15093bZV/Q==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "@types/node": "*" + }, + "dependencies": { + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + } + } + }, + "jest-resolve": { + "version": "27.2.2", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.2.2.tgz", + "integrity": "sha512-tfbHcBs/hJTb3fPQ/3hLWR+TsLNTzzK98TU+zIAsrL9nNzWfWROwopUOmiSUqmHMZW5t9au/433kSF2/Af+tTw==", + "dev": true, + "requires": { + "@jest/types": "^27.1.1", + "chalk": "^4.0.0", + "escalade": "^3.1.1", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^27.2.2", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.2.0", + "jest-validate": "^27.2.2", + "resolve": "^1.20.0", + "slash": "^3.0.0" + } + }, + "jest-runner": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.2.5.tgz", + "integrity": "sha512-n41vw9RLg5TKAnEeJK9d6pGOsBOpwE89XBniK+AD1k26oIIy3V7ogM1scbDjSheji8MUPC9pNgCrZ/FHLVDNgg==", + "dev": true, + "requires": { + "@jest/console": "^27.2.5", + "@jest/environment": "^27.2.5", + "@jest/test-result": "^27.2.5", + "@jest/transform": "^27.2.5", + "@jest/types": "^27.2.5", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "exit": "^0.1.2", + "graceful-fs": "^4.2.4", + "jest-docblock": "^27.0.6", + "jest-environment-jsdom": "^27.2.5", + "jest-environment-node": "^27.2.5", + "jest-haste-map": "^27.2.5", + "jest-leak-detector": "^27.2.5", + "jest-message-util": "^27.2.5", + "jest-resolve": "^27.2.5", + "jest-runtime": "^27.2.5", + "jest-util": "^27.2.5", + "jest-worker": "^27.2.5", + "source-map-support": "^0.5.6", + "throat": "^6.0.1" + }, + "dependencies": { + "@jest/test-result": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.2.5.tgz", + "integrity": "sha512-ub7j3BrddxZ0BdSnM5JCF6cRZJ/7j3wgdX0+Dtwhw2Po+HKsELCiXUTvh+mgS4/89mpnU1CPhZxe2mTvuLPJJg==", + "dev": true, + "requires": { + "@jest/console": "^27.2.5", + "@jest/types": "^27.2.5", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "jest-resolve": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.2.5.tgz", + "integrity": "sha512-q5irwS3oS73SKy3+FM/HL2T7WJftrk9BRzrXF92f7net5HMlS7lJMg/ZwxLB4YohKqjSsdksEw7n/jvMxV7EKg==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "chalk": "^4.0.0", + "escalade": "^3.1.1", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^27.2.5", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.2.5", + "jest-validate": "^27.2.5", + "resolve": "^1.20.0", + "slash": "^3.0.0" + } + }, + "jest-util": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.2.5.tgz", + "integrity": "sha512-QRhDC6XxISntMzFRd/OQ6TGsjbzA5ONO0tlAj2ElHs155x1aEr0rkYJBEysG6H/gZVH3oGFzCdAB/GA8leh8NQ==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "@types/node": "*", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^3.0.0", + "picomatch": "^2.2.3" + } + } + } + }, + "jest-runtime": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.2.5.tgz", + "integrity": "sha512-N0WRZ3QszKyZ3Dm27HTBbBuestsSd3Ud5ooVho47XZJ8aSKO/X1Ag8M1dNx9XzfGVRNdB/xCA3lz8MJwIzPLLA==", + "dev": true, + "requires": { + "@jest/console": "^27.2.5", + "@jest/environment": "^27.2.5", + "@jest/fake-timers": "^27.2.5", + "@jest/globals": "^27.2.5", + "@jest/source-map": "^27.0.6", + "@jest/test-result": "^27.2.5", + "@jest/transform": "^27.2.5", + "@jest/types": "^27.2.5", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^27.2.5", + "jest-message-util": "^27.2.5", + "jest-mock": "^27.2.5", + "jest-regex-util": "^27.0.6", + "jest-resolve": "^27.2.5", + "jest-snapshot": "^27.2.5", + "jest-util": "^27.2.5", + "jest-validate": "^27.2.5", + "slash": "^3.0.0", + "strip-bom": "^4.0.0", + "yargs": "^16.2.0" + }, + "dependencies": { + "@jest/test-result": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.2.5.tgz", + "integrity": "sha512-ub7j3BrddxZ0BdSnM5JCF6cRZJ/7j3wgdX0+Dtwhw2Po+HKsELCiXUTvh+mgS4/89mpnU1CPhZxe2mTvuLPJJg==", + "dev": true, + "requires": { + "@jest/console": "^27.2.5", + "@jest/types": "^27.2.5", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "jest-resolve": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.2.5.tgz", + "integrity": "sha512-q5irwS3oS73SKy3+FM/HL2T7WJftrk9BRzrXF92f7net5HMlS7lJMg/ZwxLB4YohKqjSsdksEw7n/jvMxV7EKg==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "chalk": "^4.0.0", + "escalade": "^3.1.1", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^27.2.5", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.2.5", + "jest-validate": "^27.2.5", + "resolve": "^1.20.0", + "slash": "^3.0.0" + } + }, + "jest-util": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.2.5.tgz", + "integrity": "sha512-QRhDC6XxISntMzFRd/OQ6TGsjbzA5ONO0tlAj2ElHs155x1aEr0rkYJBEysG6H/gZVH3oGFzCdAB/GA8leh8NQ==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "@types/node": "*", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^3.0.0", + "picomatch": "^2.2.3" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true + } + } + }, + "jest-snapshot": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.2.5.tgz", + "integrity": "sha512-2/Jkn+VN6Abwz0llBltZaiJMnL8b1j5Bp/gRIxe9YR3FCEh9qp0TXVV0dcpTGZ8AcJV1SZGQkczewkI9LP5yGw==", + "dev": true, + "requires": { + "@babel/core": "^7.7.2", + "@babel/generator": "^7.7.2", + "@babel/parser": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", + "@babel/types": "^7.0.0", + "@jest/transform": "^27.2.5", + "@jest/types": "^27.2.5", + "@types/babel__traverse": "^7.0.4", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^27.2.5", + "graceful-fs": "^4.2.4", + "jest-diff": "^27.2.5", + "jest-get-type": "^27.0.6", + "jest-haste-map": "^27.2.5", + "jest-matcher-utils": "^27.2.5", + "jest-message-util": "^27.2.5", + "jest-resolve": "^27.2.5", + "jest-util": "^27.2.5", + "natural-compare": "^1.4.0", + "pretty-format": "^27.2.5", + "semver": "^7.3.2" + }, + "dependencies": { + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "jest-resolve": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.2.5.tgz", + "integrity": "sha512-q5irwS3oS73SKy3+FM/HL2T7WJftrk9BRzrXF92f7net5HMlS7lJMg/ZwxLB4YohKqjSsdksEw7n/jvMxV7EKg==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "chalk": "^4.0.0", + "escalade": "^3.1.1", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^27.2.5", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.2.5", + "jest-validate": "^27.2.5", + "resolve": "^1.20.0", + "slash": "^3.0.0" + } + }, + "jest-util": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.2.5.tgz", + "integrity": "sha512-QRhDC6XxISntMzFRd/OQ6TGsjbzA5ONO0tlAj2ElHs155x1aEr0rkYJBEysG6H/gZVH3oGFzCdAB/GA8leh8NQ==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "@types/node": "*", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^3.0.0", + "picomatch": "^2.2.3" + } + } + } + }, + "jest-util": { + "version": "27.2.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.2.0.tgz", + "integrity": "sha512-T5ZJCNeFpqcLBpx+Hl9r9KoxBCUqeWlJ1Htli+vryigZVJ1vuLB9j35grEBASp4R13KFkV7jM52bBGnArpJN6A==", "dev": true, "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "@jest/types": "^27.1.1", + "@types/node": "*", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^3.0.0", + "picomatch": "^2.2.3" } }, - "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "jest-validate": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.2.5.tgz", + "integrity": "sha512-XgYtjS89nhVe+UfkbLgcm+GgXKWgL80t9nTcNeejyO3t0Sj/yHE8BtIJqjZu9NXQksYbGImoQRXmQ1gP+Guffw==", "dev": true, "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "@jest/types": "^27.2.5", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^27.0.6", + "leven": "^3.1.0", + "pretty-format": "^27.2.5" + }, + "dependencies": { + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true + } } }, - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "jest-worker": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.2.5.tgz", + "integrity": "sha512-HTjEPZtcNKZ4LnhSp02NEH4vE+5OpJ0EsOWYvGQpHgUMLngydESAAMH5Wd/asPf29+XUDQZszxpLg1BkIIA2aw==", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, "js-yaml": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", @@ -7671,14 +10301,39 @@ "esprima": "^4.0.0" } }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "jsdom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", "dev": true, "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" } }, "locate-path": { @@ -7690,6 +10345,40 @@ "p-locate": "^4.1.0" } }, + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, "open": { "version": "7.4.2", "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", @@ -7728,6 +10417,51 @@ "json-parse-better-errors": "^1.0.1" } }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true + }, + "pretty-format": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.2.5.tgz", + "integrity": "sha512-+nYn2z9GgicO9JiqmY25Xtq8SYfZ/5VCpEU3pppHHNAhd1y+ZXxmNPd1evmNcAd6Hz4iBV2kf0UpGth5A/VJ7g==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -7763,15 +10497,41 @@ "lru-cache": "^6.0.0" } }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, "string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } } }, "strip-ansi": { @@ -7783,6 +10543,12 @@ "ansi-regex": "^5.0.0" } }, + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true + }, "tmp": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", @@ -7792,11 +10558,25 @@ "rimraf": "^3.0.0" } }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true + "tough-cookie": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", + "dev": true, + "requires": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } }, "wrap-ansi": { "version": "6.2.0", @@ -7809,6 +10589,12 @@ "strip-ansi": "^6.0.0" } }, + "ws": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", + "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==", + "dev": true + }, "yargs": { "version": "15.4.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", @@ -7848,6 +10634,16 @@ } } }, + "@parcel/watcher": { + "version": "2.0.0-alpha.11", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.0.0-alpha.11.tgz", + "integrity": "sha512-zMIAsFLcnB82kkk0kSOZ/zgyihb8sty0zVrsz+3ruoYXkchymWsCDsxiX4v+X2s8Jppk3JE8vlnD4DKs3QTOEQ==", + "dev": true, + "requires": { + "node-addon-api": "^3.0.2", + "node-gyp-build": "^4.2.3" + } + }, "@phenomnomnominal/tsquery": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/@phenomnomnominal/tsquery/-/tsquery-4.1.1.tgz", @@ -9777,11 +12573,11 @@ "dev": true }, "axios": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", - "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", "requires": { - "follow-redirects": "^1.10.0" + "follow-redirects": "^1.14.0" } }, "axobject-query": { @@ -11099,9 +13895,9 @@ "dev": true }, "codelyzer": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-6.0.2.tgz", - "integrity": "sha512-v3+E0Ucu2xWJMOJ2fA/q9pDT/hlxHftHGPUay1/1cTgyPV5JTHFdO9hqo837Sx2s9vKBMTt5gO+lhF95PO6J+g==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-6.0.1.tgz", + "integrity": "sha512-cOyGQgMdhnRYtW2xrJUNrNYDjEgwQ+BrE2y93Bwz3h4DJ6vJRLfupemU5N3pbYsUlBHJf0u1j1UGk+NLW4d97g==", "dev": true, "requires": { "@angular/compiler": "9.0.0", @@ -13514,6 +16310,11 @@ "domelementtype": "1" } }, + "domino": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/domino/-/domino-2.1.6.tgz", + "integrity": "sha512-3VdM/SXBZX2omc9JF9nOPCtDaYQ67BGp5CoLpIQlO2KCAPETs8TcDHacF26jXadGbvUteZzRTeos2fhID5+ucQ==" + }, "domutils": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", @@ -15192,11 +17993,12 @@ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, "fs-extra": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", - "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dev": true, "requires": { + "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" @@ -17690,9 +20492,9 @@ "dev": true }, "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "ansi-styles": { @@ -19190,8 +21992,7 @@ }, "ansi-regex": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "resolved": "", "dev": true }, "ansi-styles": { @@ -21823,8 +24624,7 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", - "dev": true, - "optional": true + "dev": true }, "node-fetch": { "version": "2.6.1", @@ -26879,8 +29679,7 @@ "dependencies": { "ansi-regex": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "resolved": "", "dev": true }, "strip-ansi": { @@ -27036,8 +29835,7 @@ "dependencies": { "ansi-regex": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "resolved": "", "dev": true }, "strip-ansi": { @@ -27098,8 +29896,7 @@ "dependencies": { "ansi-regex": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "resolved": "", "dev": true }, "ansi-styles": { @@ -29636,16 +32433,28 @@ "dev": true }, "tar": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/tar/-/tar-5.0.7.tgz", - "integrity": "sha512-g0qlHHRtAZAxzkZkJvt0P5C6ODEolw2paouzsSbVqE7l5jKani1m9ogy7VxGp6hEngiKpPCwkh9pX5UH8Wp6QA==", + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", "requires": { - "chownr": "^1.1.3", + "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^3.0.0", - "minizlib": "^2.1.0", - "mkdirp": "^0.5.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", "yallist": "^4.0.0" + }, + "dependencies": { + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + } } }, "tar-fs": { @@ -29877,9 +32686,9 @@ } }, "tmpl": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", - "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true }, "to-arraybuffer": { @@ -32221,6 +35030,11 @@ "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", "dev": true }, + "xhr2": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.2.1.tgz", + "integrity": "sha512-sID0rrVCqkVNUn8t6xuv9+6FViXjUVXq8H5rWOH2rz9fDNQEd4g0EA2XlcEdJXRz5BMEn4O1pJFdT+z4YHhoWw==" + }, "xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", diff --git a/package.json b/package.json index e30dedb63..e1e134172 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "build:code": "nx run-many --target=build --all --configuration production --with-deps", "build:tools": "tsc -p tools/tsconfig.tools.json", "build:sample": "npm run scully -- --project sample-blog --RSD --scan ", + "build:uni": "npm run scully -- --project universal-sample --RSD --scan ", "build:docs": "npm run scully -- --project scully-docs --RSD --scan", "scully": "node ./dist/libs/scully/src/scully.js", "test": "run-s build:scully server:kill build:code symlinks server:testDocs server:wait build:docs server:kill server:testSample server:wait build:sample jest:test cypress:e2e", @@ -27,6 +28,7 @@ "server:testSample": "npm run server:sample &", "server:testDocs": "npm run server:docs &", "server:sample": "npm run scully -- --project sample-blog --tds serve --404=baseOnly --noCache", + "server:uni": "npm run scully -- --project universal-sample --tds serve --404=baseOnly --noCache", "server:docs": "npm run scully -- --project scully-docs --tds serve --noCache", "server:kill": "npm run scully -- killServer ", "e2e": "nx e2e", @@ -76,9 +78,10 @@ "@angular/forms": "12.2.6", "@angular/platform-browser": "12.2.6", "@angular/platform-browser-dynamic": "12.2.6", + "@angular/platform-server": "^12.2.6", "@angular/router": "12.2.6", "@herodevs/scully-plugin-the-vault": "^0.0.4", - "@nrwl/nx-cloud": "12.3.10", + "@nrwl/nx-cloud": "^12.3.13", "@sentry/node": "^6.12.0", "@types/compression": "^1.7.2", "@types/cors": "^2.8.12", @@ -120,7 +123,7 @@ "@nrwl/express": "12.9.0", "@nrwl/jest": "12.9.0", "@nrwl/node": "12.9.0", - "@nrwl/workspace": "12.9.0", + "@nrwl/workspace": "12.10.0", "@types/chalk": "^2.2.0", "@types/express": "4.17.13", "@types/fs-extra": "^9.0.12", @@ -140,7 +143,7 @@ "@typescript-eslint/eslint-plugin": "4.31.1", "@typescript-eslint/parser": "4.31.1", "asciidoctor.js": "^1.5.9", - "codelyzer": "6.0.2", + "codelyzer": "6.0.1", "conventional-changelog": "^3.1.24", "cypress": "^8.4.0", "cz-conventional-changelog": "^3.3.0", @@ -148,7 +151,7 @@ "eslint": "7.32.0", "eslint-config-prettier": "8.3.0", "front-matter": "^4.0.2", - "fs-extra": "^10.0.0", + "fs-extra": "^9.1.0", "guess-parser": "^0.4.22", "http-proxy-middleware": "^2.0.1", "husky": "^7.0.2", diff --git a/scully.universal-sample.config.ts b/scully.universal-sample.config.ts new file mode 100644 index 000000000..a71ea81e0 --- /dev/null +++ b/scully.universal-sample.config.ts @@ -0,0 +1,30 @@ +import {ScullyConfig} from '@scullyio/scully'; +import { removeScripts } from '@scullyio/scully-plugin-remove-scripts'; +import '@scullyio/scully-plugin-extra'; +import '@scullyio/scully-plugin-from-data'; + +const defaultPostRenderers:string[] = [];// ['seoHrefOptimise']; +export const config: ScullyConfig = { + projectName: 'universal-sample', + outDir: './dist/static/universal-sample', + defaultPostRenderers, + maxRenderThreads:64, + routes: { + '/demo/:id': { + type: 'extra', + numberOfPages: 5, + }, + '/user/:id': { + // Type is mandatory + type: 'json', + /** + * Every parameter in the route must exist here + */ + id: { + url: 'http://localhost:8200/users', + resultsHandler: (raw) => raw.filter((row) => row.id < 5), + property: 'id', + }, + }, + }, +}; diff --git a/scully/tsconfig.json b/scully/tsconfig.json index f54f42cb8..0001ba6b2 100644 --- a/scully/tsconfig.json +++ b/scully/tsconfig.json @@ -17,6 +17,6 @@ "typeRoots": ["../node_modules/@types"], "allowSyntheticDefaultImports": true }, - "include": ["**/*.ts", "/*.ts"], - "exclude": ["**/*spec.ts", "*spec.ts"] + "include": ["plugins/**/*.ts"], + "exclude": ["**/*spec.ts", "*spec.ts", "./universal/**/*.*"] } diff --git a/scully/tsconfig.universal.sample.json b/scully/tsconfig.universal.sample.json new file mode 100644 index 000000000..43ff22877 --- /dev/null +++ b/scully/tsconfig.universal.sample.json @@ -0,0 +1,19 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "outDir": "./runtime", + "target": "es2020", + "allowJs": true, + "allowSyntheticDefaultImports": true, + "skipDefaultLibCheck": true, + "skipLibCheck": true, + "lib": ["ES2020", "DOM"], + "types": ["node"], + "moduleResolution": "Node", + "module": "CommonJS" + }, + "files": ["../apps/sample-blog/src/main.universal.ts", "./universal/scully-universal-worker.ts","./universal/scully-universal.ts"], + "angularCompilerOptions": { + "entryModule": "./src/app/app.server.module#AppServerModule" + } +} diff --git a/scully/universal/scully-universal-worker.ts b/scully/universal/scully-universal-worker.ts new file mode 100644 index 000000000..2669b6a8b --- /dev/null +++ b/scully/universal/scully-universal-worker.ts @@ -0,0 +1,170 @@ +import { DOCUMENT } from '@angular/common'; +import { ResourceLoader } from '@angular/compiler'; +import { APP_INITIALIZER, Compiler, CompilerFactory, NgModuleFactory, StaticProvider, Type } from '@angular/core'; +import { platformDynamicServer, renderModuleFactory, renderModule } from '@angular/platform-server'; +import { + findPlugin, + HandledRoute, + loadConfig, + registerPlugin, + renderRoute, + scullyConfig, + ScullyConfig, + startWorkerListener, + Tasks, + WriteToStorage, +} from '@scullyio/scully'; +import { readFileSync } from 'fs'; +import { readFile } from 'fs/promises'; +import { join } from 'path'; +import { URL } from 'url'; +import { version } from 'yargs'; +// tslint:disable-next-line: ordered-imports +import 'zone.js/node'; +// tslint:disable-next-line: ordered-imports +import 'zone.js/dist/task-tracking'; + +let config: Promise; +const globalSetup: { + rawHtml?: string; +} = {}; +const executePluginsForRoute = findPlugin(renderRoute); +const writeToFs = findPlugin(WriteToStorage); +const universalRenderRunner = ('universalRender_runner'); + +async function init(path) { + const extraProviders: StaticProvider[] = [ + { provide: APP_INITIALIZER, multi: true, useFactory: domContentLoadedFactory, deps: [DOCUMENT] }, + , + ]; + const { config: myConfig } = await import(path); + config = loadConfig(await myConfig); + + const lazymodule = await import('../../apps/universal-sample/src/app/app.universal.module'); + // console.log('ls',lazymodule) + // const userModule = lazymodule.AppUniversalModule; + const { AppUniversalModule: userModule } = lazymodule + + globalSetup.rawHtml = readFileSync(join(process.cwd(), './dist/apps/universal-sample/index.html')).toString('utf-8'); + + async function universalRenderPlugin(route: HandledRoute) { + await config; + try { + const url = `http://localhost/${route.route}`; + const window: Partial = { + dispatchEvent: (...x: any[]) => undefined, + location: (new URL(url) as unknown) as Location, + }; + globalThis.window = window as Window & typeof globalThis; + const options = { + url, + document: globalSetup.rawHtml, + }; + window['scullyVersion'] = version; + window['ScullyIO-exposed'] = undefined; + window['ScullyIO-injected'] = undefined; + if (route.config && route.config.manualIdleCheck) { + route.exposeToPage = route.exposeToPage || {}; + route.exposeToPage.manualIdle = true; + } + + if (scullyConfig.inlineStateOnly) { + route.injectToPage = route.injectToPage || {}; + route.injectToPage.inlineStateOnly = true; + } + + if (route.exposeToPage !== undefined) { + window['ScullyIO-exposed'] = route.exposeToPage; + } + if (route.injectToPage !== undefined) { + window['ScullyIO-injected'] = route.injectToPage; + } + window['ScullyIO'] = 'running'; + + const factory = await getFactory(userModule); + const result = await renderModule(userModule, { + document: globalSetup.rawHtml, + url: `http://localhost/${route.route}`, + extraProviders, + }).then(r => { + console.log('renderResult', r) + return r + }).catch(e => { + return `Error while rendering: ${e}` + }); + return result; + } catch (e) { + console.log(e); + return `Error while rendering: ${e}` + } + return 'oops'; + } + registerPlugin('scullySystem', universalRenderRunner, universalRenderPlugin); + return 'init done ' + process.pid; +} + +const factoryCacheMap = new Map, NgModuleFactory<{}>>(); +async function getFactory(moduleOrFactory: Type<{}> | NgModuleFactory<{}>): Promise> { + // If module has been compiled AoT + if (moduleOrFactory instanceof NgModuleFactory) { + console.log('aot, return factory') + return moduleOrFactory; + } else { + // we're in JIT mode + if (!factoryCacheMap.has(moduleOrFactory)) { + // Compile the module and cache it + const module = await (await getCompiler().compileModuleAsync(moduleOrFactory).catch(e => { + console.log(e) + })); + factoryCacheMap.set(moduleOrFactory, module as any); + } + return factoryCacheMap.get(moduleOrFactory); + } +} + +function getCompiler(): Compiler { + const compilerFactory: CompilerFactory = platformDynamicServer().injector.get(CompilerFactory); + return compilerFactory.createCompiler([{ providers: [{ provide: ResourceLoader, useClass: FileLoader, deps: [] }] }]); +} + +class FileLoader implements ResourceLoader { + get(url: string): Promise { + return readFile(url, 'utf-8'); + } +} + +if (typeof process.send === 'function') { + const availableTasks: Tasks = { + init, + render: async (ev: HandledRoute) => { + try { + ev.renderPlugin = universalRenderRunner; + const html = await executePluginsForRoute(ev); + await writeToFs(ev.route, html); + } catch (e) { + console.error(e) + process.exit(15) + } + }, + } as const; + + startWorkerListener(availableTasks); +} + +export function domContentLoadedFactory(doc: Document): () => Promise { + return () => + new Promise((resolve, _reject) => { + if (doc.readyState === 'complete' || doc.readyState === 'interactive') { + resolve(); + + return; + } + + const contentLoaded = () => { + doc.removeEventListener('DOMContentLoaded', contentLoaded); + resolve(); + }; + + doc.addEventListener('DOMContentLoaded', contentLoaded); + }); +} diff --git a/scully/universal/scully-universal.ts b/scully/universal/scully-universal.ts new file mode 100644 index 000000000..c10792842 --- /dev/null +++ b/scully/universal/scully-universal.ts @@ -0,0 +1,68 @@ +import { findPlugin, getPool, loadConfig, scullyConfig, universalRender } from '@scullyio/scully'; +import { merge } from 'rxjs'; +import { filter, tap } from 'rxjs'; + +if (process.send) { + import('./scully-universal-worker').then(m => { + // console.log('worker module loaded') + }).catch(e => console.log(e)); +} else { + console.log('starting app') + const cacheStats = { + hits: 0, + misses: 0, + }; + setupCacheListener(); + findPlugin(universalRender)(__filename).then((r) => { + console.log(cacheStats); + }); + const cache = new Map>(); + async function setupCacheListener() { + await loadConfig(); + const pool = getPool(__filename, scullyConfig.maxRenderThreads); + const listen$ = merge(...pool.map((w) => w.messages$)).pipe( + filter(({ msg }) => Array.isArray(msg) && msg[0].startsWith('cache')) + ); + + const idChecks$ = listen$.pipe( + filter(({ msg }) => msg[0] === 'cacheHas'), + tap(({ worker, msg }) => { + const id = msg[1] as string; + if (!cache.has(id)) { + cache.set(id, new Deferred()); + cacheStats.misses += 1; + worker.send('cacheResult', false); + return; + } + cache.get(id).promise.then((cacheItem) => { + cacheStats.hits += 1; + worker.send('cacheResult',cacheItem); + }); + }) + ); + + const idSetCacheItems$ = listen$.pipe( + filter(({ msg }) => msg[0] === 'cacheSet'), + tap(({ worker, msg }) => { + const { id, response }: { id: string; response: any } = msg[1]; + const deferred = cache.get(id); + deferred.resolve(response); + }) + ); + + merge(idChecks$, idSetCacheItems$).subscribe({ + next({ worker, msg }) { + // console.log('hm',msg, worker.id); + }, + }); + } +} + +export class Deferred { + resolve!: (result?: any) => void; + reject!: (error?: any) => void; + promise = new Promise((rs, rj) => { + this.resolve = rs; + this.reject = rj; + }); +} diff --git a/testUniversal.sh b/testUniversal.sh new file mode 100755 index 000000000..addb784cf --- /dev/null +++ b/testUniversal.sh @@ -0,0 +1,11 @@ +# rm -fr node_modules/@scullyio/ng-lib/ +# rm -fr dist/libs/ng-lib +# npx nx build ng-lib --prod +# npx ngcc -l info +npx nx build universal-sample --prod +rm -fr .scully/__cache +rm ./scully.universal-sample.config.js +npx nx build scully +rm -fr ./scully/runtime +npx ngc -p ./scully/tsconfig.universal.sample.json +node --unhandled-rejections=strict ./scully/runtime/scully/universal/scully-universal.js --project universal-sample --RSD diff --git a/tsconfig.base.json b/tsconfig.base.json index 4ec43677d..6dd94ee17 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1,21 +1,10 @@ { - "compileOnSave": false, + "extends": "./tsconfig.json", "compilerOptions": { - "sourceMap": true, - "declaration": false, - "moduleResolution": "node", - "emitDecoratorMetadata": true, "experimentalDecorators": true, - "importHelpers": true, - "target": "es2015", - "module": "esnext", - "typeRoots": ["node_modules/@types"], - "lib": ["es2017", "dom"], - "skipLibCheck": true, - "skipDefaultLibCheck": true, - "baseUrl": "./", "paths": { "@scullyio/init": ["dist/libs/scully-schematics/src"], + "@scullyio/universal": ["libs/universal/src/index.ts"], "@scullyio/ng-lib": ["dist/libs/ng-lib"], "@scullyio/scully": ["dist/libs/scully"], "@scullyio/scully-plugin-base-href-rewrite": [ @@ -51,9 +40,5 @@ ], "@scullyio/scully-plugin-sentry": ["libs/plugins/sentry/src/index.ts"] } - }, - "angularCompilerOptions": { - "disableTypeScriptVersionCheck": true - }, - "exclude": ["node_modules", "tmp", "dist", "tests"] + } } diff --git a/tsconfig.json b/tsconfig.json index cda6b8875..6c2b7aa0c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -18,21 +18,12 @@ "@scullyio/scully": ["dist/libs/scully"], "@scullyio/ng-lib": ["dist/libs/ng-lib"], "@scullyio/init": ["dist/libs/scully-schematics/src"], - "@scullyio/scully-plugin-base-href-rewrite": ["libs/plugins/base-href-rewrite/src/index.ts"], - "@scullyio/scully-plugin-docs-link-update": ["libs/plugins/docs-link-update/src/index.ts"], - "@scullyio/scully-plugin-extra": ["libs/plugins/extra/src/index.ts"], - "@scullyio/scully-plugin-flash-prevention": ["dist/libs/plugins/scully-plugin-flash-prevention"], - "@scullyio/scully-plugin-from-data": ["libs/plugins/from-data/src/index.ts"], - "@scullyio/scully-plugin-google-analytics": ["libs/plugins/google-analytics/src/index.ts"], - "@scullyio/scully-plugin-logrocket": ["libs/plugins/logrocket/src/index.ts"], - "@scullyio/scully-plugin-sentry": ["libs/plugins/sentry/src/index.ts"], - "@scullyio/scully-plugin-critical-css": ["libs/plugins/scully-plugin-critical-css/src/index.ts"], - "@scullyio/scully-plugin-remove-scripts": ["libs/plugins/scully-plugin-remove-scripts/src/index.ts"], - "@scullyio/scully-plugin-copy-to-clipboard": ["libs/plugins/scully-plugin-copy-to-clipboard/src/index.ts"] + "@scullyio/universal": ["libs/universal/src/index.ts"] } }, "angularCompilerOptions": { - "disableTypeScriptVersionCheck": true + "disableTypeScriptVersionCheck": true, + "strictTemplates": true }, "exclude": ["node_modules", "tmp", "dist", "tests"] } diff --git a/tsconfig.spec.json b/tsconfig.spec.json index 14368c2ed..43d8e028f 100644 --- a/tsconfig.spec.json +++ b/tsconfig.spec.json @@ -3,7 +3,7 @@ "compilerOptions": { "outDir": "./out-tsc/spec", "types": ["jest", "node"], - "esModuleInterop": true + "esModuleInterop": true, }, "include": ["tests/jest/src/__tests__/*.spec.ts", "apps/sample-blog/src/app/**/*.d.ts"], "exclude": ["tests/cypress/**/*.spec.ts"] diff --git a/workspace.json b/workspace.json index 541300d3b..33a4fdb46 100644 --- a/workspace.json +++ b/workspace.json @@ -678,6 +678,172 @@ "outputs": ["{options.outputPath}"] } } + }, + "universal-sample": { + "projectType": "application", + "root": "apps/universal-sample", + "sourceRoot": "apps/universal-sample/src", + "prefix": "scullyio", + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:browser", + "options": { + "outputPath": "dist/apps/universal-sample", + "index": "apps/universal-sample/src/index.html", + "main": "apps/universal-sample/src/main.ts", + "polyfills": "apps/universal-sample/src/polyfills.ts", + "tsConfig": "apps/universal-sample/tsconfig.app.json", + "assets": [ + "apps/universal-sample/src/favicon.ico", + "apps/universal-sample/src/assets" + ], + "styles": [ + "apps/universal-sample/src/styles.css" + ], + "scripts": [], + "vendorChunk": true, + "extractLicenses": false, + "buildOptimizer": true, + "sourceMap": true, + "optimization": false, + "namedChunks": true, + "aot": true + }, + "configurations": { + "production": { + "fileReplacements": [ + { + "replace": "apps/universal-sample/src/environments/environment.ts", + "with": "apps/universal-sample/src/environments/environment.prod.ts" + } + ], + "optimization": true, + "outputHashing": "all", + "sourceMap": false, + "namedChunks": false, + "extractLicenses": true, + "vendorChunk": false, + "aot": true, + "buildOptimizer": true, + "budgets": [ + { + "type": "initial", + "maximumWarning": "2mb", + "maximumError": "5mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "6kb", + "maximumError": "10kb" + } + ] + } + } + }, + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "options": { + "browserTarget": "universal-sample:build" + }, + "configurations": { + "production": { + "browserTarget": "universal-sample:build:production" + } + } + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "browserTarget": "universal-sample:build" + } + }, + "lint": { + "builder": "@nrwl/linter:eslint", + "options": { + "lintFilePatterns": [ + "apps/universal-sample/src/**/*.ts", + "apps/universal-sample/src/**/*.html" + ] + } + }, + "test": { + "builder": "@nrwl/jest:jest", + "outputs": [ + "coverage/apps/universal-sample" + ], + "options": { + "jestConfig": "apps/universal-sample/jest.config.js", + "passWithNoTests": true + } + } + } + }, + "universal-sample-e2e": { + "root": "apps/universal-sample-e2e", + "sourceRoot": "apps/universal-sample-e2e/src", + "projectType": "application", + "architect": { + "e2e": { + "builder": "@nrwl/cypress:cypress", + "options": { + "cypressConfig": "apps/universal-sample-e2e/cypress.json", + "tsConfig": "apps/universal-sample-e2e/tsconfig.e2e.json", + "devServerTarget": "universal-sample:serve" + }, + "configurations": { + "production": { + "devServerTarget": "universal-sample:serve:production" + } + } + }, + "lint": { + "builder": "@nrwl/linter:eslint", + "options": { + "lintFilePatterns": [ + "apps/universal-sample-e2e/**/*.{js,ts}" + ] + } + } + } + }, + "universal": { + "projectType": "library", + "root": "libs/universal", + "sourceRoot": "libs/universal/src", + "prefix": "scullyio", + "architect": { + "build": { + "builder": "@nrwl/angular:package", + "options": { + "tsConfig": "libs/universal/tsconfig.lib.json", + "project": "libs/universal/ng-package.json" + }, + "configurations": { + "production": { + "tsConfig": "libs/universal/tsconfig.lib.prod.json" + } + } + }, + "lint": { + "builder": "@nrwl/linter:eslint", + "options": { + "lintFilePatterns": [ + "libs/universal/src/**/*.ts", + "libs/universal/src/**/*.html" + ] + } + }, + "test": { + "builder": "@nrwl/jest:jest", + "outputs": [ + "coverage/libs/universal" + ], + "options": { + "jestConfig": "libs/universal/jest.config.js", + "passWithNoTests": true + } + } + } } }, "cli": { @@ -739,11 +905,19 @@ } }, "@nrwl/angular:application": { + "style": "css", + "linter": "eslint", "unitTestRunner": "jest", - "e2eTestRunner": "cypress" + "e2eTestRunner": "cypress", + "strict": true }, "@nrwl/angular:library": { + "style": "css", + "linter": "eslint", "unitTestRunner": "jest" + }, + "@nrwl/angular:component": { + "style": "css" } } }