From 96bcf51a1fa90401ada9e32dac973df90e5ba32c Mon Sep 17 00:00:00 2001 From: James Daniels Date: Fri, 20 Nov 2020 12:02:05 -0500 Subject: [PATCH 01/11] feat(afs): Add Firestore memory-only variant --- sample/server.ts | 3 +- sample/src/app/app.browser.module.ts | 16 + sample/src/app/app.module.ts | 7 +- sample/src/app/app.server.module.ts | 4 +- sample/src/app/database/database.component.ts | 18 +- .../firestore-offline.component.spec.ts | 25 - .../firestore-offline.component.ts | 37 - .../firestore-offline.module.ts | 28 - sample/src/app/home/home.component.ts | 1 - .../protected-lazy.component.ts | 5 +- sample/src/app/upboats/upboats.component.ts | 4 +- sample/src/main.ts | 4 +- sample/yarn.lock | 1937 +++++++---------- src/firestore/firestore-memory.module.ts | 9 + src/firestore/firestore-memory.ts | 6 + src/firestore/firestore.ts | 1 - src/firestore/index.ts | 9 + src/firestore/memory/ng-package.json | 6 + src/firestore/package.json | 2 +- src/firestore/public_api.ts | 1 - tsconfig.json | 1 + yarn.lock | 576 ++--- 22 files changed, 1156 insertions(+), 1544 deletions(-) create mode 100644 sample/src/app/app.browser.module.ts delete mode 100644 sample/src/app/firestore-offline/firestore-offline.component.spec.ts delete mode 100644 sample/src/app/firestore-offline/firestore-offline.component.ts delete mode 100644 sample/src/app/firestore-offline/firestore-offline.module.ts create mode 100644 src/firestore/firestore-memory.module.ts create mode 100644 src/firestore/firestore-memory.ts create mode 100644 src/firestore/index.ts create mode 100644 src/firestore/memory/ng-package.json diff --git a/sample/server.ts b/sample/server.ts index a82723a8c..c91f2c79d 100644 --- a/sample/server.ts +++ b/sample/server.ts @@ -34,9 +34,10 @@ export function app() { // Example Express Rest API endpoints // app.get('/api/**', (req, res) => { }); // Serve static files from /browser + // TODO sort out why the types broke, express? server.get('*.*', express.static(distFolder, { maxAge: '1y' - })); + }) as any); // All regular routes use the Universal engine server.get('*', (req, res) => { diff --git a/sample/src/app/app.browser.module.ts b/sample/src/app/app.browser.module.ts new file mode 100644 index 000000000..75a1098ff --- /dev/null +++ b/sample/src/app/app.browser.module.ts @@ -0,0 +1,16 @@ +import { NgModule } from '@angular/core'; +import { AppModule } from './app.module'; +import { AppComponent } from './app.component'; +import { AngularFirestoreModule } from '@angular/fire/firestore'; + +@NgModule({ + imports: [ + AppModule, + AngularFirestoreModule.enablePersistence({ + synchronizeTabs: true, + experimentalForceOwningTab: true + }) + ], + bootstrap: [AppComponent], +}) +export class AppBrowserModule {} diff --git a/sample/src/app/app.module.ts b/sample/src/app/app.module.ts index cd31d6864..7102793e4 100644 --- a/sample/src/app/app.module.ts +++ b/sample/src/app/app.module.ts @@ -20,7 +20,7 @@ import { import { FirestoreComponent } from './firestore/firestore.component'; import { AngularFireDatabaseModule, USE_EMULATOR as USE_DATABASE_EMULATOR } from '@angular/fire/database'; -import { AngularFirestoreModule, USE_EMULATOR as USE_FIRESTORE_EMULATOR, SETTINGS as FIRESTORE_SETTINGS } from '@angular/fire/firestore'; +import { USE_EMULATOR as USE_FIRESTORE_EMULATOR, SETTINGS as FIRESTORE_SETTINGS } from '@angular/fire/firestore'; import { AngularFireStorageModule } from '@angular/fire/storage'; import { AngularFireAuthModule, USE_DEVICE_LANGUAGE, USE_EMULATOR as USE_AUTH_EMULATOR } from '@angular/fire/auth'; import { AngularFireMessagingModule, SERVICE_WORKER, VAPID_KEY } from '@angular/fire/messaging'; @@ -35,8 +35,6 @@ import { HomeComponent } from './home/home.component'; import { AuthComponent } from './auth/auth.component'; import { MessagingComponent } from './messaging/messaging.component'; import { FunctionsComponent } from './functions/functions.component'; -import { FirestoreOfflineComponent } from './firestore-offline/firestore-offline.component'; -import { FirestoreOfflineModule } from './firestore-offline/firestore-offline.module'; import { UpboatsComponent } from './upboats/upboats.component'; @NgModule({ @@ -44,7 +42,6 @@ import { UpboatsComponent } from './upboats/upboats.component'; AppComponent, StorageComponent, FirestoreComponent, - FirestoreOfflineComponent, DatabaseComponent, RemoteConfigComponent, HomeComponent, @@ -61,7 +58,6 @@ import { UpboatsComponent } from './upboats/upboats.component'; AngularFireModule.initializeApp(environment.firebase), AngularFireStorageModule, AngularFireDatabaseModule, - AngularFirestoreModule, AngularFireAuthModule, AngularFireAuthGuardModule, AngularFireRemoteConfigModule, @@ -69,7 +65,6 @@ import { UpboatsComponent } from './upboats/upboats.component'; AngularFireAnalyticsModule, AngularFireFunctionsModule, AngularFirePerformanceModule, - FirestoreOfflineModule ], providers: [ UserTrackingService, diff --git a/sample/src/app/app.server.module.ts b/sample/src/app/app.server.module.ts index dd55bd1b6..f75ede331 100644 --- a/sample/src/app/app.server.module.ts +++ b/sample/src/app/app.server.module.ts @@ -4,12 +4,14 @@ import { ServerModule, ServerTransferStateModule } from '@angular/platform-serve import { AppModule } from './app.module'; import { AppComponent } from './app.component'; import { APP_BASE_HREF } from '@angular/common'; +import { AngularFirestoreModule } from '@angular/fire/firestore/memory'; @NgModule({ imports: [ AppModule, ServerModule, - ServerTransferStateModule + ServerTransferStateModule, + AngularFirestoreModule ], providers: [ { provide: APP_BASE_HREF, useFactory: () => isDevMode() ? '/us-central1/ssr' : '/ssr' }, diff --git a/sample/src/app/database/database.component.ts b/sample/src/app/database/database.component.ts index 9438d4f52..cf1955a60 100644 --- a/sample/src/app/database/database.component.ts +++ b/sample/src/app/database/database.component.ts @@ -21,17 +21,13 @@ export class DatabaseComponent implements OnInit { public readonly testObjectValue$: Observable; constructor(state: TransferState, database: AngularFireDatabase, @Inject(PLATFORM_ID) platformId: object) { - if (isPlatformServer(platformId)) { - this.testObjectValue$ = EMPTY; - } else { - const doc = database.object('test'); - const key = makeStateKey(doc.query.toString()); - const existing = state.get(key, undefined); - this.testObjectValue$ = doc.valueChanges().pipe( - trace('database'), - existing ? startWith(existing) : tap(it => state.set(key, it)) - ); - } + const doc = database.object('test'); + const key = makeStateKey(doc.query.toString()); + const existing = state.get(key, undefined); + this.testObjectValue$ = doc.valueChanges().pipe( + trace('database'), + existing ? startWith(existing) : tap(it => state.set(key, it)) + ); } ngOnInit(): void { diff --git a/sample/src/app/firestore-offline/firestore-offline.component.spec.ts b/sample/src/app/firestore-offline/firestore-offline.component.spec.ts deleted file mode 100644 index 7c95a29de..000000000 --- a/sample/src/app/firestore-offline/firestore-offline.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; - -import { FirestoreOfflineComponent } from './firestore-offline.component'; - -describe('FirestoreComponent', () => { - let component: FirestoreOfflineComponent; - let fixture: ComponentFixture; - - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ FirestoreOfflineComponent ] - }) - .compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(FirestoreOfflineComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/sample/src/app/firestore-offline/firestore-offline.component.ts b/sample/src/app/firestore-offline/firestore-offline.component.ts deleted file mode 100644 index cb21df1fd..000000000 --- a/sample/src/app/firestore-offline/firestore-offline.component.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { AngularFirestore } from '@angular/fire/firestore'; -import { Observable } from 'rxjs'; -import { startWith, tap } from 'rxjs/operators'; -import { makeStateKey, TransferState } from '@angular/platform-browser'; -import { trace } from '@angular/fire/performance'; -import { AngularFirestoreOffline } from './firestore-offline.module'; - -@Component({ - selector: 'app-firestore-offline', - template: `

- Firestore Offline! - {{ testDocValue$ | async | json }} - {{ persistenceEnabled$ | async }} -

`, - styles: [``] -}) -export class FirestoreOfflineComponent implements OnInit { - - public readonly persistenceEnabled$: Observable; - public readonly testDocValue$: Observable; - - constructor(state: TransferState, firestore: AngularFirestoreOffline) { - const doc = firestore.doc('test/1'); - const key = makeStateKey(doc.ref.path); - const existing = state.get(key, undefined); - this.testDocValue$ = firestore.doc('test/1').valueChanges().pipe( - trace('firestore'), - existing ? startWith(existing) : tap(it => state.set(key, it)) - ); - this.persistenceEnabled$ = firestore.persistenceEnabled$; - } - - ngOnInit(): void { - } - -} diff --git a/sample/src/app/firestore-offline/firestore-offline.module.ts b/sample/src/app/firestore-offline/firestore-offline.module.ts deleted file mode 100644 index 7bd3bc678..000000000 --- a/sample/src/app/firestore-offline/firestore-offline.module.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Inject, Injectable, InjectionToken, NgModule, NgZone, Optional, PLATFORM_ID } from '@angular/core'; -import { FirebaseOptions, FIREBASE_OPTIONS } from '@angular/fire'; -import { USE_EMULATOR } from '@angular/fire/firestore'; -import { AngularFirestore, SETTINGS, Settings } from '@angular/fire/firestore'; -import { USE_EMULATOR as USE_AUTH_EMULATOR } from '@angular/fire/auth'; - -export const FIRESTORE_OFFLINE = new InjectionToken('my.firestore'); - -@Injectable() -export class AngularFirestoreOffline extends AngularFirestore { - constructor( - @Inject(FIREBASE_OPTIONS) options: FirebaseOptions, - @Optional() @Inject(SETTINGS) settings: Settings | null, - // tslint:disable-next-line:ban-types - @Inject(PLATFORM_ID) platformId: Object, - zone: NgZone, - @Optional() @Inject(USE_EMULATOR) useEmulator: any, - @Optional() @Inject(USE_AUTH_EMULATOR) useAuthEmulator: any, - ) { - super(options, 'offline', true, settings, platformId, zone, { synchronizeTabs: true }, useEmulator, useAuthEmulator); - } -} - -@NgModule({ - providers: [ AngularFirestoreOffline ] -}) export class FirestoreOfflineModule { - -} diff --git a/sample/src/app/home/home.component.ts b/sample/src/app/home/home.component.ts index 3f580e958..79f5ab976 100644 --- a/sample/src/app/home/home.component.ts +++ b/sample/src/app/home/home.component.ts @@ -8,7 +8,6 @@ import { FirebaseApp } from '@angular/fire'; {{ firebaseApp.name }} - diff --git a/sample/src/app/protected-lazy/protected-lazy.component.ts b/sample/src/app/protected-lazy/protected-lazy.component.ts index f84ce2d59..8c89f0924 100644 --- a/sample/src/app/protected-lazy/protected-lazy.component.ts +++ b/sample/src/app/protected-lazy/protected-lazy.component.ts @@ -1,7 +1,6 @@ import { Component, OnInit } from '@angular/core'; -import { DocumentChangeAction } from '@angular/fire/firestore'; +import { AngularFirestore, DocumentChangeAction } from '@angular/fire/firestore'; import { Observable } from 'rxjs'; -import { AngularFirestoreOffline } from '../firestore-offline/firestore-offline.module'; @Component({ selector: 'app-protected-lazy', @@ -12,7 +11,7 @@ export class ProtectedLazyComponent implements OnInit { public snapshot: Observable[]>; - constructor(private afs: AngularFirestoreOffline) { + constructor(private afs: AngularFirestore) { this.snapshot = afs.collection('test').snapshotChanges(); } diff --git a/sample/src/app/upboats/upboats.component.ts b/sample/src/app/upboats/upboats.component.ts index 4fa023171..bbd17ffaa 100644 --- a/sample/src/app/upboats/upboats.component.ts +++ b/sample/src/app/upboats/upboats.component.ts @@ -1,10 +1,10 @@ import { Component, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; import { map, startWith, tap } from 'rxjs/operators'; -import { AngularFirestoreOffline } from '../firestore-offline/firestore-offline.module'; import firebase from 'firebase/app'; import { makeStateKey, TransferState } from '@angular/platform-browser'; import { trace } from '@angular/fire/performance'; +import { AngularFirestore } from '@angular/fire/firestore'; type Animal = { name: string, upboats: number, id: string, hasPendingWrites: boolean }; @@ -17,7 +17,7 @@ export class UpboatsComponent implements OnInit { public animals: Observable; - constructor(private firestore: AngularFirestoreOffline, state: TransferState) { + constructor(private firestore: AngularFirestore, state: TransferState) { const collection = firestore.collection('animals', ref => ref.orderBy('upboats', 'desc').orderBy('updatedAt', 'desc') ); diff --git a/sample/src/main.ts b/sample/src/main.ts index ebf5fc9a6..852cd0e2c 100644 --- a/sample/src/main.ts +++ b/sample/src/main.ts @@ -1,7 +1,7 @@ import { enableProdMode } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; -import { AppModule } from './app/app.module'; +import { AppBrowserModule } from './app/app.browser.module'; import { environment } from './environments/environment'; if (environment.production) { @@ -9,6 +9,6 @@ if (environment.production) { } document.addEventListener('DOMContentLoaded', () => { - platformBrowserDynamic().bootstrapModule(AppModule) + platformBrowserDynamic().bootstrapModule(AppBrowserModule) .catch(err => console.error(err)); }); diff --git a/sample/yarn.lock b/sample/yarn.lock index e4f5c774c..68d3ad3eb 100644 --- a/sample/yarn.lock +++ b/sample/yarn.lock @@ -2,31 +2,31 @@ # yarn lockfile v1 -"@angular-devkit/architect@0.1100.0": - version "0.1100.0" - resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1100.0.tgz#0ef9cb3616e0368fa6898574cafeec7cd4357930" - integrity sha512-JFPEpEgxJGk5eaJsEilQNI5rOAKCawMdGFAq1uBlYeXSt3iMfFfn//ayvIsE7L2y5b4MC0rzafWSNyDSP3+WuA== +"@angular-devkit/architect@0.1100.2": + version "0.1100.2" + resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1100.2.tgz#7567af030afe7d6cdea1771bcd2a193a19a90dc9" + integrity sha512-wSMMM8eBPol48OtvIyrIq2H9rOIiJmrPEtPbH0BSuPX0B8BckVImeTPzloqxSrpul4tY7Iwx0zwISDEgb59Vbw== dependencies: - "@angular-devkit/core" "11.0.0" + "@angular-devkit/core" "11.0.2" rxjs "6.6.3" "@angular-devkit/architect@^0.1001.0", "@angular-devkit/architect@~0.1001.3": - version "0.1001.3" - resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1001.3.tgz#168aa424be9d0dad90d1a03129c3999fbf76a1cc" - integrity sha512-WS5IAN6I73jKapiHKYz3U05Kka4eVRmwCk++GWM2uGChluiZsI87eK8vxMS3KWDIqTnAOuMpDt3XWxlASv1nlQ== + version "0.1001.7" + resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1001.7.tgz#b3d75cddf5c5a2677cebba1d7b7eaffe73748d37" + integrity sha512-uFYIvMdewU44GbIyRfsUHNMLkx+C0kokpnj7eH5NbJfbyFpCfd3ijBHh+voPdPsDRWs9lLgjbxfHpswSPj4D8w== dependencies: - "@angular-devkit/core" "10.1.3" + "@angular-devkit/core" "10.1.7" rxjs "6.6.2" "@angular-devkit/build-angular@~0.1100.0": - version "0.1100.0" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-0.1100.0.tgz#11c29c3f324150ad3ae867fb06a7dc9b2dcaa910" - integrity sha512-jCgtnqfBLO00LNImqtjeW07ijYXdpzhsOM4jzlhafh/NesjWJXgg1NI1K7QJvmVL79TeqbBsMj8IOLGTMUCDJw== - dependencies: - "@angular-devkit/architect" "0.1100.0" - "@angular-devkit/build-optimizer" "0.1100.0" - "@angular-devkit/build-webpack" "0.1100.0" - "@angular-devkit/core" "11.0.0" + version "0.1100.2" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-0.1100.2.tgz#afbeef979df4dbafeed3ff3de438dc9f35e2d148" + integrity sha512-5Qo3DDKggzUJKibNgeyE5mIMFYP0tVebNvMatpbnYnR/U0fUuuQdvNC68s380M5KoOuubfeXr0Js0VFk0mkaow== + dependencies: + "@angular-devkit/architect" "0.1100.2" + "@angular-devkit/build-optimizer" "0.1100.2" + "@angular-devkit/build-webpack" "0.1100.2" + "@angular-devkit/core" "11.0.2" "@babel/core" "7.12.3" "@babel/generator" "7.12.1" "@babel/plugin-transform-runtime" "7.12.1" @@ -34,7 +34,7 @@ "@babel/runtime" "7.12.1" "@babel/template" "7.10.4" "@jsdevtools/coverage-istanbul-loader" "3.0.5" - "@ngtools/webpack" "11.0.0" + "@ngtools/webpack" "11.0.2" ansi-colors "4.1.1" autoprefixer "9.8.6" babel-loader "8.1.0" @@ -44,7 +44,7 @@ circular-dependency-plugin "5.2.0" copy-webpack-plugin "6.2.1" core-js "3.6.5" - css-loader "5.0.0" + css-loader "4.3.0" cssnano "4.1.10" file-loader "6.1.1" find-cache-dir "3.3.1" @@ -93,10 +93,10 @@ webpack-subresource-integrity "1.5.1" worker-plugin "5.0.0" -"@angular-devkit/build-optimizer@0.1100.0": - version "0.1100.0" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.1100.0.tgz#fae70c407fa2ec26ef839f9f2706cb3be990121b" - integrity sha512-RitDB5JCNDUN2CoNqf/FwLCwdWruApjxb7nUVb9C/uQgGEnrBojyxS/Rv/jCioom86s0sfY9wo79jdxd6AercQ== +"@angular-devkit/build-optimizer@0.1100.2": + version "0.1100.2" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.1100.2.tgz#93dea833aed64d265cfdfebb6580e10cf909630b" + integrity sha512-2ZdEeAs0a53g9LDkP5H2mCEPLyk7yd9P7eTepNYvIOz3xJ6W6dB2CqotPMfnHgd4o12cbzCOWrPBxbfo/VnMig== dependencies: loader-utils "2.0.0" source-map "0.7.3" @@ -104,19 +104,19 @@ typescript "4.0.5" webpack-sources "2.0.1" -"@angular-devkit/build-webpack@0.1100.0": - version "0.1100.0" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.1100.0.tgz#66b78cc1f5d9d5f2f0b551d3f848bebef4a54ad7" - integrity sha512-9diP/A6NtQxSxjbBMj9h9MHrAj4VqCvuFraR928eFaxEoRKcIwSTHhOiolRm+GL5V0VB+O53FRYDk3gC7BGjmQ== +"@angular-devkit/build-webpack@0.1100.2": + version "0.1100.2" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.1100.2.tgz#1613334c396931de295d47d8ec8ef980592cc00d" + integrity sha512-XVMtWoxNa3wJLRjJ846Y02PzupdbUizdAtggRu2731RLMvI1KawWlsTURi12MNUnoVQYm9eldiIA/Y1UqeE8mQ== dependencies: - "@angular-devkit/architect" "0.1100.0" - "@angular-devkit/core" "11.0.0" + "@angular-devkit/architect" "0.1100.2" + "@angular-devkit/core" "11.0.2" rxjs "6.6.3" -"@angular-devkit/core@10.1.3", "@angular-devkit/core@^10.1.0": - version "10.1.3" - resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-10.1.3.tgz#48776a87253b40f6005b14413e089a1fee6b7227" - integrity sha512-Ub31/eqFtSuQy3V+B74Jt0jAUw8fs8sbd0ZL2UHYUJyrwm20iIRam+mOD3Sj8HFrDGLR8m56KsxJ12KvC1oxtQ== +"@angular-devkit/core@10.1.7": + version "10.1.7" + resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-10.1.7.tgz#c4c4332d738075bf1346aa040c78756e3144ba4b" + integrity sha512-RRyDkN2FByA+nlnRx/MzUMK1FXwj7+SsrzJcvZfWx4yA5rfKmJiJryXQEzL44GL1aoaXSuvOYu3H72wxZADN8Q== dependencies: ajv "6.12.4" fast-json-stable-stringify "2.1.0" @@ -124,10 +124,10 @@ rxjs "6.6.2" source-map "0.7.3" -"@angular-devkit/core@11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-11.0.0.tgz#bf69f1fb7a00d0496785f84122daae7dc27a4b14" - integrity sha512-fXZtSs3J4S12hboi3om1FA+QS0e8nuQMyzl2nkmtuhcELUFMmSrEl36dtCni5e7Svs46BUAZ5w8EazIkgGQDJg== +"@angular-devkit/core@11.0.2": + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-11.0.2.tgz#dd3475912e830740e71e14e3168d609e8ddef8c6" + integrity sha512-vUmmUNmNM9oRcDmt0PunU/ayglo0apq4pGL9Z5jj6alf2WwEiTcGHjyuZSDIO9MOLi41519jp3mDx79qXvvyww== dependencies: ajv "6.12.6" fast-json-stable-stringify "2.1.0" @@ -135,32 +135,43 @@ rxjs "6.6.3" source-map "0.7.3" -"@angular-devkit/schematics@11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-11.0.0.tgz#ebdbd3b4cf9f740f793df3200cd28c00447abfc8" - integrity sha512-oCz9E0thA5WdGDuv6biu3X5kw5/vNE4ZZOKT2sHBQMpAuuDYrDpfTYQJjXQtjfXWvmlr8L8aqDD9N4HXsE4Esw== +"@angular-devkit/core@^10.1.0": + version "10.2.0" + resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-10.2.0.tgz#fcde160afc2786d2da0166526f065c6cf98684c0" + integrity sha512-XAszFhSF3mZw1VjoOsYGbArr5NJLcStjOvcCGjBPl1UBM2AKpuCQXHxI9XJGYKL3B93Vp5G58d8qkHvamT53OA== + dependencies: + ajv "6.12.4" + fast-json-stable-stringify "2.1.0" + magic-string "0.25.7" + rxjs "6.6.2" + source-map "0.7.3" + +"@angular-devkit/schematics@11.0.2": + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-11.0.2.tgz#b5aa914d7e91d92b4eeadb7aed3b5228497abbf3" + integrity sha512-unNewc+Y9ofrdKxXNoSHKUL6wvV8Vgh2nJMTLI1VAw8nfqgWphI+s5XwbVzog65nhZ10xJeaUm9u5R8pxLDpQg== dependencies: - "@angular-devkit/core" "11.0.0" + "@angular-devkit/core" "11.0.2" ora "5.1.0" rxjs "6.6.3" "@angular/animations@~11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-11.0.0.tgz#6f567930dca8eb8ab1320f1f48feb981493b86c6" - integrity sha512-RGaAnZOI73bPnNWrJq/p8sc+hpUBhScq139M6r4qQjQPsPahazL6v6hHAgRhZNemqw164d1oE4K/22O/i0E3Tw== + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-11.0.2.tgz#c095ab0aed4491732c81a894987bcab1a854ab15" + integrity sha512-uF/RlBY1rznbuw+1lm8Q2HKDrBOQQ2Bi2cUPuef+ALn+lxGl501eHlE+PTtBjDEzJcJPfd4pE3Ww3+3Il+D+Tw== dependencies: tslib "^2.0.0" "@angular/cli@~11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-11.0.0.tgz#8dcd73bd528e76b21178c43becab10837cfe8039" - integrity sha512-U9sh9r1CSqS78QjuosM3JDXUUTf8eVP1+kSchWEsxjJ0kfdvj7PvtKD1kmRH7HA5lD2q7QfGEvfHpfxMVzKxRg== - dependencies: - "@angular-devkit/architect" "0.1100.0" - "@angular-devkit/core" "11.0.0" - "@angular-devkit/schematics" "11.0.0" - "@schematics/angular" "11.0.0" - "@schematics/update" "0.1100.0" + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-11.0.2.tgz#15ee1732258deec8ecb93f6ccac52d95230074d8" + integrity sha512-mebt4ikwXD3gsbHRxKCpn83yW3UVnhiVDEpSXljs1YxscZ1X1dXrxb2g6LdAJwVp9xY5ERqRQeZM7eChqLTrvg== + dependencies: + "@angular-devkit/architect" "0.1100.2" + "@angular-devkit/core" "11.0.2" + "@angular-devkit/schematics" "11.0.2" + "@schematics/angular" "11.0.2" + "@schematics/update" "0.1100.2" "@yarnpkg/lockfile" "1.1.0" ansi-colors "4.1.1" debug "4.2.0" @@ -178,16 +189,16 @@ uuid "8.3.1" "@angular/common@~11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@angular/common/-/common-11.0.0.tgz#cc2a14b36c56f6c4d93427c2f8c17f55e4b464c9" - integrity sha512-chlbtxR7jpPs3Rc1ymdp3UfUzqEr57OFIxVMG6hROODclPQQk/7oOHdQB4hpUObaF9y4ZTLeKHKWiR/twi21Pg== + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular/common/-/common-11.0.2.tgz#7558b940a1110a9c6c65103b1ae8e18f2c8e939c" + integrity sha512-DGJuSBDt+bF77AzJNrLzeaFGSdwQ3OjgP9UUv1eKvaxp9D+lDam8suIJMuBwTsJII/yrDndY75ENPNTEqhmB2A== dependencies: tslib "^2.0.0" "@angular/compiler-cli@~11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-11.0.0.tgz#ff4c2c16284a31a4f8ff1d224f593f64a1458234" - integrity sha512-zrd/cU9syZ8XuQ3ItfIGaKDn1ZBCWyiqdLVRH9VDmyNqQFiCc/VWQ9Th9z8qpLptgdpzE9+lKFgeZJTDtbcveQ== + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-11.0.2.tgz#961df7f08dc98a6ea202e6aa22dc81ff29c9719d" + integrity sha512-I39zNcf6q0NN4PKCbY6Lm4WP69ujLrAew56X5yvlECW9CJlidV0qi1S/DGgAWhXTDOt8XA/KP1hD1pgJtMHjJQ== dependencies: "@babel/core" "^7.8.6" "@babel/types" "^7.8.6" @@ -203,7 +214,7 @@ source-map "^0.6.1" sourcemap-codec "^1.4.8" tslib "^2.0.0" - yargs "15.3.0" + yargs "^16.1.1" "@angular/compiler@9.0.0": version "9.0.0" @@ -211,9 +222,9 @@ integrity sha512-ctjwuntPfZZT2mNj2NDIVu51t9cvbhl/16epc5xEwyzyDt76pX9UgwvY+MbXrf/C/FWwdtmNtfP698BKI+9leQ== "@angular/compiler@~11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-11.0.0.tgz#b49997d0130e7c8cfe84fa73e5610892f4a772af" - integrity sha512-I7wVhdqvhtBTQTtW61z0lwPb1LiQQ0NOwjsbfN5sAc7/uwxw7em+Kyb/XJgBwgaTKtAL8bZEzdoQGLdsSKQF2g== + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-11.0.2.tgz#892cd38b3afa6ba63149d0bfd9265401a3d88d0c" + integrity sha512-deDT5+Lcph4nNhh6sZd0mBS5OkJL3HPbX5upDMI28Wuayt18Pn0UNotWY77/KV6wwIAInmlx9N06PoH3pq3hqg== dependencies: tslib "^2.0.0" @@ -223,9 +234,9 @@ integrity sha512-6Pxgsrf0qF9iFFqmIcWmjJGkkCaCm6V5QNnxMy2KloO3SDq6QuMVRbN9RtC8Urmo25LP+eZ6ZgYqFYpdD8Hd9w== "@angular/core@~11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@angular/core/-/core-11.0.0.tgz#cdb89f3877f6e5487a0e5f18d234447ec41e8184" - integrity sha512-FNewyMwYy+kGdw1xWfrtaPD2cSQs3kDVFbl8mNMSzp933W5yMsHDvjXb0+nPFqEb8ywEIdm3MsBMK0y3iBWZQw== + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular/core/-/core-11.0.2.tgz#490248b1d746e24513f2db996bd857e5a36d2f45" + integrity sha512-GyDebks5ZPHDyChDW3VvzJq00Ct0iuesNpb9z/GpKtOXqug3sGr4KgkFDUTbfizKPWyeoaLH9FQYP55215nCKQ== dependencies: tslib "^2.0.0" @@ -235,51 +246,51 @@ tslib "^2.0.0" "@angular/forms@~11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-11.0.0.tgz#fd9e167024e92df17ff98714ccae322ac4fbc1ab" - integrity sha512-hP6GF1ZkxKQp7Y+EVbEe9PPDQPrUQNdfVxphCWQYwu3tm8+tn1r91KVXkp2MA3M4Fh6Xo2HQEU2d+VXv4w0iNQ== + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-11.0.2.tgz#68de53edfd504b570bfcd23f371a2f21fbec5c49" + integrity sha512-Rn17VPviTTwiDn8Yt/UzdkXjFX0LdvjkmTNZoakqOk8/QNnsCG5sUDJAV7BKHk+2nEfUGCopS4kpBiLKLoaBpQ== dependencies: tslib "^2.0.0" "@angular/language-service@~11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-11.0.0.tgz#fda2e5d2ea4cac56662b04ca72a5a0b8c2dd169d" - integrity sha512-lwUVlaiIASNbKQ/EtCK5KOVIlpiyVvysN6idAD0rJHr6BRtrlqwiayNYbV5as5IJyPYLf2E8au3an9j0E/PFDw== + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-11.0.2.tgz#b9a97a9bdd3d10ac2335eb94bacf8ab5514aeeb5" + integrity sha512-Cfam/NEP8hKkcqBVGlkBVuPkojZukmVOxdtsFIkIjJW/mywad2lIfjHR/0rZ43jD1bPb7s+tyYcJBgNg42p2ng== "@angular/platform-browser-dynamic@~11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-11.0.0.tgz#630d77a0c853bcc2c80c30dfe6c101d6c7fe4ac1" - integrity sha512-NAmKGhHK+tl7dr/Hcqxvr/813Opec3Mv0IRwIgmKdlpZd7qAwT/mw4RnO4YPSEoDOM6hqGt7GdlWrSDX802duQ== + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-11.0.2.tgz#e8f621482c4fe04c14d799c771382891052ee2a2" + integrity sha512-iV7xz90FdmYFiXZRLkZtP9Lr+OXXh4bhkX7zN1L5H8SSUF4iOJGBdOts5Fiy5GZjYYILjF1pJoEIicfW/RSHjA== dependencies: tslib "^2.0.0" "@angular/platform-browser@~11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-11.0.0.tgz#314a0362e63ac7eef80adebfc5fbe4e7f2aa2a73" - integrity sha512-p8sF6JfaBI+YyLpp5OSg6UcCqjtLKRR+Otq1P/tro5SuxrsrBNRVU8j0tl/crkScsMwAvgmJ1joRyUKdI2mUGQ== + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-11.0.2.tgz#78e640400050c69ca3322b8df0f4ec48f629ec34" + integrity sha512-RHPm5/h8g3lSBgdg9OvO7w06juEwwBurvQcugXlk7+AeqznwzBodTWGPIATKzMySXQFmpy3bAZ3IxS0NkRrbWA== dependencies: tslib "^2.0.0" "@angular/platform-server@~11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-11.0.0.tgz#aca53c70e1e7010a5dd1e730c1cabd317e57b2af" - integrity sha512-0LsA4u5kCDKMOxcWf4HFH3PNYIhFcnzP/TYqYfIkY/GpQeC5agxWzddJofNi7g/Lh1UoK5hzf+3Ewn3o/aBxjA== + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-11.0.2.tgz#b9cf77c434fbaef5871c961a2def31c561bd473a" + integrity sha512-wC+JP0izKJMDQG+u7HXFYyKni7T65ELC6JknL4dODDHx+XylkFPXGI+EffffnVgJssheVDGrwe32Fh0Yjus0Lw== dependencies: domino "^2.1.2" tslib "^2.0.0" xhr2 "^0.2.0" "@angular/router@~11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@angular/router/-/router-11.0.0.tgz#59e855b0d34c4578e0556e181f2f28048fb0d5a8" - integrity sha512-10ZeobfK3HqVeWS6zjdKU16ccxFtdCHkxT11bnFg3Jwq9vKt+LI5KitAkCI5rYTY3DRfVzasRkqBzZfZMkbftw== + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular/router/-/router-11.0.2.tgz#38119a49edbfc60552d3403b4fc081ec705e2d6d" + integrity sha512-EU0lQ+3vv1ozly+Z4SgaGj/6CWMIExjnSnA1F7SI2yWmMgMMSb5CsGJ2xzr0V8ex3XZzuU2VuKF74muC58qSyg== dependencies: tslib "^2.0.0" "@angular/service-worker@^11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@angular/service-worker/-/service-worker-11.0.0.tgz#16818850529856f5a6812634b10294e99b54585e" - integrity sha512-elGlO2CxYZs0/p9I/gj4c7IPh+P4bpvMiF1BVMXU1Mj09Obvn0hHk9thhekdfKcYOQbvdZhn0wmrbYyxDifAqw== + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular/service-worker/-/service-worker-11.0.2.tgz#93b266e263d9e1c89b6587d176d9b6302f996a46" + integrity sha512-Npj+2lUoDkiSPs1VnPaHvwAyKXW2qjArAFBK3dltLTxFtjIbpSN82uP8PKajkXme8Kj40dyS4PHi2pvzQ8x3YA== dependencies: tslib "^2.0.0" @@ -292,14 +303,7 @@ call-me-maybe "^1.0.1" js-yaml "^3.13.1" -"@babel/code-frame@^7.0.0": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" - integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g== - dependencies: - "@babel/highlight" "^7.8.3" - -"@babel/code-frame@^7.10.4": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== @@ -311,7 +315,7 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.5.tgz#f56db0c4bb1bbbf221b4e81345aab4141e7cb0e9" integrity sha512-DTsS7cxrsH3by8nqQSpFSyjSfSYl57D6Cf4q8dW3LK83tBKBDCkfcay1nYkXq1nIHXnpX8WMMb/O25HOy3h1zg== -"@babel/core@7.12.3", "@babel/core@^7.8.6": +"@babel/core@7.12.3", "@babel/core@^7.7.5", "@babel/core@^7.8.6": version "7.12.3" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.3.tgz#1b436884e1e3bff6fb1328dc02b208759de92ad8" integrity sha512-0qXcZYKZp3/6N2jKYVxZv0aNCsxTSVCiK72DTiTYZAu7sjg73W0/aynWjMbiGd87EQL4WyA8reiJVh92AVla9g== @@ -333,28 +337,6 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.7.5": - version "7.11.6" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.6.tgz#3a9455dc7387ff1bac45770650bc13ba04a15651" - integrity sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.11.6" - "@babel/helper-module-transforms" "^7.11.0" - "@babel/helpers" "^7.10.4" - "@babel/parser" "^7.11.5" - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.11.5" - "@babel/types" "^7.11.5" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.1" - json5 "^2.1.2" - lodash "^4.17.19" - resolve "^1.3.2" - semver "^5.4.1" - source-map "^0.5.0" - "@babel/generator@7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.1.tgz#0d70be32bdaa03d7c51c8597dda76e0df1f15468" @@ -364,15 +346,6 @@ jsesc "^2.5.1" source-map "^0.5.0" -"@babel/generator@^7.11.5", "@babel/generator@^7.11.6": - version "7.11.6" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.6.tgz#b868900f81b163b4d464ea24545c61cbac4dc620" - integrity sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA== - dependencies: - "@babel/types" "^7.11.5" - jsesc "^2.5.1" - source-map "^0.5.0" - "@babel/generator@^7.12.1", "@babel/generator@^7.12.5": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.5.tgz#a2c50de5c8b6d708ab95be5e6053936c1884a4de" @@ -418,16 +391,7 @@ "@babel/helper-replace-supers" "^7.12.1" "@babel/helper-split-export-declaration" "^7.10.4" -"@babel/helper-create-regexp-features-plugin@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz#fdd60d88524659a0b6959c0579925e425714f3b8" - integrity sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g== - dependencies: - "@babel/helper-annotate-as-pure" "^7.10.4" - "@babel/helper-regex" "^7.10.4" - regexpu-core "^4.7.0" - -"@babel/helper-create-regexp-features-plugin@^7.12.1", "@babel/helper-create-regexp-features-plugin@^7.8.3": +"@babel/helper-create-regexp-features-plugin@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.1.tgz#18b1302d4677f9dc4740fe8c9ed96680e29d37e8" integrity sha512-rsZ4LGvFTZnzdNZR5HZdmJVuXK8834R5QkF3WvcnBhrlVtF0HSIUC6zbreL9MgjTywhKokn8RIYRiq99+DLAxA== @@ -446,11 +410,11 @@ lodash "^4.17.19" "@babel/helper-explode-assignable-expression@^7.10.4": - version "7.11.4" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.11.4.tgz#2d8e3470252cc17aba917ede7803d4a7a276a41b" - integrity sha512-ux9hm3zR4WV1Y3xXxXkdG/0gxF9nvI0YVmKVhvK9AfMoaQkemL3sJpXw+Xbz65azo8qJiEz2XVDUpK3KYhH3ZQ== + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.12.1.tgz#8006a466695c4ad86a2a5f2fb15b5f2c31ad5633" + integrity sha512-dmUwH8XmlrUpVqgtZ737tK88v07l840z9j3OEhCLwKTkjlvKpfqXVIZ0wpK3aeOxspwGrf/5AP5qLx4rO3w5rA== dependencies: - "@babel/types" "^7.10.4" + "@babel/types" "^7.12.1" "@babel/helper-function-name@^7.10.4": version "7.10.4" @@ -475,13 +439,6 @@ dependencies: "@babel/types" "^7.10.4" -"@babel/helper-member-expression-to-functions@^7.10.4": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz#ae69c83d84ee82f4b42f96e2a09410935a8f26df" - integrity sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q== - dependencies: - "@babel/types" "^7.11.0" - "@babel/helper-member-expression-to-functions@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.1.tgz#fba0f2fcff3fba00e6ecb664bb5e6e26e2d6165c" @@ -489,13 +446,6 @@ dependencies: "@babel/types" "^7.12.1" -"@babel/helper-module-imports@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz#4c5c54be04bd31670a7382797d75b9fa2e5b5620" - integrity sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw== - dependencies: - "@babel/types" "^7.10.4" - "@babel/helper-module-imports@^7.12.1": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz#1bfc0229f794988f76ed0a4d4e90860850b54dfb" @@ -503,19 +453,6 @@ dependencies: "@babel/types" "^7.12.5" -"@babel/helper-module-transforms@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz#b16f250229e47211abdd84b34b64737c2ab2d359" - integrity sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg== - dependencies: - "@babel/helper-module-imports" "^7.10.4" - "@babel/helper-replace-supers" "^7.10.4" - "@babel/helper-simple-access" "^7.10.4" - "@babel/helper-split-export-declaration" "^7.11.0" - "@babel/template" "^7.10.4" - "@babel/types" "^7.11.0" - lodash "^4.17.19" - "@babel/helper-module-transforms@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz#7954fec71f5b32c48e4b303b437c34453fd7247c" @@ -538,12 +475,7 @@ dependencies: "@babel/types" "^7.10.4" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670" - integrity sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ== - -"@babel/helper-plugin-utils@^7.10.4": +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== @@ -564,16 +496,6 @@ "@babel/helper-wrap-function" "^7.10.4" "@babel/types" "^7.12.1" -"@babel/helper-replace-supers@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz#d585cd9388ea06e6031e4cd44b6713cbead9e6cf" - integrity sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.10.4" - "@babel/helper-optimise-call-expression" "^7.10.4" - "@babel/traverse" "^7.10.4" - "@babel/types" "^7.10.4" - "@babel/helper-replace-supers@^7.12.1": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.5.tgz#f009a17543bbbbce16b06206ae73b63d3fca68d9" @@ -584,14 +506,6 @@ "@babel/traverse" "^7.12.5" "@babel/types" "^7.12.5" -"@babel/helper-simple-access@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz#0f5ccda2945277a2a7a2d3a821e15395edcf3461" - integrity sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw== - dependencies: - "@babel/template" "^7.10.4" - "@babel/types" "^7.10.4" - "@babel/helper-simple-access@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz#32427e5aa61547d38eb1e6eaf5fd1426fdad9136" @@ -624,24 +538,15 @@ integrity sha512-YpJabsXlJVWP0USHjnC/AQDTLlZERbON577YUVO/wLpqyj6HAtVYnWaQaN0iUN+1/tWn3c+uKKXjRut5115Y2A== "@babel/helper-wrap-function@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz#8a6f701eab0ff39f765b5a1cfef409990e624b87" - integrity sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug== + version "7.12.3" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.12.3.tgz#3332339fc4d1fbbf1c27d7958c27d34708e990d9" + integrity sha512-Cvb8IuJDln3rs6tzjW3Y8UeelAOdnpB8xtQ4sme2MSZ9wOxrbThporC0y/EtE16VAtoyEfLM404Xr1e0OOp+ow== dependencies: "@babel/helper-function-name" "^7.10.4" "@babel/template" "^7.10.4" "@babel/traverse" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helpers@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.4.tgz#2abeb0d721aff7c0a97376b9e1f6f65d7a475044" - integrity sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA== - dependencies: - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.10.4" - "@babel/types" "^7.10.4" - "@babel/helpers@^7.12.1": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.5.tgz#1a1ba4a768d9b58310eda516c449913fe647116e" @@ -651,7 +556,7 @@ "@babel/traverse" "^7.12.5" "@babel/types" "^7.12.5" -"@babel/highlight@^7.10.4", "@babel/highlight@^7.8.3": +"@babel/highlight@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== @@ -660,12 +565,7 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.10.4", "@babel/parser@^7.11.5": - version "7.11.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.5.tgz#c7ff6303df71080ec7a4f5b8c003c58f1cf51037" - integrity sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q== - -"@babel/parser@^7.12.3", "@babel/parser@^7.12.5": +"@babel/parser@^7.10.4", "@babel/parser@^7.12.3", "@babel/parser@^7.12.5": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.5.tgz#b4af32ddd473c0bfa643bd7ff0728b8e71b81ea0" integrity sha512-FVM6RZQ0mn2KCf1VUED7KepYeUWoVShczewOCfm3nzoBybaih51h+sYVVGthW9M6lPByEPTQf+xm27PBdlpwmQ== @@ -769,7 +669,7 @@ "@babel/helper-create-class-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-proposal-unicode-property-regex@^7.12.1": +"@babel/plugin-proposal-unicode-property-regex@^7.12.1", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz#2a183958d417765b9eae334f47758e5d6a82e072" integrity sha512-MYq+l+PvHuw/rKUz1at/vb6nCnQ2gmJBNaM62z0OgH7B2W1D9pvkpYtlti9bGtizNIU1K3zm4bZF9F91efVY0w== @@ -777,14 +677,6 @@ "@babel/helper-create-regexp-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz#4483cda53041ce3413b7fe2f00022665ddfaa75d" - integrity sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-async-generators@^7.8.0": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" @@ -927,7 +819,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-dotall-regex@^7.12.1": +"@babel/plugin-transform-dotall-regex@^7.12.1", "@babel/plugin-transform-dotall-regex@^7.4.4": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.1.tgz#a1d16c14862817b6409c0a678d6f9373ca9cd975" integrity sha512-B2pXeRKoLszfEW7J4Hg9LoFaWEbr/kzo3teWHmtFCszjRNa/b40f9mfeqZsIDLLt/FjwQ6pz/Gdlwy85xNckBA== @@ -935,14 +827,6 @@ "@babel/helper-create-regexp-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz#c3c6ec5ee6125c6993c5cbca20dc8621a9ea7a6e" - integrity sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-transform-duplicate-keys@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.1.tgz#745661baba295ac06e686822797a69fbaa2ca228" @@ -1228,9 +1112,9 @@ regenerator-runtime "^0.13.4" "@babel/runtime@^7.8.4": - version "7.9.2" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.2.tgz#d90df0583a3a252f09aaa619665367bae518db06" - integrity sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q== + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e" + integrity sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg== dependencies: regenerator-runtime "^0.13.4" @@ -1243,22 +1127,7 @@ "@babel/parser" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/traverse@^7.10.4", "@babel/traverse@^7.11.5": - version "7.11.5" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.5.tgz#be777b93b518eb6d76ee2e1ea1d143daa11e61c3" - integrity sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.11.5" - "@babel/helper-function-name" "^7.10.4" - "@babel/helper-split-export-declaration" "^7.11.0" - "@babel/parser" "^7.11.5" - "@babel/types" "^7.11.5" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.19" - -"@babel/traverse@^7.12.1", "@babel/traverse@^7.12.5": +"@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.5": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.5.tgz#78a0c68c8e8a35e4cacfd31db8bb303d5606f095" integrity sha512-xa15FbQnias7z9a62LwYAA5SZZPkHIXpd42C6uW68o8uTuua96FHZy1y61Va5P/i83FAAcMpW8+A/QayntzuqA== @@ -1273,16 +1142,7 @@ globals "^11.1.0" lodash "^4.17.19" -"@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.11.5", "@babel/types@^7.4.4": - version "7.11.5" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.5.tgz#d9de577d01252d77c6800cee039ee64faf75662d" - integrity sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q== - dependencies: - "@babel/helper-validator-identifier" "^7.10.4" - lodash "^4.17.19" - to-fast-properties "^2.0.0" - -"@babel/types@^7.12.1", "@babel/types@^7.12.5", "@babel/types@^7.8.6": +"@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.12.1", "@babel/types@^7.12.5", "@babel/types@^7.4.4", "@babel/types@^7.8.6": version "7.12.6" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.6.tgz#ae0e55ef1cce1fbc881cd26f8234eb3e657edc96" integrity sha512-hwyjw6GvjBLiyy3W0YQf0Z5Zf4NpYejUnKFcfcUhZCSffoBBp30w6wP2Wn6pk31jMYZvcOrB/1b7cGXvEoKogA== @@ -1305,16 +1165,16 @@ resolved "https://registry.yarnpkg.com/@firebase/analytics-types/-/analytics-types-0.4.0.tgz#d6716f9fa36a6e340bc0ecfe68af325aa6f60508" integrity sha512-Jj2xW+8+8XPfWGkv9HPv/uR+Qrmq37NPYT352wf7MvE9LrstpLVmFg3LqG6MCRr5miLAom5sen2gZ+iOhVDeRA== -"@firebase/analytics@0.6.1": - version "0.6.1" - resolved "https://registry.yarnpkg.com/@firebase/analytics/-/analytics-0.6.1.tgz#dea1504e75563b516f637d4e62c2fb887be54796" - integrity sha512-Pn7KPkH/M2JXoyoDHfdSjTBHTlnqe6rHo/vjsSvveA46dUP/GfDpcKWGfy/OBXKrIvKUVP7ZhyZo0Gb6jKB0cw== +"@firebase/analytics@0.6.2": + version "0.6.2" + resolved "https://registry.yarnpkg.com/@firebase/analytics/-/analytics-0.6.2.tgz#7f45675a1b524fff4d9e9fe318fd6e2ed067a325" + integrity sha512-4Ceov+rPfOEPIdbjlpTim/wbcUUneIesHag4UOzvmFsRRXqbxLwQpyZQWEbTSriUeU8uTKj9yOW32hsskV9Klg== dependencies: "@firebase/analytics-types" "0.4.0" - "@firebase/component" "0.1.20" - "@firebase/installations" "0.4.18" + "@firebase/component" "0.1.21" + "@firebase/installations" "0.4.19" "@firebase/logger" "0.2.6" - "@firebase/util" "0.3.3" + "@firebase/util" "0.3.4" tslib "^1.11.1" "@firebase/app-types@0.6.1", "@firebase/app-types@^0.6.1": @@ -1322,15 +1182,15 @@ resolved "https://registry.yarnpkg.com/@firebase/app-types/-/app-types-0.6.1.tgz#dcbd23030a71c0c74fc95d4a3f75ba81653850e9" integrity sha512-L/ZnJRAq7F++utfuoTKX4CLBG5YR7tFO3PLzG1/oXXKEezJ0kRL3CMRoueBEmTCzVb/6SIs2Qlaw++uDgi5Xyg== -"@firebase/app@0.6.12": - version "0.6.12" - resolved "https://registry.yarnpkg.com/@firebase/app/-/app-0.6.12.tgz#003fbee35ea31e9ce21b86d92070cd7d61047dd9" - integrity sha512-gko1NxRLJn+BMqDK6GBhcCDApD5rX5zhNfS7frl/uic8us9GnAuo6NtHuO0Q+AAjYB1Sv3YtPLXI7ckQEO9Wew== +"@firebase/app@0.6.13": + version "0.6.13" + resolved "https://registry.yarnpkg.com/@firebase/app/-/app-0.6.13.tgz#f2e9fa9e75815e54161dc34659a60f1fffd9a450" + integrity sha512-xGrJETzvCb89VYbGSHFHCW7O/y067HRxT7MGehUE1xMxdPVBDNayHnxEuKwzfGvXAjVmajXBKFlKxaCWpgSjCQ== dependencies: "@firebase/app-types" "0.6.1" - "@firebase/component" "0.1.20" + "@firebase/component" "0.1.21" "@firebase/logger" "0.2.6" - "@firebase/util" "0.3.3" + "@firebase/util" "0.3.4" dom-storage "2.1.0" tslib "^1.11.1" xmlhttprequest "1.8.0" @@ -1345,10 +1205,10 @@ resolved "https://registry.yarnpkg.com/@firebase/auth-types/-/auth-types-0.10.1.tgz#7815e71c9c6f072034415524b29ca8f1d1770660" integrity sha512-/+gBHb1O9x/YlG7inXfxff/6X3BPZt4zgBv4kql6HEmdzNQCodIRlEYnI+/da+lN+dha7PjaFH7C7ewMmfV7rw== -"@firebase/auth@0.15.1": - version "0.15.1" - resolved "https://registry.yarnpkg.com/@firebase/auth/-/auth-0.15.1.tgz#2e0e7397d6f754d81916babd9bce21a51f4b25a3" - integrity sha512-qVJTmq/6l3/o6V93nAD+n1ExTywbKEFYbuuI1TZIUryy5KSXOFnxilmZI4yJeQSZ3ee06YiJsIRYRaYUeg6JQQ== +"@firebase/auth@0.15.2": + version "0.15.2" + resolved "https://registry.yarnpkg.com/@firebase/auth/-/auth-0.15.2.tgz#9ada3f37620d131a1c56994138a599b5c9f9ca2e" + integrity sha512-2n32PBi6x9jVhc0E/ewKLUCYYTzFEXL4PNkvrrlGKbzeTBEkkyzfgUX7OV9UF5wUOG+gurtUthuur1zspZ/9hg== dependencies: "@firebase/auth-types" "0.10.1" @@ -1360,12 +1220,12 @@ "@firebase/util" "0.3.2" tslib "^1.11.1" -"@firebase/component@0.1.20": - version "0.1.20" - resolved "https://registry.yarnpkg.com/@firebase/component/-/component-0.1.20.tgz#bc8ab0e40d181783c477f68de57e585be96405eb" - integrity sha512-UF9kBCco3U5AMJVNrup8kzOjksvmjmwL88vr/cL3BQ7DeTZWMf15iBOmBf+9HnhtPboN8Cw+84VT21aXGHBgNQ== +"@firebase/component@0.1.21": + version "0.1.21" + resolved "https://registry.yarnpkg.com/@firebase/component/-/component-0.1.21.tgz#56062eb0d449dc1e7bbef3c084a9b5fa48c7c14d" + integrity sha512-kd5sVmCLB95EK81Pj+yDTea8pzN2qo/1yr0ua9yVi6UgMzm6zAeih73iVUkaat96MAHy26yosMufkvd3zC4IKg== dependencies: - "@firebase/util" "0.3.3" + "@firebase/util" "0.3.4" tslib "^1.11.1" "@firebase/database-types@0.5.2": @@ -1375,23 +1235,23 @@ dependencies: "@firebase/app-types" "0.6.1" -"@firebase/database-types@0.6.0": - version "0.6.0" - resolved "https://registry.yarnpkg.com/@firebase/database-types/-/database-types-0.6.0.tgz#7795bc6b1db93f4cbda9a241c8dfe1bb86033dc6" - integrity sha512-ljpU7/uboCGqFSe9CNgwd3+Xu5N8YCunzfPpeueuj2vjnmmypUi4QWxgC3UKtGbuv1q+crjeudZGLxnUoO0h7w== +"@firebase/database-types@0.6.1": + version "0.6.1" + resolved "https://registry.yarnpkg.com/@firebase/database-types/-/database-types-0.6.1.tgz#cf1cfc03e617ed4c2561703781f85ba4c707ff65" + integrity sha512-JtL3FUbWG+bM59iYuphfx9WOu2Mzf0OZNaqWiQ7lJR8wBe7bS9rIm9jlBFtksB7xcya1lZSQPA/GAy2jIlMIkA== dependencies: "@firebase/app-types" "0.6.1" -"@firebase/database@0.7.0": - version "0.7.0" - resolved "https://registry.yarnpkg.com/@firebase/database/-/database-0.7.0.tgz#969b69e5ac6a9ef6c388a2a50fcdf7ea44fbc580" - integrity sha512-pVio41uGhy6HNSk1uBHq9wTzO83bg2Jb527XFILIk4p/KFBbuQwKnQn+65SfnsDlElC1HjHBerTaonHLYevJqA== +"@firebase/database@0.8.1": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@firebase/database/-/database-0.8.1.tgz#a7bc1c01052d35817a242c21bfe09ab29ee485a3" + integrity sha512-/1HhR4ejpqUaM9Cn3KSeNdQvdlehWIhdfTVWFxS73ZlLYf7ayk9jITwH10H3ZOIm5yNzxF67p/U7Z/0IPhgWaQ== dependencies: "@firebase/auth-interop-types" "0.1.5" - "@firebase/component" "0.1.20" - "@firebase/database-types" "0.6.0" + "@firebase/component" "0.1.21" + "@firebase/database-types" "0.6.1" "@firebase/logger" "0.2.6" - "@firebase/util" "0.3.3" + "@firebase/util" "0.3.4" faye-websocket "0.11.3" tslib "^1.11.1" @@ -1413,16 +1273,16 @@ resolved "https://registry.yarnpkg.com/@firebase/firestore-types/-/firestore-types-2.0.0.tgz#1f6212553b240f1a8905bb8dcf1f87769138c5c0" integrity sha512-ZGb7p1SSQJP0Z+kc9GAUi+Fx5rJatFddBrS1ikkayW+QHfSIz0omU23OgSHcBGTxe8dJCeKiKA2Yf+tkDKO/LA== -"@firebase/firestore@2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@firebase/firestore/-/firestore-2.0.0.tgz#d12841165788da148299d73babec62bf8e16154e" - integrity sha512-KHp5/yRmdQkpfGg8zotTJlUweXVsTe6Ip68iruc51VhYjWgmIb5QorelE1N5+O3kFqiDTOfBfeCXaO14bXk4wA== +"@firebase/firestore@2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@firebase/firestore/-/firestore-2.0.4.tgz#c4be6f3540f607fd8e200cfba83c4997c29447fe" + integrity sha512-fzJKj/4h4jOwPSfHB42XBJIC0zsPsepU6FcBO+8nSx7G2IPfTw8cMgSNin2gPqX6tR1w1NQtHiSlXiRKsbMZdA== dependencies: - "@firebase/component" "0.1.20" + "@firebase/component" "0.1.21" "@firebase/firestore-types" "2.0.0" "@firebase/logger" "0.2.6" - "@firebase/util" "0.3.3" - "@firebase/webchannel-wrapper" "0.4.0" + "@firebase/util" "0.3.4" + "@firebase/webchannel-wrapper" "0.4.1" "@grpc/grpc-js" "^1.0.0" "@grpc/proto-loader" "^0.5.0" node-fetch "2.6.1" @@ -1433,12 +1293,12 @@ resolved "https://registry.yarnpkg.com/@firebase/functions-types/-/functions-types-0.4.0.tgz#0b789f4fe9a9c0b987606c4da10139345b40f6b9" integrity sha512-3KElyO3887HNxtxNF1ytGFrNmqD+hheqjwmT3sI09FaDCuaxGbOnsXAXH2eQ049XRXw9YQpHMgYws/aUNgXVyQ== -"@firebase/functions@0.6.0": - version "0.6.0" - resolved "https://registry.yarnpkg.com/@firebase/functions/-/functions-0.6.0.tgz#38e4ba62885c25c631ff53469a8aa5fbbd3ff9d9" - integrity sha512-XDVyDLBJwGCqI/agGxRrPYfit7HTcOSXTrjlC8NJr5+h3zzUuAB/+VEfaa8mSEZR+0AjY67B1cPed0WuXsU48g== +"@firebase/functions@0.6.1": + version "0.6.1" + resolved "https://registry.yarnpkg.com/@firebase/functions/-/functions-0.6.1.tgz#32640b8f877637057dfaaeb122be8c8e99ad1af7" + integrity sha512-xNCAY3cLlVWE8Azf+/84OjnaXMoyUstJ3vwVRG0ie22QhsdQuPa1tXTiPX4Tmm+Hbbd/Aw0A/7dkEnuW+zYzaQ== dependencies: - "@firebase/component" "0.1.20" + "@firebase/component" "0.1.21" "@firebase/functions-types" "0.4.0" "@firebase/messaging-types" "0.5.0" node-fetch "2.6.1" @@ -1449,14 +1309,14 @@ resolved "https://registry.yarnpkg.com/@firebase/installations-types/-/installations-types-0.3.4.tgz#589a941d713f4f64bf9f4feb7f463505bab1afa2" integrity sha512-RfePJFovmdIXb6rYwtngyxuEcWnOrzdZd9m7xAW0gRxDIjBT20n3BOhjpmgRWXo/DAxRmS7bRjWAyTHY9cqN7Q== -"@firebase/installations@0.4.18": - version "0.4.18" - resolved "https://registry.yarnpkg.com/@firebase/installations/-/installations-0.4.18.tgz#2a1842ae25521e170c7915e8a97bf8180e0d578b" - integrity sha512-el1PvpVbsNb6uXIoSKzI0A52K+h8yeLvI1tjMqdjnp+0xZQr2pwRJcBMvzt6aLrgBT06jMVB3R+fxfxxqgoO2g== +"@firebase/installations@0.4.19": + version "0.4.19" + resolved "https://registry.yarnpkg.com/@firebase/installations/-/installations-0.4.19.tgz#53f50aeb022996963f89f59560d7b4cf801869da" + integrity sha512-QqAQzosKVVqIx7oMt5ujF4NsIXgtlTnej4JXGJ8sQQuJoMnt3T+PFQRHbr7uOfVaBiHYhEaXCcmmhfKUHwKftw== dependencies: - "@firebase/component" "0.1.20" + "@firebase/component" "0.1.21" "@firebase/installations-types" "0.3.4" - "@firebase/util" "0.3.3" + "@firebase/util" "0.3.4" idb "3.0.2" tslib "^1.11.1" @@ -1470,15 +1330,15 @@ resolved "https://registry.yarnpkg.com/@firebase/messaging-types/-/messaging-types-0.5.0.tgz#c5d0ef309ced1758fda93ef3ac70a786de2e73c4" integrity sha512-QaaBswrU6umJYb/ZYvjR5JDSslCGOH6D9P136PhabFAHLTR4TWjsaACvbBXuvwrfCXu10DtcjMxqfhdNIB1Xfg== -"@firebase/messaging@0.7.2": - version "0.7.2" - resolved "https://registry.yarnpkg.com/@firebase/messaging/-/messaging-0.7.2.tgz#f9000d2837c37c163ad9eadc93220a72cced0daf" - integrity sha512-5FzxklNgZS5S03p0eKvhsj6mLGG06qgnaLEbLluKeuDJ5STR/+gWySuCdP9BhcJCsTGN77Qwa06MLK/d46R0rQ== +"@firebase/messaging@0.7.3": + version "0.7.3" + resolved "https://registry.yarnpkg.com/@firebase/messaging/-/messaging-0.7.3.tgz#31dded892455e4d0680e1452ff2fbfdfb9e4ce9b" + integrity sha512-63nOP2SmQJrj9jrhV3K96L5MRKS6AqmFVLX1XbGk6K6lz38ZC4LIoCcHxzUBXY7fCAuZvNmh/YB3pE8B2mTs8A== dependencies: - "@firebase/component" "0.1.20" - "@firebase/installations" "0.4.18" + "@firebase/component" "0.1.21" + "@firebase/installations" "0.4.19" "@firebase/messaging-types" "0.5.0" - "@firebase/util" "0.3.3" + "@firebase/util" "0.3.4" idb "3.0.2" tslib "^1.11.1" @@ -1487,16 +1347,16 @@ resolved "https://registry.yarnpkg.com/@firebase/performance-types/-/performance-types-0.0.13.tgz#58ce5453f57e34b18186f74ef11550dfc558ede6" integrity sha512-6fZfIGjQpwo9S5OzMpPyqgYAUZcFzZxHFqOyNtorDIgNXq33nlldTL/vtaUZA8iT9TT5cJlCrF/jthKU7X21EA== -"@firebase/performance@0.4.3": - version "0.4.3" - resolved "https://registry.yarnpkg.com/@firebase/performance/-/performance-0.4.3.tgz#f64b914a7cc3bf8dc533755de89d8b827e34eec3" - integrity sha512-oP7EvI8qvlAJgVGY25ZabXl/Xb82ykxKyYP+xNDs0Imdg+8GBOfzqQiGpM+BqovhTTdGPcpJmry7JYwpWMZ8bg== +"@firebase/performance@0.4.4": + version "0.4.4" + resolved "https://registry.yarnpkg.com/@firebase/performance/-/performance-0.4.4.tgz#5f13ea3b9a72a0ae9c36520c419be31448a0955a" + integrity sha512-CY/fzz7qGQ9hUkvOow22MeJhayHSjXmI4+0AqcxaUC4CWk4oQubyIC4pk62aH+yCwZNNeC7JJUEDbtqI/0rGkQ== dependencies: - "@firebase/component" "0.1.20" - "@firebase/installations" "0.4.18" + "@firebase/component" "0.1.21" + "@firebase/installations" "0.4.19" "@firebase/logger" "0.2.6" "@firebase/performance-types" "0.0.13" - "@firebase/util" "0.3.3" + "@firebase/util" "0.3.4" tslib "^1.11.1" "@firebase/polyfill@0.3.36": @@ -1513,16 +1373,16 @@ resolved "https://registry.yarnpkg.com/@firebase/remote-config-types/-/remote-config-types-0.1.9.tgz#fe6bbe4d08f3b6e92fce30e4b7a9f4d6a96d6965" integrity sha512-G96qnF3RYGbZsTRut7NBX0sxyczxt1uyCgXQuH/eAfUCngxjEGcZQnBdy6mvSdqdJh5mC31rWPO4v9/s7HwtzA== -"@firebase/remote-config@0.1.29": - version "0.1.29" - resolved "https://registry.yarnpkg.com/@firebase/remote-config/-/remote-config-0.1.29.tgz#a7e76e3f16a7c4fa07e203cc721dfbc975959dcc" - integrity sha512-VuKoubiE/kEfp5FXx7Nxw5c1TRYApBey7zdwTu/+U7qZFofHnUGDZs1vu82xTRnwbPtxh228FOwpZZ0iTrpVtA== +"@firebase/remote-config@0.1.30": + version "0.1.30" + resolved "https://registry.yarnpkg.com/@firebase/remote-config/-/remote-config-0.1.30.tgz#2cd6bbbed526a98b154e13a2cc73e748a77d7c3d" + integrity sha512-LAfLDcp1AN0V/7AkxBuTKy+Qnq9fKYKxbA5clrXRNVzJbTVnF5eFGsaUOlkes0ESG6lbqKy5ZcDgdl73zBIhAA== dependencies: - "@firebase/component" "0.1.20" - "@firebase/installations" "0.4.18" + "@firebase/component" "0.1.21" + "@firebase/installations" "0.4.19" "@firebase/logger" "0.2.6" "@firebase/remote-config-types" "0.1.9" - "@firebase/util" "0.3.3" + "@firebase/util" "0.3.4" tslib "^1.11.1" "@firebase/storage-types@0.3.13": @@ -1530,14 +1390,14 @@ resolved "https://registry.yarnpkg.com/@firebase/storage-types/-/storage-types-0.3.13.tgz#cd43e939a2ab5742e109eb639a313673a48b5458" integrity sha512-pL7b8d5kMNCCL0w9hF7pr16POyKkb3imOW7w0qYrhBnbyJTdVxMWZhb0HxCFyQWC0w3EiIFFmxoz8NTFZDEFog== -"@firebase/storage@0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@firebase/storage/-/storage-0.4.0.tgz#713d6a5a78880a4ee66afacb9ff47f5e293d3201" - integrity sha512-6AG1g2WbbVxscf40rHar+IAk6ocvg8IOM5NmlXHxcXt9KENSQYGNiHsGEROm+W7FOx2izuHTEfqPUr8Qh5EwNA== +"@firebase/storage@0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@firebase/storage/-/storage-0.4.2.tgz#bc5924b87bd2fdd4ab0de49851c0125ebc236b89" + integrity sha512-87CrvKrf8kijVekRBmUs8htsNz7N5X/pDhv3BvJBqw8K65GsUolpyjx0f4QJRkCRUYmh3MSkpa5P08lpVbC6nQ== dependencies: - "@firebase/component" "0.1.20" + "@firebase/component" "0.1.21" "@firebase/storage-types" "0.3.13" - "@firebase/util" "0.3.3" + "@firebase/util" "0.3.4" tslib "^1.11.1" "@firebase/util@0.3.2": @@ -1547,17 +1407,17 @@ dependencies: tslib "^1.11.1" -"@firebase/util@0.3.3": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@firebase/util/-/util-0.3.3.tgz#f85db70ca6ededd3d67c05c5f63c6da78a8aec00" - integrity sha512-VBuyR+6QAvrumzEtp3hMTRYkDnvsWuDMzqObca2Phn30RJTEV24P1RSMG5fw8LbSE+KkD9WiiiMJN++YoeyFaA== +"@firebase/util@0.3.4": + version "0.3.4" + resolved "https://registry.yarnpkg.com/@firebase/util/-/util-0.3.4.tgz#e389d0e0e2aac88a5235b06ba9431db999d4892b" + integrity sha512-VwjJUE2Vgr2UMfH63ZtIX9Hd7x+6gayi6RUXaTqEYxSbf/JmehLmAEYSuxS/NckfzAXWeGnKclvnXVibDgpjQQ== dependencies: tslib "^1.11.1" -"@firebase/webchannel-wrapper@0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.4.0.tgz#becce788818d3f47f0ac1a74c3c061ac1dcf4f6d" - integrity sha512-8cUA/mg0S+BxIZ72TdZRsXKBP5n5uRcE3k29TZhZw6oIiHBt9JA7CTb/4pE1uKtE/q5NeTY2tBDcagoZ+1zjXQ== +"@firebase/webchannel-wrapper@0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.4.1.tgz#600f2275ff54739ad5ac0102f1467b8963cd5f71" + integrity sha512-0yPjzuzGMkW1GkrC8yWsiN7vt1OzkMIi9HgxRmKREZl2wnNPOKo/yScTjXf/O57HM8dltqxPF6jlNLFVtc2qdw== "@google-cloud/common@^2.1.1": version "2.4.0" @@ -1665,13 +1525,12 @@ semver "^6.2.0" "@grpc/grpc-js@^1.0.0": - version "1.1.7" - resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.1.7.tgz#d3d71c6da95397e2d63895ccc4a05e7572f7b7e6" - integrity sha512-EuxMstI0u778dp0nk6Fe3gHXYPeV6FYsWOe0/QFwxv1NQ6bc5Wl/0Yxa4xl9uBlKElL6AIxuASmSfu7KEJhqiw== + version "1.2.1" + resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.2.1.tgz#6a0b4e1bc6039d84f945569ff8c3059f81284afe" + integrity sha512-JpGh2CgqnwVII0S9TMEX3HY+PkLJnb7HSAar3Md1Y3aWxTZqAGb7gTrNyBWn/zueaGFsMYRm2u/oYufWFYVoIQ== dependencies: - "@grpc/proto-loader" "^0.6.0-pre14" "@types/node" "^12.12.47" - google-auth-library "^6.0.0" + google-auth-library "^6.1.1" semver "^6.2.0" "@grpc/grpc-js@~1.0.3": @@ -1689,17 +1548,6 @@ lodash.camelcase "^4.3.0" protobufjs "^6.8.6" -"@grpc/proto-loader@^0.6.0-pre14": - version "0.6.0-pre9" - resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.6.0-pre9.tgz#0c6fe42f6c5ef9ce1b3cef7be64d5b09d6fe4d6d" - integrity sha512-oM+LjpEjNzW5pNJjt4/hq1HYayNeQT+eGrOPABJnYHv7TyNPDNzkQ76rDYZF86X5swJOa4EujEMzQ9iiTdPgww== - dependencies: - "@types/long" "^4.0.1" - lodash.camelcase "^4.3.0" - long "^4.0.0" - protobufjs "^6.9.0" - yargs "^15.3.1" - "@istanbuljs/schema@^0.1.2": version "0.1.2" resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" @@ -1721,12 +1569,12 @@ resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796" integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg== -"@ngtools/webpack@11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-11.0.0.tgz#bddc9ad4677de55d9df9418408079c2a2be4f482" - integrity sha512-thWOXiMfyVUUWDDRUUAIvb5HASovX1C0GcxRBFE8fXJMCwOPIwqZiAyJJlUUnie8BEP9yC/x6uLCud56ai4Uaw== +"@ngtools/webpack@11.0.2": + version "11.0.2" + resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-11.0.2.tgz#d9513854d474fe09350ce705d04fee38ffb8f0c7" + integrity sha512-GbNP6HMBVoee2CkYW/pknprFCeiOLz4FGE06yr4m0700c1i6wuX7AzyHfBcLGAIP6nVblNOT3eh5M41b3cDf8g== dependencies: - "@angular-devkit/core" "11.0.0" + "@angular-devkit/core" "11.0.2" enhanced-resolve "5.3.1" webpack-sources "2.0.1" @@ -1839,22 +1687,22 @@ resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA= -"@schematics/angular@11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-11.0.0.tgz#d292aeb472e1f5f11917df9f660d38b3f792dd5b" - integrity sha512-/4fkfryoCKQv7nnZgbQ/2aLg8418/SdrCi4ASN0xpfcj34oe2FqsKypeoJG+3bQVF8CLfseorvPNR2YINb4RQA== +"@schematics/angular@11.0.2": + version "11.0.2" + resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-11.0.2.tgz#63041d1931fe2d56135d730a6e43937a3eef4bab" + integrity sha512-tUIuCYJUzHYuiXGJ2KCuwxMocS56kPHaM8+neVYWwWbOxKzLZXv80gMm/pIWxrqUDCkIUi3yb4ienudFhgQLYg== dependencies: - "@angular-devkit/core" "11.0.0" - "@angular-devkit/schematics" "11.0.0" + "@angular-devkit/core" "11.0.2" + "@angular-devkit/schematics" "11.0.2" jsonc-parser "2.3.1" -"@schematics/update@0.1100.0": - version "0.1100.0" - resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.1100.0.tgz#1b7f834d88cdd86d13b2cd0f8d826bf4c934d064" - integrity sha512-61zhqIvKHiMR3nezM5FlUoWe2Lw2uKzmuSwcxA2d6SqjDXYyXrOSKmaPcbi7Emgh3VWsQadNpXuc5A2tbKCQhg== +"@schematics/update@0.1100.2": + version "0.1100.2" + resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.1100.2.tgz#d3a5c726d434d6c8ff04db8836f829299ca7108a" + integrity sha512-pETCmQylIQ7RM+8uqDkI3KfOaX5H7nuzmMXby28zdLPMZniYti0gJxieiVFhvdz2Ot2Axj0hznfmraFgC9mQMw== dependencies: - "@angular-devkit/core" "11.0.0" - "@angular-devkit/schematics" "11.0.0" + "@angular-devkit/core" "11.0.2" + "@angular-devkit/schematics" "11.0.2" "@yarnpkg/lockfile" "1.1.0" ini "1.3.5" npm-package-arg "^8.0.0" @@ -1887,11 +1735,6 @@ "@types/connect" "*" "@types/node" "*" -"@types/color-name@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" - integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== - "@types/connect@*": version "3.4.33" resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.33.tgz#31610c901eca573b8713c3330abc6e6b9f588546" @@ -1946,7 +1789,12 @@ dependencies: "@types/node" "*" -"@types/jasmine@*", "@types/jasmine@~3.5.0": +"@types/jasmine@*": + version "3.6.2" + resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-3.6.2.tgz#02f64450016f7de70f145d698be311136d7c6374" + integrity sha512-AzfesNFLvOs6Q1mHzIsVJXSeUnqVh4ZHG8ngygKJfbkcSLwzrBVm/LKa+mR8KrOfnWtUL47112gde1MC0IXqpQ== + +"@types/jasmine@~3.5.0": version "3.5.14" resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-3.5.14.tgz#f41a14e8ffa939062a71cf9722e5ee7d4e1f94af" integrity sha512-Fkgk536sHPqcOtd+Ow+WiUNuk0TSo/BntKkF8wSvcd6M2FvPjeXcUE6Oz/bwDZiUZEaXLslAgw00Q94Pnx6T4w== @@ -1958,24 +1806,15 @@ dependencies: "@types/jasmine" "*" -"@types/jsdom@^16.1.0": - version "16.2.4" - resolved "https://registry.yarnpkg.com/@types/jsdom/-/jsdom-16.2.4.tgz#527ca99943e00561ca4056b1904fd5f4facebc3b" - integrity sha512-RssgLa5ptjVKRkHho/Ex0+DJWkVsYuV8oh2PSG3gKxFp8n/VNyB7kOrZGQkk2zgPlcBkIKOItUc/T5BXit9uhg== - dependencies: - "@types/node" "*" - "@types/parse5" "*" - "@types/tough-cookie" "*" - -"@types/json-schema@^7.0.4", "@types/json-schema@^7.0.6": +"@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6": version "7.0.6" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== "@types/lodash@^4.14.104": - version "4.14.161" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.161.tgz#a21ca0777dabc6e4f44f3d07f37b765f54188b18" - integrity sha512-EP6O3Jkr7bXvZZSZYlsgt5DIjiGr0dXP1/jVEwVLTFgg0d+3lWVQkRavYVQszV7dYUwvg0B8R0MBDpcmXg7XIA== + version "4.14.165" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.165.tgz#74d55d947452e2de0742bad65270433b63a8c30f" + integrity sha512-tjSSOTHhI5mCHTy/OOXYIhi2Wt1qcbHmuXD1Ha7q70CgI/I71afO4XtLb/cVexki1oVYchpul/TOuu3Arcdxrg== "@types/long@^4.0.0", "@types/long@^4.0.1": version "4.0.1" @@ -1993,45 +1832,30 @@ integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== "@types/node@*": - version "14.11.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.11.2.tgz#2de1ed6670439387da1c9f549a2ade2b0a799256" - integrity sha512-jiE3QIxJ8JLNcb1Ps6rDbysDhN4xa8DJJvuC9prr6w+1tIh+QAbYyNF3tyiZNLDBIuBCf4KEcV2UvQm/V60xfA== - -"@types/node@^10.1.0": - version "10.17.44" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.44.tgz#3945e6b702cb6403f22b779c8ea9e5c3f44ead40" - integrity sha512-vHPAyBX1ffLcy4fQHmDyIUMUb42gHZjPHU66nhvbMzAWJqHnySGZ6STwN3rwrnSd1FHB0DI/RWgGELgKSYRDmw== + version "14.14.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.9.tgz#04afc9a25c6ff93da14deabd65dc44485b53c8d6" + integrity sha512-JsoLXFppG62tWTklIoO4knA+oDTYsmqWxHRvd4lpmfQRNhX6osheUOWETP2jMoV/2bEHuMra8Pp3Dmo/stBFcw== "@types/node@^12.12.47": - version "12.12.62" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.62.tgz#733923d73669188d35950253dd18a21570085d2b" - integrity sha512-qAfo81CsD7yQIM9mVyh6B/U47li5g7cfpVQEDMfQeF8pSZVwzbhwU3crc0qG4DmpsebpJPR49AKOExQyJ05Cpg== + version "12.19.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.6.tgz#fbf249fa46487dd8c7386d785231368b92a33a53" + integrity sha512-U2VopDdmBoYBmtm8Rz340mvvSz34VgX/K9+XCuckvcLGMkt3rbMX8soqFOikIPlPBc5lmw8By9NUK7bEFSBFlQ== -"@types/node@^13.7.0", "@types/node@^13.7.7": - version "13.13.21" - resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.21.tgz#e48d3c2e266253405cf404c8654d1bcf0d333e5c" - integrity sha512-tlFWakSzBITITJSxHV4hg4KvrhR/7h3xbJdSFbYJBVzKubrASbnnIFuSgolUh7qKGo/ZeJPKUfbZ0WS6Jp14DQ== +"@types/node@^13.7.0": + version "13.13.32" + resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.32.tgz#f0edd0fb57b3c9f6e64a0b3ddb1e0f729b6f71ce" + integrity sha512-sPBvDnrwZE1uePhkCEyI/qQlgZM5kePPAhHIFDWNsOrWBFRBOk3LKJYmVCLeLZlL9Ub/FzMJb31OTWCg2F+06g== "@types/node@^8.10.59": - version "8.10.64" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.64.tgz#0dddc4c53ca4819a32b7478232d8b446ca90e1c6" - integrity sha512-/EwBIb+imu8Qi/A3NF9sJ9iuKo7yV+pryqjmeRqaU0C4wBAOhas5mdvoYeJ5PCKrh6thRSJHdoasFqh3BQGILA== - -"@types/object-path@^0.11.0": - version "0.11.0" - resolved "https://registry.yarnpkg.com/@types/object-path/-/object-path-0.11.0.tgz#0b744309b2573dc8bf867ef589b6288be998e602" - integrity sha512-/tuN8jDbOXcPk+VzEVZzzAgw1Byz7s/itb2YI10qkSyy6nykJH02DuhfrflxVdAdE7AZ91h5X6Cn0dmVdFw2TQ== + version "8.10.66" + resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.66.tgz#dd035d409df322acc83dff62a602f12a5783bbb3" + integrity sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw== "@types/parse-json@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== -"@types/parse5@*": - version "5.0.3" - resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-5.0.3.tgz#e7b5aebbac150f8b5fdd4a46e7f0bd8e65e19109" - integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw== - "@types/q@^1.5.1": version "1.5.4" resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24" @@ -2048,23 +1872,18 @@ integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA== "@types/serve-static@*": - version "1.13.5" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.5.tgz#3d25d941a18415d3ab092def846e135a08bbcf53" - integrity sha512-6M64P58N+OXjU432WoLLBQxbA0LRGBCRm7aAGQJ+SMC1IMl0dgRVi9EFfoDcS2a7Xogygk/eGN94CfwU9UF7UQ== + version "1.13.8" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.8.tgz#851129d434433c7082148574ffec263d58309c46" + integrity sha512-MoJhSQreaVoL+/hurAZzIm8wafFR6ajiTM1m4A0kv6AGeVBl4r4pOV8bGFrjjq1sGxDTnCoF8i22o0/aE5XCyA== dependencies: - "@types/express-serve-static-core" "*" "@types/mime" "*" + "@types/node" "*" "@types/source-list-map@*": version "0.1.2" resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9" integrity sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA== -"@types/tough-cookie@*": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.0.tgz#fef1904e4668b6e5ecee60c52cc6a078ffa6697d" - integrity sha512-I99sngh224D0M7XgW1s120zxCt3VYQ3IQsuw3P3jbq5GG4yc79+ZjyKznyOGIQrflfylLgcfekeZW/vk0yng6A== - "@types/webpack-sources@^0.1.5": version "0.1.8" resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-0.1.8.tgz#078d75410435993ec8a0a2855e88706f3f751f81" @@ -2219,19 +2038,15 @@ "@webassemblyjs/wast-parser" "1.9.0" "@xtuc/long" "4.2.2" -"@wessberg/ts-evaluator@0.0.25": - version "0.0.25" - resolved "https://registry.yarnpkg.com/@wessberg/ts-evaluator/-/ts-evaluator-0.0.25.tgz#23a2585d8f5fb197ae26ba17b80c7fae263ea357" - integrity sha512-/Bo/enrMymuoR3/hnmpOeoaciKt/ILLOrhHa5yhjQNNYDumRYhIx40gjfe/yNwAtZWrVCyB69rBoEy/YGln/+A== +"@wessberg/ts-evaluator@0.0.27": + version "0.0.27" + resolved "https://registry.yarnpkg.com/@wessberg/ts-evaluator/-/ts-evaluator-0.0.27.tgz#06e8b901d5e84f11199b9f84577c6426ae761767" + integrity sha512-7gOpVm3yYojUp/Yn7F4ZybJRxyqfMNf0LXK5KJiawbPfL0XTsJV+0mgrEDjOIR6Bi0OYk2Cyg4tjFu1r8MCZaA== dependencies: - "@types/node" "^13.7.7" - "@types/object-path" "^0.11.0" - chalk "^3.0.0" - object-path "^0.11.4" - tslib "^1.11.1" - optionalDependencies: - "@types/jsdom" "^16.1.0" - jsdom "^16.2.0" + chalk "^4.1.0" + jsdom "^16.4.0" + object-path "^0.11.5" + tslib "^2.0.3" "@xtuc/ieee754@^1.2.0": version "1.2.0" @@ -2300,9 +2115,9 @@ acorn@^6.4.1: integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== acorn@^7.1.1: - version "7.4.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.0.tgz#e1ad486e6c54501634c6c397c5c121daa383607c" - integrity sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w== + version "7.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== adjust-sourcemap-loader@3.0.0: version "3.0.0" @@ -2325,9 +2140,9 @@ agent-base@4, agent-base@^4.3.0: es6-promisify "^5.0.0" agent-base@6: - version "6.0.1" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.1.tgz#808007e4e5867decb0ab6ab2f928fbdb5a596db4" - integrity sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg== + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== dependencies: debug "4" @@ -2373,7 +2188,7 @@ ajv@6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@6.12.6, ajv@^6.10.2, ajv@^6.12.5: +ajv@6.12.6, ajv@^6.1.0, ajv@^6.10.2, ajv@^6.12.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -2383,36 +2198,6 @@ ajv@6.12.6, ajv@^6.10.2, ajv@^6.12.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^6.1.0, ajv@^6.12.0: - version "6.12.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.0.tgz#06d60b96d87b8454a5adaba86e7854da629db4b7" - integrity sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ajv@^6.12.2: - version "6.12.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.2.tgz#c629c5eced17baf314437918d2da88c99d5958cd" - integrity sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ajv@^6.12.3: - version "6.12.5" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.5.tgz#19b0e8bae8f476e5ba666300387775fb1a00a4da" - integrity sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - alphanum-sort@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" @@ -2485,11 +2270,10 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: color-convert "^1.9.0" ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" - integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: - "@types/color-name" "^1.1.1" color-convert "^2.0.1" ansicolors@~0.3.2: @@ -2774,9 +2558,9 @@ aws-sign2@~0.7.0: integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= aws4@^1.8.0: - version "1.10.1" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.1.tgz#e1e82e4f3e999e2cfd61b161280d16a111f86428" - integrity sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA== + version "1.11.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" + integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== axios@0.19.0: version "0.19.0" @@ -2821,15 +2605,20 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= +base64-arraybuffer@0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz#9818c79e059b1355f97e0428a017c838e90ba812" + integrity sha1-mBjHngWbE1X5fgQooBfIOOkLqBI= + base64-arraybuffer@0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8" integrity sha1-c5JncZI7Whl0etZmqlzUv5xunOg= -base64-js@^1.0.2, base64-js@^1.2.3, base64-js@^1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" - integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== +base64-js@^1.0.2, base64-js@^1.2.3, base64-js@^1.3.0, base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== base64id@1.0.0: version "1.0.0" @@ -2901,9 +2690,9 @@ big.js@^5.2.2: integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== bignumber.js@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.0.tgz#805880f84a329b5eac6e7cb6f8274b6d82bdf075" - integrity sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A== + version "9.0.1" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.1.tgz#8d7ba124c882bfd8e43260c67475518d0689e4e5" + integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA== binary-extensions@^1.0.0: version "1.13.1" @@ -3057,20 +2846,20 @@ browser-process-hrtime@^1.0.0: resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== -browser-sync-client@^2.26.12: - version "2.26.12" - resolved "https://registry.yarnpkg.com/browser-sync-client/-/browser-sync-client-2.26.12.tgz#b6c81335c6a9f1a79bca1951438800d3e7f170c8" - integrity sha512-bEBDRkufKxrIfjOsIB1FN9itUEXr2oLtz1AySgSSr80K2AWzmtoYnxtVASx/i40qFrSdeI31pNvdCjHivihLVA== +browser-sync-client@^2.26.13: + version "2.26.13" + resolved "https://registry.yarnpkg.com/browser-sync-client/-/browser-sync-client-2.26.13.tgz#ee5fa3ec36fe2a03f9887553cac6846751c8232d" + integrity sha512-p2VbZoYrpuDhkreq+/Sv1MkToHklh7T1OaIntDwpG6Iy2q/XkBcgwPcWjX+WwRNiZjN8MEehxIjEUh12LweLmQ== dependencies: etag "1.8.1" fresh "0.5.2" mitt "^1.1.3" rxjs "^5.5.6" -browser-sync-ui@^2.26.12: - version "2.26.12" - resolved "https://registry.yarnpkg.com/browser-sync-ui/-/browser-sync-ui-2.26.12.tgz#6a309644d3ae0fe743906558a94caf6fd118719f" - integrity sha512-PkAJNf/TfCFTCkQUfXplR2Kp/+/lbCWFO9lrgLZsmxIhvMLx2pYZFBbTBIaem8qjXhld9ZcESUC8EdU5VWFJgQ== +browser-sync-ui@^2.26.13: + version "2.26.13" + resolved "https://registry.yarnpkg.com/browser-sync-ui/-/browser-sync-ui-2.26.13.tgz#7a0622df2c1cc4fb0dd8edd511f90737f84239b4" + integrity sha512-6NJ/pCnhCnBMzaty1opWo7ipDmFAIk8U71JMQGKJxblCUaGfdsbF2shf6XNZSkXYia1yS0vwKu9LIOzpXqQZCA== dependencies: async-each-series "0.1.1" connect-history-api-fallback "^1" @@ -3080,12 +2869,12 @@ browser-sync-ui@^2.26.12: stream-throttle "^0.1.3" browser-sync@^2.26.7: - version "2.26.12" - resolved "https://registry.yarnpkg.com/browser-sync/-/browser-sync-2.26.12.tgz#2724df702ef8880e711c1bf62afd7c93a3a80462" - integrity sha512-1GjAe+EpZQJgtKhWsxklEjpaMV0DrRylpHRvZWgOphDQt+bfLZjfynl/j1WjSFIx8ozj9j78g6Yk4TqD3gKaMA== + version "2.26.13" + resolved "https://registry.yarnpkg.com/browser-sync/-/browser-sync-2.26.13.tgz#a74541c104aec7eda318a5d8abdb3317ae9eda3d" + integrity sha512-JPYLTngIzI+Dzx+StSSlMtF+Q9yjdh58HW6bMFqkFXuzQkJL8FCvp4lozlS6BbECZcsM2Gmlgp0uhEjvl18X4w== dependencies: - browser-sync-client "^2.26.12" - browser-sync-ui "^2.26.12" + browser-sync-client "^2.26.13" + browser-sync-ui "^2.26.13" bs-recipes "1.3.4" bs-snippet-injector "^2.0.1" chokidar "^3.4.1" @@ -3093,7 +2882,7 @@ browser-sync@^2.26.7: connect-history-api-fallback "^1" dev-ip "^1.0.1" easy-extender "^2.3.4" - eazy-logger "^3" + eazy-logger "3.1.0" etag "^1.8.1" fresh "^0.5.2" fs-extra "3.0.1" @@ -3176,27 +2965,7 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist@^4.0.0, browserslist@^4.8.5, browserslist@^4.9.1: - version "4.14.5" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.5.tgz#1c751461a102ddc60e40993639b709be7f2c4015" - integrity sha512-Z+vsCZIvCBvqLoYkBFTwEYH3v5MCQbsAjp50ERycpOjnPmolg1Gjy4+KaWWpm8QOJt9GHkhdqAl14NpCX73CWA== - dependencies: - caniuse-lite "^1.0.30001135" - electron-to-chromium "^1.3.571" - escalade "^3.1.0" - node-releases "^1.1.61" - -browserslist@^4.12.0: - version "4.12.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.12.1.tgz#6d08bef149b70d153930780ba762644e0f329122" - integrity sha512-WMjXwFtPskSW1pQUDJRxvRKRkeCr7usN0O/Za76N+F4oadaTdQHotSGcX9jT/Hs7mSKPkyMFNvqawB/1HzYDKQ== - dependencies: - caniuse-lite "^1.0.30001088" - electron-to-chromium "^1.3.481" - escalade "^3.0.1" - node-releases "^1.1.58" - -browserslist@^4.14.5: +browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.14.6, browserslist@^4.9.1: version "4.14.7" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.7.tgz#c071c1b3622c1c2e790799a37bb09473a4351cb6" integrity sha512-BSVRLCeG3Xt/j/1cCGj1019Wbty0H+Yvu2AOuZSuoaUWn3RatbL33Cxk+Q4jRMRAbOm0p7SLravLjpnT6s0vzQ== @@ -3257,12 +3026,12 @@ buffer@^4.3.0: isarray "^1.0.0" buffer@^5.1.0, buffer@^5.5.0: - version "5.6.0" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.6.0.tgz#a31749dc7d81d84db08abf937b6b8c4033f62786" - integrity sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw== + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" + base64-js "^1.3.1" + ieee754 "^1.1.13" buffers@~0.1.1: version "0.1.1" @@ -3366,6 +3135,14 @@ cacheable-request@^6.0.0: normalize-url "^4.1.0" responselike "^1.0.2" +call-bind@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.0.tgz#24127054bb3f9bdcb4b1fb82418186072f77b8ce" + integrity sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.0" + call-me-maybe@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" @@ -3405,7 +3182,7 @@ camelcase@5.3.1, camelcase@^5.0.0, camelcase@^5.3.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -camelcase@^6.1.0: +camelcase@^6.0.0: version "6.2.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== @@ -3420,30 +3197,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001032: - version "1.0.30001038" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001038.tgz#44da3cbca2ab6cb6aa83d1be5d324e17f141caff" - integrity sha512-zii9quPo96XfOiRD4TrfYGs+QsGZpb2cGiMAzPjtf/hpFgB6zCPZgJb7I1+EATeMw/o+lG8FyRAnI+CWStHcaQ== - -caniuse-lite@^1.0.30001088: - version "1.0.30001088" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001088.tgz#23a6b9e192106107458528858f2c0e0dba0d9073" - integrity sha512-6eYUrlShRYveyqKG58HcyOfPgh3zb2xqs7NvT2VVtP3hEUeeWvc3lqhpeMTxYWBBeeaT9A4bKsrtjATm66BTHg== - -caniuse-lite@^1.0.30001109: - version "1.0.30001135" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001135.tgz#995b1eb94404a3c9a0d7600c113c9bb27f2cd8aa" - integrity sha512-ziNcheTGTHlu9g34EVoHQdIu5g4foc8EsxMGC7Xkokmvw0dqNtX8BS8RgCgFBaAiSp2IdjvBxNdh0ssib28eVQ== - -caniuse-lite@^1.0.30001135: - version "1.0.30001153" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001153.tgz#9a0942fe777cd7178fb084693b79415ff747ecd9" - integrity sha512-qv14w7kWwm2IW7DBvAKWlCqGTmV2XxNtSejJBVplwRjhkohHuhRUpeSlPjtu9erru0+A12zCDUiSmvx/AcqVRA== - -caniuse-lite@^1.0.30001157: - version "1.0.30001157" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001157.tgz#2d11aaeb239b340bc1aa730eca18a37fdb07a9ab" - integrity sha512-gOerH9Wz2IRZ2ZPdMfBvyOi3cjaz4O4dgNwPGzx8EhqAs4+2IL/O+fJsbt+znSigujoZG8bVcIAUM/I/E5K3MA== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001032, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001157: + version "1.0.30001159" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001159.tgz#bebde28f893fa9594dadcaa7d6b8e2aa0299df20" + integrity sha512-w9Ph56jOsS8RL20K9cLND3u/+5WASWdhC/PPrf+V3/HsM3uHOavWOR1Xzakbv4Puo/srmPHudkmCRWM7Aq+/UA== canonical-path@1.0.0: version "1.0.0" @@ -3470,7 +3227,7 @@ chainsaw@~0.1.0: dependencies: traverse ">=0.3.0 <0.4" -chalk@^1.1.1, chalk@^1.1.3: +chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= @@ -3517,9 +3274,9 @@ chardet@^0.7.0: integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== "chokidar@>=2.0.0 <4.0.0", chokidar@^3.0.0, chokidar@^3.0.2, chokidar@^3.4.1: - version "3.4.2" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.2.tgz#38dc8e658dec3809741eb3ef7bb0a47fe424232d" - integrity sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A== + version "3.4.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.3.tgz#c1df38231448e45ca4ac588e6c79573ba6a57d5b" + integrity sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ== dependencies: anymatch "~3.1.1" braces "~3.0.2" @@ -3527,7 +3284,7 @@ chardet@^0.7.0: is-binary-path "~2.1.0" is-glob "~4.0.1" normalize-path "~3.0.0" - readdirp "~3.4.0" + readdirp "~3.5.0" optionalDependencies: fsevents "~2.1.2" @@ -3638,15 +3395,10 @@ cli-cursor@^3.1.0: dependencies: restore-cursor "^3.1.0" -cli-spinners@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.2.0.tgz#e8b988d9206c692302d8ee834e7a85c0144d8f77" - integrity sha512-tgU3fKwzYjiLEQgPMD9Jt+JjHVL9kW93FiIMX/l7rivvOD4/LL0Mf7gda3+4U2KJBloybwgj5KEoQgGRioMiKQ== - -cli-spinners@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.4.0.tgz#c6256db216b878cfba4720e719cec7cf72685d7f" - integrity sha512-sJAofoarcm76ZGpuooaO0eDy8saEy+YoZBLjC4h8srt4jeBnkYeOgqxgsJQTpyt2LjI5PTfLJHSL+41Yu4fEJA== +cli-spinners@^2.0.0, cli-spinners@^2.4.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.5.0.tgz#12763e47251bf951cb75c201dfa58ff1bcb2d047" + integrity sha512-PC+AmIuK04E6aeSs/pUccSujsTzBhu4HzC2dL+CfJB/Jcc2qTRbEwZQDfIUpt2Xl8BodYBEq8w4fc0kU2I9DjQ== cli-table@^0.3.1: version "0.3.1" @@ -3683,6 +3435,15 @@ cliui@^6.0.0: strip-ansi "^6.0.0" wrap-ansi "^6.2.0" +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + clone-deep@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" @@ -3719,9 +3480,9 @@ code-point-at@^1.0.0: integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= codelyzer@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/codelyzer/-/codelyzer-6.0.0.tgz#50c98581cc2890e0e9a9f93878dc317115d836ed" - integrity sha512-edJIQCIcxD9DhVSyBEdJ38AbLikm515Wl91t5RDGNT88uA6uQdTm4phTWfn9JhzAI8kXNUcfYyAE90lJElpGtA== + version "6.0.1" + resolved "https://registry.yarnpkg.com/codelyzer/-/codelyzer-6.0.1.tgz#c0e9668e847255b37c759e68fb2700b11e277d0f" + integrity sha512-cOyGQgMdhnRYtW2xrJUNrNYDjEgwQ+BrE2y93Bwz3h4DJ6vJRLfupemU5N3pbYsUlBHJf0u1j1UGk+NLW4d97g== dependencies: "@angular/compiler" "9.0.0" "@angular/core" "9.0.0" @@ -3770,10 +3531,10 @@ color-name@^1.0.0, color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -color-string@^1.5.2: - version "1.5.3" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" - integrity sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw== +color-string@^1.5.2, color-string@^1.5.4: + version "1.5.4" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.4.tgz#dd51cd25cfee953d138fe4002372cc3d0e504cb6" + integrity sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw== dependencies: color-name "^1.0.0" simple-swizzle "^0.2.2" @@ -3787,12 +3548,12 @@ color@3.0.x: color-string "^1.5.2" color@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/color/-/color-3.1.2.tgz#68148e7f85d41ad7649c5fa8c8106f098d229e10" - integrity sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg== + version "3.1.3" + resolved "https://registry.yarnpkg.com/color/-/color-3.1.3.tgz#ca67fb4e7b97d611dcde39eceed422067d91596e" + integrity sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ== dependencies: color-convert "^1.9.1" - color-string "^1.5.2" + color-string "^1.5.4" colorette@^1.2.1: version "1.2.1" @@ -4076,18 +3837,23 @@ copy-webpack-plugin@6.2.1: webpack-sources "^1.4.3" core-js-compat@^3.6.2: - version "3.6.5" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.5.tgz#2a51d9a4e25dfd6e690251aa81f99e3c05481f1c" - integrity sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng== + version "3.7.0" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.7.0.tgz#8479c5d3d672d83f1f5ab94cf353e57113e065ed" + integrity sha512-V8yBI3+ZLDVomoWICO6kq/CD28Y4r1M7CWeO4AGpMdMfseu8bkSubBmUPySMGKRTS+su4XQ07zUkAsiu9FCWTg== dependencies: - browserslist "^4.8.5" + browserslist "^4.14.6" semver "7.0.0" -core-js@3.6.5, core-js@^3.6.5: +core-js@3.6.5: version "3.6.5" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a" integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA== +core-js@^3.6.5: + version "3.7.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.7.0.tgz#b0a761a02488577afbf97179e4681bf49568520f" + integrity sha512-NwS7fI5M5B85EwpWuIwJN4i/fbisQUwLwiSNUWeXlkAZ0sbBjLEvLvFLf1uzAUV66PcEPt4xCGCmOZSxVf3xzA== + core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -4230,22 +3996,22 @@ css-declaration-sorter@^4.0.1: postcss "^7.0.1" timsort "^0.3.0" -css-loader@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-5.0.0.tgz#f0a48dfacc3ab9936a05ee16a09e7f313872e117" - integrity sha512-9g35eXRBgjvswyJWoqq/seWp+BOxvUl8IinVNTsUBFFxtwfEYvlmEn6ciyn0liXGbGh5HyJjPGCuobDSfqMIVg== +css-loader@4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-4.3.0.tgz#c888af64b2a5b2e85462c72c0f4a85c7e2e0821e" + integrity sha512-rdezjCjScIrsL8BSYszgT4s476IcNKt6yX69t0pHjJVnPUTDpn4WfIpDQTN3wCJvUvfsz/mFjuGOekf3PY3NUg== dependencies: - camelcase "^6.1.0" + camelcase "^6.0.0" cssesc "^3.0.0" - icss-utils "^5.0.0" + icss-utils "^4.1.1" loader-utils "^2.0.0" - postcss "^8.1.1" - postcss-modules-extract-imports "^3.0.0" - postcss-modules-local-by-default "^4.0.0" - postcss-modules-scope "^3.0.0" - postcss-modules-values "^4.0.0" + postcss "^7.0.32" + postcss-modules-extract-imports "^2.0.0" + postcss-modules-local-by-default "^3.0.3" + postcss-modules-scope "^2.2.0" + postcss-modules-values "^3.0.0" postcss-value-parser "^4.1.0" - schema-utils "^3.0.0" + schema-utils "^2.7.1" semver "^7.3.2" css-parse@~2.0.0: @@ -4286,18 +4052,18 @@ css-tree@1.0.0-alpha.37: mdn-data "2.0.4" source-map "^0.6.1" -css-tree@1.0.0-alpha.39: - version "1.0.0-alpha.39" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.39.tgz#2bff3ffe1bb3f776cf7eefd91ee5cba77a149eeb" - integrity sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA== +css-tree@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.1.tgz#30b8c0161d9fb4e9e2141d762589b6ec2faebd2e" + integrity sha512-NVN42M2fjszcUNpDbdkvutgQSlFYsr1z7kqeuCagHnNLBfYor6uP1WL1KrkmdYZ5Y1vTBCIOI/C/+8T98fJ71w== dependencies: - mdn-data "2.0.6" + mdn-data "2.0.14" source-map "^0.6.1" css-what@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.3.0.tgz#10fec696a9ece2e591ac772d759aacabac38cd39" - integrity sha512-pv9JPyatiPaQ6pf4OvD/dbfm0o5LviWmwxNWzblYf/1u9QZd0ihV+PMwy5jdQWQ3349kZmKEx9WXuSka2dM4cg== + version "3.4.2" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.4.2.tgz#ea7026fcb01777edbde52124e21f327e7ae950e4" + integrity sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ== css@^2.0.0: version "2.2.4" @@ -4390,11 +4156,11 @@ cssnano@4.1.10: postcss "^7.0.0" csso@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/csso/-/csso-4.0.3.tgz#0d9985dc852c7cc2b2cacfbbe1079014d1a8e903" - integrity sha512-NL3spysxUkcrOgnpsT4Xdl2aiEiBG6bXswAABQVHcMrfjjBisFOKwLDOmf4wf32aPdcJws1zds2B0Rg+jqMyHQ== + version "4.1.1" + resolved "https://registry.yarnpkg.com/csso/-/csso-4.1.1.tgz#e0cb02d6eb3af1df719222048e4359efd662af13" + integrity sha512-Rvq+e1e0TFB8E8X+8MQjHSY6vtol45s5gxtLI/018UsAn2IBMmwNEZRM/h+HVnAJRHjasLIKKUO3uvoMM28LvA== dependencies: - css-tree "1.0.0-alpha.39" + css-tree "^1.0.0" cssom@^0.4.4: version "0.4.4" @@ -4493,10 +4259,10 @@ debug@3.1.0, debug@=3.1.0, debug@~3.1.0: dependencies: ms "2.0.0" -debug@4, debug@4.2.0, debug@^4.1.0, debug@^4.1.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" - integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== +debug@4, debug@^4.1.0, debug@^4.1.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== dependencies: ms "2.1.2" @@ -4514,10 +4280,17 @@ debug@4.1.1, debug@~4.1.0: dependencies: ms "^2.1.1" -debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.5: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== +debug@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" + integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== + dependencies: + ms "2.1.2" + +debug@^3.1.0, debug@^3.1.1, debug@^3.2.5: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== dependencies: ms "^2.1.1" @@ -4527,9 +4300,9 @@ decamelize@^1.2.0: integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= decimal.js@^10.2.0: - version "10.2.0" - resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.0.tgz#39466113a9e036111d02f82489b5fd6b0b5ed231" - integrity sha512-vDPw+rDgn3bZe1+F/pyEwb1oMG2XTlRVgAa6B4KccTEpYgF8w6eQllVbQcfIJnZyvzFtFpxnpGtx8dd7DJp/Rw== + version "10.2.1" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.1.tgz#238ae7b0f0c793d3e3cea410108b35a2c01426a3" + integrity sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw== decode-uri-component@^0.2.0: version "0.2.0" @@ -4556,21 +4329,21 @@ deep-equal@^1.0.1: regexp.prototype.flags "^1.2.0" deep-equal@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.0.3.tgz#cad1c15277ad78a5c01c49c2dee0f54de8a6a7b0" - integrity sha512-Spqdl4H+ky45I9ByyJtXteOm9CaIrPmnIPmOhrkKGNYWeDgCvJ8jNYVCTjChxW4FqGuZnLHADc8EKRMX6+CgvA== + version "2.0.4" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.0.4.tgz#6b0b407a074666033169df3acaf128e1c6f3eab6" + integrity sha512-BUfaXrVoCfgkOQY/b09QdO9L3XNoF2XH0A3aY9IQwQL/ZjLOe8FQgCNVl1wiolhsFo8kFdO9zdPViCPbmaJA5w== dependencies: - es-abstract "^1.17.5" + es-abstract "^1.18.0-next.1" es-get-iterator "^1.1.0" is-arguments "^1.0.4" is-date-object "^1.0.2" - is-regex "^1.0.5" + is-regex "^1.1.1" isarray "^2.0.5" - object-is "^1.1.2" + object-is "^1.1.3" object-keys "^1.1.1" - object.assign "^4.1.0" + object.assign "^4.1.1" regexp.prototype.flags "^1.3.0" - side-channel "^1.0.2" + side-channel "^1.0.3" which-boxed-primitive "^1.0.1" which-collection "^1.0.1" which-typed-array "^1.1.2" @@ -4741,6 +4514,11 @@ dir-loader@^0.3.0: loader-utils "^0.2.9" object-assign "^4.0.1" +dlv@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79" + integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA== + dns-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" @@ -4870,12 +4648,12 @@ easy-extender@^2.3.4: dependencies: lodash "^4.17.10" -eazy-logger@^3: - version "3.0.2" - resolved "https://registry.yarnpkg.com/eazy-logger/-/eazy-logger-3.0.2.tgz#a325aa5e53d13a2225889b2ac4113b2b9636f4fc" - integrity sha1-oyWqXlPROiIliJsqxBE7K5Y29Pw= +eazy-logger@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/eazy-logger/-/eazy-logger-3.1.0.tgz#b169eb56df714608fa114f164c8a2956bec9f0f3" + integrity sha512-/snsn2JqBtUSSstEl4R0RKjkisGHAhvYj89i7r3ytNUKW12y178KDZwXLXIgwDqLW6E/VRMT9qfld7wvFae8bQ== dependencies: - tfunk "^3.0.1" + tfunk "^4.0.0" ecc-jsbn@~0.1.1: version "0.1.2" @@ -4897,20 +4675,10 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -electron-to-chromium@^1.3.481: - version "1.3.571" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.571.tgz#e57977f1569f8326ae2a7905e26f3943536ba28f" - integrity sha512-UYEQ2Gtc50kqmyOmOVtj6Oqi38lm5yRJY3pLuWt6UIot0No1L09uu6Ja6/1XKwmz/p0eJFZTUZi+khd1PV1hHA== - -electron-to-chromium@^1.3.571: - version "1.3.584" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.584.tgz#506cf7ba5895aafa8241876ab028654b61fd9ceb" - integrity sha512-NB3DzrTzJFhWkUp+nl2KtUtoFzrfGXTir2S+BU4tXGyXH9vlluPuFpE3pTKeH7+PY460tHLjKzh6K2+TWwW+Ww== - electron-to-chromium@^1.3.591: - version "1.3.593" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.593.tgz#947ccf6dc8e013e2b053d2463ecd1043c164fcef" - integrity sha512-GvO7G1ZxvffnMvPCr4A7+iQPVuvpyqMrx2VWSERAjG+pHK6tmO9XqYdBfMIq9corRyi4bNImSDEiDvIoDb8HrA== + version "1.3.603" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.603.tgz#1b71bec27fb940eccd79245f6824c63d5f7e8abf" + integrity sha512-J8OHxOeJkoSLgBXfV9BHgKccgfLMHh+CoeRo6wJsi6m0k3otaxS/5vrHpMNSEYY4MISwewqanPOuhAtuE8riQQ== elliptic@^6.5.3: version "6.5.3" @@ -4987,18 +4755,18 @@ engine.io-client@~3.2.0: yeast "0.1.2" engine.io-client@~3.4.0: - version "3.4.3" - resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.4.3.tgz#192d09865403e3097e3575ebfeb3861c4d01a66c" - integrity sha512-0NGY+9hioejTEJCaSJZfWZLk4FPI9dN+1H1C4+wj2iuFba47UgZbJzfWs4aNFajnX/qAaYKbe2lLTfEEWzCmcw== + version "3.4.4" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.4.4.tgz#77d8003f502b0782dd792b073a4d2cf7ca5ab967" + integrity sha512-iU4CRr38Fecj8HoZEnFtm2EiKGbYZcPn3cHxqNGl/tmdWRf60KhK+9vE0JeSjgnlS/0oynEfLgKbT9ALpim0sQ== dependencies: component-emitter "~1.3.0" component-inherit "0.0.3" - debug "~4.1.0" + debug "~3.1.0" engine.io-parser "~2.2.0" has-cors "1.1.0" indexof "0.0.1" - parseqs "0.0.5" - parseuri "0.0.5" + parseqs "0.0.6" + parseuri "0.0.6" ws "~6.1.0" xmlhttprequest-ssl "~1.5.4" yeast "0.1.2" @@ -5015,13 +4783,13 @@ engine.io-parser@~2.1.0, engine.io-parser@~2.1.1: has-binary2 "~1.0.2" engine.io-parser@~2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.2.0.tgz#312c4894f57d52a02b420868da7b5c1c84af80ed" - integrity sha512-6I3qD9iUxotsC5HEMuuGsKA0cXerGz+4uGcXQEkfBidgKf0amsjrrtwcbwK/nzpZBxclXlV7gGl9dgWvu4LF6w== + version "2.2.1" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.2.1.tgz#57ce5611d9370ee94f99641b589f94c97e4f5da7" + integrity sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg== dependencies: after "0.8.2" arraybuffer.slice "~0.0.7" - base64-arraybuffer "0.1.5" + base64-arraybuffer "0.1.4" blob "0.0.5" has-binary2 "~1.0.2" @@ -5072,9 +4840,9 @@ ent@^2.2.0, ent@~2.2.0: integrity sha1-6WQhkyWiHQX0RGai9obtbOX13R0= entities@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.3.tgz#5c487e5742ab93c15abb5da22759b8590ec03b7f" - integrity sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ== + version "2.1.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" + integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== env-paths@^2.2.0: version "2.2.0" @@ -5101,46 +4869,47 @@ error-ex@^1.3.1: is-arrayish "^0.2.1" es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.4, es-abstract@^1.17.5: - version "1.17.6" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.6.tgz#9142071707857b2cacc7b89ecb670316c3e2d52a" - integrity sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw== + version "1.17.7" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.7.tgz#a4de61b2f66989fc7421676c1cb9787573ace54c" + integrity sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g== dependencies: es-to-primitive "^1.2.1" function-bind "^1.1.1" has "^1.0.3" has-symbols "^1.0.1" - is-callable "^1.2.0" - is-regex "^1.1.0" - object-inspect "^1.7.0" + is-callable "^1.2.2" + is-regex "^1.1.1" + object-inspect "^1.8.0" object-keys "^1.1.1" - object.assign "^4.1.0" + object.assign "^4.1.1" string.prototype.trimend "^1.0.1" string.prototype.trimstart "^1.0.1" -es-abstract@^1.18.0-next.0: - version "1.18.0-next.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.0.tgz#b302834927e624d8e5837ed48224291f2c66e6fc" - integrity sha512-elZXTZXKn51hUBdJjSZGYRujuzilgXo8vSPQzjGYXLvSlGiCo8VO8ZGV3kjo9a0WNJJ57hENagwbtlRuHuzkcQ== +es-abstract@^1.18.0-next.0, es-abstract@^1.18.0-next.1: + version "1.18.0-next.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68" + integrity sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA== dependencies: es-to-primitive "^1.2.1" function-bind "^1.1.1" has "^1.0.3" has-symbols "^1.0.1" - is-callable "^1.2.0" + is-callable "^1.2.2" is-negative-zero "^2.0.0" is-regex "^1.1.1" object-inspect "^1.8.0" object-keys "^1.1.1" - object.assign "^4.1.0" + object.assign "^4.1.1" string.prototype.trimend "^1.0.1" string.prototype.trimstart "^1.0.1" es-get-iterator@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.0.tgz#bb98ad9d6d63b31aacdc8f89d5d0ee57bcb5b4c8" - integrity sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ== + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.1.tgz#b93ddd867af16d5118e00881396533c1c6647ad9" + integrity sha512-qorBw8Y7B15DVLaJWy6WdEV/ZkieBcu6QCq/xzWzGOKJqgG1j754vXRfZ3NY7HSShneqU43mPB4OkQBTkvHhFw== dependencies: - es-abstract "^1.17.4" + call-bind "^1.0.0" + get-intrinsic "^1.0.1" has-symbols "^1.0.1" is-arguments "^1.0.4" is-map "^2.0.1" @@ -5205,12 +4974,7 @@ es6-weak-map@^2.0.2: es6-iterator "^2.0.3" es6-symbol "^3.1.1" -escalade@^3.0.1: - version "3.1.0" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.0.tgz#e8e2d7c7a8b76f6ee64c2181d6b8151441602d4e" - integrity sha512-mAk+hPSO8fLDkhV7V0dXazH5pDc6MrjBTPyD3VeKzxnVFjH1MIxbCdqGZB9O8+EwWakZs3ZCbDS4IpRt79V1ig== - -escalade@^3.1.0, escalade@^3.1.1: +escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== @@ -5536,9 +5300,9 @@ fastparse@^1.1.2: integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ== fastq@^1.6.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.8.0.tgz#550e1f9f59bbc65fe185cb6a9b4d95357107f481" - integrity sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q== + version "1.9.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.9.0.tgz#e16a72f338eaca48e91b5c23593bcc2ef66b7947" + integrity sha512-i7FVWL8HhVY+CTkwFxkN2mk3h+787ixS5S63eb78diVRc1MCssarHq3W5cj0av7YDSwmaV928RNag+U1etRQ7w== dependencies: reusify "^1.0.4" @@ -5689,9 +5453,9 @@ firebase-admin@^8.13.0: "@google-cloud/storage" "^4.1.2" firebase-functions-test@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/firebase-functions-test/-/firebase-functions-test-0.2.2.tgz#d2d96de17af45cf9e0e4e2f5e6c951a9e8e8c3ca" - integrity sha512-SlHLnpKRn5nMsg4Y0CUTGs/R8NatghJCYZGw3fHzaS/5xDqwWPWuxmdHHc+MSuxrSrUROEwOrDTwrbjmRaSNjw== + version "0.2.3" + resolved "https://registry.yarnpkg.com/firebase-functions-test/-/firebase-functions-test-0.2.3.tgz#90d6da662d604ed013a3735c6cdba5984e0d57ea" + integrity sha512-zYX0QTm53wCazuej7O0xqbHl90r/v1PTXt/hwa0jo1YF8nDM+iBKnLDlkIoW66MDd0R6aGg4BvKzTTdJpvigUA== dependencies: "@types/lodash" "^4.14.104" lodash "^4.17.5" @@ -5707,9 +5471,9 @@ firebase-functions@^3.11.0: lodash "^4.17.14" firebase-tools@^8.16.1: - version "8.16.1" - resolved "https://registry.yarnpkg.com/firebase-tools/-/firebase-tools-8.16.1.tgz#f1737ec16dbf6dd79c8b23b0e26f576e7fc906d0" - integrity sha512-D5foH0EMg2retKViCFgrH3x8OVjDcfgyw6NWg97RsRHWcEvHx+yMylSfIZIVEzqblrrxRxW/dYwEk1HRETbrYA== + version "8.16.2" + resolved "https://registry.yarnpkg.com/firebase-tools/-/firebase-tools-8.16.2.tgz#fdcae8fe12411aaac90fb5d1602d34bd721fcd3f" + integrity sha512-3deje+CJ5XtYDsb92YqKdNZaV6+OBJqGA2zatozSaBaKpVkIqTyt9vpglKaar/9N+UIqsIfpjruLS6dCkVk/Gg== dependencies: "@google-cloud/pubsub" "^1.7.0" JSONStream "^1.2.1" @@ -5767,24 +5531,24 @@ firebase-tools@^8.16.1: ws "^7.2.3" firebase@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/firebase/-/firebase-8.0.0.tgz#786b3126d97b44073b1d48d01f78770963e03179" - integrity sha512-0JMwNGg5CeoYBJ27QuDYJe1pYdJ+lspKbK1Pr+aNtYBfJfZTNy265rRroQsSOTGbXiT6cUqObVPeGwnbi8wZHw== + version "8.1.1" + resolved "https://registry.yarnpkg.com/firebase/-/firebase-8.1.1.tgz#379094b724053931fda1086e9020a17b578e50d5" + integrity sha512-w1plr2jYvzBkx/rHE6A0EJf9318ufA5omShLuGocPlQtrvphel+KJcd+R02outE5E2lSDhyM0l3EoiA0YCD4hA== dependencies: - "@firebase/analytics" "0.6.1" - "@firebase/app" "0.6.12" + "@firebase/analytics" "0.6.2" + "@firebase/app" "0.6.13" "@firebase/app-types" "0.6.1" - "@firebase/auth" "0.15.1" - "@firebase/database" "0.7.0" - "@firebase/firestore" "2.0.0" - "@firebase/functions" "0.6.0" - "@firebase/installations" "0.4.18" - "@firebase/messaging" "0.7.2" - "@firebase/performance" "0.4.3" + "@firebase/auth" "0.15.2" + "@firebase/database" "0.8.1" + "@firebase/firestore" "2.0.4" + "@firebase/functions" "0.6.1" + "@firebase/installations" "0.4.19" + "@firebase/messaging" "0.7.3" + "@firebase/performance" "0.4.4" "@firebase/polyfill" "0.3.36" - "@firebase/remote-config" "0.1.29" - "@firebase/storage" "0.4.0" - "@firebase/util" "0.3.3" + "@firebase/remote-config" "0.1.30" + "@firebase/storage" "0.4.2" + "@firebase/util" "0.3.4" first-input-delay@^0.1.3: version "0.1.3" @@ -6036,6 +5800,17 @@ gaxios@^3.0.0: is-stream "^2.0.0" node-fetch "^2.3.0" +gaxios@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-4.0.1.tgz#bc7b205a89d883452822cc75e138620c35e3291e" + integrity sha512-jOin8xRZ/UytQeBpSXFqIzqU7Fi5TqgPNLlUsSB8kjJ76+FiGBfImF8KJu++c6J4jOldfJUtt0YmkRj2ZpSHTQ== + dependencies: + abort-controller "^3.0.0" + extend "^3.0.2" + https-proxy-agent "^5.0.0" + is-stream "^2.0.0" + node-fetch "^2.3.0" + gcp-metadata@^3.4.0: version "3.5.0" resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-3.5.0.tgz#6d28343f65a6bbf8449886a0c0e4a71c77577055" @@ -6044,12 +5819,12 @@ gcp-metadata@^3.4.0: gaxios "^2.1.0" json-bigint "^0.3.0" -gcp-metadata@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-4.2.0.tgz#3b424355ccdc240ee07c5791e2fd6a60a283d89a" - integrity sha512-vQZD57cQkqIA6YPGXM/zc+PIZfNRFdukWGsGZ5+LcJzesi5xp6Gn7a02wRJi4eXPyArNMIYpPET4QMxGqtlk6Q== +gcp-metadata@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-4.2.1.tgz#31849fbcf9025ef34c2297c32a89a1e7e9f2cd62" + integrity sha512-tSk+REe5iq/N+K+SK1XjZJUrFPuDqGZVzCy2vocIHIGmPlTGsa8owXMJwGkrXr73NO0AzhPW4MF2DEHz7P2AVw== dependencies: - gaxios "^3.0.0" + gaxios "^4.0.0" json-bigint "^1.0.0" gcs-resumable-upload@^2.2.4: @@ -6070,15 +5845,24 @@ genfun@^5.0.0: integrity sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA== gensync@^1.0.0-beta.1: - version "1.0.0-beta.1" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" - integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== -get-caller-file@^2.0.1: +get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== +get-intrinsic@^1.0.0, get-intrinsic@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.1.tgz#94a9768fcbdd0595a1c9273aacf4c89d075631be" + integrity sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + get-stream@^4.0.0, get-stream@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" @@ -6196,18 +5980,18 @@ google-auth-library@^5.0.0, google-auth-library@^5.5.0: jws "^4.0.0" lru-cache "^5.0.0" -google-auth-library@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-6.1.0.tgz#db3bbe2b3add5783442c84efdcb1c061721c1bfb" - integrity sha512-GbalszIADE1YPWhUyfFMrkLhFHnlAgoRcqGVW+MsLDPsuaOB5MRPk7NNafPDv9SherNE4EKzcYuxMJjaxzXMOw== +google-auth-library@^6.1.1: + version "6.1.3" + resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-6.1.3.tgz#39d868140b70d0c4b32c6f6d8f4ccc1400d84dca" + integrity sha512-m9mwvY3GWbr7ZYEbl61isWmk+fvTmOt0YNUfPOUY2VH8K5pZlAIWJjxEi0PqR3OjMretyiQLI6GURMrPSwHQ2g== dependencies: arrify "^2.0.0" base64-js "^1.3.0" ecdsa-sig-formatter "^1.0.11" fast-text-encoding "^1.0.0" - gaxios "^3.0.0" - gcp-metadata "^4.1.0" - gtoken "^5.0.0" + gaxios "^4.0.0" + gcp-metadata "^4.2.0" + gtoken "^5.0.4" jws "^4.0.0" lru-cache "^6.0.0" @@ -6259,7 +6043,7 @@ google-p12-pem@^2.0.0: dependencies: node-forge "^0.9.0" -google-p12-pem@^3.0.0: +google-p12-pem@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-3.0.3.tgz#673ac3a75d3903a87f05878f3c75e06fc151669e" integrity sha512-wS0ek4ZtFx/ACKYF3JhyGe5kzH7pgiQ7J5otlumqR9psmWMYc+U9cErKlCYVYHoUaidXHdZ2xbo34kB+S+24hA== @@ -6298,22 +6082,22 @@ gtoken@^4.1.0: jws "^4.0.0" mime "^2.2.0" -gtoken@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-5.0.3.tgz#b76ef8e9a2fed6fef165e47f7d05b60c498e4d05" - integrity sha512-Nyd1wZCMRc2dj/mAD0LlfQLcAO06uKdpKJXvK85SGrF5+5+Bpfil9u/2aw35ltvEHjvl0h5FMKN5knEU+9JrOg== +gtoken@^5.0.4: + version "5.1.0" + resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-5.1.0.tgz#4ba8d2fc9a8459098f76e7e8fd7beaa39fda9fe4" + integrity sha512-4d8N6Lk8TEAHl9vVoRVMh9BNOKWVgl2DdNtr3428O75r3QFrF/a5MMu851VmK0AA8+iSvbwRv69k5XnMLURGhg== dependencies: - gaxios "^3.0.0" - google-p12-pem "^3.0.0" + gaxios "^4.0.0" + google-p12-pem "^3.0.3" jws "^4.0.0" mime "^2.2.0" guess-parser@^0.4.12: - version "0.4.19" - resolved "https://registry.yarnpkg.com/guess-parser/-/guess-parser-0.4.19.tgz#2ebc60e4199529f4b5b0150501f825d71f3e4376" - integrity sha512-JxeD9GhTkluaXxk053dPFOBq7QfSlEcg+zmw1q9Ln5AUmrqMnITfNIQxnSzXCISbckatsIBEDS6zNmkEXdbDDg== + version "0.4.22" + resolved "https://registry.yarnpkg.com/guess-parser/-/guess-parser-0.4.22.tgz#c26ab9e21b69bbc761960c5a1511476ae85428eb" + integrity sha512-KcUWZ5ACGaBM69SbqwVIuWGoSAgD+9iJnchR9j/IarVI1jHVeXv+bUXBIMeqVMSKt3zrn0Dgf9UpcOEpPBLbSg== dependencies: - "@wessberg/ts-evaluator" "0.0.25" + "@wessberg/ts-evaluator" "0.0.27" handle-thing@^2.0.0: version "2.0.1" @@ -6466,13 +6250,6 @@ hosted-git-info@^2.1.4, hosted-git-info@^2.7.1: resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== -hosted-git-info@^3.0.2: - version "3.0.5" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-3.0.5.tgz#bea87905ef7317442e8df3087faa3c842397df03" - integrity sha512-i4dpK6xj9BIpVOTboXIlKG9+8HMKggcrMX7WA24xZtKwX0TPelq/rbaS5rCKeNX8sJXZJGdSxpnEGtta+wismQ== - dependencies: - lru-cache "^6.0.0" - hosted-git-info@^3.0.6: version "3.0.7" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-3.0.7.tgz#a30727385ea85acfcee94e0aad9e368c792e036c" @@ -6602,14 +6379,14 @@ http-proxy-middleware@0.19.1: micromatch "^3.1.10" http-proxy-middleware@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-1.0.5.tgz#4c6e25d95a411e3d750bc79ccf66290675176dc2" - integrity sha512-CKzML7u4RdGob8wuKI//H8Ein6wNTEQR7yjVEzPbhBLGdOfkfvgTnp2HLnniKBDP9QW4eG10/724iTWLBeER3g== + version "1.0.6" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-1.0.6.tgz#0618557722f450375d3796d701a8ac5407b3b94e" + integrity sha512-NyL6ZB6cVni7pl+/IT2W0ni5ME00xR0sN27AQZZrpKn1b+qRh+mLbBxIq9Cq1oGfmTc7BUq4HB77mxwCaxAYNg== dependencies: "@types/http-proxy" "^1.17.4" http-proxy "^1.18.1" is-glob "^4.0.1" - lodash "^4.17.19" + lodash "^4.17.20" micromatch "^4.0.2" http-proxy@^1.17.0, http-proxy@^1.18.1: @@ -6672,20 +6449,22 @@ iconv-lite@^0.6.2: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" -icss-utils@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.0.0.tgz#03ed56c3accd32f9caaf1752ebf64ef12347bb84" - integrity sha512-aF2Cf/CkEZrI/vsu5WI/I+akFgdbwQHVE9YRZxATrhH4PVIe6a3BIjwjEcW+z+jP/hNh+YvM3lAAn1wJQ6opSg== +icss-utils@^4.0.0, icss-utils@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" + integrity sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA== + dependencies: + postcss "^7.0.14" idb@3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/idb/-/idb-3.0.2.tgz#c8e9122d5ddd40f13b60ae665e4862f8b13fa384" integrity sha512-+FLa/0sTXqyux0o6C+i2lOR0VoS60LU/jzUo5xjfY6+7sEEgy4Gz1O7yFBXvjd7N0NyIGWIRg8DcQSLEG+VSPw== -ieee754@^1.1.4: - version "1.1.13" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" - integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== +ieee754@^1.1.13, ieee754@^1.1.4: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== iferr@^0.1.5: version "0.1.5" @@ -6797,9 +6576,9 @@ ini@1.3.5, ini@^1.3.5, ini@~1.3.0: integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== inquirer-autocomplete-prompt@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/inquirer-autocomplete-prompt/-/inquirer-autocomplete-prompt-1.1.0.tgz#e7745b49122e56b483659c91328a2c3fca33ffd6" - integrity sha512-mrSeUSFGnTSid/DCKG+E+IcN4MaOnT2bW7NuSagZAguD4k3hZ0UladdYNP4EstZOwgeqv0C3M1zYa1QIIf0Oyg== + version "1.3.0" + resolved "https://registry.yarnpkg.com/inquirer-autocomplete-prompt/-/inquirer-autocomplete-prompt-1.3.0.tgz#fcbba926be2d3cf338e3dd24380ae7c408113b46" + integrity sha512-zvAc+A6SZdcN+earG5SsBu1RnQdtBS4o8wZ/OqJiCfL34cfOx+twVRq7wumYix6Rkdjn1N2nVCcO3wHqKqgdGg== dependencies: ansi-escapes "^4.3.1" chalk "^4.0.0" @@ -6864,10 +6643,10 @@ inquirer@~6.3.1: strip-ansi "^5.1.0" through "^2.3.6" -install-artifact-from-github@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/install-artifact-from-github/-/install-artifact-from-github-1.0.2.tgz#e1e478dd29880b9112ecd684a84029603e234a9d" - integrity sha512-yuMFBSVIP3vD0SDBGUqeIpgOAIlFx8eQFknQObpkYEM5gsl9hy6R9Ms3aV+Vw9MMyYsoPMeex0XDnfgY7uzc+Q== +install-artifact-from-github@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/install-artifact-from-github/-/install-artifact-from-github-1.2.0.tgz#adcbd123c16a4337ec44ea76d0ebf253cc16b074" + integrity sha512-3OxCPcY55XlVM3kkfIpeCgmoSKnMsz2A3Dbhsq0RXpIknKQmrX1YiznCeW9cD2ItFmDxziA3w6Eg8d80AoL3oA== internal-ip@^4.3.0: version "4.3.0" @@ -6961,11 +6740,11 @@ is-buffer@^1.1.5: integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== is-buffer@^2.0.2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" - integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== + version "2.0.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== -is-callable@^1.1.4, is-callable@^1.2.0: +is-callable@^1.1.4, is-callable@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9" integrity sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA== @@ -6989,7 +6768,7 @@ is-color-stop@^1.0.0: rgb-regex "^1.0.1" rgba-regex "^1.0.0" -is-core-module@^2.0.0: +is-core-module@^2.0.0, is-core-module@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.1.0.tgz#a4cc031d9b1aca63eecbd18a650e13cb4eeab946" integrity sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA== @@ -7185,18 +6964,11 @@ is-potential-custom-element-name@^1.0.0: integrity sha1-DFLlS8yjkbssSUsh6GJtczbG45c= is-promise@^2.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= - -is-regex@^1.0.4, is-regex@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" - integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ== - dependencies: - has "^1.0.3" + version "2.2.2" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" + integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== -is-regex@^1.1.0, is-regex@^1.1.1: +is-regex@^1.0.4, is-regex@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg== @@ -7470,7 +7242,7 @@ jsbn@~0.1.0: resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= -jsdom@^16.2.0: +jsdom@^16.4.0: version "16.4.0" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.4.0.tgz#36005bde2d136f73eee1a830c6d45e55408edddb" integrity sha512-lYMm3wYdgPhrl7pDcRmvzPhhrGVBeVhPIqeHjzeiHN3DFmD1RBpbExbi8vU7BJdH8VAZYovR8DMt0PNNDM7k8w== @@ -7626,9 +7398,9 @@ jsonparse@^1.2.0: integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA= jsonschema@^1.0.2: - version "1.2.5" - resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.2.5.tgz#bab69d97fa28946aec0a56a9cc266d23fe80ae61" - integrity sha512-kVTF+08x25PQ0CjuVc0gRM9EUPb0Fe9Ln/utFOgcdxEIOHuU7ooBk/UPTd7t1M91pP35m0MU1T8M5P7vP1bRRw== + version "1.4.0" + resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.4.0.tgz#1afa34c4bc22190d8e42271ec17ac8b3404f87b2" + integrity sha512-/YgW6pRMr6M7C+4o8kS+B/2myEpHCrxO4PEWnqJNBFMjn7EWXqlQ4tGwL6xTHeRplwuZmcAncdvfOad1nT2yMw== jsonwebtoken@^8.2.1, jsonwebtoken@^8.5.1: version "8.5.1" @@ -7874,14 +7646,6 @@ limiter@^1.0.5: resolved "https://registry.yarnpkg.com/limiter/-/limiter-1.1.5.tgz#8f92a25b3b16c6131293a0cc834b4a838a2aa7c2" integrity sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA== -line-column@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/line-column/-/line-column-1.0.2.tgz#d25af2936b6f4849172b312e4792d1d987bc34a2" - integrity sha1-0lryk2tvSEkXKzEuR5LR2Ye8NKI= - dependencies: - isarray "^1.0.0" - isobject "^2.0.0" - lines-and-columns@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" @@ -8114,12 +7878,7 @@ lodash.values@^2.4.1: dependencies: lodash.keys "~2.4.1" -lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.5: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== - -lodash@^4.17.19: +lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.5: version "4.17.20" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== @@ -8283,16 +8042,16 @@ md5.js@^1.3.4: inherits "^2.0.1" safe-buffer "^5.1.2" +mdn-data@2.0.14: + version "2.0.14" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" + integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== + mdn-data@2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== -mdn-data@2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.6.tgz#852dc60fcaa5daa2e8cf6c9189c440ed3e042978" - integrity sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA== - media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -8511,7 +8270,7 @@ minizlib@^1.2.1: dependencies: minipass "^2.9.0" -minizlib@^2.1.0, minizlib@^2.1.1: +minizlib@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== @@ -8548,26 +8307,14 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: - version "0.5.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.4.tgz#fd01504a6797ec5c9be81ff43d204961ed64a512" - integrity sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw== - dependencies: - minimist "^1.2.5" - -mkdirp@^0.5.3, mkdirp@^0.5.5: +"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== dependencies: minimist "^1.2.5" -mkdirp@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.3.tgz#4cf2e30ad45959dddea53ad97d518b6c8205e1ea" - integrity sha512-6uCP4Qc0sWsgMLy1EOqqS/3rjDHOEnsStVr/4vtAIK2Y5i2kA7lFFejYrpIyiN9w0pYf4ckeCYT9f1r1P9KX5g== - -mkdirp@^1.0.4, mkdirp@~1.0.4: +mkdirp@^1.0.3, mkdirp@^1.0.4, mkdirp@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== @@ -8633,20 +8380,10 @@ mute-stream@0.0.8: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -nan@^2.12.1: - version "2.14.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" - integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== - -nan@^2.14.1: - version "2.14.1" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" - integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== - -nanoid@^3.1.16: - version "3.1.16" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.16.tgz#b21f0a7d031196faf75314d7c65d36352beeef64" - integrity sha512-+AK8MN0WHji40lj8AEuwLOvLSbWYApQpre/aFJZD71r43wVRLrOYS4FmJOPQYon1TqB462RzrrxlfA74XRES8w== +nan@^2.12.1, nan@^2.14.2: + version "2.14.2" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" + integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== nanomatch@^1.2.9: version "1.2.13" @@ -8676,9 +8413,9 @@ nash@^3.0.0: minimist "^1.1.0" native-request@^1.0.5: - version "1.0.7" - resolved "https://registry.yarnpkg.com/native-request/-/native-request-1.0.7.tgz#ff742dc555b4c8f2f1c14b548639ba174e573856" - integrity sha512-9nRjinI9bmz+S7dgNtf4A70+/vPhnd+2krGpy4SUlADuOuSa24IDkNaZ+R/QT1wQ6S8jBdi6wE7fLekFZNfUpQ== + version "1.0.8" + resolved "https://registry.yarnpkg.com/native-request/-/native-request-1.0.8.tgz#8f66bf606e0f7ea27c0e5995eb2f5d03e33ae6fb" + integrity sha512-vU2JojJVelUGp6jRcLwToPoWGxSx23z/0iX+I77J3Ht17rf2INGjrhOoQnjVo60nQd8wVsgzKkPfRXBiVdD2ag== negotiator@0.6.2: version "0.6.2" @@ -8721,16 +8458,11 @@ node-fetch-npm@^2.0.2: json-parse-better-errors "^1.0.0" safe-buffer "^5.1.1" -node-fetch@2.6.1, node-fetch@^2.6.1: +node-fetch@2.6.1, node-fetch@^2.2.0, node-fetch@^2.3.0, node-fetch@^2.6.0, node-fetch@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== -node-fetch@^2.2.0, node-fetch@^2.3.0, node-fetch@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" - integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== - node-forge@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" @@ -8746,20 +8478,20 @@ node-forge@^0.9.0: resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.2.tgz#b35a44c28889b2ea55cabf8c79e3563f9676190a" integrity sha512-naKSScof4Wn+aoHU6HBsifh92Zeicm1GDQKd1vp3Y/kOi8ub0DozCa9KpvYNCXslFHYRmLNiqRopGdTGwNLpNw== -node-gyp@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-7.1.0.tgz#cb8aed7ab772e73ad592ae0c71b0e3741099fe39" - integrity sha512-rjlHQlnl1dqiDZxZYiKqQdrjias7V+81OVR5PTzZioCBtWkNdrKy06M05HLKxy/pcKikKRCabeDRoZaEc6nIjw== +node-gyp@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-7.1.2.tgz#21a810aebb187120251c3bcec979af1587b188ae" + integrity sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ== dependencies: env-paths "^2.2.0" glob "^7.1.4" graceful-fs "^4.2.3" - nopt "^4.0.3" + nopt "^5.0.0" npmlog "^4.1.2" request "^2.88.2" - rimraf "^2.6.3" + rimraf "^3.0.2" semver "^7.3.2" - tar "^6.0.1" + tar "^6.0.2" which "^2.0.2" node-libs-browser@^2.2.1: @@ -8791,28 +8523,17 @@ node-libs-browser@^2.2.1: util "^0.11.0" vm-browserify "^1.0.1" -node-releases@^1.1.58: - version "1.1.61" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.61.tgz#707b0fca9ce4e11783612ba4a2fcba09047af16e" - integrity sha512-DD5vebQLg8jLCOzwupn954fbIiZht05DAZs0k2u8NStSe6h9XdsuIQL8hSRKYiU8WUQRznmSDrKGbv3ObOmC7g== - -node-releases@^1.1.61: - version "1.1.64" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.64.tgz#71b4ae988e9b1dd7c1ffce58dd9e561752dfebc5" - integrity sha512-Iec8O9166/x2HRMJyLLLWkd0sFFLrFNy+Xf+JQfSQsdBJzPcHpNl3JQ9gD4j+aJxmCa25jNsIbM4bmACtSbkSg== - node-releases@^1.1.66: - version "1.1.66" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.66.tgz#609bd0dc069381015cd982300bae51ab4f1b1814" - integrity sha512-JHEQ1iWPGK+38VLB2H9ef2otU4l8s3yAMt9Xf934r6+ojCYDMHPMqvCc9TnzfeFSP1QEOeU6YZEd3+De0LTCgg== + version "1.1.67" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.67.tgz#28ebfcccd0baa6aad8e8d4d8fe4cbc49ae239c12" + integrity sha512-V5QF9noGFl3EymEwUYzO+3NTDpGfQB4ve6Qfnzf3UNydMhjQRVPR1DZTuvWiLzaFJYw2fmDwAfnRNEVb64hSIg== -nopt@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48" - integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg== +nopt@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" + integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== dependencies: abbrev "1" - osenv "^0.1.4" normalize-package-data@^2.3.2, normalize-package-data@^2.4.0: version "2.5.0" @@ -8870,7 +8591,7 @@ npm-normalize-package-bin@^1.0.0, npm-normalize-package-bin@^1.0.1: resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== -npm-package-arg@8.1.0: +npm-package-arg@8.1.0, npm-package-arg@^8.0.0: version "8.1.0" resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-8.1.0.tgz#b5f6319418c3246a1c38e1a8fbaa06231bc5308f" integrity sha512-/ep6QDxBkm9HvOhOg0heitSd7JHA1U7y1qhhlRlteYYAi9Pdb/ZV7FW5aHpkrpM8+P+4p/jjR8zCyKPBMBjSig== @@ -8889,15 +8610,6 @@ npm-package-arg@^6.0.0, npm-package-arg@^6.1.0: semver "^5.6.0" validate-npm-package-name "^3.0.0" -npm-package-arg@^8.0.0: - version "8.0.1" - resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-8.0.1.tgz#9d76f8d7667b2373ffda60bb801a27ef71e3e270" - integrity sha512-/h5Fm6a/exByzFSTm7jAyHbgOqErl9qSNJDQF32Si/ZzgwT2TERVxRxn3Jurw1wflgyVVAxnFR4fRHPM7y1ClQ== - dependencies: - hosted-git-info "^3.0.2" - semver "^7.0.0" - validate-npm-package-name "^3.0.0" - npm-packlist@^1.1.12: version "1.4.8" resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e" @@ -9001,33 +8713,28 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-inspect@^1.7.0, object-inspect@^1.8.0: +object-inspect@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA== -object-is@^1.0.1, object-is@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.2.tgz#c5d2e87ff9e119f78b7a088441519e2eec1573b6" - integrity sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ== +object-is@^1.0.1, object-is@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.3.tgz#2e3b9e65560137455ee3bd62aec4d90a2ea1cc81" + integrity sha512-teyqLvFWzLkq5B9ki8FVWA902UER2qkxmdA4nLf+wjOLAWgxzCWZNCxpDq9MvE8MmhWNr+I8w3BN49Vx36Y6Xg== dependencies: define-properties "^1.1.3" - es-abstract "^1.17.5" + es-abstract "^1.18.0-next.1" object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object-path@^0.11.4: - version "0.11.4" - resolved "https://registry.yarnpkg.com/object-path/-/object-path-0.11.4.tgz#370ae752fbf37de3ea70a861c23bba8915691949" - integrity sha1-NwrnUvvzfePqcKhhwju6iRVpGUk= - -object-path@^0.9.0: - version "0.9.2" - resolved "https://registry.yarnpkg.com/object-path/-/object-path-0.9.2.tgz#0fd9a74fc5fad1ae3968b586bda5c632bd6c05a5" - integrity sha1-D9mnT8X60a45aLWGvaXGMr1sBaU= +object-path@^0.11.5: + version "0.11.5" + resolved "https://registry.yarnpkg.com/object-path/-/object-path-0.11.5.tgz#d4e3cf19601a5140a55a16ad712019a9c50b577a" + integrity sha512-jgSbThcoR/s+XumvGMTMf81QVBmah+/Q7K7YduKeKVWL7N111unR2d6pZZarSk6kY/caeNxUDyxOvMWyzoU2eg== object-visit@^1.0.0: version "1.0.1" @@ -9036,13 +8743,13 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" -object.assign@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.1.tgz#303867a666cdd41936ecdedfb1f8f3e32a478cdd" - integrity sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA== +object.assign@^4.1.0, object.assign@^4.1.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== dependencies: + call-bind "^1.0.0" define-properties "^1.1.3" - es-abstract "^1.18.0-next.0" has-symbols "^1.0.1" object-keys "^1.1.1" @@ -9215,7 +8922,7 @@ os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= -osenv@^0.1.4, osenv@^0.1.5: +osenv@^0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== @@ -9239,9 +8946,9 @@ p-finally@^1.0.0: integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= p-limit@^2.0.0, p-limit@^2.2.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.2.tgz#61279b67721f5287aa1c13a9a7fbbc48c9291b1e" - integrity sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ== + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== dependencies: p-try "^2.0.0" @@ -9418,6 +9125,11 @@ parseqs@0.0.5: dependencies: better-assert "~1.0.0" +parseqs@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.6.tgz#8e4bb5a19d1cdc844a08ac974d34e273afa670d5" + integrity sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w== + parseuri@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a" @@ -9425,6 +9137,11 @@ parseuri@0.0.5: dependencies: better-assert "~1.0.0" +parseuri@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.6.tgz#e1496e829e3ac2ff47f39a4dd044b32823c4a25a" + integrity sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow== + parseurl@~1.3.2, parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -9598,9 +9315,9 @@ posix-character-classes@^0.1.0: integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= postcss-calc@^7.0.1: - version "7.0.4" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.4.tgz#5e177ddb417341e6d4a193c5d9fd8ada79094f8b" - integrity sha512-0I79VRAd1UTkaHzY9w83P39YGO/M3bG7/tNLrHGEunBolfoGM0hSjrGvjoeaj0JE/zIw5GsI2KZ0UwDJqv5hjw== + version "7.0.5" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.5.tgz#f8a6e99f12e619c2ebc23cf6c486fdc15860933e" + integrity sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg== dependencies: postcss "^7.0.27" postcss-selector-parser "^6.0.2" @@ -9736,33 +9453,38 @@ postcss-minify-selectors@^4.0.2: postcss "^7.0.0" postcss-selector-parser "^3.0.0" -postcss-modules-extract-imports@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" - integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== +postcss-modules-extract-imports@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e" + integrity sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ== + dependencies: + postcss "^7.0.5" -postcss-modules-local-by-default@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz#ebbb54fae1598eecfdf691a02b3ff3b390a5a51c" - integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ== +postcss-modules-local-by-default@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz#bb14e0cc78279d504dbdcbfd7e0ca28993ffbbb0" + integrity sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw== dependencies: - icss-utils "^5.0.0" + icss-utils "^4.1.1" + postcss "^7.0.32" postcss-selector-parser "^6.0.2" postcss-value-parser "^4.1.0" -postcss-modules-scope@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06" - integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg== +postcss-modules-scope@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz#385cae013cc7743f5a7d7602d1073a89eaae62ee" + integrity sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ== dependencies: - postcss-selector-parser "^6.0.4" + postcss "^7.0.6" + postcss-selector-parser "^6.0.0" -postcss-modules-values@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" - integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== +postcss-modules-values@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10" + integrity sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg== dependencies: - icss-utils "^5.0.0" + icss-utils "^4.0.0" + postcss "^7.0.6" postcss-normalize-charset@^4.0.1: version "4.0.1" @@ -9883,17 +9605,7 @@ postcss-selector-parser@^3.0.0: indexes-of "^1.0.1" uniq "^1.0.1" -postcss-selector-parser@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.3.tgz#766d77728728817cc140fa1ac6da5e77f9fada98" - integrity sha512-0ClFaY4X1ra21LRqbW6y3rUbWcxnSVkDFG57R7Nxus9J9myPFlv+jYDMohzpkBx0RrjjiqjtycpchQ+PLGmZ9w== - dependencies: - cssesc "^3.0.0" - indexes-of "^1.0.1" - uniq "^1.0.1" - util-deprecate "^1.0.2" - -postcss-selector-parser@^6.0.4: +postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: version "6.0.4" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz#56075a1380a04604c38b063ea7767a129af5c2b3" integrity sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw== @@ -9927,12 +9639,7 @@ postcss-value-parser@^3.0.0, postcss-value-parser@^3.2.3: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== -postcss-value-parser@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.3.tgz#651ff4593aa9eda8d5d0d66593a2417aeaeb325d" - integrity sha512-N7h4pG+Nnu5BEIzyeaaIYWs0LI5XC40OrRh5L60z0QjFsqGWcHcbkBvpe1WYpcIS9yQ8sOi/vIPt1ejQCrMVrg== - -postcss-value-parser@^4.1.0: +postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== @@ -9955,34 +9662,15 @@ postcss@7.0.32: source-map "^0.6.1" supports-color "^6.1.0" -postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.27: - version "7.0.27" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.27.tgz#cc67cdc6b0daa375105b7c424a85567345fc54d9" - integrity sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ== +postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.27, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: + version "7.0.35" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.35.tgz#d2be00b998f7f211d8a276974079f2e92b970e24" + integrity sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg== dependencies: chalk "^2.4.2" source-map "^0.6.1" supports-color "^6.1.0" -postcss@^7.0.32: - version "7.0.34" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.34.tgz#f2baf57c36010df7de4009940f21532c16d65c20" - integrity sha512-H/7V2VeNScX9KE83GDrDZNiGT1m2H+UTnlinIzhjlLX9hfMUn1mHNnGeX81a1c8JSBdBvqk7c2ZOG6ZPn5itGw== - dependencies: - chalk "^2.4.2" - source-map "^0.6.1" - supports-color "^6.1.0" - -postcss@^8.1.1: - version "8.1.7" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.1.7.tgz#ff6a82691bd861f3354fd9b17b2332f88171233f" - integrity sha512-llCQW1Pz4MOPwbZLmOddGM9eIJ8Bh7SZ2Oj5sxZva77uVaotYDsYTch1WBTNu7fUY0fpWp0fdt7uW40D4sRiiQ== - dependencies: - colorette "^1.2.1" - line-column "^1.0.2" - nanoid "^3.1.16" - source-map "^0.6.1" - prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" @@ -10037,28 +9725,9 @@ promise-retry@^1.1.1: retry "^0.10.0" protobufjs@^6.8.1, protobufjs@^6.8.6, protobufjs@^6.8.8, protobufjs@^6.8.9: - version "6.8.9" - resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.8.9.tgz#0b1adbcdaa983d369c3d9108a97c814edc030754" - integrity sha512-j2JlRdUeL/f4Z6x4aU4gj9I2LECglC+5qR2TrWb193Tla1qfdaNQTZ8I27Pt7K0Ajmvjjpft7O3KWTGciz4gpw== - dependencies: - "@protobufjs/aspromise" "^1.1.2" - "@protobufjs/base64" "^1.1.2" - "@protobufjs/codegen" "^2.0.4" - "@protobufjs/eventemitter" "^1.1.0" - "@protobufjs/fetch" "^1.1.0" - "@protobufjs/float" "^1.0.2" - "@protobufjs/inquire" "^1.1.0" - "@protobufjs/path" "^1.1.2" - "@protobufjs/pool" "^1.1.0" - "@protobufjs/utf8" "^1.1.0" - "@types/long" "^4.0.0" - "@types/node" "^10.1.0" - long "^4.0.0" - -protobufjs@^6.9.0: - version "6.10.1" - resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.10.1.tgz#e6a484dd8f04b29629e9053344e3970cccf13cd2" - integrity sha512-pb8kTchL+1Ceg4lFd5XUpK8PdWacbvV5SK2ULH2ebrYtl4GjJmS24m6CKME67jzV53tbJxHlnNOSqQHbTsR9JQ== + version "6.10.2" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.10.2.tgz#b9cb6bd8ec8f87514592ba3fdfd28e93f33a469b" + integrity sha512-27yj+04uF6ya9l+qfpH187aqEzfCF4+Uit0I9ZBQVqK09hk/SQzKa2MUqUpXaVa7LOFRg1TSSr3lVxGOk6c0SQ== dependencies: "@protobufjs/aspromise" "^1.1.2" "@protobufjs/base64" "^1.1.2" @@ -10166,9 +9835,9 @@ punycode@^2.1.0, punycode@^2.1.1: integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== pupa@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.0.1.tgz#dbdc9ff48ffbea4a26a069b6f9f7abb051008726" - integrity sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA== + version "2.1.1" + resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62" + integrity sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A== dependencies: escape-goat "^2.0.0" @@ -10281,13 +9950,13 @@ rc@^1.2.8: strip-json-comments "~2.0.1" re2@^1.15.0: - version "1.15.4" - resolved "https://registry.yarnpkg.com/re2/-/re2-1.15.4.tgz#2ffc3e4894fb60430393459978197648be01a0a9" - integrity sha512-7w3K+Daq/JjbX/dz5voMt7B9wlprVBQnMiypyCojAZ99kcAL+3LiJ5uBoX/u47l8eFTVq3Wj+V0pmvU+CT8tOg== + version "1.15.9" + resolved "https://registry.yarnpkg.com/re2/-/re2-1.15.9.tgz#9ed16171edcb0bc4f0e239bf55229ff3f26acbe3" + integrity sha512-AXWEhpMTBdC+3oqbjdU07dk0pBCvxh5vbOMLERL6Y8FYBSGn4vXlLe8cYszn64Yy7H8keVMrgPzoSvOd4mePpg== dependencies: - install-artifact-from-github "^1.0.2" - nan "^2.14.1" - node-gyp "^7.0.0" + install-artifact-from-github "^1.2.0" + nan "^2.14.2" + node-gyp "^7.1.2" read-cache@^1.0.0: version "1.0.0" @@ -10348,10 +10017,10 @@ readdirp@^2.2.1: micromatch "^3.1.10" readable-stream "^2.0.2" -readdirp@~3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.4.0.tgz#9fdccdf9e9155805449221ac645e8303ab5b9ada" - integrity sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ== +readdirp@~3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" + integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== dependencies: picomatch "^2.2.1" @@ -10375,20 +10044,15 @@ regenerate-unicode-properties@^8.2.0: regenerate "^1.4.0" regenerate@^1.4.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.1.tgz#cad92ad8e6b591773485fbe05a485caf4f457e6f" - integrity sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A== + version "1.4.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== -regenerator-runtime@0.13.7: +regenerator-runtime@0.13.7, regenerator-runtime@^0.13.4: version "0.13.7" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== -regenerator-runtime@^0.13.4: - version "0.13.5" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" - integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== - regenerator-transform@^0.14.2: version "0.14.5" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" @@ -10417,7 +10081,7 @@ regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.3.0: define-properties "^1.1.3" es-abstract "^1.17.0-next.1" -regexpu-core@^4.7.0, regexpu-core@^4.7.1: +regexpu-core@^4.7.1: version "4.7.1" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6" integrity sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ== @@ -10430,9 +10094,9 @@ regexpu-core@^4.7.0, regexpu-core@^4.7.1: unicode-match-property-value-ecmascript "^1.2.0" registry-auth-token@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.0.tgz#1d37dffda72bbecd0f581e4715540213a65eb7da" - integrity sha512-P+lWzPrsgfN+UEpDS3U8AQKg/UjZX6mQSJueZj3EK+vNESoqBSpBUD3gmu4sF9lOsjXWjF11dQKUqemf3veq1w== + version "4.2.1" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250" + integrity sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw== dependencies: rc "^1.2.8" @@ -10486,7 +10150,7 @@ request-promise-native@^1.0.8: stealthy-require "^1.1.1" tough-cookie "^2.3.3" -request@^2.87.0, request@^2.88.0, request@^2.88.2: +request@^2.87.0, request@^2.88.2: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -10574,10 +10238,11 @@ resolve@1.18.1: path-parse "^1.0.6" resolve@^1.1.7, resolve@^1.10.0, resolve@^1.3.2, resolve@^1.8.1: - version "1.17.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" - integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + version "1.19.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" + integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== dependencies: + is-core-module "^2.1.0" path-parse "^1.0.6" resp-modifier@6.0.2: @@ -10719,9 +10384,9 @@ run-async@^2.2.0, run-async@^2.4.0: integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== run-parallel@^1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" - integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== + version "1.1.10" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.10.tgz#60a51b2ae836636c81377df16cb107351bcd13ef" + integrity sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw== run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" @@ -10742,7 +10407,7 @@ rxjs@6.6.2: dependencies: tslib "^1.9.0" -rxjs@6.6.3, rxjs@^6.5.2, rxjs@^6.5.3, rxjs@^6.5.5, rxjs@^6.6.0, rxjs@^6.6.2, rxjs@~6.6.3: +rxjs@6.6.3, rxjs@^6.4.0, rxjs@^6.5.2, rxjs@^6.5.3, rxjs@^6.5.5, rxjs@^6.6.0, rxjs@^6.6.2, rxjs@~6.6.3: version "6.6.3" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.3.tgz#8ca84635c4daa900c0d3967a6ee7ac60271ee552" integrity sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ== @@ -10756,13 +10421,6 @@ rxjs@^5.5.6: dependencies: symbol-observable "1.0.1" -rxjs@^6.4.0: - version "6.5.4" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c" - integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q== - dependencies: - tslib "^1.9.0" - safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -10824,22 +10482,14 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" -schema-utils@^2.6.5: - version "2.6.5" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.5.tgz#c758f0a7e624263073d396e29cd40aa101152d8a" - integrity sha512-5KXuwKziQrTVHh8j/Uxz+QUbxkaLW9X/86NBlx/gnKgtsZA2GIVMUn17qWhRFwF8jdYb3Dig5hRO/W5mZqy6SQ== - dependencies: - ajv "^6.12.0" - ajv-keywords "^3.4.1" - -schema-utils@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7" - integrity sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A== +schema-utils@^2.6.5, schema-utils@^2.7.0, schema-utils@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" + integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== dependencies: - "@types/json-schema" "^7.0.4" - ajv "^6.12.2" - ajv-keywords "^3.4.1" + "@types/json-schema" "^7.0.5" + ajv "^6.12.4" + ajv-keywords "^3.5.2" schema-utils@^3.0.0: version "3.0.0" @@ -11067,7 +10717,7 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -side-channel@^1.0.2: +side-channel@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.3.tgz#cdc46b057550bbab63706210838df5d4c19519c3" integrity sha512-A6+ByhlLkksFoUepsGxfj5x1gTSrs+OydsRptUxeNCabQpCFUvcwIczgOigI8vhY/OJCnPnyE9rGiwgvr9cS1g== @@ -11157,7 +10807,7 @@ socket.io-client@2.1.1: socket.io-parser "~3.2.0" to-array "0.1.4" -socket.io-client@2.3.0, socket.io-client@^2.0.4: +socket.io-client@2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.3.0.tgz#14d5ba2e00b9bcd145ae443ab96b3f86cbcc1bb4" integrity sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA== @@ -11177,6 +10827,23 @@ socket.io-client@2.3.0, socket.io-client@^2.0.4: socket.io-parser "~3.3.0" to-array "0.1.4" +socket.io-client@^2.0.4: + version "2.3.1" + resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.3.1.tgz#91a4038ef4d03c19967bb3c646fec6e0eaa78cff" + integrity sha512-YXmXn3pA8abPOY//JtYxou95Ihvzmg8U6kQyolArkIyLd0pgVhrfor/iMsox8cn07WCOOvvuJ6XKegzIucPutQ== + dependencies: + backo2 "1.0.2" + component-bind "1.0.0" + component-emitter "~1.3.0" + debug "~3.1.0" + engine.io-client "~3.4.0" + has-binary2 "~1.0.2" + indexof "0.0.1" + parseqs "0.0.6" + parseuri "0.0.6" + socket.io-parser "~3.3.0" + to-array "0.1.4" + socket.io-parser@~3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.2.0.tgz#e7c6228b6aa1f814e6148aea325b51aa9499e077" @@ -11187,11 +10854,11 @@ socket.io-parser@~3.2.0: isarray "2.0.1" socket.io-parser@~3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.3.0.tgz#2b52a96a509fdf31440ba40fed6094c7d4f1262f" - integrity sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng== + version "3.3.1" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.3.1.tgz#f07d9c8cb3fb92633aa93e76d98fd3a334623199" + integrity sha512-1QLvVAe8dTz+mKmZ07Swxt+LAo4Y1ff50rlyoEx00TQmDFVQYPfcqGvIDJLGaBdhdNCecXtyKpD+EgKGcmmbuQ== dependencies: - component-emitter "1.2.1" + component-emitter "~1.3.0" debug "~3.1.0" isarray "2.0.1" @@ -11293,7 +10960,7 @@ source-map-resolve@^0.5.0, source-map-resolve@^0.5.2: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@0.5.19, source-map-support@^0.5.17, source-map-support@~0.5.12, source-map-support@~0.5.19: +source-map-support@0.5.19, source-map-support@^0.5.17, source-map-support@^0.5.5, source-map-support@~0.5.12, source-map-support@~0.5.19: version "0.5.19" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== @@ -11301,14 +10968,6 @@ source-map-support@0.5.19, source-map-support@^0.5.17, source-map-support@~0.5.1 buffer-from "^1.0.0" source-map "^0.6.0" -source-map-support@^0.5.5: - version "0.5.16" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" - integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - source-map-url@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" @@ -11583,20 +11242,20 @@ string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0: strip-ansi "^6.0.0" string.prototype.trimend@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913" - integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g== + version "1.0.2" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz#6ddd9a8796bc714b489a3ae22246a208f37bfa46" + integrity sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw== dependencies: define-properties "^1.1.3" - es-abstract "^1.17.5" + es-abstract "^1.18.0-next.1" string.prototype.trimstart@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54" - integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw== + version "1.0.2" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz#22d45da81015309cd0cdd79787e8919fc5c613e7" + integrity sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg== dependencies: define-properties "^1.1.3" - es-abstract "^1.17.5" + es-abstract "^1.18.0-next.1" string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" @@ -11703,9 +11362,9 @@ stylus@0.54.8: source-map "^0.7.3" superstatic@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/superstatic/-/superstatic-7.0.0.tgz#ac365bd8f224c4904b46c47bddfbebcc30df23d6" - integrity sha512-rFXKNsouDBIor3PeroAcZAaCIjXCoocR6Drk7XK3oynFzcgv2Vkgt/6B5GqSe+qp4+N0SDTtVLP/PamBrG/Kfg== + version "7.0.1" + resolved "https://registry.yarnpkg.com/superstatic/-/superstatic-7.0.1.tgz#cf82b0fd03100d294636ec76ccfa4eda6f255676" + integrity sha512-oph3y5srRKrF8qeCVnQXbysb7U9ixPZQBlqniQymZimJwy2D1xba0EMouCFquhkwRrZYLgd7YPtkSBaPwyFYZA== dependencies: as-array "^2.0.0" async "^1.5.2" @@ -11842,7 +11501,7 @@ tar@^4.3.0, tar@^4.4.10: safe-buffer "^5.1.2" yallist "^3.0.3" -tar@^6.0.1: +tar@^6.0.2: version "6.0.5" resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.5.tgz#bde815086e10b39f1dcd298e89d596e1535e200f" integrity sha512-0b4HOimQHj9nXNEAA7zWwMM91Zhhba3pspja6sQbgTpynOJf+bkjBnfybNYzbpLbnwXnbyB4LOREvlyXLkCHSg== @@ -11854,18 +11513,6 @@ tar@^6.0.1: mkdirp "^1.0.3" yallist "^4.0.0" -tar@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.2.tgz#5df17813468a6264ff14f766886c622b84ae2f39" - integrity sha512-Glo3jkRtPcvpDlAs/0+hozav78yoXKFr+c4wgw62NNMO3oo4AaJdCo21Uu7lcwr55h39W2XD1LMERc64wtbItg== - dependencies: - chownr "^2.0.0" - fs-minipass "^2.0.0" - minipass "^3.0.0" - minizlib "^2.1.0" - mkdirp "^1.0.3" - yallist "^4.0.0" - tcp-port-used@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/tcp-port-used/-/tcp-port-used-1.0.1.tgz#46061078e2d38c73979a2c2c12b5a674e6689d70" @@ -11886,9 +11533,9 @@ teeny-request@^6.0.0: uuid "^7.0.0" term-size@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.0.tgz#1f16adedfe9bdc18800e1776821734086fcc6753" - integrity sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw== + version "2.2.1" + resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54" + integrity sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg== terser-webpack-plugin@4.2.3: version "4.2.3" @@ -11939,9 +11586,9 @@ terser@^4.1.2: source-map-support "~0.5.12" terser@^5.3.4: - version "5.3.8" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.3.8.tgz#991ae8ba21a3d990579b54aa9af11586197a75dd" - integrity sha512-zVotuHoIfnYjtlurOouTazciEfL7V38QMAOhGqpXDEg6yT13cF4+fEP9b0rrCEQTn+tT46uxgFsTZzhygk+CzQ== + version "5.5.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.5.0.tgz#1406fcb4d4bc517add3b22a9694284c040e33448" + integrity sha512-eopt1Gf7/AQyPhpygdKePTzaet31TvQxXvrf7xYUvD/d8qkCJm4SKPDzu+GHK5ZaYTn8rvttfqaZc3swK21e5g== dependencies: commander "^2.20.0" source-map "~0.7.2" @@ -11957,13 +11604,13 @@ text-table@0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= -tfunk@^3.0.1: - version "3.1.0" - resolved "https://registry.yarnpkg.com/tfunk/-/tfunk-3.1.0.tgz#38e4414fc64977d87afdaa72facb6d29f82f7b5b" - integrity sha1-OORBT8ZJd9h6/apy+sttKfgve1s= +tfunk@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/tfunk/-/tfunk-4.0.0.tgz#de9399feaf2060901d590b7faad80fcd5443077e" + integrity sha512-eJQ0dGfDIzWNiFNYFVjJ+Ezl/GmwHaFTBTjrtqNPW0S7cuVDBrZrmzUz6VkMeCR4DZFqhd4YtLwsw3i2wYHswQ== dependencies: - chalk "^1.1.1" - object-path "^0.9.0" + chalk "^1.1.3" + dlv "^1.1.3" through2@2.0.1: version "2.0.1" @@ -12157,25 +11804,15 @@ ts-pnp@^1.1.6: resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw== -tslib@2.0.3: +tslib@2.0.3, tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.3.tgz#8e0741ac45fc0c226e58a17bfc3e64b9bc6ca61c" integrity sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ== tslib@^1.10.0, tslib@^1.11.1, tslib@^1.13.0, tslib@^1.8.1, tslib@^1.9.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" - integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== - -tslib@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.0.tgz#18d13fc2dce04051e20f074cc8387fd8089ce4f3" - integrity sha512-lTqkx847PI7xEDYJntxZH89L2/aXInsyF2luSafe/+0fHOMjlBNXdH6th7f70qxLDhul7KZK0zC8V5ZIyHl0/g== - -tslib@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.1.tgz#410eb0d113e5b6356490eec749603725b021b43e" - integrity sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ== + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== tslint@~6.1.3: version "6.1.3" @@ -12364,7 +12001,7 @@ unique-string@^2.0.0: dependencies: crypto-random-string "^2.0.0" -universal-analytics@0.4.23: +universal-analytics@0.4.23, universal-analytics@^0.4.16: version "0.4.23" resolved "https://registry.yarnpkg.com/universal-analytics/-/universal-analytics-0.4.23.tgz#d915e676850c25c4156762471bdd7cf2eaaca8ac" integrity sha512-lgMIH7XBI6OgYn1woDEmxhGdj8yDefMKg7GkWdeATAlQZFrMrNyxSkpDzY57iY0/6fdlzTbBV03OawvvzG+q7A== @@ -12373,15 +12010,6 @@ universal-analytics@0.4.23: request "^2.88.2" uuid "^3.0.0" -universal-analytics@^0.4.16: - version "0.4.20" - resolved "https://registry.yarnpkg.com/universal-analytics/-/universal-analytics-0.4.20.tgz#d6b64e5312bf74f7c368e3024a922135dbf24b03" - integrity sha512-gE91dtMvNkjO+kWsPstHRtSwHXz0l2axqptGYp5ceg4MsuurloM0PU3pdOfpb5zBXUvyjT4PwhWK2m39uczZuw== - dependencies: - debug "^3.0.0" - request "^2.88.0" - uuid "^3.0.0" - universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" @@ -12427,9 +12055,9 @@ upath@^1.1.1: integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== update-notifier@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-4.1.1.tgz#895fc8562bbe666179500f9f2cebac4f26323746" - integrity sha512-9y+Kds0+LoLG6yN802wVXoIfxYEwh3FlZwzMwpCZp62S2i1/Jzeqb9Eeeju3NSHccGGasfGlK5/vEHbAifYRDg== + version "4.1.3" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-4.1.3.tgz#be86ee13e8ce48fb50043ff72057b5bd598e1ea3" + integrity sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A== dependencies: boxen "^4.2.0" chalk "^3.0.0" @@ -12801,9 +12429,9 @@ whatwg-fetch@2.0.4: integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng== whatwg-fetch@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.4.1.tgz#e5f871572d6879663fa5674c8f833f15a8425ab3" - integrity sha512-sofZVzE1wKwO+EYPbWfiwzaKovWiZXf4coEzjGP9b2GBVgQRLQUZ2QcuPpQExGDAW5GItpEm6Tl4OU5mywnAoQ== + version "3.5.0" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.5.0.tgz#605a2cd0a7146e5db141e29d1c62ab84c0c4c868" + integrity sha512-jXkLtsR42xhXg7akoDKvKWE40eJeI+2KZqcp2h3NsOrRnDvtWX36KcKl30dy+hxECivdk2BVUHVNrPtoMBUx6A== whatwg-mimetype@^2.3.0: version "2.3.0" @@ -12811,9 +12439,9 @@ whatwg-mimetype@^2.3.0: integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== whatwg-url@^8.0.0: - version "8.2.2" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.2.2.tgz#85e7f9795108b53d554cec640b2e8aee2a0d4bfd" - integrity sha512-PcVnO6NiewhkmzV0qn7A+UZ9Xx4maNTI+O+TShmfE4pqjoCMwUMjkvoNhNHPTvgR7QH9Xt3R13iHuWy2sToFxQ== + version "8.4.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.4.0.tgz#50fb9615b05469591d2b2bd6dfaed2942ed72837" + integrity sha512-vwTUFf6V4zhcPkWp/4CQPr1TW9Ml6SF4lVyaIMBdJw5i6qUUJ1QWM4Z6YYVkfka0OUIzVo/0aNtGVGk256IKWw== dependencies: lodash.sortby "^4.7.0" tr46 "^2.0.2" @@ -12950,6 +12578,15 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -12973,9 +12610,9 @@ ws@^6.2.1: async-limiter "~1.0.0" ws@^7.1.2, ws@^7.2.3: - version "7.3.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.3.1.tgz#d0547bf67f7ce4f12a72dfe31262c68d7dc551c8" - integrity sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA== + version "7.4.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.0.tgz#a5dd76a24197940d4a8bb9e0e152bb4503764da7" + integrity sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ== ws@~3.3.1: version "3.3.3" @@ -13043,6 +12680,11 @@ y18n@^4.0.0: resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== +y18n@^5.0.5: + version "5.0.5" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.5.tgz#8769ec08d03b1ea2df2500acef561743bbb9ab18" + integrity sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg== + yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" @@ -13066,7 +12708,7 @@ yargs-parser@^13.1.1, yargs-parser@^13.1.2: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^18.1.0, yargs-parser@^18.1.2: +yargs-parser@^18.1.2: version "18.1.3" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== @@ -13074,6 +12716,11 @@ yargs-parser@^18.1.0, yargs-parser@^18.1.2: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^20.2.2: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + yargs@13.3.0: version "13.3.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" @@ -13090,23 +12737,6 @@ yargs@13.3.0: y18n "^4.0.0" yargs-parser "^13.1.1" -yargs@15.3.0: - version "15.3.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.0.tgz#403af6edc75b3ae04bf66c94202228ba119f0976" - integrity sha512-g/QCnmjgOl1YJjGsnUg2SatC7NUYEiLXJqxNOQU9qSpjzGtGXda9b+OKccr1kLTy8BN9yqEyqfq5lxlwdc13TA== - dependencies: - 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.0" - yargs@^13.3.0, yargs@^13.3.2: version "13.3.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" @@ -13140,6 +12770,19 @@ yargs@^15.3.1, yargs@^15.4.1: y18n "^4.0.0" yargs-parser "^18.1.2" +yargs@^16.1.1: + version "16.1.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.1.1.tgz#5a4a095bd1ca806b0a50d0c03611d38034d219a1" + integrity sha512-hAD1RcFP/wfgfxgMVswPE+z3tlPFtxG8/yWUrG2i17sTWGCGqWnxKcLTF4cUKDUK8fzokwsmO9H0TDkRbMHy8w== + dependencies: + 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" + yeast@0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" diff --git a/src/firestore/firestore-memory.module.ts b/src/firestore/firestore-memory.module.ts new file mode 100644 index 000000000..e4fda5da5 --- /dev/null +++ b/src/firestore/firestore-memory.module.ts @@ -0,0 +1,9 @@ +import { NgModule } from '@angular/core'; +import { AngularFirestore } from './firestore'; + +@NgModule({ + providers: [ AngularFirestore ] +}) +export class AngularFirestoreModule { + // firebase/firestore/memory does not have persistence capabilities +} diff --git a/src/firestore/firestore-memory.ts b/src/firestore/firestore-memory.ts new file mode 100644 index 000000000..f7f8ee511 --- /dev/null +++ b/src/firestore/firestore-memory.ts @@ -0,0 +1,6 @@ +// See index.ts, this variant is built by ./memory/ng-package.json +import 'firebase/firestore/memory'; + +/** @internal */ +export * from './public_api'; +export * from './firestore-memory.module'; diff --git a/src/firestore/firestore.ts b/src/firestore/firestore.ts index cbf68b8cb..a36793c69 100644 --- a/src/firestore/firestore.ts +++ b/src/firestore/firestore.ts @@ -25,7 +25,6 @@ import { } from '@angular/fire'; import { isPlatformServer } from '@angular/common'; import firebase from 'firebase/app'; -import 'firebase/firestore'; import { USE_EMULATOR as USE_AUTH_EMULATOR } from '@angular/fire/auth'; import { ɵfetchInstance, ɵlogAuthEmulatorError } from '@angular/fire'; diff --git a/src/firestore/index.ts b/src/firestore/index.ts new file mode 100644 index 000000000..91043225c --- /dev/null +++ b/src/firestore/index.ts @@ -0,0 +1,9 @@ +// DO NOT MODIFY. This entry point is intended only for the side-effect import +// for firebase/firestore, it's here so Firestore variants can be used in other +// entry points. Ensure all APIs are exported on ./public_api as that's what +// the other entry points reexport. + +import 'firebase/firestore'; + +export * from './public_api'; +export * from './firestore.module'; diff --git a/src/firestore/memory/ng-package.json b/src/firestore/memory/ng-package.json new file mode 100644 index 000000000..e122fa715 --- /dev/null +++ b/src/firestore/memory/ng-package.json @@ -0,0 +1,6 @@ +{ + "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", + "lib": { + "entryFile": "../firestore-memory.ts" + } +} diff --git a/src/firestore/package.json b/src/firestore/package.json index 75b34a51b..277850f56 100644 --- a/src/firestore/package.json +++ b/src/firestore/package.json @@ -2,7 +2,7 @@ "$schema": "../../node_modules/ng-packagr/package.schema.json", "ngPackage": { "lib": { - "entryFile": "public_api.ts", + "entryFile": "index.ts", "umdModuleIds": { "firebase/app": "firebase", "@firebase/firestore": "firebase-firestore" diff --git a/src/firestore/public_api.ts b/src/firestore/public_api.ts index 1670f1451..d17c942cd 100644 --- a/src/firestore/public_api.ts +++ b/src/firestore/public_api.ts @@ -1,5 +1,4 @@ export * from './firestore'; -export * from './firestore.module'; export * from './collection/collection'; export * from './collection-group/collection-group'; export * from './document/document'; diff --git a/tsconfig.json b/tsconfig.json index aa1210871..95263ebbf 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,6 +5,7 @@ "target": "es2015", "declaration": true, "inlineSources": true, + "stripInternal": true, "types": [ "node", "zone.js" diff --git a/yarn.lock b/yarn.lock index f8d2144d2..8d2b9c010 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10,23 +10,23 @@ "@angular-devkit/core" "10.2.0" rxjs "6.6.2" -"@angular-devkit/architect@0.1100.0", "@angular-devkit/architect@>= 0.900 < 0.1200": - version "0.1100.0" - resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1100.0.tgz#0ef9cb3616e0368fa6898574cafeec7cd4357930" - integrity sha512-JFPEpEgxJGk5eaJsEilQNI5rOAKCawMdGFAq1uBlYeXSt3iMfFfn//ayvIsE7L2y5b4MC0rzafWSNyDSP3+WuA== +"@angular-devkit/architect@0.1100.2", "@angular-devkit/architect@>= 0.900 < 0.1200": + version "0.1100.2" + resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1100.2.tgz#7567af030afe7d6cdea1771bcd2a193a19a90dc9" + integrity sha512-wSMMM8eBPol48OtvIyrIq2H9rOIiJmrPEtPbH0BSuPX0B8BckVImeTPzloqxSrpul4tY7Iwx0zwISDEgb59Vbw== dependencies: - "@angular-devkit/core" "11.0.0" + "@angular-devkit/core" "11.0.2" rxjs "6.6.3" "@angular-devkit/build-angular@>= 0.900 < 0.1200": - version "0.1100.0" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-0.1100.0.tgz#11c29c3f324150ad3ae867fb06a7dc9b2dcaa910" - integrity sha512-jCgtnqfBLO00LNImqtjeW07ijYXdpzhsOM4jzlhafh/NesjWJXgg1NI1K7QJvmVL79TeqbBsMj8IOLGTMUCDJw== - dependencies: - "@angular-devkit/architect" "0.1100.0" - "@angular-devkit/build-optimizer" "0.1100.0" - "@angular-devkit/build-webpack" "0.1100.0" - "@angular-devkit/core" "11.0.0" + version "0.1100.2" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-0.1100.2.tgz#afbeef979df4dbafeed3ff3de438dc9f35e2d148" + integrity sha512-5Qo3DDKggzUJKibNgeyE5mIMFYP0tVebNvMatpbnYnR/U0fUuuQdvNC68s380M5KoOuubfeXr0Js0VFk0mkaow== + dependencies: + "@angular-devkit/architect" "0.1100.2" + "@angular-devkit/build-optimizer" "0.1100.2" + "@angular-devkit/build-webpack" "0.1100.2" + "@angular-devkit/core" "11.0.2" "@babel/core" "7.12.3" "@babel/generator" "7.12.1" "@babel/plugin-transform-runtime" "7.12.1" @@ -34,7 +34,7 @@ "@babel/runtime" "7.12.1" "@babel/template" "7.10.4" "@jsdevtools/coverage-istanbul-loader" "3.0.5" - "@ngtools/webpack" "11.0.0" + "@ngtools/webpack" "11.0.2" ansi-colors "4.1.1" autoprefixer "9.8.6" babel-loader "8.1.0" @@ -44,7 +44,7 @@ circular-dependency-plugin "5.2.0" copy-webpack-plugin "6.2.1" core-js "3.6.5" - css-loader "5.0.0" + css-loader "4.3.0" cssnano "4.1.10" file-loader "6.1.1" find-cache-dir "3.3.1" @@ -101,10 +101,10 @@ "@angular-devkit/architect" "0.1002.0" rxjs "6.6.2" -"@angular-devkit/build-optimizer@0.1100.0": - version "0.1100.0" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.1100.0.tgz#fae70c407fa2ec26ef839f9f2706cb3be990121b" - integrity sha512-RitDB5JCNDUN2CoNqf/FwLCwdWruApjxb7nUVb9C/uQgGEnrBojyxS/Rv/jCioom86s0sfY9wo79jdxd6AercQ== +"@angular-devkit/build-optimizer@0.1100.2": + version "0.1100.2" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.1100.2.tgz#93dea833aed64d265cfdfebb6580e10cf909630b" + integrity sha512-2ZdEeAs0a53g9LDkP5H2mCEPLyk7yd9P7eTepNYvIOz3xJ6W6dB2CqotPMfnHgd4o12cbzCOWrPBxbfo/VnMig== dependencies: loader-utils "2.0.0" source-map "0.7.3" @@ -112,13 +112,13 @@ typescript "4.0.5" webpack-sources "2.0.1" -"@angular-devkit/build-webpack@0.1100.0": - version "0.1100.0" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.1100.0.tgz#66b78cc1f5d9d5f2f0b551d3f848bebef4a54ad7" - integrity sha512-9diP/A6NtQxSxjbBMj9h9MHrAj4VqCvuFraR928eFaxEoRKcIwSTHhOiolRm+GL5V0VB+O53FRYDk3gC7BGjmQ== +"@angular-devkit/build-webpack@0.1100.2": + version "0.1100.2" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.1100.2.tgz#1613334c396931de295d47d8ec8ef980592cc00d" + integrity sha512-XVMtWoxNa3wJLRjJ846Y02PzupdbUizdAtggRu2731RLMvI1KawWlsTURi12MNUnoVQYm9eldiIA/Y1UqeE8mQ== dependencies: - "@angular-devkit/architect" "0.1100.0" - "@angular-devkit/core" "11.0.0" + "@angular-devkit/architect" "0.1100.2" + "@angular-devkit/core" "11.0.2" rxjs "6.6.3" "@angular-devkit/core@10.2.0": @@ -132,10 +132,10 @@ rxjs "6.6.2" source-map "0.7.3" -"@angular-devkit/core@11.0.0", "@angular-devkit/core@^9.0.0 || ^10.0.0 || ^11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-11.0.0.tgz#bf69f1fb7a00d0496785f84122daae7dc27a4b14" - integrity sha512-fXZtSs3J4S12hboi3om1FA+QS0e8nuQMyzl2nkmtuhcELUFMmSrEl36dtCni5e7Svs46BUAZ5w8EazIkgGQDJg== +"@angular-devkit/core@11.0.2", "@angular-devkit/core@^9.0.0 || ^10.0.0 || ^11.0.0": + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-11.0.2.tgz#dd3475912e830740e71e14e3168d609e8ddef8c6" + integrity sha512-vUmmUNmNM9oRcDmt0PunU/ayglo0apq4pGL9Z5jj6alf2WwEiTcGHjyuZSDIO9MOLi41519jp3mDx79qXvvyww== dependencies: ajv "6.12.6" fast-json-stable-stringify "2.1.0" @@ -154,12 +154,12 @@ rxjs "6.4.0" source-map "0.7.3" -"@angular-devkit/schematics@11.0.0", "@angular-devkit/schematics@^9.0.0 || ^10.0.0 || ^11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-11.0.0.tgz#ebdbd3b4cf9f740f793df3200cd28c00447abfc8" - integrity sha512-oCz9E0thA5WdGDuv6biu3X5kw5/vNE4ZZOKT2sHBQMpAuuDYrDpfTYQJjXQtjfXWvmlr8L8aqDD9N4HXsE4Esw== +"@angular-devkit/schematics@11.0.2", "@angular-devkit/schematics@^9.0.0 || ^10.0.0 || ^11.0.0": + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-11.0.2.tgz#b5aa914d7e91d92b4eeadb7aed3b5228497abbf3" + integrity sha512-unNewc+Y9ofrdKxXNoSHKUL6wvV8Vgh2nJMTLI1VAw8nfqgWphI+s5XwbVzog65nhZ10xJeaUm9u5R8pxLDpQg== dependencies: - "@angular-devkit/core" "11.0.0" + "@angular-devkit/core" "11.0.2" ora "5.1.0" rxjs "6.6.3" @@ -172,22 +172,22 @@ rxjs "6.4.0" "@angular/animations@ ^9.0.0 || ^10.0.0 || ^11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-11.0.0.tgz#6f567930dca8eb8ab1320f1f48feb981493b86c6" - integrity sha512-RGaAnZOI73bPnNWrJq/p8sc+hpUBhScq139M6r4qQjQPsPahazL6v6hHAgRhZNemqw164d1oE4K/22O/i0E3Tw== + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-11.0.2.tgz#c095ab0aed4491732c81a894987bcab1a854ab15" + integrity sha512-uF/RlBY1rznbuw+1lm8Q2HKDrBOQQ2Bi2cUPuef+ALn+lxGl501eHlE+PTtBjDEzJcJPfd4pE3Ww3+3Il+D+Tw== dependencies: tslib "^2.0.0" "@angular/cli@^9.0.0 || ^10.0.0 || ^11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-11.0.0.tgz#8dcd73bd528e76b21178c43becab10837cfe8039" - integrity sha512-U9sh9r1CSqS78QjuosM3JDXUUTf8eVP1+kSchWEsxjJ0kfdvj7PvtKD1kmRH7HA5lD2q7QfGEvfHpfxMVzKxRg== - dependencies: - "@angular-devkit/architect" "0.1100.0" - "@angular-devkit/core" "11.0.0" - "@angular-devkit/schematics" "11.0.0" - "@schematics/angular" "11.0.0" - "@schematics/update" "0.1100.0" + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-11.0.2.tgz#15ee1732258deec8ecb93f6ccac52d95230074d8" + integrity sha512-mebt4ikwXD3gsbHRxKCpn83yW3UVnhiVDEpSXljs1YxscZ1X1dXrxb2g6LdAJwVp9xY5ERqRQeZM7eChqLTrvg== + dependencies: + "@angular-devkit/architect" "0.1100.2" + "@angular-devkit/core" "11.0.2" + "@angular-devkit/schematics" "11.0.2" + "@schematics/angular" "11.0.2" + "@schematics/update" "0.1100.2" "@yarnpkg/lockfile" "1.1.0" ansi-colors "4.1.1" debug "4.2.0" @@ -205,16 +205,16 @@ uuid "8.3.1" "@angular/common@^9.0.0 || ^10.0.0 || ^11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@angular/common/-/common-11.0.0.tgz#cc2a14b36c56f6c4d93427c2f8c17f55e4b464c9" - integrity sha512-chlbtxR7jpPs3Rc1ymdp3UfUzqEr57OFIxVMG6hROODclPQQk/7oOHdQB4hpUObaF9y4ZTLeKHKWiR/twi21Pg== + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular/common/-/common-11.0.2.tgz#7558b940a1110a9c6c65103b1ae8e18f2c8e939c" + integrity sha512-DGJuSBDt+bF77AzJNrLzeaFGSdwQ3OjgP9UUv1eKvaxp9D+lDam8suIJMuBwTsJII/yrDndY75ENPNTEqhmB2A== dependencies: tslib "^2.0.0" "@angular/compiler-cli@^9.0.0 || ^10.0.0 || ^11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-11.0.0.tgz#ff4c2c16284a31a4f8ff1d224f593f64a1458234" - integrity sha512-zrd/cU9syZ8XuQ3ItfIGaKDn1ZBCWyiqdLVRH9VDmyNqQFiCc/VWQ9Th9z8qpLptgdpzE9+lKFgeZJTDtbcveQ== + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-11.0.2.tgz#961df7f08dc98a6ea202e6aa22dc81ff29c9719d" + integrity sha512-I39zNcf6q0NN4PKCbY6Lm4WP69ujLrAew56X5yvlECW9CJlidV0qi1S/DGgAWhXTDOt8XA/KP1hD1pgJtMHjJQ== dependencies: "@babel/core" "^7.8.6" "@babel/types" "^7.8.6" @@ -230,7 +230,7 @@ source-map "^0.6.1" sourcemap-codec "^1.4.8" tslib "^2.0.0" - yargs "15.3.0" + yargs "^16.1.1" "@angular/compiler@9.0.0": version "9.0.0" @@ -238,9 +238,9 @@ integrity sha512-ctjwuntPfZZT2mNj2NDIVu51t9cvbhl/16epc5xEwyzyDt76pX9UgwvY+MbXrf/C/FWwdtmNtfP698BKI+9leQ== "@angular/compiler@^9.0.0 || ^10.0.0 || ^11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-11.0.0.tgz#b49997d0130e7c8cfe84fa73e5610892f4a772af" - integrity sha512-I7wVhdqvhtBTQTtW61z0lwPb1LiQQ0NOwjsbfN5sAc7/uwxw7em+Kyb/XJgBwgaTKtAL8bZEzdoQGLdsSKQF2g== + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-11.0.2.tgz#892cd38b3afa6ba63149d0bfd9265401a3d88d0c" + integrity sha512-deDT5+Lcph4nNhh6sZd0mBS5OkJL3HPbX5upDMI28Wuayt18Pn0UNotWY77/KV6wwIAInmlx9N06PoH3pq3hqg== dependencies: tslib "^2.0.0" @@ -250,39 +250,39 @@ integrity sha512-6Pxgsrf0qF9iFFqmIcWmjJGkkCaCm6V5QNnxMy2KloO3SDq6QuMVRbN9RtC8Urmo25LP+eZ6ZgYqFYpdD8Hd9w== "@angular/core@^9.0.0 || ^10.0.0 || ^11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@angular/core/-/core-11.0.0.tgz#cdb89f3877f6e5487a0e5f18d234447ec41e8184" - integrity sha512-FNewyMwYy+kGdw1xWfrtaPD2cSQs3kDVFbl8mNMSzp933W5yMsHDvjXb0+nPFqEb8ywEIdm3MsBMK0y3iBWZQw== + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular/core/-/core-11.0.2.tgz#490248b1d746e24513f2db996bd857e5a36d2f45" + integrity sha512-GyDebks5ZPHDyChDW3VvzJq00Ct0iuesNpb9z/GpKtOXqug3sGr4KgkFDUTbfizKPWyeoaLH9FQYP55215nCKQ== dependencies: tslib "^2.0.0" "@angular/platform-browser-dynamic@^9.0.0 || ^10.0.0 || ^11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-11.0.0.tgz#630d77a0c853bcc2c80c30dfe6c101d6c7fe4ac1" - integrity sha512-NAmKGhHK+tl7dr/Hcqxvr/813Opec3Mv0IRwIgmKdlpZd7qAwT/mw4RnO4YPSEoDOM6hqGt7GdlWrSDX802duQ== + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-11.0.2.tgz#e8f621482c4fe04c14d799c771382891052ee2a2" + integrity sha512-iV7xz90FdmYFiXZRLkZtP9Lr+OXXh4bhkX7zN1L5H8SSUF4iOJGBdOts5Fiy5GZjYYILjF1pJoEIicfW/RSHjA== dependencies: tslib "^2.0.0" "@angular/platform-browser@^9.0.0 || ^10.0.0 || ^11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-11.0.0.tgz#314a0362e63ac7eef80adebfc5fbe4e7f2aa2a73" - integrity sha512-p8sF6JfaBI+YyLpp5OSg6UcCqjtLKRR+Otq1P/tro5SuxrsrBNRVU8j0tl/crkScsMwAvgmJ1joRyUKdI2mUGQ== + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-11.0.2.tgz#78e640400050c69ca3322b8df0f4ec48f629ec34" + integrity sha512-RHPm5/h8g3lSBgdg9OvO7w06juEwwBurvQcugXlk7+AeqznwzBodTWGPIATKzMySXQFmpy3bAZ3IxS0NkRrbWA== dependencies: tslib "^2.0.0" "@angular/platform-server@^9.0.0 || ^10.0.0 || ^11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-11.0.0.tgz#aca53c70e1e7010a5dd1e730c1cabd317e57b2af" - integrity sha512-0LsA4u5kCDKMOxcWf4HFH3PNYIhFcnzP/TYqYfIkY/GpQeC5agxWzddJofNi7g/Lh1UoK5hzf+3Ewn3o/aBxjA== + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-11.0.2.tgz#b9cf77c434fbaef5871c961a2def31c561bd473a" + integrity sha512-wC+JP0izKJMDQG+u7HXFYyKni7T65ELC6JknL4dODDHx+XylkFPXGI+EffffnVgJssheVDGrwe32Fh0Yjus0Lw== dependencies: domino "^2.1.2" tslib "^2.0.0" xhr2 "^0.2.0" "@angular/router@^9.0.0 || ^10.0.0 || ^11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@angular/router/-/router-11.0.0.tgz#59e855b0d34c4578e0556e181f2f28048fb0d5a8" - integrity sha512-10ZeobfK3HqVeWS6zjdKU16ccxFtdCHkxT11bnFg3Jwq9vKt+LI5KitAkCI5rYTY3DRfVzasRkqBzZfZMkbftw== + version "11.0.2" + resolved "https://registry.yarnpkg.com/@angular/router/-/router-11.0.2.tgz#38119a49edbfc60552d3403b4fc081ec705e2d6d" + integrity sha512-EU0lQ+3vv1ozly+Z4SgaGj/6CWMIExjnSnA1F7SI2yWmMgMMSb5CsGJ2xzr0V8ex3XZzuU2VuKF74muC58qSyg== dependencies: tslib "^2.0.0" @@ -1197,10 +1197,10 @@ resolved "https://registry.yarnpkg.com/@firebase/auth-types/-/auth-types-0.10.1.tgz#7815e71c9c6f072034415524b29ca8f1d1770660" integrity sha512-/+gBHb1O9x/YlG7inXfxff/6X3BPZt4zgBv4kql6HEmdzNQCodIRlEYnI+/da+lN+dha7PjaFH7C7ewMmfV7rw== -"@firebase/auth@0.15.1": - version "0.15.1" - resolved "https://registry.yarnpkg.com/@firebase/auth/-/auth-0.15.1.tgz#2e0e7397d6f754d81916babd9bce21a51f4b25a3" - integrity sha512-qVJTmq/6l3/o6V93nAD+n1ExTywbKEFYbuuI1TZIUryy5KSXOFnxilmZI4yJeQSZ3ee06YiJsIRYRaYUeg6JQQ== +"@firebase/auth@0.15.2": + version "0.15.2" + resolved "https://registry.yarnpkg.com/@firebase/auth/-/auth-0.15.2.tgz#9ada3f37620d131a1c56994138a599b5c9f9ca2e" + integrity sha512-2n32PBi6x9jVhc0E/ewKLUCYYTzFEXL4PNkvrrlGKbzeTBEkkyzfgUX7OV9UF5wUOG+gurtUthuur1zspZ/9hg== dependencies: "@firebase/auth-types" "0.10.1" @@ -1227,21 +1227,21 @@ dependencies: "@firebase/app-types" "0.6.1" -"@firebase/database-types@0.6.0": - version "0.6.0" - resolved "https://registry.yarnpkg.com/@firebase/database-types/-/database-types-0.6.0.tgz#7795bc6b1db93f4cbda9a241c8dfe1bb86033dc6" - integrity sha512-ljpU7/uboCGqFSe9CNgwd3+Xu5N8YCunzfPpeueuj2vjnmmypUi4QWxgC3UKtGbuv1q+crjeudZGLxnUoO0h7w== +"@firebase/database-types@0.6.1": + version "0.6.1" + resolved "https://registry.yarnpkg.com/@firebase/database-types/-/database-types-0.6.1.tgz#cf1cfc03e617ed4c2561703781f85ba4c707ff65" + integrity sha512-JtL3FUbWG+bM59iYuphfx9WOu2Mzf0OZNaqWiQ7lJR8wBe7bS9rIm9jlBFtksB7xcya1lZSQPA/GAy2jIlMIkA== dependencies: "@firebase/app-types" "0.6.1" -"@firebase/database@0.7.1": - version "0.7.1" - resolved "https://registry.yarnpkg.com/@firebase/database/-/database-0.7.1.tgz#900d2e6ed734249e65e5f159293830e4f4285d6e" - integrity sha512-8j3KwksaYMSbIsEjOIarZD3vj4jGJjIlLGIAiO/4P4XyOtrlnxIiH7G0UdIZlcvKU4Gsgg0nthT2+EapROmHWA== +"@firebase/database@0.8.1": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@firebase/database/-/database-0.8.1.tgz#a7bc1c01052d35817a242c21bfe09ab29ee485a3" + integrity sha512-/1HhR4ejpqUaM9Cn3KSeNdQvdlehWIhdfTVWFxS73ZlLYf7ayk9jITwH10H3ZOIm5yNzxF67p/U7Z/0IPhgWaQ== dependencies: "@firebase/auth-interop-types" "0.1.5" "@firebase/component" "0.1.21" - "@firebase/database-types" "0.6.0" + "@firebase/database-types" "0.6.1" "@firebase/logger" "0.2.6" "@firebase/util" "0.3.4" faye-websocket "0.11.3" @@ -1265,16 +1265,16 @@ resolved "https://registry.yarnpkg.com/@firebase/firestore-types/-/firestore-types-2.0.0.tgz#1f6212553b240f1a8905bb8dcf1f87769138c5c0" integrity sha512-ZGb7p1SSQJP0Z+kc9GAUi+Fx5rJatFddBrS1ikkayW+QHfSIz0omU23OgSHcBGTxe8dJCeKiKA2Yf+tkDKO/LA== -"@firebase/firestore@2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@firebase/firestore/-/firestore-2.0.1.tgz#2d4734ecd5d165582eedea8487849c5535a55c0e" - integrity sha512-7WMv3b+2P/6SOE0RxPB+S6k75/vYTDhOpPBp6JH6nPQjS9mGtR9m0adKtXjOBBugcbK6sBgPMzxmQGwQl8lW4w== +"@firebase/firestore@2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@firebase/firestore/-/firestore-2.0.4.tgz#c4be6f3540f607fd8e200cfba83c4997c29447fe" + integrity sha512-fzJKj/4h4jOwPSfHB42XBJIC0zsPsepU6FcBO+8nSx7G2IPfTw8cMgSNin2gPqX6tR1w1NQtHiSlXiRKsbMZdA== dependencies: "@firebase/component" "0.1.21" "@firebase/firestore-types" "2.0.0" "@firebase/logger" "0.2.6" "@firebase/util" "0.3.4" - "@firebase/webchannel-wrapper" "0.4.0" + "@firebase/webchannel-wrapper" "0.4.1" "@grpc/grpc-js" "^1.0.0" "@grpc/proto-loader" "^0.5.0" node-fetch "2.6.1" @@ -1382,10 +1382,10 @@ resolved "https://registry.yarnpkg.com/@firebase/storage-types/-/storage-types-0.3.13.tgz#cd43e939a2ab5742e109eb639a313673a48b5458" integrity sha512-pL7b8d5kMNCCL0w9hF7pr16POyKkb3imOW7w0qYrhBnbyJTdVxMWZhb0HxCFyQWC0w3EiIFFmxoz8NTFZDEFog== -"@firebase/storage@0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@firebase/storage/-/storage-0.4.1.tgz#b86973a8ab3ef52f38d6463fcc7613f5801ff8e4" - integrity sha512-/l05Dn3UYynPELt0ZFJz24H49sQ8c8KnOEGR/Pk1AOjLmc71vjjobVEkgkHyy1eyfmYuAZtsc6ePOwc89YnBTg== +"@firebase/storage@0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@firebase/storage/-/storage-0.4.2.tgz#bc5924b87bd2fdd4ab0de49851c0125ebc236b89" + integrity sha512-87CrvKrf8kijVekRBmUs8htsNz7N5X/pDhv3BvJBqw8K65GsUolpyjx0f4QJRkCRUYmh3MSkpa5P08lpVbC6nQ== dependencies: "@firebase/component" "0.1.21" "@firebase/storage-types" "0.3.13" @@ -1406,10 +1406,10 @@ dependencies: tslib "^1.11.1" -"@firebase/webchannel-wrapper@0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.4.0.tgz#becce788818d3f47f0ac1a74c3c061ac1dcf4f6d" - integrity sha512-8cUA/mg0S+BxIZ72TdZRsXKBP5n5uRcE3k29TZhZw6oIiHBt9JA7CTb/4pE1uKtE/q5NeTY2tBDcagoZ+1zjXQ== +"@firebase/webchannel-wrapper@0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.4.1.tgz#600f2275ff54739ad5ac0102f1467b8963cd5f71" + integrity sha512-0yPjzuzGMkW1GkrC8yWsiN7vt1OzkMIi9HgxRmKREZl2wnNPOKo/yScTjXf/O57HM8dltqxPF6jlNLFVtc2qdw== "@google-cloud/common@^2.1.1": version "2.4.0" @@ -1517,9 +1517,9 @@ semver "^6.2.0" "@grpc/grpc-js@^1.0.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.2.0.tgz#4ff1ac4cdf7eb2af80d3c67316be9c2308d8d9bf" - integrity sha512-09H50V7rmz0gFrGz6IbP49z9A8+2p4yZYcNDEb7bytr90vWn52VBQE1a+LMBlrucmNN0wSsiCr3TJx+dStHTng== + version "1.2.1" + resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.2.1.tgz#6a0b4e1bc6039d84f945569ff8c3059f81284afe" + integrity sha512-JpGh2CgqnwVII0S9TMEX3HY+PkLJnb7HSAar3Md1Y3aWxTZqAGb7gTrNyBWn/zueaGFsMYRm2u/oYufWFYVoIQ== dependencies: "@types/node" "^12.12.47" google-auth-library "^6.1.1" @@ -1561,12 +1561,12 @@ resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796" integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg== -"@ngtools/webpack@11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-11.0.0.tgz#bddc9ad4677de55d9df9418408079c2a2be4f482" - integrity sha512-thWOXiMfyVUUWDDRUUAIvb5HASovX1C0GcxRBFE8fXJMCwOPIwqZiAyJJlUUnie8BEP9yC/x6uLCud56ai4Uaw== +"@ngtools/webpack@11.0.2": + version "11.0.2" + resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-11.0.2.tgz#d9513854d474fe09350ce705d04fee38ffb8f0c7" + integrity sha512-GbNP6HMBVoee2CkYW/pknprFCeiOLz4FGE06yr4m0700c1i6wuX7AzyHfBcLGAIP6nVblNOT3eh5M41b3cDf8g== dependencies: - "@angular-devkit/core" "11.0.0" + "@angular-devkit/core" "11.0.2" enhanced-resolve "5.3.1" webpack-sources "2.0.1" @@ -1692,13 +1692,13 @@ estree-walker "^1.0.1" picomatch "^2.2.2" -"@schematics/angular@11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-11.0.0.tgz#d292aeb472e1f5f11917df9f660d38b3f792dd5b" - integrity sha512-/4fkfryoCKQv7nnZgbQ/2aLg8418/SdrCi4ASN0xpfcj34oe2FqsKypeoJG+3bQVF8CLfseorvPNR2YINb4RQA== +"@schematics/angular@11.0.2": + version "11.0.2" + resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-11.0.2.tgz#63041d1931fe2d56135d730a6e43937a3eef4bab" + integrity sha512-tUIuCYJUzHYuiXGJ2KCuwxMocS56kPHaM8+neVYWwWbOxKzLZXv80gMm/pIWxrqUDCkIUi3yb4ienudFhgQLYg== dependencies: - "@angular-devkit/core" "11.0.0" - "@angular-devkit/schematics" "11.0.0" + "@angular-devkit/core" "11.0.2" + "@angular-devkit/schematics" "11.0.2" jsonc-parser "2.3.1" "@schematics/angular@^8.3.8": @@ -1709,13 +1709,13 @@ "@angular-devkit/core" "8.3.29" "@angular-devkit/schematics" "8.3.29" -"@schematics/update@0.1100.0": - version "0.1100.0" - resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.1100.0.tgz#1b7f834d88cdd86d13b2cd0f8d826bf4c934d064" - integrity sha512-61zhqIvKHiMR3nezM5FlUoWe2Lw2uKzmuSwcxA2d6SqjDXYyXrOSKmaPcbi7Emgh3VWsQadNpXuc5A2tbKCQhg== +"@schematics/update@0.1100.2": + version "0.1100.2" + resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.1100.2.tgz#d3a5c726d434d6c8ff04db8836f829299ca7108a" + integrity sha512-pETCmQylIQ7RM+8uqDkI3KfOaX5H7nuzmMXby28zdLPMZniYti0gJxieiVFhvdz2Ot2Axj0hznfmraFgC9mQMw== dependencies: - "@angular-devkit/core" "11.0.0" - "@angular-devkit/schematics" "11.0.0" + "@angular-devkit/core" "11.0.2" + "@angular-devkit/schematics" "11.0.2" "@yarnpkg/lockfile" "1.1.0" ini "1.3.5" npm-package-arg "^8.0.0" @@ -1849,9 +1849,9 @@ "@types/through" "*" "@types/jasmine@^3.3.13": - version "3.6.1" - resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-3.6.1.tgz#f8b95def0016411c58c7adb4791dff29bc62992c" - integrity sha512-eeSCVhBsgwHNS1FmaMu4zrLxfykCTWJMLFZv7lmyrZQjw7foUUXoPu4GukSN9v7JvUw7X+/aDH3kCaymirBSTg== + version "3.6.2" + resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-3.6.2.tgz#02f64450016f7de70f145d698be311136d7c6374" + integrity sha512-AzfesNFLvOs6Q1mHzIsVJXSeUnqVh4ZHG8ngygKJfbkcSLwzrBVm/LKa+mR8KrOfnWtUL47112gde1MC0IXqpQ== "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6": version "7.0.6" @@ -1884,9 +1884,9 @@ integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== "@types/node@*": - version "14.14.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.7.tgz#8ea1e8f8eae2430cf440564b98c6dfce1ec5945d" - integrity sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg== + version "14.14.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.9.tgz#04afc9a25c6ff93da14deabd65dc44485b53c8d6" + integrity sha512-JsoLXFppG62tWTklIoO4knA+oDTYsmqWxHRvd4lpmfQRNhX6osheUOWETP2jMoV/2bEHuMra8Pp3Dmo/stBFcw== "@types/node@6.0.*": version "6.0.118" @@ -1894,9 +1894,9 @@ integrity sha512-N33cKXGSqhOYaPiT4xUGsYlPPDwFtQM/6QxJxuMXA/7BcySW+lkn2yigWP7vfs4daiL/7NJNU6DMCqg5N4B+xQ== "@types/node@^12.12.47": - version "12.19.4" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.4.tgz#cdfbb62e26c7435ed9aab9c941393cc3598e9b46" - integrity sha512-o3oj1bETk8kBwzz1WlO6JWL/AfAA3Vm6J1B3C9CsdxHYp7XgPiH7OEXPUbZTndHlRaIElrANkQfe6ZmfJb3H2w== + version "12.19.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.6.tgz#fbf249fa46487dd8c7386d785231368b92a33a53" + integrity sha512-U2VopDdmBoYBmtm8Rz340mvvSz34VgX/K9+XCuckvcLGMkt3rbMX8soqFOikIPlPBc5lmw8By9NUK7bEFSBFlQ== "@types/node@^12.6.2 < 12.12.42": version "12.12.41" @@ -1904,9 +1904,9 @@ integrity sha512-Q+eSkdYQJ2XK1AJnr4Ji8Gvk3sRDybEwfTvtL9CA25FFUSD2EgZQewN6VCyWYZCXg5MWZdwogdTNBhlWRcWS1w== "@types/node@^13.7.0": - version "13.13.30" - resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.30.tgz#1ed6e01e4ca576d5aec9cc802cc3bcf94c274192" - integrity sha512-HmqFpNzp3TSELxU/bUuRK+xzarVOAsR00hzcvM0TXrMlt/+wcSLa5q6YhTb6/cA6wqDCZLDcfd8fSL95x5h7AA== + version "13.13.32" + resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.32.tgz#f0edd0fb57b3c9f6e64a0b3ddb1e0f729b6f71ce" + integrity sha512-sPBvDnrwZE1uePhkCEyI/qQlgZM5kePPAhHIFDWNsOrWBFRBOk3LKJYmVCLeLZlL9Ub/FzMJb31OTWCg2F+06g== "@types/node@^8.10.59": version "8.10.66" @@ -2070,9 +2070,9 @@ integrity sha512-+nVsLKlcUCeMzD2ufHEYuJ9a2ovstb6Dp52A5VsoKxDXgvE051XgHI/33I1EymwkRGQkwnA0LkhnUzituGs4EQ== "@types/serve-static@*": - version "1.13.7" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.7.tgz#e51b51a0becda910f9fd04c718044da69d6c492e" - integrity sha512-3diZWucbR+xTmbDlU+FRRxBf+31OhFew7cJXML/zh9NmvSPTNoFecAwHB66BUqFgENJtqMiyl7JAwUE/siqdLw== + version "1.13.8" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.8.tgz#851129d434433c7082148574ffec263d58309c46" + integrity sha512-MoJhSQreaVoL+/hurAZzIm8wafFR6ajiTM1m4A0kv6AGeVBl4r4pOV8bGFrjjq1sGxDTnCoF8i22o0/aE5XCyA== dependencies: "@types/mime" "*" "@types/node" "*" @@ -3558,7 +3558,7 @@ camelcase@^4.1.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= -camelcase@^6.1.0: +camelcase@^6.0.0: version "6.2.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== @@ -3574,9 +3574,9 @@ caniuse-api@^3.0.0: lodash.uniq "^4.5.0" caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001032, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001157: - version "1.0.30001157" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001157.tgz#2d11aaeb239b340bc1aa730eca18a37fdb07a9ab" - integrity sha512-gOerH9Wz2IRZ2ZPdMfBvyOi3cjaz4O4dgNwPGzx8EhqAs4+2IL/O+fJsbt+znSigujoZG8bVcIAUM/I/E5K3MA== + version "1.0.30001159" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001159.tgz#bebde28f893fa9594dadcaa7d6b8e2aa0299df20" + integrity sha512-w9Ph56jOsS8RL20K9cLND3u/+5WASWdhC/PPrf+V3/HsM3uHOavWOR1Xzakbv4Puo/srmPHudkmCRWM7Aq+/UA== canonical-path@1.0.0: version "1.0.0" @@ -3839,6 +3839,15 @@ cliui@^6.0.0: strip-ansi "^6.0.0" wrap-ansi "^6.2.0" +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + clone-deep@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" @@ -4570,22 +4579,22 @@ css-declaration-sorter@^4.0.1: postcss "^7.0.1" timsort "^0.3.0" -css-loader@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-5.0.0.tgz#f0a48dfacc3ab9936a05ee16a09e7f313872e117" - integrity sha512-9g35eXRBgjvswyJWoqq/seWp+BOxvUl8IinVNTsUBFFxtwfEYvlmEn6ciyn0liXGbGh5HyJjPGCuobDSfqMIVg== +css-loader@4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-4.3.0.tgz#c888af64b2a5b2e85462c72c0f4a85c7e2e0821e" + integrity sha512-rdezjCjScIrsL8BSYszgT4s476IcNKt6yX69t0pHjJVnPUTDpn4WfIpDQTN3wCJvUvfsz/mFjuGOekf3PY3NUg== dependencies: - camelcase "^6.1.0" + camelcase "^6.0.0" cssesc "^3.0.0" - icss-utils "^5.0.0" + icss-utils "^4.1.1" loader-utils "^2.0.0" - postcss "^8.1.1" - postcss-modules-extract-imports "^3.0.0" - postcss-modules-local-by-default "^4.0.0" - postcss-modules-scope "^3.0.0" - postcss-modules-values "^4.0.0" + postcss "^7.0.32" + postcss-modules-extract-imports "^2.0.0" + postcss-modules-local-by-default "^3.0.3" + postcss-modules-scope "^2.2.0" + postcss-modules-values "^3.0.0" postcss-value-parser "^4.1.0" - schema-utils "^3.0.0" + schema-utils "^2.7.1" semver "^7.3.2" css-parse@~2.0.0: @@ -4627,11 +4636,11 @@ css-tree@1.0.0-alpha.37: source-map "^0.6.1" css-tree@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.1.tgz#7726678dfe2a57993a018d9dce519bf1760e3b6d" - integrity sha512-WroX+2MvsYcRGP8QA0p+rxzOniT/zpAoQ/DTKDSJzh5T3IQKUkFHeIIfgIapm2uaP178GWY3Mime1qbk8GO/tA== + version "1.1.1" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.1.tgz#30b8c0161d9fb4e9e2141d762589b6ec2faebd2e" + integrity sha512-NVN42M2fjszcUNpDbdkvutgQSlFYsr1z7kqeuCagHnNLBfYor6uP1WL1KrkmdYZ5Y1vTBCIOI/C/+8T98fJ71w== dependencies: - mdn-data "2.0.12" + mdn-data "2.0.14" source-map "^0.6.1" css-what@^3.2.1: @@ -4730,9 +4739,9 @@ cssnano@4.1.10: postcss "^7.0.0" csso@^4.0.2: - version "4.1.0" - resolved "https://registry.yarnpkg.com/csso/-/csso-4.1.0.tgz#1d31193efa99b87aa6bad6c0cef155e543d09e8b" - integrity sha512-h+6w/W1WqXaJA4tb1dk7r5tVbOm97MsKxzwnvOR04UQ6GILroryjMWu3pmCCtL2mLaEStQ0fZgeGiy99mo7iyg== + version "4.1.1" + resolved "https://registry.yarnpkg.com/csso/-/csso-4.1.1.tgz#e0cb02d6eb3af1df719222048e4359efd662af13" + integrity sha512-Rvq+e1e0TFB8E8X+8MQjHSY6vtol45s5gxtLI/018UsAn2IBMmwNEZRM/h+HVnAJRHjasLIKKUO3uvoMM28LvA== dependencies: css-tree "^1.0.0" @@ -4831,10 +4840,10 @@ debug@3.1.0, debug@~3.1.0: dependencies: ms "2.0.0" -debug@4, debug@4.2.0, debug@^4.1.0, debug@^4.1.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" - integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== +debug@4, debug@^4.1.0, debug@^4.1.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== dependencies: ms "2.1.2" @@ -4845,10 +4854,17 @@ debug@4.1.0: dependencies: ms "^2.1.1" +debug@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" + integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== + dependencies: + ms "2.1.2" + debug@^3.1.0, debug@^3.1.1, debug@^3.2.5: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== dependencies: ms "^2.1.1" @@ -5196,7 +5212,7 @@ duplexer3@^0.1.4: resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= -duplexer@^0.1.1: +duplexer@^0.1.1, duplexer@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== @@ -5242,9 +5258,9 @@ ee-first@1.1.1: integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= electron-to-chromium@^1.3.591: - version "1.3.593" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.593.tgz#947ccf6dc8e013e2b053d2463ecd1043c164fcef" - integrity sha512-GvO7G1ZxvffnMvPCr4A7+iQPVuvpyqMrx2VWSERAjG+pHK6tmO9XqYdBfMIq9corRyi4bNImSDEiDvIoDb8HrA== + version "1.3.603" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.603.tgz#1b71bec27fb940eccd79245f6824c63d5f7e8abf" + integrity sha512-J8OHxOeJkoSLgBXfV9BHgKccgfLMHh+CoeRo6wJsi6m0k3otaxS/5vrHpMNSEYY4MISwewqanPOuhAtuE8riQQ== elliptic@^6.5.3: version "6.5.3" @@ -6025,9 +6041,9 @@ firebase-functions@^3.6.0: lodash "^4.17.14" firebase-tools@^8.0.0: - version "8.16.0" - resolved "https://registry.yarnpkg.com/firebase-tools/-/firebase-tools-8.16.0.tgz#ef81ee17a34f433301abce7315ac33803e08f5de" - integrity sha512-FhkA2QRX1fxN5RCyI0N56esYMCySlAlyKt8inIyP8+anrh/5WHt0FL1JpC2/U3ufTc7jq+eZlCkv31iIyFMOzw== + version "8.16.2" + resolved "https://registry.yarnpkg.com/firebase-tools/-/firebase-tools-8.16.2.tgz#fdcae8fe12411aaac90fb5d1602d34bd721fcd3f" + integrity sha512-3deje+CJ5XtYDsb92YqKdNZaV6+OBJqGA2zatozSaBaKpVkIqTyt9vpglKaar/9N+UIqsIfpjruLS6dCkVk/Gg== dependencies: "@google-cloud/pubsub" "^1.7.0" JSONStream "^1.2.1" @@ -6085,23 +6101,23 @@ firebase-tools@^8.0.0: ws "^7.2.3" "firebase@^7.0.0 || ^8.0.0": - version "8.0.1" - resolved "https://registry.yarnpkg.com/firebase/-/firebase-8.0.1.tgz#24836c654c8577abd640439a5f1bc707bbd9f236" - integrity sha512-7QQKw+ycoR3LhMlxhPM+ND1F2Fx1eDlf3E55xYbmooxFW1t0p94HNENBc3JZytR1H0VoG9nSm2QEHsdr/Ca1Rg== + version "8.1.1" + resolved "https://registry.yarnpkg.com/firebase/-/firebase-8.1.1.tgz#379094b724053931fda1086e9020a17b578e50d5" + integrity sha512-w1plr2jYvzBkx/rHE6A0EJf9318ufA5omShLuGocPlQtrvphel+KJcd+R02outE5E2lSDhyM0l3EoiA0YCD4hA== dependencies: "@firebase/analytics" "0.6.2" "@firebase/app" "0.6.13" "@firebase/app-types" "0.6.1" - "@firebase/auth" "0.15.1" - "@firebase/database" "0.7.1" - "@firebase/firestore" "2.0.1" + "@firebase/auth" "0.15.2" + "@firebase/database" "0.8.1" + "@firebase/firestore" "2.0.4" "@firebase/functions" "0.6.1" "@firebase/installations" "0.4.19" "@firebase/messaging" "0.7.3" "@firebase/performance" "0.4.4" "@firebase/polyfill" "0.3.36" "@firebase/remote-config" "0.1.30" - "@firebase/storage" "0.4.1" + "@firebase/storage" "0.4.2" "@firebase/util" "0.3.4" flat-arguments@^1.0.0: @@ -6392,7 +6408,7 @@ gensync@^1.0.0-beta.1: resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== -get-caller-file@^2.0.1: +get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== @@ -6719,16 +6735,23 @@ gtoken@^4.1.0: mime "^2.2.0" gtoken@^5.0.4: - version "5.0.5" - resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-5.0.5.tgz#e752d18538576777dfe237887e30fc0627870eae" - integrity sha512-wvjkecutFh8kVfbcdBdUWqDRrXb+WrgD79DBDEYf1Om8S1FluhylhtFjrL7Tx69vNhh259qA3Q1P4sPtb+kUYw== + version "5.1.0" + resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-5.1.0.tgz#4ba8d2fc9a8459098f76e7e8fd7beaa39fda9fe4" + integrity sha512-4d8N6Lk8TEAHl9vVoRVMh9BNOKWVgl2DdNtr3428O75r3QFrF/a5MMu851VmK0AA8+iSvbwRv69k5XnMLURGhg== dependencies: gaxios "^4.0.0" google-p12-pem "^3.0.3" jws "^4.0.0" mime "^2.2.0" -gzip-size@*, gzip-size@^5.1.1: +gzip-size@*: + version "6.0.0" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" + integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q== + dependencies: + duplexer "^0.1.2" + +gzip-size@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274" integrity sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA== @@ -6888,9 +6911,9 @@ hex-color-regex@^1.1.0: integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== highlight.js@^9.17.1: - version "9.18.3" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.18.3.tgz#a1a0a2028d5e3149e2380f8a865ee8516703d634" - integrity sha512-zBZAmhSupHIl5sITeMqIJnYCDfAEc3Gdkqj65wC1lpI468MMQeeQkhcIAvk+RylAkxrCcI9xy9piHiXeQ1BdzQ== + version "9.18.5" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.18.5.tgz#d18a359867f378c138d6819edfc2a8acd5f29825" + integrity sha512-a5bFyofd/BHCX52/8i8uJkjr9DYwXIPnM/plwI6W7ezItLGqzt7X2G2nXuYSfsIJdkwwj/g9DG1LkcGJI/dDoA== hmac-drbg@^1.0.0: version "1.0.1" @@ -7116,10 +7139,12 @@ iconv-lite@^0.6.2: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" -icss-utils@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.0.0.tgz#03ed56c3accd32f9caaf1752ebf64ef12347bb84" - integrity sha512-aF2Cf/CkEZrI/vsu5WI/I+akFgdbwQHVE9YRZxATrhH4PVIe6a3BIjwjEcW+z+jP/hNh+YvM3lAAn1wJQ6opSg== +icss-utils@^4.0.0, icss-utils@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" + integrity sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA== + dependencies: + postcss "^7.0.14" idb@3.0.2: version "3.0.2" @@ -7327,10 +7352,10 @@ inquirer@~6.3.1: strip-ansi "^5.1.0" through "^2.3.6" -install-artifact-from-github@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/install-artifact-from-github/-/install-artifact-from-github-1.1.3.tgz#552f1ec3e693f970726e3f68018ff5885665ec9e" - integrity sha512-iNuncO/pI1w0UOrebs9dwwVpXqERkszPcb7AYq2hbsJDS3X+XdZ+E5kE91EBSc98mjvCMWOoBa1Zk3hVeP1ddA== +install-artifact-from-github@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/install-artifact-from-github/-/install-artifact-from-github-1.2.0.tgz#adcbd123c16a4337ec44ea76d0ebf253cc16b074" + integrity sha512-3OxCPcY55XlVM3kkfIpeCgmoSKnMsz2A3Dbhsq0RXpIknKQmrX1YiznCeW9cD2ItFmDxziA3w6Eg8d80AoL3oA== internal-ip@^4.3.0: version "4.3.0" @@ -8402,14 +8427,6 @@ lie@~3.3.0: dependencies: immediate "~3.0.5" -line-column@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/line-column/-/line-column-1.0.2.tgz#d25af2936b6f4849172b312e4792d1d987bc34a2" - integrity sha1-0lryk2tvSEkXKzEuR5LR2Ye8NKI= - dependencies: - isarray "^1.0.0" - isobject "^2.0.0" - lines-and-columns@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" @@ -8872,10 +8889,10 @@ md5.js@^1.3.4: inherits "^2.0.1" safe-buffer "^5.1.2" -mdn-data@2.0.12: - version "2.0.12" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.12.tgz#bbb658d08b38f574bbb88f7b83703defdcc46844" - integrity sha512-ULbAlgzVb8IqZ0Hsxm6hHSlQl3Jckst2YEQS7fODu9ilNWy2LvcoSY7TRFIktABP2mdppBioc66va90T+NUs8Q== +mdn-data@2.0.14: + version "2.0.14" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" + integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== mdn-data@2.0.4: version "2.0.4" @@ -9261,11 +9278,6 @@ nan@^2.12.1, nan@^2.14.2: resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== -nanoid@^3.1.16: - version "3.1.16" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.16.tgz#b21f0a7d031196faf75314d7c65d36352beeef64" - integrity sha512-+AK8MN0WHji40lj8AEuwLOvLSbWYApQpre/aFJZD71r43wVRLrOYS4FmJOPQYon1TqB462RzrrxlfA74XRES8w== - nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -9446,9 +9458,9 @@ node-libs-browser@^2.2.1: vm-browserify "^1.0.1" node-releases@^1.1.66: - version "1.1.66" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.66.tgz#609bd0dc069381015cd982300bae51ab4f1b1814" - integrity sha512-JHEQ1iWPGK+38VLB2H9ef2otU4l8s3yAMt9Xf934r6+ojCYDMHPMqvCc9TnzfeFSP1QEOeU6YZEd3+De0LTCgg== + version "1.1.67" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.67.tgz#28ebfcccd0baa6aad8e8d4d8fe4cbc49ae239c12" + integrity sha512-V5QF9noGFl3EymEwUYzO+3NTDpGfQB4ve6Qfnzf3UNydMhjQRVPR1DZTuvWiLzaFJYw2fmDwAfnRNEVb64hSIg== node-sass-tilde-importer@^1.0.0: version "1.0.2" @@ -10449,33 +10461,38 @@ postcss-minify-selectors@^4.0.2: postcss "^7.0.0" postcss-selector-parser "^3.0.0" -postcss-modules-extract-imports@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" - integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== +postcss-modules-extract-imports@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e" + integrity sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ== + dependencies: + postcss "^7.0.5" -postcss-modules-local-by-default@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz#ebbb54fae1598eecfdf691a02b3ff3b390a5a51c" - integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ== +postcss-modules-local-by-default@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz#bb14e0cc78279d504dbdcbfd7e0ca28993ffbbb0" + integrity sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw== dependencies: - icss-utils "^5.0.0" + icss-utils "^4.1.1" + postcss "^7.0.32" postcss-selector-parser "^6.0.2" postcss-value-parser "^4.1.0" -postcss-modules-scope@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06" - integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg== +postcss-modules-scope@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz#385cae013cc7743f5a7d7602d1073a89eaae62ee" + integrity sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ== dependencies: - postcss-selector-parser "^6.0.4" + postcss "^7.0.6" + postcss-selector-parser "^6.0.0" -postcss-modules-values@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" - integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== +postcss-modules-values@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10" + integrity sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg== dependencies: - icss-utils "^5.0.0" + icss-utils "^4.0.0" + postcss "^7.0.6" postcss-normalize-charset@^4.0.1: version "4.0.1" @@ -10596,7 +10613,7 @@ postcss-selector-parser@^3.0.0: indexes-of "^1.0.1" uniq "^1.0.1" -postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: +postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: version "6.0.4" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz#56075a1380a04604c38b063ea7767a129af5c2b3" integrity sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw== @@ -10664,7 +10681,7 @@ postcss@7.0.32: source-map "^0.6.1" supports-color "^6.1.0" -postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.2, postcss@^7.0.27, postcss@^7.0.29, postcss@^7.0.32: +postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.2, postcss@^7.0.27, postcss@^7.0.29, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: version "7.0.35" resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.35.tgz#d2be00b998f7f211d8a276974079f2e92b970e24" integrity sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg== @@ -10673,16 +10690,6 @@ postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.2, postcss@^7.0.27, postcss@^7.0.29 source-map "^0.6.1" supports-color "^6.1.0" -postcss@^8.1.1: - version "8.1.7" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.1.7.tgz#ff6a82691bd861f3354fd9b17b2332f88171233f" - integrity sha512-llCQW1Pz4MOPwbZLmOddGM9eIJ8Bh7SZ2Oj5sxZva77uVaotYDsYTch1WBTNu7fUY0fpWp0fdt7uW40D4sRiiQ== - dependencies: - colorette "^1.2.1" - line-column "^1.0.2" - nanoid "^3.1.16" - source-map "^0.6.1" - prepend-http@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" @@ -10742,9 +10749,9 @@ promise-retry@^1.1.1: retry "^0.10.0" protobufjs@^6.8.1, protobufjs@^6.8.6, protobufjs@^6.8.8, protobufjs@^6.8.9: - version "6.10.1" - resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.10.1.tgz#e6a484dd8f04b29629e9053344e3970cccf13cd2" - integrity sha512-pb8kTchL+1Ceg4lFd5XUpK8PdWacbvV5SK2ULH2ebrYtl4GjJmS24m6CKME67jzV53tbJxHlnNOSqQHbTsR9JQ== + version "6.10.2" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.10.2.tgz#b9cb6bd8ec8f87514592ba3fdfd28e93f33a469b" + integrity sha512-27yj+04uF6ya9l+qfpH187aqEzfCF4+Uit0I9ZBQVqK09hk/SQzKa2MUqUpXaVa7LOFRg1TSSr3lVxGOk6c0SQ== dependencies: "@protobufjs/aspromise" "^1.1.2" "@protobufjs/base64" "^1.1.2" @@ -10988,11 +10995,11 @@ rc@^1.2.8: strip-json-comments "~2.0.1" re2@^1.15.0: - version "1.15.8" - resolved "https://registry.yarnpkg.com/re2/-/re2-1.15.8.tgz#654dfbd889acc2649773a2b32dfb9feb357ca9bc" - integrity sha512-CZm4HMuNbY+LP5LjFQvBxbQmvS7iJiVR3w23Bk3jYxZFUj6wPiYRvDikyVpqHYLioVAWcgjG6F90Pk4z7ehUSg== + version "1.15.9" + resolved "https://registry.yarnpkg.com/re2/-/re2-1.15.9.tgz#9ed16171edcb0bc4f0e239bf55229ff3f26acbe3" + integrity sha512-AXWEhpMTBdC+3oqbjdU07dk0pBCvxh5vbOMLERL6Y8FYBSGn4vXlLe8cYszn64Yy7H8keVMrgPzoSvOd4mePpg== dependencies: - install-artifact-from-github "^1.1.3" + install-artifact-from-github "^1.2.0" nan "^2.14.2" node-gyp "^7.1.2" @@ -11489,9 +11496,9 @@ rollup@^0.36.3: source-map-support "^0.4.0" rollup@^2.22.0, rollup@^2.8.0: - version "2.33.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.33.1.tgz#802795164164ee63cd47769d8879c33ec8ae0c40" - integrity sha512-uY4O/IoL9oNW8MMcbA5hcOaz6tZTMIh7qJHx/tzIJm+n1wLoY38BLn6fuy7DhR57oNFLMbDQtDeJoFURt5933w== + version "2.33.3" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.33.3.tgz#ae72ce31f992b09a580072951bfea76e9df17342" + integrity sha512-RpayhPTe4Gu/uFGCmk7Gp5Z9Qic2VsqZ040G+KZZvsZYdcuWaJg678JeDJJvJeEQXminu24a2au+y92CUWVd+w== optionalDependencies: fsevents "~2.1.2" @@ -11631,7 +11638,7 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" -schema-utils@^2.6.5, schema-utils@^2.7.0: +schema-utils@^2.6.5, schema-utils@^2.7.0, schema-utils@^2.7.1: version "2.7.1" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== @@ -12783,9 +12790,9 @@ terser@^4.1.2: source-map-support "~0.5.12" terser@^5.0.0, terser@^5.3.4: - version "5.3.8" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.3.8.tgz#991ae8ba21a3d990579b54aa9af11586197a75dd" - integrity sha512-zVotuHoIfnYjtlurOouTazciEfL7V38QMAOhGqpXDEg6yT13cF4+fEP9b0rrCEQTn+tT46uxgFsTZzhygk+CzQ== + version "5.5.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.5.0.tgz#1406fcb4d4bc517add3b22a9694284c040e33448" + integrity sha512-eopt1Gf7/AQyPhpygdKePTzaet31TvQxXvrf7xYUvD/d8qkCJm4SKPDzu+GHK5ZaYTn8rvttfqaZc3swK21e5g== dependencies: commander "^2.20.0" source-map "~0.7.2" @@ -13211,9 +13218,9 @@ ua-parser-js@0.7.21: integrity sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ== uglify-js@^3.1.4: - version "3.11.5" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.11.5.tgz#d6788bc83cf35ff18ea78a65763e480803409bc6" - integrity sha512-btvv/baMqe7HxP7zJSF7Uc16h1mSfuuSplT0/qdjxseesDU+yYzH33eHBH+eMdeRXwujXspaCTooWHQVVBh09w== + version "3.11.6" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.11.6.tgz#144b50d3e05eadd3ad4dd047c60ca541a8cd4e9c" + integrity sha512-oASI1FOJ7BBFkSCNDZ446EgkSuHkOZBuqRFrwXIKWCoXw8ZXQETooTQjkAcBS03Acab7ubCKsXnwuV2svy061g== uglify-js@~2.7.5: version "2.7.5" @@ -13898,6 +13905,15 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -13997,6 +14013,11 @@ y18n@^4.0.0: resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== +y18n@^5.0.5: + version "5.0.5" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.5.tgz#8769ec08d03b1ea2df2500acef561743bbb9ab18" + integrity sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg== + yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" @@ -14020,7 +14041,7 @@ yargs-parser@^13.1.2: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^18.1.0, yargs-parser@^18.1.2: +yargs-parser@^18.1.2: version "18.1.3" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== @@ -14028,22 +14049,10 @@ yargs-parser@^18.1.0, yargs-parser@^18.1.2: camelcase "^5.0.0" decamelize "^1.2.0" -yargs@15.3.0: - version "15.3.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.0.tgz#403af6edc75b3ae04bf66c94202228ba119f0976" - integrity sha512-g/QCnmjgOl1YJjGsnUg2SatC7NUYEiLXJqxNOQU9qSpjzGtGXda9b+OKccr1kLTy8BN9yqEyqfq5lxlwdc13TA== - dependencies: - 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.0" +yargs-parser@^20.2.2: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== yargs@^13.3.2: version "13.3.2" @@ -14078,6 +14087,19 @@ yargs@^15.0.2, yargs@^15.3.1: y18n "^4.0.0" yargs-parser "^18.1.2" +yargs@^16.1.1: + version "16.1.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.1.1.tgz#5a4a095bd1ca806b0a50d0c03611d38034d219a1" + integrity sha512-hAD1RcFP/wfgfxgMVswPE+z3tlPFtxG8/yWUrG2i17sTWGCGqWnxKcLTF4cUKDUK8fzokwsmO9H0TDkRbMHy8w== + dependencies: + 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@~3.10.0: version "3.10.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" From 770886add0fe8ce0084a5add5bb575e6af27fad8 Mon Sep 17 00:00:00 2001 From: James Daniels Date: Fri, 20 Nov 2020 12:05:18 -0500 Subject: [PATCH 02/11] TODO --- src/firestore/firestore.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/firestore/firestore.ts b/src/firestore/firestore.ts index a36793c69..662904f6b 100644 --- a/src/firestore/firestore.ts +++ b/src/firestore/firestore.ts @@ -164,6 +164,9 @@ export class AngularFirestore { firestore.useEmulator(...useEmulator); } + // TODO can I tell if they are using the memory-only variant? would skip the warning if they + // try to enable persistence via DI. Also I could add a console.info suggesting memory-only + // if they aren't using it & not trying to enable persistence. if (shouldEnablePersistence && !isPlatformServer(platformId)) { // We need to try/catch here because not all enablePersistence() failures are caught // https://github.com/firebase/firebase-js-sdk/issues/608 From df75fca19d0b5c7912b2c2ff4cac0f1cc14f26e4 Mon Sep 17 00:00:00 2001 From: James Daniels Date: Fri, 20 Nov 2020 13:15:24 -0500 Subject: [PATCH 03/11] The imports arent being pulled in pure, reexport and file replace --- sample/angular.json | 5 ++++- sample/src/app/app.browser.module.ts | 3 +-- sample/src/app/app.module.ts | 2 +- sample/src/app/firestore/firestore.component.ts | 2 +- sample/src/app/protected-lazy/protected-lazy.component.ts | 2 +- sample/src/app/upboats/upboats.component.ts | 2 +- sample/src/firestore.server.ts | 1 + sample/src/firestore.ts | 1 + sample/tsconfig.app.json | 3 ++- src/firestore/firestore-memory.module.ts | 2 ++ src/firestore/firestore-memory.ts | 3 --- src/firestore/firestore.module.ts | 2 ++ src/firestore/index.ts | 3 --- 13 files changed, 17 insertions(+), 14 deletions(-) create mode 100644 sample/src/firestore.server.ts create mode 100644 sample/src/firestore.ts diff --git a/sample/angular.json b/sample/angular.json index bd7dc84a9..758b32f39 100644 --- a/sample/angular.json +++ b/sample/angular.json @@ -129,7 +129,10 @@ "main": "server.ts", "tsConfig": "tsconfig.server.json", "bundleDependencies": true, - "externalDependencies": [ ] + "externalDependencies": [ ], + "fileReplacements": [ + { "replace": "src/firestore.ts", "with": "src/firestore.server.ts" } + ] }, "configurations": { "production": { diff --git a/sample/src/app/app.browser.module.ts b/sample/src/app/app.browser.module.ts index 75a1098ff..5fdd4f4fa 100644 --- a/sample/src/app/app.browser.module.ts +++ b/sample/src/app/app.browser.module.ts @@ -7,8 +7,7 @@ import { AngularFirestoreModule } from '@angular/fire/firestore'; imports: [ AppModule, AngularFirestoreModule.enablePersistence({ - synchronizeTabs: true, - experimentalForceOwningTab: true + synchronizeTabs: true }) ], bootstrap: [AppComponent], diff --git a/sample/src/app/app.module.ts b/sample/src/app/app.module.ts index 7102793e4..9dae1ce0f 100644 --- a/sample/src/app/app.module.ts +++ b/sample/src/app/app.module.ts @@ -20,7 +20,7 @@ import { import { FirestoreComponent } from './firestore/firestore.component'; import { AngularFireDatabaseModule, USE_EMULATOR as USE_DATABASE_EMULATOR } from '@angular/fire/database'; -import { USE_EMULATOR as USE_FIRESTORE_EMULATOR, SETTINGS as FIRESTORE_SETTINGS } from '@angular/fire/firestore'; +import { USE_EMULATOR as USE_FIRESTORE_EMULATOR, SETTINGS as FIRESTORE_SETTINGS } from '../firestore'; import { AngularFireStorageModule } from '@angular/fire/storage'; import { AngularFireAuthModule, USE_DEVICE_LANGUAGE, USE_EMULATOR as USE_AUTH_EMULATOR } from '@angular/fire/auth'; import { AngularFireMessagingModule, SERVICE_WORKER, VAPID_KEY } from '@angular/fire/messaging'; diff --git a/sample/src/app/firestore/firestore.component.ts b/sample/src/app/firestore/firestore.component.ts index d01e0cf1c..1385b0229 100644 --- a/sample/src/app/firestore/firestore.component.ts +++ b/sample/src/app/firestore/firestore.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { AngularFirestore } from '@angular/fire/firestore'; +import { AngularFirestore } from '../../firestore'; import { Observable } from 'rxjs'; import { startWith, tap } from 'rxjs/operators'; import { makeStateKey, TransferState } from '@angular/platform-browser'; diff --git a/sample/src/app/protected-lazy/protected-lazy.component.ts b/sample/src/app/protected-lazy/protected-lazy.component.ts index 8c89f0924..9563566fb 100644 --- a/sample/src/app/protected-lazy/protected-lazy.component.ts +++ b/sample/src/app/protected-lazy/protected-lazy.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { AngularFirestore, DocumentChangeAction } from '@angular/fire/firestore'; +import { AngularFirestore, DocumentChangeAction } from '../../firestore'; import { Observable } from 'rxjs'; @Component({ diff --git a/sample/src/app/upboats/upboats.component.ts b/sample/src/app/upboats/upboats.component.ts index bbd17ffaa..0bd42307e 100644 --- a/sample/src/app/upboats/upboats.component.ts +++ b/sample/src/app/upboats/upboats.component.ts @@ -4,7 +4,7 @@ import { map, startWith, tap } from 'rxjs/operators'; import firebase from 'firebase/app'; import { makeStateKey, TransferState } from '@angular/platform-browser'; import { trace } from '@angular/fire/performance'; -import { AngularFirestore } from '@angular/fire/firestore'; +import { AngularFirestore } from '../../firestore'; type Animal = { name: string, upboats: number, id: string, hasPendingWrites: boolean }; diff --git a/sample/src/firestore.server.ts b/sample/src/firestore.server.ts new file mode 100644 index 000000000..7e2983272 --- /dev/null +++ b/sample/src/firestore.server.ts @@ -0,0 +1 @@ +export * from '@angular/fire/firestore/memory'; diff --git a/sample/src/firestore.ts b/sample/src/firestore.ts new file mode 100644 index 000000000..343a20b57 --- /dev/null +++ b/sample/src/firestore.ts @@ -0,0 +1 @@ +export * from '@angular/fire/firestore'; diff --git a/sample/tsconfig.app.json b/sample/tsconfig.app.json index 23dfeb122..9ee7ccfe4 100644 --- a/sample/tsconfig.app.json +++ b/sample/tsconfig.app.json @@ -7,7 +7,8 @@ }, "files": [ "src/main.ts", - "src/polyfills.ts" + "src/polyfills.ts", + "src/firestore.ts" ], "include": [ "src/**/*.d.ts" diff --git a/src/firestore/firestore-memory.module.ts b/src/firestore/firestore-memory.module.ts index e4fda5da5..a0c3c06e0 100644 --- a/src/firestore/firestore-memory.module.ts +++ b/src/firestore/firestore-memory.module.ts @@ -1,6 +1,8 @@ import { NgModule } from '@angular/core'; import { AngularFirestore } from './firestore'; +import 'firebase/firestore/memory'; + @NgModule({ providers: [ AngularFirestore ] }) diff --git a/src/firestore/firestore-memory.ts b/src/firestore/firestore-memory.ts index f7f8ee511..db678e004 100644 --- a/src/firestore/firestore-memory.ts +++ b/src/firestore/firestore-memory.ts @@ -1,6 +1,3 @@ // See index.ts, this variant is built by ./memory/ng-package.json -import 'firebase/firestore/memory'; - -/** @internal */ export * from './public_api'; export * from './firestore-memory.module'; diff --git a/src/firestore/firestore.module.ts b/src/firestore/firestore.module.ts index f770fc38c..8f2fcf3c3 100644 --- a/src/firestore/firestore.module.ts +++ b/src/firestore/firestore.module.ts @@ -2,6 +2,8 @@ import { ModuleWithProviders, NgModule } from '@angular/core'; import { PersistenceSettings } from './interfaces'; import { AngularFirestore, ENABLE_PERSISTENCE, PERSISTENCE_SETTINGS } from './firestore'; +import 'firebase/firestore'; + @NgModule({ providers: [ AngularFirestore ] }) diff --git a/src/firestore/index.ts b/src/firestore/index.ts index 91043225c..62bd09bbe 100644 --- a/src/firestore/index.ts +++ b/src/firestore/index.ts @@ -2,8 +2,5 @@ // for firebase/firestore, it's here so Firestore variants can be used in other // entry points. Ensure all APIs are exported on ./public_api as that's what // the other entry points reexport. - -import 'firebase/firestore'; - export * from './public_api'; export * from './firestore.module'; From f9e880e316274f7eb3817304d660e629bda327ec Mon Sep 17 00:00:00 2001 From: James Daniels Date: Fri, 20 Nov 2020 14:00:06 -0500 Subject: [PATCH 04/11] Need to swap in production too --- sample/angular.json | 9 ++++++++- sample/src/app/app.component.ts | 6 ++++-- sample/src/app/app.server.module.ts | 2 +- sample/src/app/firestore/firestore.component.ts | 3 +++ 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/sample/angular.json b/sample/angular.json index 758b32f39..7a978ca9d 100644 --- a/sample/angular.json +++ b/sample/angular.json @@ -131,7 +131,10 @@ "bundleDependencies": true, "externalDependencies": [ ], "fileReplacements": [ - { "replace": "src/firestore.ts", "with": "src/firestore.server.ts" } + { + "replace": "src/firestore.ts", + "with": "src/firestore.server.ts" + } ] }, "configurations": { @@ -141,6 +144,10 @@ { "replace": "src/environments/environment.ts", "with": "src/environments/environment.prod.ts" + }, + { + "replace": "src/firestore.ts", + "with": "src/firestore.server.ts" } ], "sourceMap": false, diff --git a/sample/src/app/app.component.ts b/sample/src/app/app.component.ts index 9b6ffc97c..250f33e56 100644 --- a/sample/src/app/app.component.ts +++ b/sample/src/app/app.component.ts @@ -1,4 +1,4 @@ -import { ApplicationRef, Component } from '@angular/core'; +import { ApplicationRef, Component, isDevMode } from '@angular/core'; import { FirebaseApp } from '@angular/fire'; @Component({ @@ -25,6 +25,8 @@ import { FirebaseApp } from '@angular/fire'; }) export class AppComponent { constructor(public readonly firebaseApp: FirebaseApp, appRef: ApplicationRef) { - appRef.isStable.subscribe(it => console.log('isStable', it)); + if (isDevMode()) { + appRef.isStable.subscribe(it => console.log('isStable', it)); + } } } diff --git a/sample/src/app/app.server.module.ts b/sample/src/app/app.server.module.ts index f75ede331..dd15e9334 100644 --- a/sample/src/app/app.server.module.ts +++ b/sample/src/app/app.server.module.ts @@ -14,7 +14,7 @@ import { AngularFirestoreModule } from '@angular/fire/firestore/memory'; AngularFirestoreModule ], providers: [ - { provide: APP_BASE_HREF, useFactory: () => isDevMode() ? '/us-central1/ssr' : '/ssr' }, + { provide: APP_BASE_HREF, useFactory: () => process.env.FUNCTIONS_EMULATOR === 'true' ? '/aftest-94085/us-central1/ssr' : '/ssr' }, ], bootstrap: [AppComponent], }) diff --git a/sample/src/app/firestore/firestore.component.ts b/sample/src/app/firestore/firestore.component.ts index 1385b0229..7e50b3abe 100644 --- a/sample/src/app/firestore/firestore.component.ts +++ b/sample/src/app/firestore/firestore.component.ts @@ -11,6 +11,7 @@ import { trace } from '@angular/fire/performance'; Firestore! {{ testDocValue$ | async | json }} {{ persistenceEnabled$ | async }} + {{ persistenceProvider || 'unknown (mangled)' }}

`, styles: [``] }) @@ -18,8 +19,10 @@ export class FirestoreComponent implements OnInit { public readonly persistenceEnabled$: Observable; public readonly testDocValue$: Observable; + public readonly persistenceProvider: any; constructor(state: TransferState, firestore: AngularFirestore) { + this.persistenceProvider = (firestore.firestore as any)._persistenceProvider?.constructor.name; const doc = firestore.doc('test/1'); const key = makeStateKey(doc.ref.path); const existing = state.get(key, undefined); From e04df50d00941139dca6c74416f5293939ac9f4f Mon Sep 17 00:00:00 2001 From: James Daniels Date: Fri, 20 Nov 2020 14:40:24 -0500 Subject: [PATCH 05/11] Adding index.html path match --- sample/src/app/app-routing.module.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sample/src/app/app-routing.module.ts b/sample/src/app/app-routing.module.ts index 750e62d3c..e444ac0fc 100644 --- a/sample/src/app/app-routing.module.ts +++ b/sample/src/app/app-routing.module.ts @@ -6,9 +6,10 @@ import { AngularFireAuthGuard, canActivate, isNotAnonymous } from '@angular/fire import { SecondaryComponent } from './secondary/secondary.component'; const routes: Routes = [ - { path: '', component: HomeComponent, outlet: 'primary', pathMatch: 'prefix' }, - { path: '', component: SecondaryComponent, outlet: 'secondary', pathMatch: 'prefix' }, - { path: '', component: SecondaryComponent, outlet: 'tertiary', pathMatch: 'prefix' }, + { path: '', component: HomeComponent, outlet: 'primary' }, + { path: '', component: SecondaryComponent, outlet: 'secondary' }, + { path: '', component: SecondaryComponent, outlet: 'tertiary' }, + { path: 'index.html', component: HomeComponent, outlet: 'primary', pathMatch: 'full' }, { path: 'protected', component: ProtectedComponent, canActivate: [AngularFireAuthGuard] }, { path: 'lazy', loadChildren: () => import('./protected-lazy/protected-lazy.module').then(m => m.ProtectedLazyModule) }, { path: 'protected-lazy', From 0c825ba116bc4c9806a26df638703204d7e873de Mon Sep 17 00:00:00 2001 From: James Daniels Date: Fri, 20 Nov 2020 15:34:59 -0500 Subject: [PATCH 06/11] Skip DEBUG_MODE on prod --- sample/src/app/app.module.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sample/src/app/app.module.ts b/sample/src/app/app.module.ts index 9dae1ce0f..c1ce6630f 100644 --- a/sample/src/app/app.module.ts +++ b/sample/src/app/app.module.ts @@ -71,7 +71,7 @@ import { UpboatsComponent } from './upboats/upboats.component'; ScreenTrackingService, PerformanceMonitoringService, { provide: FIRESTORE_SETTINGS, useValue: { ignoreUndefinedProperties: true } }, - { provide: ANALYTICS_DEBUG_MODE, useValue: true }, + { provide: ANALYTICS_DEBUG_MODE, useFactory: isDevMode }, { provide: COLLECTION_ENABLED, useValue: true }, { provide: USE_AUTH_EMULATOR, useValue: environment.useEmulators ? ['localhost', 9099] : undefined }, { provide: USE_DATABASE_EMULATOR, useValue: environment.useEmulators ? ['localhost', 9000] : undefined }, From 7a530ff7cf1e22482bc78eac183eb8d264a70381 Mon Sep 17 00:00:00 2001 From: James Daniels Date: Thu, 26 Nov 2020 03:18:16 -0500 Subject: [PATCH 07/11] Adding firestore-lazy module --- sample/src/app/app.browser.module.ts | 2 +- sample/src/app/app.server.module.ts | 5 +- .../src/app/firestore/firestore.component.ts | 22 +- sample/src/app/upboats/upboats.component.ts | 28 +- sample/src/firestore.server.ts | 2 +- sample/src/firestore.ts | 2 +- .../collection-group/collection-group.spec.ts | 504 ++++++++++++++++++ .../collection-group/collection-group.ts | 114 ++++ .../collection/changes.ts | 0 .../collection/collection.spec.ts | 486 +++++++++++++++++ src/firestore-lazy/collection/collection.ts | 151 ++++++ src/firestore-lazy/document/document.spec.ts | 101 ++++ src/firestore-lazy/document/document.ts | 114 ++++ src/firestore-lazy/firestore-memory.module.ts | 9 + src/firestore-lazy/firestore-memory.ts | 3 + src/firestore-lazy/firestore.module.ts | 23 + src/firestore-lazy/firestore.spec.ts | 175 ++++++ src/firestore-lazy/firestore.ts | 256 +++++++++ src/firestore-lazy/index.ts | 6 + src/firestore-lazy/interfaces.ts | 86 +++ src/firestore-lazy/memory/ng-package.json | 6 + .../observable/fromRef.ts | 0 src/firestore-lazy/package.json | 12 + src/firestore-lazy/public_api.ts | 10 + src/firestore-lazy/util.ts | 44 ++ src/firestore-lazy/utils.spec.ts | 57 ++ .../collection-group/collection-group.ts | 4 +- src/firestore/collection/collection.ts | 4 +- src/firestore/document/document.ts | 2 +- src/firestore/firestore.module.ts | 2 +- src/firestore/firestore.ts | 45 +- src/firestore/interfaces.ts | 110 +--- src/firestore/public_api.ts | 4 +- src/root.spec.ts | 4 + tools/build.ts | 39 +- tsconfig.base.json | 1 + 36 files changed, 2264 insertions(+), 169 deletions(-) create mode 100644 src/firestore-lazy/collection-group/collection-group.spec.ts create mode 100644 src/firestore-lazy/collection-group/collection-group.ts rename src/{firestore => firestore-lazy}/collection/changes.ts (100%) create mode 100644 src/firestore-lazy/collection/collection.spec.ts create mode 100644 src/firestore-lazy/collection/collection.ts create mode 100644 src/firestore-lazy/document/document.spec.ts create mode 100644 src/firestore-lazy/document/document.ts create mode 100644 src/firestore-lazy/firestore-memory.module.ts create mode 100644 src/firestore-lazy/firestore-memory.ts create mode 100644 src/firestore-lazy/firestore.module.ts create mode 100644 src/firestore-lazy/firestore.spec.ts create mode 100644 src/firestore-lazy/firestore.ts create mode 100644 src/firestore-lazy/index.ts create mode 100644 src/firestore-lazy/interfaces.ts create mode 100644 src/firestore-lazy/memory/ng-package.json rename src/{firestore => firestore-lazy}/observable/fromRef.ts (100%) create mode 100644 src/firestore-lazy/package.json create mode 100644 src/firestore-lazy/public_api.ts create mode 100644 src/firestore-lazy/util.ts create mode 100644 src/firestore-lazy/utils.spec.ts diff --git a/sample/src/app/app.browser.module.ts b/sample/src/app/app.browser.module.ts index 5fdd4f4fa..8acbc17e3 100644 --- a/sample/src/app/app.browser.module.ts +++ b/sample/src/app/app.browser.module.ts @@ -1,7 +1,7 @@ import { NgModule } from '@angular/core'; import { AppModule } from './app.module'; import { AppComponent } from './app.component'; -import { AngularFirestoreModule } from '@angular/fire/firestore'; +import { AngularFirestoreModule } from '@angular/fire/firestore-lazy'; @NgModule({ imports: [ diff --git a/sample/src/app/app.server.module.ts b/sample/src/app/app.server.module.ts index dd15e9334..fcb9f15d5 100644 --- a/sample/src/app/app.server.module.ts +++ b/sample/src/app/app.server.module.ts @@ -1,10 +1,9 @@ -import { isDevMode, NgModule } from '@angular/core'; +import { NgModule } from '@angular/core'; import { ServerModule, ServerTransferStateModule } from '@angular/platform-server'; - import { AppModule } from './app.module'; import { AppComponent } from './app.component'; import { APP_BASE_HREF } from '@angular/common'; -import { AngularFirestoreModule } from '@angular/fire/firestore/memory'; +import { AngularFirestoreModule } from '@angular/fire/firestore-lazy/memory'; @NgModule({ imports: [ diff --git a/sample/src/app/firestore/firestore.component.ts b/sample/src/app/firestore/firestore.component.ts index 7e50b3abe..0421313fa 100644 --- a/sample/src/app/firestore/firestore.component.ts +++ b/sample/src/app/firestore/firestore.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { AngularFirestore } from '../../firestore'; -import { Observable } from 'rxjs'; -import { startWith, tap } from 'rxjs/operators'; +import { from, Observable } from 'rxjs'; +import { map, startWith, switchMap, tap } from 'rxjs/operators'; import { makeStateKey, TransferState } from '@angular/platform-browser'; import { trace } from '@angular/fire/performance'; @@ -11,7 +11,7 @@ import { trace } from '@angular/fire/performance'; Firestore! {{ testDocValue$ | async | json }} {{ persistenceEnabled$ | async }} - {{ persistenceProvider || 'unknown (mangled)' }} + {{ (persistenceProvider | async) || 'unknown (mangled)' }}

`, styles: [``] }) @@ -22,13 +22,17 @@ export class FirestoreComponent implements OnInit { public readonly persistenceProvider: any; constructor(state: TransferState, firestore: AngularFirestore) { - this.persistenceProvider = (firestore.firestore as any)._persistenceProvider?.constructor.name; + this.persistenceProvider = from((firestore as any)._persistenceProvider).pipe(map(it => it?.constructor.name)); const doc = firestore.doc('test/1'); - const key = makeStateKey(doc.ref.path); - const existing = state.get(key, undefined); - this.testDocValue$ = firestore.doc('test/1').valueChanges().pipe( - trace('firestore'), - existing ? startWith(existing) : tap(it => state.set(key, it)) + this.testDocValue$ = from(doc.ref).pipe( + switchMap(ref => { + const key = makeStateKey(ref.path); + const existing = state.get(key, undefined); + return doc.valueChanges().pipe( + trace('firestore'), + existing ? startWith(existing) : tap(it => state.set(key, it)) + ); + }) ); this.persistenceEnabled$ = firestore.persistenceEnabled$; } diff --git a/sample/src/app/upboats/upboats.component.ts b/sample/src/app/upboats/upboats.component.ts index 0bd42307e..2bcc58354 100644 --- a/sample/src/app/upboats/upboats.component.ts +++ b/sample/src/app/upboats/upboats.component.ts @@ -1,6 +1,6 @@ import { Component, OnInit } from '@angular/core'; -import { Observable } from 'rxjs'; -import { map, startWith, tap } from 'rxjs/operators'; +import { from, Observable } from 'rxjs'; +import { map, startWith, switchMap, tap } from 'rxjs/operators'; import firebase from 'firebase/app'; import { makeStateKey, TransferState } from '@angular/platform-browser'; import { trace } from '@angular/fire/performance'; @@ -21,16 +21,20 @@ export class UpboatsComponent implements OnInit { const collection = firestore.collection('animals', ref => ref.orderBy('upboats', 'desc').orderBy('updatedAt', 'desc') ); - const key = makeStateKey(collection.ref.path); - const existing = state.get(key, undefined); - this.animals = collection.snapshotChanges().pipe( - trace('animals'), - map(it => it.map(change => ({ - ...change.payload.doc.data(), - id: change.payload.doc.id, - hasPendingWrites: change.payload.doc.metadata.hasPendingWrites - }))), - existing ? startWith(existing) : tap(it => state.set(key, it)) + this.animals = from(collection.ref).pipe( + switchMap(ref => { + const key = makeStateKey(ref.path); + const existing = state.get(key, undefined); + return collection.snapshotChanges().pipe( + trace('animals'), + map(it => it.map(change => ({ + ...change.payload.doc.data(), + id: change.payload.doc.id, + hasPendingWrites: change.payload.doc.metadata.hasPendingWrites + }))), + existing ? startWith(existing) : tap(it => state.set(key, it)) + ); + }) ); } diff --git a/sample/src/firestore.server.ts b/sample/src/firestore.server.ts index 7e2983272..d9d0cf949 100644 --- a/sample/src/firestore.server.ts +++ b/sample/src/firestore.server.ts @@ -1 +1 @@ -export * from '@angular/fire/firestore/memory'; +export * from '@angular/fire/firestore-lazy/memory'; diff --git a/sample/src/firestore.ts b/sample/src/firestore.ts index 343a20b57..ddee491e4 100644 --- a/sample/src/firestore.ts +++ b/sample/src/firestore.ts @@ -1 +1 @@ -export * from '@angular/fire/firestore'; +export * from '@angular/fire/firestore-lazy'; diff --git a/src/firestore-lazy/collection-group/collection-group.spec.ts b/src/firestore-lazy/collection-group/collection-group.spec.ts new file mode 100644 index 000000000..1b704107b --- /dev/null +++ b/src/firestore-lazy/collection-group/collection-group.spec.ts @@ -0,0 +1,504 @@ +import { AngularFireModule, FirebaseApp } from '@angular/fire'; +import { AngularFirestore, AngularFirestoreCollectionGroup, AngularFirestoreModule, SETTINGS } from '../public_api'; +import { QueryGroupFn, Query } from '../interfaces'; +import { BehaviorSubject } from 'rxjs'; +import { skip, switchMap, take } from 'rxjs/operators'; +import { TestBed } from '@angular/core/testing'; +import { COMMON_CONFIG } from '../../test-config'; +import 'firebase/firestore'; + +import { + createRandomStocks, + delayAdd, + delayDelete, + delayUpdate, + deleteThemAll, + FAKE_STOCK_DATA, + rando, + randomName, + Stock +} from '../utils.spec'; + +async function collectionHarness(afs: AngularFirestore, items: number, queryGroupFn?: QueryGroupFn) { + const randomCollectionName = randomName(afs.firestore); + const ref = afs.firestore.collection(`${randomCollectionName}`); + const firestore = afs.firestore; + const collectionGroup = firestore.collectionGroup(randomCollectionName) as Query; + const queryFn = queryGroupFn || (ref => ref); + const stocks = new AngularFirestoreCollectionGroup(queryFn(collectionGroup), afs); + const names = await createRandomStocks(afs.firestore, ref, items); + return { randomCollectionName, ref, stocks, names }; +} + +describe('AngularFirestoreLazyCollectionGroup', () => { + let app: FirebaseApp; + let afs: AngularFirestore; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + AngularFireModule.initializeApp(COMMON_CONFIG, rando()), + AngularFirestoreModule + ], + providers: [ + { provide: SETTINGS, useValue: { host: 'localhost:8080', ssl: false } } + ] + }); + + app = TestBed.inject(FirebaseApp); + afs = TestBed.inject(AngularFirestore); + }); + + afterEach(() => { + app.delete(); + }); + + describe('valueChanges()', () => { + + it('should get unwrapped snapshot', async (done: any) => { + const ITEMS = 4; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + + const sub = stocks.valueChanges().subscribe(data => { + // unsub immediately as we will be deleting data at the bottom + // and that will trigger another subscribe callback and fail + // the test + sub.unsubscribe(); + // We added four things. This should be four. + // This could not be four if the batch failed or + // if the collection state is altered during a test run + expect(data.length).toEqual(ITEMS); + data.forEach(stock => { + // We used the same piece of data so they should all equal + expect(stock).toEqual(FAKE_STOCK_DATA); + }); + // Delete them all + const promises = names.map(name => ref.doc(name).delete()); + Promise.all(promises).then(done).catch(fail); + }); + + }); + + it('should handle multiple subscriptions (hot)', async (done: any) => { + const ITEMS = 4; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + const changes = stocks.valueChanges(); + const sub = changes.subscribe(() => { + }).add( + changes.pipe(take(1)).subscribe(data => { + expect(data.length).toEqual(ITEMS); + sub.unsubscribe(); + }) + ).add(() => { + deleteThemAll(names, ref).then(done).catch(done.fail); + }); + }); + + it('should handle multiple subscriptions (warm)', async (done: any) => { + const ITEMS = 4; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + const changes = stocks.valueChanges(); + changes.pipe(take(1)).subscribe(() => { + }).add(() => { + changes.pipe(take(1)).subscribe(data => { + expect(data.length).toEqual(ITEMS); + }).add(() => { + deleteThemAll(names, ref).then(done).catch(done.fail); + }); + }); + }); + + it('should handle dynamic queries that return empty sets', async (done) => { + const ITEMS = 10; + let count = 0; + + const pricefilter$ = new BehaviorSubject(null); + const randomCollectionName = randomName(afs.firestore); + const ref = afs.firestore.collection(`${randomCollectionName}`); + const names = await createRandomStocks(afs.firestore, ref, ITEMS); + const sub = pricefilter$.pipe(switchMap(price => { + return afs.collection(randomCollectionName, ref => price ? ref.where('price', '==', price) : ref).valueChanges(); + })).subscribe(data => { + count = count + 1; + // the first time should all be 'added' + if (count === 1) { + expect(data.length).toEqual(ITEMS); + pricefilter$.next(-1); + } + // on the second round, we should have filtered out everything + if (count === 2) { + expect(data.length).toEqual(0); + sub.unsubscribe(); + deleteThemAll(names, ref).then(done).catch(done.fail); + } + }); + }); + + it('should return the document\'s id along with the data if the idField option is provided.', async () => { + const ITEMS = 4; + const DOC_ID = 'docId'; + const { stocks } = await collectionHarness(afs, ITEMS); + + const sub = stocks.valueChanges({idField: DOC_ID}).subscribe(data => { + const allDocumentsHaveId = data.every(d => d.docId !== undefined); + + expect(allDocumentsHaveId).toBe(true); + sub.unsubscribe(); + }); + }); + + }); + + describe('snapshotChanges()', () => { + + it('should listen to all snapshotChanges() by default', async (done) => { + const ITEMS = 10; + let count = 0; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + const sub = stocks.snapshotChanges().subscribe(data => { + count = count + 1; + // the first time should all be 'added' + if (count === 1) { + // make an update + ref.doc(names[0]).update({ price: 2 }); + } + // on the second round, make sure the array is still the same + // length but the updated item is now modified + if (count === 2) { + expect(data.length).toEqual(ITEMS); + const change = data.filter(x => x.payload.doc.id === names[0])[0]; + expect(change.type).toEqual('modified'); + sub.unsubscribe(); + deleteThemAll(names, ref).then(done).catch(done.fail); + } + }); + }); + + it('should handle multiple subscriptions (hot)', async (done: any) => { + const ITEMS = 4; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + const changes = stocks.snapshotChanges(); + const sub = changes.subscribe(() => { + }).add( + changes.pipe(take(1)).subscribe(data => { + expect(data.length).toEqual(ITEMS); + sub.unsubscribe(); + }) + ).add(() => { + deleteThemAll(names, ref).then(done).catch(done.fail); + }); + }); + + it('should handle multiple subscriptions (warm)', async (done: any) => { + const ITEMS = 4; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + const changes = stocks.snapshotChanges(); + changes.pipe(take(1)).subscribe(() => { + }).add(() => { + changes.pipe(take(1)).subscribe(data => { + expect(data.length).toEqual(ITEMS); + }).add(() => { + deleteThemAll(names, ref).then(done).catch(done.fail); + }); + }); + }); + + it('should update order on queries', async (done) => { + const ITEMS = 10; + let count = 0; + let firstIndex = 0; + const { ref, stocks, names } = + await collectionHarness(afs, ITEMS, ref => ref.orderBy('price', 'desc')); + const sub = stocks.snapshotChanges().subscribe(data => { + count = count + 1; + // the first time should all be 'added' + if (count === 1) { + // make an update + firstIndex = data.filter(d => d.payload.doc.id === names[0])[0].payload.newIndex; + ref.doc(names[0]).update({ price: 2 }); + } + // on the second round, make sure the array is still the same + // length but the updated item is now modified + if (count === 2) { + expect(data.length).toEqual(ITEMS); + const change = data.filter(x => x.payload.doc.id === names[0])[0]; + expect(change.type).toEqual('modified'); + expect(change.payload.oldIndex).toEqual(firstIndex); + sub.unsubscribe(); + deleteThemAll(names, ref).then(done).catch(done.fail); + } + }); + }); + + it('should be able to filter snapshotChanges() types - modified', async (done) => { + const ITEMS = 10; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + + const sub = stocks.snapshotChanges(['modified']).pipe(skip(1)).subscribe(data => { + sub.unsubscribe(); + const change = data.filter(x => x.payload.doc.id === names[0])[0]; + expect(data.length).toEqual(1); + expect(change.payload.doc.data().price).toEqual(2); + expect(change.type).toEqual('modified'); + deleteThemAll(names, ref).then(done).catch(done.fail); + }); + + delayUpdate(ref, names[0], { price: 2 }); + }); + + it('should be able to filter snapshotChanges() types - added', async (done) => { + const ITEMS = 10; + const harness = await collectionHarness(afs, ITEMS); + const { randomCollectionName, ref, stocks } = harness; + let { names } = harness; + const nextId = ref.doc('a').id; + + const sub = stocks.snapshotChanges(['added']).pipe(skip(1)).subscribe(data => { + sub.unsubscribe(); + const change = data.filter(x => x.payload.doc.id === nextId)[0]; + expect(data.length).toEqual(ITEMS + 1); + expect(change.payload.doc.data().price).toEqual(2); + expect(change.type).toEqual('added'); + deleteThemAll(names, ref).then(done).catch(done.fail); + done(); + }); + + + names = names.concat([nextId]); + // TODO these two add tests are the only one really testing collection-group queries + // should flex more, maybe split the stocks between more than one collection + delayAdd(ref.doc(names[0]).collection(randomCollectionName), nextId, { price: 2 }); + }); + + it('should be able to filter snapshotChanges() types - added w/same id', async (done) => { + const ITEMS = 10; + const { randomCollectionName, ref, stocks, names } = await collectionHarness(afs, ITEMS); + + const sub = stocks.snapshotChanges(['added']).pipe(skip(1)).subscribe(data => { + sub.unsubscribe(); + const change = data.filter(x => x.payload.doc.id === names[0])[1]; + expect(data.length).toEqual(ITEMS + 1); + expect(change.payload.doc.data().price).toEqual(3); + expect(change.type).toEqual('added'); + ref.doc(names[0]).collection(randomCollectionName).doc(names[0]).delete() + .then(() => deleteThemAll(names, ref)) + .then(done).catch(done.fail); + done(); + }); + + delayAdd(ref.doc(names[0]).collection(randomCollectionName), names[0], { price: 3 }); + }); + + /* TODO(jamesdaniels): revisit this test with metadata changes, need to do some additional skips + it('should be able to filter snapshotChanges() types - added/modified', async (done) => { + const ITEMS = 10; + + const harness = await collectionHarness(afs, ITEMS); + const { ref, stocks } = harness; + let { names } = harness; + + const nextId = ref.doc('a').id; + let count = 0; + + stocks.snapshotChanges(['added', 'modified']).pipe(skip(1), take(2)).subscribe(data => { + count += 1; + if (count === 1) { + const change = data.filter(x => x.payload.doc.id === nextId)[0]; + expect(data.length).toEqual(ITEMS + 1); + expect(change.payload.doc.data().price).toEqual(2); + expect(change.type).toEqual('added'); + delayUpdate(ref, names[0], { price: 2 }); + } + if (count === 2) { + const change = data.filter(x => x.payload.doc.id === names[0])[0]; + expect(data.length).toEqual(ITEMS + 1); + expect(change.payload.doc.data().price).toEqual(2); + expect(change.type).toEqual('modified'); + } + }).add(() => { + deleteThemAll(names, ref).then(done).catch(done.fail); + }); + + names = names.concat([nextId]); + delayAdd(ref, nextId, { price: 2 }); + }); + */ + + it('should be able to filter snapshotChanges() types - removed', async (done) => { + const ITEMS = 10; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + + const sub = stocks.snapshotChanges(['added', 'removed']).pipe(skip(1)).subscribe(data => { + sub.unsubscribe(); + const change = data.filter(x => x.payload.doc.id === names[0]); + expect(data.length).toEqual(ITEMS - 1); + expect(change.length).toEqual(0); + deleteThemAll(names, ref).then(done).catch(done.fail); + done(); + }); + + delayDelete(ref, names[0], 400); + }); + + }); + + describe('stateChanges()', () => { + + it('should get stateChanges() updates', async (done: any) => { + const ITEMS = 10; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + + const sub = stocks.stateChanges().subscribe(data => { + // unsub immediately as we will be deleting data at the bottom + // and that will trigger another subscribe callback and fail + // the test + sub.unsubscribe(); + // We added ten things. This should be ten. + // This could not be ten if the batch failed or + // if the collection state is altered during a test run + expect(data.length).toEqual(ITEMS); + data.forEach(action => { + // We used the same piece of data so they should all equal + expect(action.payload.doc.data()).toEqual(FAKE_STOCK_DATA); + }); + deleteThemAll(names, ref).then(done).catch(done.fail); + }); + + }); + + it('should listen to all stateChanges() by default', async (done) => { + const ITEMS = 10; + let count = 0; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + stocks.stateChanges().subscribe(data => { + count = count + 1; + if (count === 1) { + ref.doc(names[0]).update({ price: 2 }); + } + if (count === 2) { + expect(data.length).toEqual(1); + expect(data[0].type).toEqual('modified'); + deleteThemAll(names, ref).then(done).catch(done.fail); + } + }); + }); + + it('should handle multiple subscriptions (hot)', async (done: any) => { + const ITEMS = 4; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + const changes = stocks.stateChanges(); + const sub = changes.subscribe(() => { + }).add( + changes.pipe(take(1)).subscribe(data => { + expect(data.length).toEqual(ITEMS); + sub.unsubscribe(); + }) + ).add(() => { + deleteThemAll(names, ref).then(done).catch(done.fail); + }); + }); + + it('should handle multiple subscriptions (warm)', async (done: any) => { + const ITEMS = 4; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + const changes = stocks.stateChanges(); + changes.pipe(take(1)).subscribe(() => { + }).add(() => { + changes.pipe(take(1)).subscribe(data => { + expect(data.length).toEqual(ITEMS); + }).add(() => { + deleteThemAll(names, ref).then(done).catch(done.fail); + }); + }); + }); + + it('should be able to filter stateChanges() types - modified', async (done) => { + const ITEMS = 10; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + + const sub = stocks.stateChanges(['modified']).subscribe(data => { + sub.unsubscribe(); + expect(data.length).toEqual(1); + expect(data[0].payload.doc.data().price).toEqual(2); + expect(data[0].type).toEqual('modified'); + deleteThemAll(names, ref).then(done).catch(done.fail); + done(); + }); + + delayUpdate(ref, names[0], { price: 2 }); + }); + + it('should be able to filter stateChanges() types - added', async (done) => { + const ITEMS = 10; + + const harness = await collectionHarness(afs, ITEMS); + const { ref, stocks } = harness; + let { names } = harness; + + + const sub = stocks.stateChanges(['added']).pipe(skip(1)).subscribe(data => { + sub.unsubscribe(); + expect(data.length).toEqual(1); + expect(data[0].payload.doc.data().price).toEqual(2); + expect(data[0].type).toEqual('added'); + deleteThemAll(names, ref).then(done).catch(done.fail); + done(); + }); + + const nextId = ref.doc('a').id; + names = names.concat([nextId]); + delayAdd(ref, nextId, { price: 2 }); + }); + + it('should be able to filter stateChanges() types - removed', async (done) => { + const ITEMS = 10; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + + const sub = stocks.stateChanges(['removed']).subscribe(data => { + sub.unsubscribe(); + expect(data.length).toEqual(1); + expect(data[0].type).toEqual('removed'); + deleteThemAll(names, ref).then(done).catch(done.fail); + done(); + }); + + delayDelete(ref, names[0], 400); + }); + }); + + describe('auditTrail()', () => { + it('should listen to all events for auditTrail() by default', async (done) => { + const ITEMS = 10; + let count = 0; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + const sub = stocks.auditTrail().subscribe(data => { + count = count + 1; + if (count === 1) { + ref.doc(names[0]).update({ price: 2 }); + } + if (count === 2) { + sub.unsubscribe(); + expect(data.length).toEqual(ITEMS + 1); + expect(data[data.length - 1].type).toEqual('modified'); + deleteThemAll(names, ref).then(done).catch(done.fail); + } + }); + }); + + it('should be able to filter auditTrail() types - removed', async (done) => { + const ITEMS = 10; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + + const sub = stocks.auditTrail(['removed']).subscribe(data => { + sub.unsubscribe(); + expect(data.length).toEqual(1); + expect(data[0].type).toEqual('removed'); + deleteThemAll(names, ref).then(done).catch(done.fail); + done(); + }); + + delayDelete(ref, names[0], 400); + }); + }); + +}); diff --git a/src/firestore-lazy/collection-group/collection-group.ts b/src/firestore-lazy/collection-group/collection-group.ts new file mode 100644 index 000000000..4a448ec6f --- /dev/null +++ b/src/firestore-lazy/collection-group/collection-group.ts @@ -0,0 +1,114 @@ +import { Observable } from 'rxjs'; +import { fromCollectionRef } from '../observable/fromRef'; +import { filter, map, observeOn, scan, switchMap } from 'rxjs/operators'; +import firebase from 'firebase/app'; +import { DocumentChangeAction, DocumentChangeType, DocumentData, Query } from '../interfaces'; +import { validateEventsArray } from '../collection/collection'; +import { docChanges, sortedChanges } from '../collection/changes'; +import { AngularFirestore } from '../firestore'; + +/** + * AngularFirestoreCollectionGroup service + * + * This class holds a reference to a Firestore Collection Group Query. + * + * This class uses Symbol.observable to transform into Observable using Observable.from(). + * + * This class is rarely used directly and should be created from the AngularFirestore service. + * + * Example: + * + * const collectionGroup = firebase.firestore.collectionGroup('stocks'); + * const query = collectionRef.where('price', '>', '0.01'); + * const fakeStock = new AngularFirestoreCollectionGroup(query, afs); + * + * // Subscribe to changes as snapshots. This provides you data updates as well as delta updates. + * fakeStock.valueChanges().subscribe(value => console.log(value)); + */ +export class AngularFirestoreCollectionGroup { + /** + * The constructor takes in a CollectionGroupQuery to provide wrapper methods + * for data operations and data streaming. + */ + constructor( + private readonly query: Observable>, + private readonly afs: AngularFirestore) { } + + /** + * Listen to the latest change in the stream. This method returns changes + * as they occur and they are not sorted by query order. This allows you to construct + * your own data structure. + */ + stateChanges(events?: DocumentChangeType[]): Observable[]> { + if (!events || events.length === 0) { + return this.query.pipe( + switchMap(query => docChanges(query, this.afs.schedulers.outsideAngular)), + this.afs.keepUnstableUntilFirst + ); + } + return this.query.pipe( + switchMap(query => docChanges(query, this.afs.schedulers.outsideAngular)), + map(actions => actions.filter(change => events.indexOf(change.type) > -1)), + filter(changes => changes.length > 0), + this.afs.keepUnstableUntilFirst + ); + } + + /** + * Create a stream of changes as they occur it time. This method is similar to stateChanges() + * but it collects each event in an array over time. + */ + auditTrail(events?: DocumentChangeType[]): Observable[]> { + return this.stateChanges(events).pipe(scan((current, action) => [...current, ...action], [])); + } + + /** + * Create a stream of synchronized changes. This method keeps the local array in sorted + * query order. + */ + snapshotChanges(events?: DocumentChangeType[]): Observable[]> { + const validatedEvents = validateEventsArray(events); + return this.query.pipe( + switchMap(query => sortedChanges(query, validatedEvents, this.afs.schedulers.outsideAngular)), + this.afs.keepUnstableUntilFirst + ); + } + + /** + * Listen to all documents in the collection and its possible query as an Observable. + * + * If the `idField` option is provided, document IDs are included and mapped to the + * provided `idField` property name. + */ + valueChanges(): Observable; + // tslint:disable-next-line:unified-signatures + valueChanges({}): Observable; + valueChanges(options: {idField: K}): Observable<(T & { [T in K]: string })[]>; + valueChanges(options: {idField?: K} = {}): Observable { + return this.query.pipe( + switchMap(query => fromCollectionRef(query, this.afs.schedulers.outsideAngular)), + map(actions => actions.payload.docs.map(a => { + if (options.idField) { + return { + [options.idField]: a.id, + ...a.data() + } as T & { [T in K]: string }; + } else { + return a.data(); + } + })), + this.afs.keepUnstableUntilFirst + ); + } + + /** + * Retrieve the results of the query once. + */ + get(options?: firebase.firestore.GetOptions) { + return this.query.pipe( + switchMap(query => query.get(options)), + observeOn(this.afs.schedulers.insideAngular) + ); + } + +} diff --git a/src/firestore/collection/changes.ts b/src/firestore-lazy/collection/changes.ts similarity index 100% rename from src/firestore/collection/changes.ts rename to src/firestore-lazy/collection/changes.ts diff --git a/src/firestore-lazy/collection/collection.spec.ts b/src/firestore-lazy/collection/collection.spec.ts new file mode 100644 index 000000000..17b904235 --- /dev/null +++ b/src/firestore-lazy/collection/collection.spec.ts @@ -0,0 +1,486 @@ +import { AngularFireModule, FirebaseApp } from '@angular/fire'; +import { AngularFirestore, SETTINGS } from '../firestore'; +import { AngularFirestoreModule } from '../firestore.module'; +import { AngularFirestoreCollection } from './collection'; +import { QueryFn, CollectionReference } from '../interfaces'; +import { BehaviorSubject } from 'rxjs'; +import { skip, switchMap, take } from 'rxjs/operators'; +import 'firebase/firestore'; + +import { TestBed } from '@angular/core/testing'; +import { COMMON_CONFIG } from '../../test-config'; + +import { + createRandomStocks, + delayAdd, + delayDelete, + delayUpdate, + deleteThemAll, + FAKE_STOCK_DATA, + rando, + randomName, + Stock +} from '../utils.spec'; + +async function collectionHarness(afs: AngularFirestore, items: number, queryFn?: QueryFn) { + const randomCollectionName = randomName(afs.firestore); + const ref = afs.firestore.collection(`${randomCollectionName}`) as CollectionReference; + if (!queryFn) { + queryFn = (ref) => ref; + } + const stocks = new AngularFirestoreCollection(ref, queryFn(ref), afs); + const names = await createRandomStocks(afs.firestore, ref, items); + return { randomCollectionName, ref, stocks, names }; +} + +describe('AngularFirestoreLazyCollection', () => { + let app: FirebaseApp; + let afs: AngularFirestore; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + AngularFireModule.initializeApp(COMMON_CONFIG, rando()), + AngularFirestoreModule + ], + providers: [ + { provide: SETTINGS, useValue: { host: 'localhost:8080', ssl: false } } + ] + }); + + app = TestBed.inject(FirebaseApp); + afs = TestBed.inject(AngularFirestore); + }); + + afterEach(() => { + app.delete(); + }); + + describe('valueChanges()', () => { + + it('should get unwrapped snapshot', async (done: any) => { + const ITEMS = 4; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + + const sub = stocks.valueChanges().subscribe(data => { + // unsub immediately as we will be deleting data at the bottom + // and that will trigger another subscribe callback and fail + // the test + sub.unsubscribe(); + // We added four things. This should be four. + // This could not be four if the batch failed or + // if the collection state is altered during a test run + expect(data.length).toEqual(ITEMS); + data.forEach(stock => { + // We used the same piece of data so they should all equal + expect(stock).toEqual(FAKE_STOCK_DATA); + }); + // Delete them all + const promises = names.map(name => ref.doc(name).delete()); + Promise.all(promises).then(done).catch(fail); + }); + + }); + + /* FLAKE? timing out + it('should optionally map the doc ID to the emitted data object', async (done: any) => { + const ITEMS = 1; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + const idField = 'myCustomID'; + const sub = stocks.valueChanges({idField}).subscribe(data => { + sub.unsubscribe(); + const stock = data[0]; + expect(stock[idField]).toBeDefined(); + expect(stock).toEqual(jasmine.objectContaining(FAKE_STOCK_DATA)); + deleteThemAll(names, ref).then(done).catch(fail); + }) + });*/ + + it('should handle multiple subscriptions (hot)', async (done: any) => { + const ITEMS = 4; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + const changes = stocks.valueChanges(); + const sub = changes.subscribe(() => { + }).add( + changes.pipe(take(1)).subscribe(data => { + expect(data.length).toEqual(ITEMS); + sub.unsubscribe(); + }) + ).add(() => { + deleteThemAll(names, ref).then(done).catch(done.fail); + }); + }); + + it('should handle multiple subscriptions (warm)', async (done: any) => { + const ITEMS = 4; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + const changes = stocks.valueChanges(); + changes.pipe(take(1)).subscribe(() => { + }).add(() => { + changes.pipe(take(1)).subscribe(data => { + expect(data.length).toEqual(ITEMS); + }).add(() => { + deleteThemAll(names, ref).then(done).catch(done.fail); + }); + }); + }); + + it('should handle dynamic queries that return empty sets', async (done) => { + const ITEMS = 10; + let count = 0; + + const pricefilter$ = new BehaviorSubject(null); + const randomCollectionName = randomName(afs.firestore); + const ref = afs.firestore.collection(`${randomCollectionName}`); + const names = await createRandomStocks(afs.firestore, ref, ITEMS); + const sub = pricefilter$.pipe(switchMap(price => { + return afs.collection(randomCollectionName, ref => price ? ref.where('price', '==', price) : ref).valueChanges(); + })).subscribe(data => { + count = count + 1; + // the first time should all be 'added' + if (count === 1) { + expect(data.length).toEqual(ITEMS); + pricefilter$.next(-1); + } + // on the second round, we should have filtered out everything + if (count === 2) { + expect(data.length).toEqual(0); + sub.unsubscribe(); + deleteThemAll(names, ref).then(done).catch(done.fail); + } + }); + }); + + }); + + describe('snapshotChanges()', () => { + + it('should listen to all snapshotChanges() by default', async (done) => { + const ITEMS = 10; + let count = 0; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + const sub = stocks.snapshotChanges().subscribe(data => { + count = count + 1; + // the first time should all be 'added' + if (count === 1) { + // make an update + stocks.doc(names[0]).update({ price: 2 }); + } + // on the second round, make sure the array is still the same + // length but the updated item is now modified + if (count === 2) { + expect(data.length).toEqual(ITEMS); + const change = data.filter(x => x.payload.doc.id === names[0])[0]; + expect(change.type).toEqual('modified'); + sub.unsubscribe(); + deleteThemAll(names, ref).then(done).catch(done.fail); + } + }); + }); + + it('should handle multiple subscriptions (hot)', async (done: any) => { + const ITEMS = 4; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + const changes = stocks.snapshotChanges(); + const sub = changes.subscribe(() => { + }).add( + changes.pipe(take(1)).subscribe(data => { + expect(data.length).toEqual(ITEMS); + sub.unsubscribe(); + }) + ).add(() => { + deleteThemAll(names, ref).then(done).catch(done.fail); + }); + }); + + it('should handle multiple subscriptions (warm)', async (done: any) => { + const ITEMS = 4; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + const changes = stocks.snapshotChanges(); + changes.pipe(take(1)).subscribe(() => { + }).add(() => { + changes.pipe(take(1)).subscribe(data => { + expect(data.length).toEqual(ITEMS); + }).add(() => { + deleteThemAll(names, ref).then(done).catch(done.fail); + }); + }); + }); + + it('should update order on queries', async (done) => { + const ITEMS = 10; + let count = 0; + let firstIndex = 0; + const { ref, stocks, names } = + await collectionHarness(afs, ITEMS, ref => ref.orderBy('price', 'desc')); + const sub = stocks.snapshotChanges().subscribe(data => { + count = count + 1; + // the first time should all be 'added' + if (count === 1) { + // make an update + firstIndex = data.filter(d => d.payload.doc.id === names[0])[0].payload.newIndex; + stocks.doc(names[0]).update({ price: 2 }); + } + // on the second round, make sure the array is still the same + // length but the updated item is now modified + if (count === 2) { + expect(data.length).toEqual(ITEMS); + const change = data.filter(x => x.payload.doc.id === names[0])[0]; + expect(change.type).toEqual('modified'); + expect(change.payload.oldIndex).toEqual(firstIndex); + sub.unsubscribe(); + deleteThemAll(names, ref).then(done).catch(done.fail); + } + }); + }); + + it('should be able to filter snapshotChanges() types - modified', async (done) => { + const ITEMS = 10; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + + const sub = stocks.snapshotChanges(['modified']).pipe(skip(1)).subscribe(data => { + sub.unsubscribe(); + const change = data.filter(x => x.payload.doc.id === names[0])[0]; + expect(data.length).toEqual(1); + expect(change.payload.doc.data().price).toEqual(2); + expect(change.type).toEqual('modified'); + deleteThemAll(names, ref).then(done).catch(done.fail); + }); + + delayUpdate(stocks, names[0], { price: 2 }); + }); + + it('should be able to filter snapshotChanges() types - added', async (done) => { + const ITEMS = 10; + const harness = await collectionHarness(afs, ITEMS); + const { ref, stocks } = harness; + let names = harness.names; + + const nextId = ref.doc('a').id; + + const sub = stocks.snapshotChanges(['added']).pipe(skip(1)).subscribe(data => { + sub.unsubscribe(); + const change = data.filter(x => x.payload.doc.id === nextId)[0]; + expect(data.length).toEqual(ITEMS + 1); + expect(change.payload.doc.data().price).toEqual(2); + expect(change.type).toEqual('added'); + deleteThemAll(names, ref).then(done).catch(done.fail); + done(); + }); + + + names = names.concat([nextId]); + delayAdd(stocks, nextId, { price: 2 }); + }); + + /* TODO(jamesdaniels): revisit this now that we have metadata + it('should be able to filter snapshotChanges() types - added/modified', async (done) => { + const ITEMS = 10; + const harness = await collectionHarness(afs, ITEMS); + const { ref, stocks } = harness; + let names = harness.names; + + const nextId = ref.doc('a').id; + let count = 0; + + stocks.snapshotChanges(['added', 'modified']).pipe(skip(1), take(2)).subscribe(data => { + count += 1; + if (count === 1) { + const change = data.filter(x => x.payload.doc.id === nextId)[0]; + expect(data.length).toEqual(ITEMS + 1); + expect(change.payload.doc.data().price).toEqual(2); + expect(change.type).toEqual('added'); + delayUpdate(stocks, names[0], { price: 2 }); + } + if (count === 2) { + const change = data.filter(x => x.payload.doc.id === names[0])[0]; + expect(data.length).toEqual(ITEMS + 1); + expect(change.payload.doc.data().price).toEqual(2); + expect(change.type).toEqual('modified'); + } + }).add(() => { + deleteThemAll(names, ref).then(done).catch(done.fail); + }); + + names = names.concat([nextId]); + delayAdd(stocks, nextId, { price: 2 }); + }); + */ + + it('should be able to filter snapshotChanges() types - removed', async (done) => { + const ITEMS = 10; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + + const sub = stocks.snapshotChanges(['added', 'removed']).pipe(skip(1)).subscribe(data => { + sub.unsubscribe(); + const change = data.filter(x => x.payload.doc.id === names[0]); + expect(data.length).toEqual(ITEMS - 1); + expect(change.length).toEqual(0); + deleteThemAll(names, ref).then(done).catch(done.fail); + done(); + }); + + delayDelete(stocks, names[0], 400); + }); + + }); + + describe('stateChanges()', () => { + + it('should get stateChanges() updates', async (done: any) => { + const ITEMS = 10; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + + const sub = stocks.stateChanges().subscribe(data => { + // unsub immediately as we will be deleting data at the bottom + // and that will trigger another subscribe callback and fail + // the test + sub.unsubscribe(); + // We added ten things. This should be ten. + // This could not be ten if the batch failed or + // if the collection state is altered during a test run + expect(data.length).toEqual(ITEMS); + data.forEach(action => { + // We used the same piece of data so they should all equal + expect(action.payload.doc.data()).toEqual(FAKE_STOCK_DATA); + }); + deleteThemAll(names, ref).then(done).catch(done.fail); + }); + + }); + + it('should listen to all stateChanges() by default', async (done) => { + const ITEMS = 10; + let count = 0; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + stocks.stateChanges().subscribe(data => { + count = count + 1; + if (count === 1) { + stocks.doc(names[0]).update({ price: 2 }); + } + if (count === 2) { + expect(data.length).toEqual(1); + expect(data[0].type).toEqual('modified'); + deleteThemAll(names, ref).then(done).catch(done.fail); + } + }); + }); + + it('should handle multiple subscriptions (hot)', async (done: any) => { + const ITEMS = 4; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + const changes = stocks.stateChanges(); + const sub = changes.subscribe(() => { + }).add( + changes.pipe(take(1)).subscribe(data => { + expect(data.length).toEqual(ITEMS); + sub.unsubscribe(); + }) + ).add(() => { + deleteThemAll(names, ref).then(done).catch(done.fail); + }); + }); + + it('should handle multiple subscriptions (warm)', async (done: any) => { + const ITEMS = 4; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + const changes = stocks.stateChanges(); + changes.pipe(take(1)).subscribe(() => { + }).add(() => { + changes.pipe(take(1)).subscribe(data => { + expect(data.length).toEqual(ITEMS); + }).add(() => { + deleteThemAll(names, ref).then(done).catch(done.fail); + }); + }); + }); + + it('should be able to filter stateChanges() types - modified', async (done) => { + const ITEMS = 10; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + + const sub = stocks.stateChanges(['modified']).subscribe(data => { + sub.unsubscribe(); + expect(data.length).toEqual(1); + expect(data[0].payload.doc.data().price).toEqual(2); + expect(data[0].type).toEqual('modified'); + deleteThemAll(names, ref).then(done).catch(done.fail); + done(); + }); + + delayUpdate(stocks, names[0], { price: 2 }); + }); + + it('should be able to filter stateChanges() types - added', async (done) => { + const ITEMS = 10; + + const harness = await collectionHarness(afs, ITEMS); + const { ref, stocks } = harness; + let names = harness.names; + + const sub = stocks.stateChanges(['added']).pipe(skip(1)).subscribe(data => { + sub.unsubscribe(); + expect(data.length).toEqual(1); + expect(data[0].payload.doc.data().price).toEqual(2); + expect(data[0].type).toEqual('added'); + deleteThemAll(names, ref).then(done).catch(done.fail); + done(); + }); + + const nextId = ref.doc('a').id; + names = names.concat([nextId]); + delayAdd(stocks, nextId, { price: 2 }); + }); + + it('should be able to filter stateChanges() types - removed', async (done) => { + const ITEMS = 10; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + + const sub = stocks.stateChanges(['removed']).subscribe(data => { + sub.unsubscribe(); + expect(data.length).toEqual(1); + expect(data[0].type).toEqual('removed'); + deleteThemAll(names, ref).then(done).catch(done.fail); + done(); + }); + + delayDelete(stocks, names[0], 400); + }); + }); + + describe('auditTrail()', () => { + it('should listen to all events for auditTrail() by default', async (done) => { + const ITEMS = 10; + let count = 0; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + const sub = stocks.auditTrail().subscribe(data => { + count = count + 1; + if (count === 1) { + stocks.doc(names[0]).update({ price: 2 }); + } + if (count === 2) { + sub.unsubscribe(); + expect(data.length).toEqual(ITEMS + 1); + expect(data[data.length - 1].type).toEqual('modified'); + deleteThemAll(names, ref).then(done).catch(done.fail); + } + }); + }); + + it('should be able to filter auditTrail() types - removed', async (done) => { + const ITEMS = 10; + const { ref, stocks, names } = await collectionHarness(afs, ITEMS); + + const sub = stocks.auditTrail(['removed']).subscribe(data => { + sub.unsubscribe(); + expect(data.length).toEqual(1); + expect(data[0].type).toEqual('removed'); + deleteThemAll(names, ref).then(done).catch(done.fail); + done(); + }); + + delayDelete(stocks, names[0], 400); + }); + }); + +}); diff --git a/src/firestore-lazy/collection/collection.ts b/src/firestore-lazy/collection/collection.ts new file mode 100644 index 000000000..495249b7a --- /dev/null +++ b/src/firestore-lazy/collection/collection.ts @@ -0,0 +1,151 @@ +import { Observable } from 'rxjs'; +import { fromCollectionRef } from '../observable/fromRef'; +import { filter, map, observeOn, scan, switchMap } from 'rxjs/operators'; +import firebase from 'firebase/app'; +import { CollectionReference, DocumentChangeAction, DocumentChangeType, DocumentData, DocumentReference, Query } from '../interfaces'; +import { docChanges, sortedChanges } from './changes'; +import { AngularFirestoreDocument } from '../document/document'; +import { AngularFirestore } from '../firestore'; + +export function validateEventsArray(events?: DocumentChangeType[]) { + if (!events || events.length === 0) { + events = ['added', 'removed', 'modified']; + } + return events; +} + +/** + * AngularFirestoreCollection service + * + * This class creates a reference to a Firestore Collection. A reference and a query are provided in + * in the constructor. The query can be the unqueried reference if no query is desired.The class + * is generic which gives you type safety for data update methods and data streaming. + * + * This class uses Symbol.observable to transform into Observable using Observable.from(). + * + * This class is rarely used directly and should be created from the AngularFirestore service. + * + * Example: + * + * const collectionRef = firebase.firestore.collection('stocks'); + * const query = collectionRef.where('price', '>', '0.01'); + * const fakeStock = new AngularFirestoreCollection(collectionRef, query); + * + * // NOTE!: the updates are performed on the reference not the query + * await fakeStock.add({ name: 'FAKE', price: 0.01 }); + * + * // Subscribe to changes as snapshots. This provides you data updates as well as delta updates. + * fakeStock.valueChanges().subscribe(value => console.log(value)); + */ +export class AngularFirestoreCollection { + /** + * The constructor takes in a CollectionReference and Query to provide wrapper methods + * for data operations and data streaming. + * + * Note: Data operation methods are done on the reference not the query. This means + * when you update data it is not updating data to the window of your query unless + * the data fits the criteria of the query. See the AssociatedRefence type for details + * on this implication. + */ + constructor( + public readonly ref: Observable>, + private readonly query: Observable>, + private readonly afs: AngularFirestore) { } + + /** + * Listen to the latest change in the stream. This method returns changes + * as they occur and they are not sorted by query order. This allows you to construct + * your own data structure. + */ + stateChanges(events?: DocumentChangeType[]): Observable[]> { + if (!events || events.length === 0) { + this.query.pipe( + switchMap(query => docChanges(query, this.afs.schedulers.outsideAngular)), + filter(changes => changes.length > 0), + this.afs.keepUnstableUntilFirst + ); + } + return this.query.pipe( + switchMap(query => docChanges(query, this.afs.schedulers.outsideAngular)), + map(actions => actions.filter(change => events.indexOf(change.type) > -1)), + filter(changes => changes.length > 0), + this.afs.keepUnstableUntilFirst + ); + } + + /** + * Create a stream of changes as they occur it time. This method is similar to stateChanges() + * but it collects each event in an array over time. + */ + auditTrail(events?: DocumentChangeType[]): Observable[]> { + return this.stateChanges(events).pipe(scan((current, action) => [...current, ...action], [])); + } + + /** + * Create a stream of synchronized changes. This method keeps the local array in sorted + * query order. + */ + snapshotChanges(events?: DocumentChangeType[]): Observable[]> { + const validatedEvents = validateEventsArray(events); + return this.query.pipe( + switchMap(query => sortedChanges(query, validatedEvents, this.afs.schedulers.outsideAngular)), + this.afs.keepUnstableUntilFirst + ); + } + + /** + * Listen to all documents in the collection and its possible query as an Observable. + * + * If the `idField` option is provided, document IDs are included and mapped to the + * provided `idField` property name. + */ + valueChanges(): Observable; + // tslint:disable-next-line:unified-signatures + valueChanges({}): Observable; + valueChanges(options: {idField: K}): Observable<(T & { [T in K]: string })[]>; + valueChanges(options: {idField?: K} = {}): Observable { + return this.query.pipe( + switchMap(query => fromCollectionRef(query, this.afs.schedulers.outsideAngular)), + map(actions => actions.payload.docs.map(a => { + if (options.idField) { + return { + ...a.data() as {}, + ...{ [options.idField]: a.id } + } as T & { [T in K]: string }; + } else { + return a.data(); + } + })), + this.afs.keepUnstableUntilFirst + ); + } + + /** + * Retrieve the results of the query once. + */ + get(options?: firebase.firestore.GetOptions) { + return this.query.pipe( + switchMap(query => query.get(options)), + observeOn(this.afs.schedulers.insideAngular), + ); + } + + /** + * Add data to a collection reference. + * + * Note: Data operation methods are done on the reference not the query. This means + * when you update data it is not updating data to the window of your query unless + * the data fits the criteria of the query. + */ + add(data: T): Promise> { + return this.ref.toPromise().then(ref => ref.add(data)); + } + + /** + * Create a reference to a single document in a collection. + */ + doc(path?: string): AngularFirestoreDocument { + // TODO is there a better way to solve this type issue + return new AngularFirestoreDocument(this.ref.pipe(map(ref => ref.doc(path) as any)), this.afs); + } +} diff --git a/src/firestore-lazy/document/document.spec.ts b/src/firestore-lazy/document/document.spec.ts new file mode 100644 index 000000000..2a981b53d --- /dev/null +++ b/src/firestore-lazy/document/document.spec.ts @@ -0,0 +1,101 @@ +import { AngularFireModule, FirebaseApp } from '@angular/fire'; +import { AngularFirestore, SETTINGS } from '../firestore'; +import { AngularFirestoreModule } from '../firestore.module'; +import { AngularFirestoreDocument } from './document'; +import { DocumentReference } from '../interfaces'; +import { take } from 'rxjs/operators'; + +import { TestBed } from '@angular/core/testing'; +import { COMMON_CONFIG } from '../../test-config'; + +import { FAKE_STOCK_DATA, rando, randomName, Stock } from '../utils.spec'; +import firebase from 'firebase/app'; +import 'firebase/firestore'; + +describe('AngularFirestoreLazyDocument', () => { + let app: FirebaseApp; + let afs: AngularFirestore; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + AngularFireModule.initializeApp(COMMON_CONFIG, rando()), + AngularFirestoreModule + ], + providers: [ + { provide: SETTINGS, useValue: { host: 'localhost:8080', ssl: false } } + ] + }); + + app = TestBed.inject(FirebaseApp); + afs = TestBed.inject(AngularFirestore); + }); + + afterEach(() => { + app.delete(); + }); + + describe('valueChanges()', () => { + + it('should get unwrapped snapshot', async (done: any) => { + const randomCollectionName = afs.firestore.collection('a').doc().id; + const ref = afs.firestore.doc(`${randomCollectionName}/FAKE`) as firebase.firestore.DocumentReference; + const stock = new AngularFirestoreDocument(ref, afs); + await stock.set(FAKE_STOCK_DATA); + const obs$ = stock.valueChanges(); + obs$.pipe(take(1)).subscribe(async data => { + expect(data).toEqual(FAKE_STOCK_DATA); + stock.delete().then(done).catch(done.fail); + }); + }); + + /* TODO(jamesdaniels): test is flaking, look into this + it('should optionally map the doc ID to the emitted data object', async (done: any) => { + const randomCollectionName = afs.firestore.collection('a').doc().id; + const ref = afs.firestore.doc(`${randomCollectionName}/FAKE`); + const stock = new AngularFirestoreDocument(ref, afs); + await stock.set(FAKE_STOCK_DATA); + const idField = 'myCustomID'; + const obs$ = stock.valueChanges({ idField }); + obs$.pipe(take(1)).subscribe(async data => { + expect(data[idField]).toBeDefined(); + expect(data).toEqual(jasmine.objectContaining(FAKE_STOCK_DATA)); + stock.delete().then(done).catch(done.fail); + }); + });*/ + + }); + + describe('snapshotChanges()', () => { + + it('should get action updates', async (done: any) => { + const randomCollectionName = randomName(afs.firestore); + const ref = afs.firestore.doc(`${randomCollectionName}/FAKE`) as DocumentReference; + const stock = new AngularFirestoreDocument(ref, afs); + await stock.set(FAKE_STOCK_DATA); + const sub = stock + .snapshotChanges() + .subscribe(async a => { + sub.unsubscribe(); + if (a.payload.exists) { + expect(a.payload.data()).toEqual(FAKE_STOCK_DATA); + stock.delete().then(done).catch(done.fail); + } + }); + }); + + it('should get unwrapped snapshot', async (done: any) => { + const randomCollectionName = afs.firestore.collection('a').doc().id; + const ref = afs.firestore.doc(`${randomCollectionName}/FAKE`) as DocumentReference; + const stock = new AngularFirestoreDocument(ref, afs); + await stock.set(FAKE_STOCK_DATA); + const obs$ = stock.valueChanges(); + obs$.pipe(take(1)).subscribe(async data => { + expect(data).toEqual(FAKE_STOCK_DATA); + stock.delete().then(done).catch(done.fail); + }); + }); + + }); + +}); diff --git a/src/firestore-lazy/document/document.ts b/src/firestore-lazy/document/document.ts new file mode 100644 index 000000000..19fbec8e7 --- /dev/null +++ b/src/firestore-lazy/document/document.ts @@ -0,0 +1,114 @@ +import { from, Observable } from 'rxjs'; +import { Action, DocumentData, DocumentReference, DocumentSnapshot, QueryFn, SetOptions } from '../interfaces'; +import { fromDocRef } from '../observable/fromRef'; +import { map, observeOn, switchMap } from 'rxjs/operators'; +import { AngularFirestore, associateQuery } from '../firestore'; +import { AngularFirestoreCollection } from '../collection/collection'; +import firebase from 'firebase/app'; + +/** + * AngularFirestoreDocument service + * + * This class creates a reference to a Firestore Document. A reference is provided in + * in the constructor. The class is generic which gives you type safety for data update + * methods and data streaming. + * + * This class uses Symbol.observable to transform into Observable using Observable.from(). + * + * This class is rarely used directly and should be created from the AngularFirestore service. + * + * Example: + * + * const fakeStock = new AngularFirestoreDocument(doc('stocks/FAKE')); + * await fakeStock.set({ name: 'FAKE', price: 0.01 }); + * fakeStock.valueChanges().map(snap => { + * if(snap.exists) return snap.data(); + * return null; + * }).subscribe(value => console.log(value)); + * // OR! Transform using Observable.from() and the data is unwrapped for you + * Observable.from(fakeStock).subscribe(value => console.log(value)); + */ +export class AngularFirestoreDocument { + + /** + * The constructor takes in a DocumentReference to provide wrapper methods + * for data operations, data streaming, and Symbol.observable. + */ + constructor(public ref: Observable>, private afs: AngularFirestore) { } + + /** + * Create or overwrite a single document. + */ + set(data: T, options?: SetOptions): Promise { + return this.ref.toPromise().then(ref => ref.set(data, options)); + } + + /** + * Update some fields of a document without overwriting the entire document. + */ + update(data: Partial): Promise { + return this.ref.toPromise().then(ref => ref.update(data)); + } + + /** + * Delete a document. + */ + delete(): Promise { + return this.ref.toPromise().then(ref => ref.delete()); + } + + /** + * Create a reference to a sub-collection given a path and an optional query + * function. + */ + collection(path: string, queryFn?: QueryFn): AngularFirestoreCollection { + const promise = this.ref.pipe( + map(ref => { + const collectionRef = ref.collection(path) as firebase.firestore.CollectionReference; + return associateQuery(collectionRef, queryFn); + } + )); + const ref = promise.pipe(map(it => it.ref)); + const query = promise.pipe(map(it => it.query)); + return new AngularFirestoreCollection(ref, query, this.afs); + } + + /** + * Listen to snapshot updates from the document. + */ + snapshotChanges(): Observable>> { + return this.ref.pipe( + switchMap(ref => fromDocRef(ref, this.afs.schedulers.outsideAngular)), + this.afs.keepUnstableUntilFirst + ); + } + + /** + * Listen to unwrapped snapshot updates from the document. + * + * If the `idField` option is provided, document IDs are included and mapped to the + * provided `idField` property name. + */ + valueChanges(options?: { }): Observable; + valueChanges(options: { idField: K }): Observable<(T & { [T in K]: string }) | undefined>; + valueChanges(options: { idField?: K } = {}): Observable { + return this.snapshotChanges().pipe( + map(({ payload }) => + options.idField ? { + ...payload.data(), + ...{ [options.idField]: payload.id } + } as T & { [T in K]: string } : payload.data() + ) + ); + } + + /** + * Retrieve the document once. + */ + get(options?: firebase.firestore.GetOptions) { + return this.ref.pipe( + switchMap(ref => ref.get(options)), + observeOn(this.afs.schedulers.insideAngular), + ); + } +} diff --git a/src/firestore-lazy/firestore-memory.module.ts b/src/firestore-lazy/firestore-memory.module.ts new file mode 100644 index 000000000..e4fda5da5 --- /dev/null +++ b/src/firestore-lazy/firestore-memory.module.ts @@ -0,0 +1,9 @@ +import { NgModule } from '@angular/core'; +import { AngularFirestore } from './firestore'; + +@NgModule({ + providers: [ AngularFirestore ] +}) +export class AngularFirestoreModule { + // firebase/firestore/memory does not have persistence capabilities +} diff --git a/src/firestore-lazy/firestore-memory.ts b/src/firestore-lazy/firestore-memory.ts new file mode 100644 index 000000000..db678e004 --- /dev/null +++ b/src/firestore-lazy/firestore-memory.ts @@ -0,0 +1,3 @@ +// See index.ts, this variant is built by ./memory/ng-package.json +export * from './public_api'; +export * from './firestore-memory.module'; diff --git a/src/firestore-lazy/firestore.module.ts b/src/firestore-lazy/firestore.module.ts new file mode 100644 index 000000000..37499f71f --- /dev/null +++ b/src/firestore-lazy/firestore.module.ts @@ -0,0 +1,23 @@ +import { ModuleWithProviders, NgModule } from '@angular/core'; +import { PersistenceSettings } from './interfaces'; +import { AngularFirestore, ENABLE_PERSISTENCE, PERSISTENCE_SETTINGS } from './firestore'; + +import 'firebase/firestore'; // removed in build process when not UMD + +@NgModule({ + providers: [ AngularFirestore ] +}) +export class AngularFirestoreModule { + /** + * Attempt to enable persistent storage, if possible + */ + static enablePersistence(persistenceSettings?: PersistenceSettings): ModuleWithProviders { + return { + ngModule: AngularFirestoreModule, + providers: [ + { provide: ENABLE_PERSISTENCE, useValue: true }, + { provide: PERSISTENCE_SETTINGS, useValue: persistenceSettings }, + ] + }; + } +} diff --git a/src/firestore-lazy/firestore.spec.ts b/src/firestore-lazy/firestore.spec.ts new file mode 100644 index 000000000..fa7138e9b --- /dev/null +++ b/src/firestore-lazy/firestore.spec.ts @@ -0,0 +1,175 @@ +import { AngularFireModule, FIREBASE_APP_NAME, FIREBASE_OPTIONS, FirebaseApp } from '@angular/fire'; +import { AngularFirestore, SETTINGS } from './firestore'; +import { AngularFirestoreModule } from './firestore.module'; +import { AngularFirestoreDocument } from './document/document'; +import { AngularFirestoreCollection } from './collection/collection'; + +import { TestBed } from '@angular/core/testing'; +import { COMMON_CONFIG } from '../test-config'; +import 'firebase/firestore'; +import { rando } from './utils.spec'; + +describe('AngularFirestoreLazy', () => { + let app: FirebaseApp; + let afs: AngularFirestore; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + AngularFireModule.initializeApp(COMMON_CONFIG, rando()), + AngularFirestoreModule.enablePersistence() + ], + providers: [ + { provide: SETTINGS, useValue: { host: 'localhost:8080', ssl: false } } + ] + }); + + app = TestBed.inject(FirebaseApp); + afs = TestBed.inject(AngularFirestore); + }); + + afterEach(() => { + app.delete(); + }); + + it('should be the properly initialized type', () => { + expect(afs instanceof AngularFirestore).toBe(true); + }); + + it('should have an initialized Firebase app', () => { + expect(afs.firestore.app).toBeDefined(); + }); + + it('should create an AngularFirestoreDocument from a string path', () => { + const doc = afs.doc('a/doc'); + expect(doc instanceof AngularFirestoreDocument).toBe(true); + }); + + it('should create an AngularFirestoreDocument from a string path', () => { + const doc = afs.doc(afs.doc('a/doc').ref); + expect(doc instanceof AngularFirestoreDocument).toBe(true); + }); + + it('should create an AngularFirestoreCollection from a string path', () => { + const collection = afs.collection('stuffs'); + expect(collection instanceof AngularFirestoreCollection).toBe(true); + }); + + it('should create an AngularFirestoreCollection from a reference', () => { + const collection = afs.collection(afs.collection('stuffs').ref); + expect(collection instanceof AngularFirestoreCollection).toBe(true); + }); + + it('should throw on an invalid document path', () => { + const singleWrapper = () => afs.doc('collection'); + const tripleWrapper = () => afs.doc('collection/doc/subcollection'); + expect(singleWrapper).toThrowError(); + expect(tripleWrapper).toThrowError(); + }); + + it('should throw on an invalid collection path', () => { + const singleWrapper = () => afs.collection('collection/doc'); + const quadWrapper = () => afs.collection('collection/doc/subcollection/doc'); + expect(singleWrapper).toThrowError(); + expect(quadWrapper).toThrowError(); + }); + + if (typeof window === 'undefined') { + + it('should not enable persistence (Node.js)', (done) => { + afs.persistenceEnabled$.subscribe(isEnabled => { + expect(isEnabled).toBe(false); + done(); + }); + }); + + } else { + + it('should enable persistence', (done) => { + afs.persistenceEnabled$.subscribe(isEnabled => { + expect(isEnabled).toBe(true); + done(); + }); + }); + + } + +}); + +describe('AngularFirestore with different app', () => { + let app: FirebaseApp; + let afs: AngularFirestore; + let firebaseAppName: string; + + beforeEach(() => { + firebaseAppName = rando(); + TestBed.configureTestingModule({ + imports: [ + AngularFireModule.initializeApp(COMMON_CONFIG, rando()), + AngularFirestoreModule + ], + providers: [ + { provide: FIREBASE_APP_NAME, useValue: firebaseAppName }, + { provide: FIREBASE_OPTIONS, useValue: COMMON_CONFIG }, + { provide: SETTINGS, useValue: { host: 'localhost:8080', ssl: false } } + ] + }); + + + app = TestBed.inject(FirebaseApp); + afs = TestBed.inject(AngularFirestore); + }); + + afterEach(() => { + app.delete(); + }); + + describe('', () => { + + it('should be an AngularFirestore type', () => { + expect(afs instanceof AngularFirestore).toEqual(true); + }); + + it('should have an initialized Firebase app', () => { + expect(afs.firestore.app).toBeDefined(); + }); + + it('should have an initialized Firebase app instance member', () => { + expect(afs.firestore.app.name).toEqual(firebaseAppName); + }); + }); + +}); + + +describe('AngularFirestore without persistance', () => { + let app: FirebaseApp; + let afs: AngularFirestore; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + AngularFireModule.initializeApp(COMMON_CONFIG, rando()), + AngularFirestoreModule + ], + providers: [ + { provide: SETTINGS, useValue: { host: 'localhost:8080', ssl: false } } + ] + }); + + app = TestBed.inject(FirebaseApp); + afs = TestBed.inject(AngularFirestore); + }); + + afterEach(() => { + app.delete(); + }); + + it('should not enable persistence', (done) => { + afs.persistenceEnabled$.subscribe(isEnabled => { + expect(isEnabled).toBe(false); + done(); + }); + }); + +}); diff --git a/src/firestore-lazy/firestore.ts b/src/firestore-lazy/firestore.ts new file mode 100644 index 000000000..c34f54625 --- /dev/null +++ b/src/firestore-lazy/firestore.ts @@ -0,0 +1,256 @@ +import { Inject, Injectable, InjectionToken, NgZone, Optional, PLATFORM_ID } from '@angular/core'; +import { from, Observable, of } from 'rxjs'; +import { + AssociatedReference, + CollectionReference, + DocumentReference, + PersistenceSettings, + Query, + QueryFn, + QueryGroupFn, + Settings +} from './interfaces'; +import { AngularFirestoreDocument } from './document/document'; +import { AngularFirestoreCollection } from './collection/collection'; +import { AngularFirestoreCollectionGroup } from './collection-group/collection-group'; +import { + FIREBASE_APP_NAME, + FIREBASE_OPTIONS, + FirebaseAppConfig, + FirebaseOptions, + ɵAngularFireSchedulers, + ɵfirebaseAppFactory, + ɵkeepUnstableUntilFirstFactory, + ɵlazySDKProxy, + ɵPromiseProxy, + ɵapplyMixins, +} from '@angular/fire'; +import { isPlatformServer } from '@angular/common'; +import firebase from 'firebase/app'; +import { ɵfetchInstance } from '@angular/fire'; +import { map, observeOn, shareReplay, switchMap } from 'rxjs/operators'; +import { newId } from './util'; +import { proxyPolyfillCompat } from './base'; + +/** + * The value of this token determines whether or not the firestore will have persistance enabled + */ +export const ENABLE_PERSISTENCE = new InjectionToken('angularfire2.enableFirestorePersistence'); +export const PERSISTENCE_SETTINGS = new InjectionToken('angularfire2.firestore.persistenceSettings'); +export const SETTINGS = new InjectionToken('angularfire2.firestore.settings'); + +// SEMVER(7): use Parameters to detirmine the useEmulator arguments +// type UseEmulatorArguments = Parameters; +export type ɵUseEmulatorArguments = [string, number]; +export const USE_EMULATOR = new InjectionToken<ɵUseEmulatorArguments>('angularfire2.firestore.use-emulator'); + +/** + * A utility methods for associating a collection reference with + * a query. + * + * @param collectionRef - A collection reference to query + * @param queryFn - The callback to create a query + * + * Example: + * const { query, ref } = associateQuery(docRef.collection('items'), ref => { + * return ref.where('age', '<', 200); + * }); + */ +export function associateQuery(collectionRef: CollectionReference, queryFn = ref => ref): AssociatedReference { + const query = queryFn(collectionRef); + const ref = collectionRef; + return { query, ref }; +} + +export interface AngularFirestore extends Omit<ɵPromiseProxy, 'doc' | 'collection' | 'collectionGroup'> {} + +/** + * AngularFirestore Service + * + * This service is the main entry point for this feature module. It provides + * an API for creating Collection and Reference services. These services can + * then be used to do data updates and observable streams of the data. + * + * Example: + * + * import { Component } from '@angular/core'; + * import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from '@angular/fire/firestore'; + * import { Observable } from 'rxjs/Observable'; + * import { from } from 'rxjs/observable'; + * + * @Component({ + * selector: 'app-my-component', + * template: ` + *

Items for {{ (profile | async)?.name }} + *
    + *
  • {{ item.name }}
  • + *
+ *
+ * + * + *
+ * ` + * }) + * export class MyComponent implements OnInit { + * + * // services for data operations and data streaming + * private readonly itemsRef: AngularFirestoreCollection; + * private readonly profileRef: AngularFirestoreDocument; + * + * // observables for template + * items: Observable; + * profile: Observable; + * + * // inject main service + * constructor(private readonly afs: AngularFirestore) {} + * + * ngOnInit() { + * this.itemsRef = afs.collection('items', ref => ref.where('user', '==', 'davideast').limit(10)); + * this.items = this.itemsRef.valueChanges().map(snap => snap.docs.map(data => doc.data())); + * // this.items = from(this.itemsRef); // you can also do this with no mapping + * + * this.profileRef = afs.doc('users/davideast'); + * this.profile = this.profileRef.valueChanges(); + * } + * + * addItem(name: string) { + * const user = 'davideast'; + * this.itemsRef.add({ name, user }); + * } + * } + */ +@Injectable({ + providedIn: 'any' +}) +export class AngularFirestore { + + public readonly persistenceEnabled$: Observable; + public readonly schedulers: ɵAngularFireSchedulers; + public readonly keepUnstableUntilFirst: (obs: Observable) => Observable; + + /** + * Create a reference to a Firestore Collection based on a path or + * CollectionReference and an optional query function to narrow the result + * set. + */ + public readonly collection: (pathOrRef: string | CollectionReference, queryFn?: QueryFn) => AngularFirestoreCollection; + + /** + * Create a reference to a Firestore Collection Group based on a collectionId + * and an optional query function to narrow the result + * set. + */ + public readonly collectionGroup: (collectionId: string, queryGroupFn?: QueryGroupFn) => AngularFirestoreCollectionGroup; + + /** + * Create a reference to a Firestore Document based on a path or + * DocumentReference. Note that documents are not queryable because they are + * simply objects. However, documents have sub-collections that return a + * Collection reference and can be queried. + */ + public readonly doc: (pathOrRef: string | DocumentReference) => AngularFirestoreDocument; + + /** + * Returns a generated Firestore Document Id. + */ + public readonly createId = () => newId(); + + constructor( + @Inject(FIREBASE_OPTIONS) options: FirebaseOptions, + @Optional() @Inject(FIREBASE_APP_NAME) nameOrConfig: string | FirebaseAppConfig | null | undefined, + @Optional() @Inject(ENABLE_PERSISTENCE) shouldEnablePersistence: boolean | null, + @Optional() @Inject(SETTINGS) settings: Settings | null, + // tslint:disable-next-line:ban-types + @Inject(PLATFORM_ID) platformId: Object, + zone: NgZone, + @Optional() @Inject(PERSISTENCE_SETTINGS) persistenceSettings: PersistenceSettings | null, + @Optional() @Inject(USE_EMULATOR) _useEmulator: any, + ) { + this.schedulers = new ɵAngularFireSchedulers(zone); + this.keepUnstableUntilFirst = ɵkeepUnstableUntilFirstFactory(this.schedulers); + + const firestoreAndPersistenceEnabled = of(undefined).pipe( + observeOn(this.schedulers.outsideAngular), + // TODO wait for AngularFireAuth if it's available + switchMap(() => zone.runOutsideAngular(() => import('firebase/firestore'))), + map(() => ɵfirebaseAppFactory(options, zone, nameOrConfig)), + map(app => zone.runOutsideAngular(() => { + const useEmulator: ɵUseEmulatorArguments | null = _useEmulator; + return ɵfetchInstance(`${app.name}.firestore`, 'AngularFirestore', app, () => { + const firestore = zone.runOutsideAngular(() => app.firestore()); + if (settings) { + firestore.settings(settings); + } + if (useEmulator) { + firestore.useEmulator(...useEmulator); + } + + if (shouldEnablePersistence && !isPlatformServer(platformId)) { + // We need to try/catch here because not all enablePersistence() failures are caught + // https://github.com/firebase/firebase-js-sdk/issues/608 + const enablePersistence = () => { + try { + return from(firestore.enablePersistence(persistenceSettings || undefined).then(() => true, () => false)); + } catch (e) { + if (typeof console !== 'undefined') { console.warn(e); } + return of(false); + } + }; + return [firestore, zone.runOutsideAngular(enablePersistence)]; + } else { + return [firestore, of(false)]; + } + + }, [settings, useEmulator, shouldEnablePersistence]); + })), + shareReplay({ bufferSize: 1, refCount: false }), + ); + + const firestore = firestoreAndPersistenceEnabled.pipe(map(([firestore]) => firestore as firebase.firestore.Firestore)); + this.persistenceEnabled$ = firestoreAndPersistenceEnabled.pipe(switchMap(([_, it]) => it as Observable)); + + this.collection = (pathOrRef: string | CollectionReference, queryFn?: QueryFn) => { + const zoneAndQuery = firestore.pipe(map(firestoreInstance => { + let collectionRef: CollectionReference; + if (typeof pathOrRef === 'string') { + collectionRef = firestoreInstance.collection(pathOrRef) as firebase.firestore.CollectionReference; + } else { + collectionRef = pathOrRef; + } + return associateQuery(collectionRef, queryFn); + })); + const ref = zoneAndQuery.pipe(map(it => this.schedulers.ngZone.run(() => it.ref))); + const query = zoneAndQuery.pipe(map(it => it.query)); + return new AngularFirestoreCollection(ref, query, this); + }; + + this.doc = (pathOrRef: string | DocumentReference) => { + const ref = firestore.pipe( + map(firestoreInstance => { + if (typeof pathOrRef === 'string') { + return firestoreInstance.doc(pathOrRef) as DocumentReference; + } else { + return pathOrRef; + } + }), + map(ref => this.schedulers.ngZone.run(() => ref)) + ); + return new AngularFirestoreDocument(ref, this); + }; + + this.collectionGroup = (collectionId: string, queryGroupFn?: QueryGroupFn) => { + const queryFn = queryGroupFn || (ref => ref); + const query = firestore.pipe(map(firestoreInstance => { + const collectionGroup: Query = firestoreInstance.collectionGroup(collectionId) as firebase.firestore.Query; + return queryFn(collectionGroup); + })); + return new AngularFirestoreCollectionGroup(query, this); + }; + + return ɵlazySDKProxy(this, firestore, zone); + + } + +} + +ɵapplyMixins(AngularFirestore, [proxyPolyfillCompat]); diff --git a/src/firestore-lazy/index.ts b/src/firestore-lazy/index.ts new file mode 100644 index 000000000..62bd09bbe --- /dev/null +++ b/src/firestore-lazy/index.ts @@ -0,0 +1,6 @@ +// DO NOT MODIFY. This entry point is intended only for the side-effect import +// for firebase/firestore, it's here so Firestore variants can be used in other +// entry points. Ensure all APIs are exported on ./public_api as that's what +// the other entry points reexport. +export * from './public_api'; +export * from './firestore.module'; diff --git a/src/firestore-lazy/interfaces.ts b/src/firestore-lazy/interfaces.ts new file mode 100644 index 000000000..e512d7f1c --- /dev/null +++ b/src/firestore-lazy/interfaces.ts @@ -0,0 +1,86 @@ +import { Subscriber } from 'rxjs'; +import firebase from 'firebase/app'; + +export type Settings = firebase.firestore.Settings; +export type CollectionReference = firebase.firestore.CollectionReference; +export type DocumentReference = firebase.firestore.DocumentReference; +export type PersistenceSettings = firebase.firestore.PersistenceSettings; +export type DocumentChangeType = firebase.firestore.DocumentChangeType; +export type SnapshotOptions = firebase.firestore.SnapshotOptions; +export type FieldPath = firebase.firestore.FieldPath; +export type Query = firebase.firestore.Query; + +export type SetOptions = firebase.firestore.SetOptions; +export type DocumentData = firebase.firestore.DocumentData; + +export interface DocumentSnapshotExists extends firebase.firestore.DocumentSnapshot { + readonly exists: true; + data(options?: SnapshotOptions): T; +} + +export interface DocumentSnapshotDoesNotExist extends firebase.firestore.DocumentSnapshot { + readonly exists: false; + data(options?: SnapshotOptions): undefined; + get(fieldPath: string | FieldPath, options?: SnapshotOptions): undefined; +} + +export type DocumentSnapshot = DocumentSnapshotExists | DocumentSnapshotDoesNotExist; + +export interface QueryDocumentSnapshot extends firebase.firestore.QueryDocumentSnapshot { + data(options?: SnapshotOptions): T; +} + +export interface QuerySnapshot extends firebase.firestore.QuerySnapshot { + readonly docs: QueryDocumentSnapshot[]; +} + +export interface DocumentChange extends firebase.firestore.DocumentChange { + readonly doc: QueryDocumentSnapshot; +} + +export interface DocumentChangeAction { + type: DocumentChangeType; + payload: DocumentChange; +} + +export interface Action { + type: string; + payload: T; +} + +export interface Reference { + onSnapshot: (options: firebase.firestore.SnapshotListenOptions, sub: Subscriber) => any; +} + +// A convience type for making a query. +// Example: const query = (ref) => ref.where('name', == 'david'); +export type QueryFn = (ref: CollectionReference) => Query; + +export type QueryGroupFn = (query: Query) => Query; + +/** + * A structure that provides an association between a reference + * and a query on that reference. Note: Performing operations + * on the reference can lead to confusing results with complicated + * queries. + * + * Example: + * + * const query = ref.where('type', '==', 'Book'). + * .where('price', '>' 18.00) + * .where('price', '<' 100.00) + * .where('category', '==', 'Fiction') + * .where('publisher', '==', 'BigPublisher') + * + * // This addition would not be a result of the query above + * ref.add({ + * type: 'Magazine', + * price: 4.99, + * category: 'Sports', + * publisher: 'SportsPublisher' + * }); + */ +export interface AssociatedReference { + ref: CollectionReference; + query: Query; +} diff --git a/src/firestore-lazy/memory/ng-package.json b/src/firestore-lazy/memory/ng-package.json new file mode 100644 index 000000000..e122fa715 --- /dev/null +++ b/src/firestore-lazy/memory/ng-package.json @@ -0,0 +1,6 @@ +{ + "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", + "lib": { + "entryFile": "../firestore-memory.ts" + } +} diff --git a/src/firestore/observable/fromRef.ts b/src/firestore-lazy/observable/fromRef.ts similarity index 100% rename from src/firestore/observable/fromRef.ts rename to src/firestore-lazy/observable/fromRef.ts diff --git a/src/firestore-lazy/package.json b/src/firestore-lazy/package.json new file mode 100644 index 000000000..277850f56 --- /dev/null +++ b/src/firestore-lazy/package.json @@ -0,0 +1,12 @@ +{ + "$schema": "../../node_modules/ng-packagr/package.schema.json", + "ngPackage": { + "lib": { + "entryFile": "index.ts", + "umdModuleIds": { + "firebase/app": "firebase", + "@firebase/firestore": "firebase-firestore" + } + } + } +} diff --git a/src/firestore-lazy/public_api.ts b/src/firestore-lazy/public_api.ts new file mode 100644 index 000000000..6f2906f4a --- /dev/null +++ b/src/firestore-lazy/public_api.ts @@ -0,0 +1,10 @@ + +import 'firebase/firestore'; // removed in build process when not UMD + +export * from './firestore'; +export * from './collection/collection'; +export * from './collection-group/collection-group'; +export * from './document/document'; +export * from './collection/changes'; +export * from './observable/fromRef'; +export * from './interfaces'; diff --git a/src/firestore-lazy/util.ts b/src/firestore-lazy/util.ts new file mode 100644 index 000000000..5e6af715c --- /dev/null +++ b/src/firestore-lazy/util.ts @@ -0,0 +1,44 @@ + +function randomBytes(nBytes: number): Uint8Array { + // Polyfills for IE and WebWorker by using `self` and `msCrypto` when `crypto` is not available. + const crypto = + // eslint-disable-next-line @typescript-eslint/no-explicit-any + typeof self !== 'undefined' && (self.crypto || (self as any).msCrypto); + if ((crypto as any).generateRandomBytes) { + return (crypto as any).generateRandomBytes(nBytes); + } + const bytes = new Uint8Array(nBytes); + if (crypto && typeof crypto.getRandomValues === 'function') { + crypto.getRandomValues(bytes); + } else { + // Falls back to Math.random + for (let i = 0; i < nBytes; i++) { + bytes[i] = Math.floor(Math.random() * 256); + } + } + return bytes; +} + +// just grabbed this from Firestore, so we don't need to await +export function newId() { + // Alphanumeric characters + const chars = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + // The largest byte value that is a multiple of `char.length`. + const maxMultiple = Math.floor(256 / chars.length) * chars.length; + + let autoId = ''; + const targetLength = 20; + while (autoId.length < targetLength) { + const bytes = randomBytes(40); + // tslint:disable-next-line:prefer-for-of + for (let i = 0; i < bytes.length; ++i) { + // Only accept values that are [0, maxMultiple), this ensures they can + // be evenly mapped to indices of `chars` via a modulo operation. + if (autoId.length < targetLength && bytes[i] < maxMultiple) { + autoId += chars.charAt(bytes[i] % chars.length); + } + } + } + return autoId; +} diff --git a/src/firestore-lazy/utils.spec.ts b/src/firestore-lazy/utils.spec.ts new file mode 100644 index 000000000..87bb97b00 --- /dev/null +++ b/src/firestore-lazy/utils.spec.ts @@ -0,0 +1,57 @@ +import firebase from 'firebase/app'; +import { AngularFirestoreCollection } from './collection/collection'; + +export interface Stock { + name: string; + price: number; +} + +export const FAKE_STOCK_DATA = { name: 'FAKE', price: 1 }; + +export const randomName = (firestore): string => firestore.collection('a').doc().id; + +export const createRandomStocks = async ( + firestore: firebase.firestore.Firestore, + collectionRef: firebase.firestore.CollectionReference, + numberOfItems +) => { + // Create a batch to update everything at once + const batch = firestore.batch(); + // Store the random names to delete them later + const count = 0; + let names: string[] = []; + Array.from(Array(numberOfItems)).forEach((a, i) => { + const name = randomName(firestore); + batch.set(collectionRef.doc(name), FAKE_STOCK_DATA); + names = [...names, name]; + }); + // Create the batch entries + // Commit! + await batch.commit(); + return names; +}; + +export function deleteThemAll(names, ref) { + const promises = names.map(name => ref.doc(name).delete()); + return Promise.all(promises); +} + +export function delayUpdate(collection: AngularFirestoreCollection|firebase.firestore.CollectionReference, path, data, delay = 250) { + setTimeout(() => { + collection.doc(path).update(data); + }, delay); +} + +export function delayAdd(collection: AngularFirestoreCollection|firebase.firestore.CollectionReference, path, data, delay = 250) { + setTimeout(() => { + collection.doc(path).set(data); + }, delay); +} + +export function delayDelete(collection: AngularFirestoreCollection|firebase.firestore.CollectionReference, path, delay = 250) { + setTimeout(() => { + collection.doc(path).delete(); + }, delay); +} + +export const rando = () => (Math.random() + 1).toString(36).substring(7); diff --git a/src/firestore/collection-group/collection-group.ts b/src/firestore/collection-group/collection-group.ts index 5e8ed5437..cc14031d8 100644 --- a/src/firestore/collection-group/collection-group.ts +++ b/src/firestore/collection-group/collection-group.ts @@ -1,11 +1,9 @@ import { from, Observable } from 'rxjs'; -import { fromCollectionRef } from '../observable/fromRef'; +import { fromCollectionRef, docChanges, sortedChanges } from '@angular/fire/firestore-lazy'; import { filter, map, observeOn, scan } from 'rxjs/operators'; import firebase from 'firebase/app'; - import { DocumentChangeAction, DocumentChangeType, DocumentData, Query } from '../interfaces'; import { validateEventsArray } from '../collection/collection'; -import { docChanges, sortedChanges } from '../collection/changes'; import { AngularFirestore } from '../firestore'; /** diff --git a/src/firestore/collection/collection.ts b/src/firestore/collection/collection.ts index 9e77f27a0..f9837ac44 100644 --- a/src/firestore/collection/collection.ts +++ b/src/firestore/collection/collection.ts @@ -1,10 +1,8 @@ import { from, Observable } from 'rxjs'; -import { fromCollectionRef } from '../observable/fromRef'; +import { fromCollectionRef, docChanges, sortedChanges } from '@angular/fire/firestore-lazy'; import { filter, map, observeOn, scan } from 'rxjs/operators'; import firebase from 'firebase/app'; - import { CollectionReference, DocumentChangeAction, DocumentChangeType, DocumentData, DocumentReference, Query } from '../interfaces'; -import { docChanges, sortedChanges } from './changes'; import { AngularFirestoreDocument } from '../document/document'; import { AngularFirestore } from '../firestore'; diff --git a/src/firestore/document/document.ts b/src/firestore/document/document.ts index f0a7ab992..c8dcf3d12 100644 --- a/src/firestore/document/document.ts +++ b/src/firestore/document/document.ts @@ -1,6 +1,6 @@ import { from, Observable } from 'rxjs'; import { Action, DocumentData, DocumentReference, DocumentSnapshot, QueryFn, SetOptions } from '../interfaces'; -import { fromDocRef } from '../observable/fromRef'; +import { fromDocRef } from '@angular/fire/firestore-lazy'; import { map, observeOn } from 'rxjs/operators'; import { AngularFirestore, associateQuery } from '../firestore'; import { AngularFirestoreCollection } from '../collection/collection'; diff --git a/src/firestore/firestore.module.ts b/src/firestore/firestore.module.ts index 8f2fcf3c3..7323f05b1 100644 --- a/src/firestore/firestore.module.ts +++ b/src/firestore/firestore.module.ts @@ -1,5 +1,5 @@ import { ModuleWithProviders, NgModule } from '@angular/core'; -import { PersistenceSettings } from './interfaces'; +import { PersistenceSettings } from '@angular/fire/firestore-lazy'; import { AngularFirestore, ENABLE_PERSISTENCE, PERSISTENCE_SETTINGS } from './firestore'; import 'firebase/firestore'; diff --git a/src/firestore/firestore.ts b/src/firestore/firestore.ts index 662904f6b..de0b34307 100644 --- a/src/firestore/firestore.ts +++ b/src/firestore/firestore.ts @@ -1,7 +1,6 @@ -import { Inject, Injectable, InjectionToken, NgZone, Optional, PLATFORM_ID } from '@angular/core'; +import { Inject, Injectable, NgZone, Optional, PLATFORM_ID } from '@angular/core'; import { from, Observable, of } from 'rxjs'; import { - AssociatedReference, CollectionReference, DocumentReference, PersistenceSettings, @@ -21,49 +20,13 @@ import { ɵAngularFireSchedulers, ɵfirebaseAppFactory, ɵkeepUnstableUntilFirstFactory, - FirebaseApp } from '@angular/fire'; import { isPlatformServer } from '@angular/common'; import firebase from 'firebase/app'; import { USE_EMULATOR as USE_AUTH_EMULATOR } from '@angular/fire/auth'; import { ɵfetchInstance, ɵlogAuthEmulatorError } from '@angular/fire'; - -/** - * The value of this token determines whether or not the firestore will have persistance enabled - */ -export const ENABLE_PERSISTENCE = new InjectionToken('angularfire2.enableFirestorePersistence'); -export const PERSISTENCE_SETTINGS = new InjectionToken('angularfire2.firestore.persistenceSettings'); -export const SETTINGS = new InjectionToken('angularfire2.firestore.settings'); - -// SEMVER(7): use Parameters to detirmine the useEmulator arguments -// type UseEmulatorArguments = Parameters; -type UseEmulatorArguments = [string, number]; -export const USE_EMULATOR = new InjectionToken('angularfire2.firestore.use-emulator'); - -/** - * A utility methods for associating a collection reference with - * a query. - * - * @param collectionRef - A collection reference to query - * @param queryFn - The callback to create a query - * - * Example: - * const { query, ref } = associateQuery(docRef.collection('items'), ref => { - * return ref.where('age', '<', 200); - * }); - */ -export function associateQuery(collectionRef: CollectionReference, queryFn = ref => ref): AssociatedReference { - const query = queryFn(collectionRef); - const ref = collectionRef; - return { query, ref }; -} - -type InstanceCache = Map; +import { ENABLE_PERSISTENCE, PERSISTENCE_SETTINGS, SETTINGS, USE_EMULATOR, associateQuery, ɵUseEmulatorArguments } from '@angular/fire/firestore-lazy'; +export { ENABLE_PERSISTENCE, PERSISTENCE_SETTINGS, SETTINGS, USE_EMULATOR, associateQuery }; /** * AngularFirestore Service @@ -153,7 +116,7 @@ export class AngularFirestore { if (!firebase.auth && useAuthEmulator) { ɵlogAuthEmulatorError(); } - const useEmulator: UseEmulatorArguments | null = _useEmulator; + const useEmulator: ɵUseEmulatorArguments | null = _useEmulator; [this.firestore, this.persistenceEnabled$] = ɵfetchInstance(`${app.name}.firestore`, 'AngularFirestore', app, () => { const firestore = zone.runOutsideAngular(() => app.firestore()); diff --git a/src/firestore/interfaces.ts b/src/firestore/interfaces.ts index e512d7f1c..92163b9d6 100644 --- a/src/firestore/interfaces.ts +++ b/src/firestore/interfaces.ts @@ -1,86 +1,24 @@ -import { Subscriber } from 'rxjs'; -import firebase from 'firebase/app'; - -export type Settings = firebase.firestore.Settings; -export type CollectionReference = firebase.firestore.CollectionReference; -export type DocumentReference = firebase.firestore.DocumentReference; -export type PersistenceSettings = firebase.firestore.PersistenceSettings; -export type DocumentChangeType = firebase.firestore.DocumentChangeType; -export type SnapshotOptions = firebase.firestore.SnapshotOptions; -export type FieldPath = firebase.firestore.FieldPath; -export type Query = firebase.firestore.Query; - -export type SetOptions = firebase.firestore.SetOptions; -export type DocumentData = firebase.firestore.DocumentData; - -export interface DocumentSnapshotExists extends firebase.firestore.DocumentSnapshot { - readonly exists: true; - data(options?: SnapshotOptions): T; -} - -export interface DocumentSnapshotDoesNotExist extends firebase.firestore.DocumentSnapshot { - readonly exists: false; - data(options?: SnapshotOptions): undefined; - get(fieldPath: string | FieldPath, options?: SnapshotOptions): undefined; -} - -export type DocumentSnapshot = DocumentSnapshotExists | DocumentSnapshotDoesNotExist; - -export interface QueryDocumentSnapshot extends firebase.firestore.QueryDocumentSnapshot { - data(options?: SnapshotOptions): T; -} - -export interface QuerySnapshot extends firebase.firestore.QuerySnapshot { - readonly docs: QueryDocumentSnapshot[]; -} - -export interface DocumentChange extends firebase.firestore.DocumentChange { - readonly doc: QueryDocumentSnapshot; -} - -export interface DocumentChangeAction { - type: DocumentChangeType; - payload: DocumentChange; -} - -export interface Action { - type: string; - payload: T; -} - -export interface Reference { - onSnapshot: (options: firebase.firestore.SnapshotListenOptions, sub: Subscriber) => any; -} - -// A convience type for making a query. -// Example: const query = (ref) => ref.where('name', == 'david'); -export type QueryFn = (ref: CollectionReference) => Query; - -export type QueryGroupFn = (query: Query) => Query; - -/** - * A structure that provides an association between a reference - * and a query on that reference. Note: Performing operations - * on the reference can lead to confusing results with complicated - * queries. - * - * Example: - * - * const query = ref.where('type', '==', 'Book'). - * .where('price', '>' 18.00) - * .where('price', '<' 100.00) - * .where('category', '==', 'Fiction') - * .where('publisher', '==', 'BigPublisher') - * - * // This addition would not be a result of the query above - * ref.add({ - * type: 'Magazine', - * price: 4.99, - * category: 'Sports', - * publisher: 'SportsPublisher' - * }); - */ -export interface AssociatedReference { - ref: CollectionReference; - query: Query; -} +export { + Settings, + CollectionReference, + DocumentReference, + PersistenceSettings, + DocumentChangeType, + SnapshotOptions, + FieldPath, + Query, + SetOptions, + DocumentData, + DocumentSnapshotExists, + DocumentSnapshotDoesNotExist, + DocumentSnapshot, + QueryDocumentSnapshot, + QuerySnapshot, + DocumentChange, + DocumentChangeAction, + Action, + Reference, + QueryFn, + QueryGroupFn, + AssociatedReference, +} from '@angular/fire/firestore-lazy'; diff --git a/src/firestore/public_api.ts b/src/firestore/public_api.ts index d17c942cd..681f64953 100644 --- a/src/firestore/public_api.ts +++ b/src/firestore/public_api.ts @@ -2,6 +2,6 @@ export * from './firestore'; export * from './collection/collection'; export * from './collection-group/collection-group'; export * from './document/document'; -export * from './collection/changes'; -export * from './observable/fromRef'; +export { docChanges, sortedChanges, combineChanges, combineChange } from '@angular/fire/firestore-lazy'; +export { fromRef, fromDocRef, fromCollectionRef } from '@angular/fire/firestore-lazy'; export * from './interfaces'; diff --git a/src/root.spec.ts b/src/root.spec.ts index 36a35b732..b99486932 100644 --- a/src/root.spec.ts +++ b/src/root.spec.ts @@ -7,6 +7,10 @@ export * from './firestore/firestore.spec'; export * from './firestore/document/document.spec'; export * from './firestore/collection/collection.spec'; export * from './firestore/collection-group/collection-group.spec'; +export * from './firestore-lazy/firestore.spec'; +export * from './firestore-lazy/document/document.spec'; +export * from './firestore-lazy/collection/collection.spec'; +export * from './firestore-lazy/collection-group/collection-group.spec'; export * from './functions/functions.spec'; export * from './database/database.spec'; export * from './database/utils.spec'; diff --git a/tools/build.ts b/tools/build.ts index b7cf5e0d0..cea1d7d64 100644 --- a/tools/build.ts +++ b/tools/build.ts @@ -9,10 +9,10 @@ import firebase from 'firebase/app'; // TODO infer these from the package.json const MODULES = [ 'core', 'analytics', 'auth', 'auth-guard', 'database', - 'firestore', 'functions', 'remote-config', + 'firestore', 'firestore-lazy', 'functions', 'remote-config', 'storage', 'messaging', 'performance' ]; -const LAZY_MODULES = ['analytics', 'auth', 'functions', 'messaging', 'remote-config']; +const LAZY_MODULES = [['analytics'], ['auth'], ['functions'], ['firestore-lazy', 'firestore'], ['messaging'], ['remote-config']]; const UMD_NAMES = MODULES.map(m => m === 'core' ? 'angular-fire' : `angular-fire-${m}`); const ENTRY_NAMES = MODULES.map(m => m === 'core' ? '@angular/fire' : `@angular/fire/${m}`); @@ -24,6 +24,7 @@ function proxyPolyfillCompat() { messaging: tsKeys(), performance: tsKeys(), 'remote-config': tsKeys(), + 'firestore-lazy': tsKeys(), }; return Promise.all(Object.keys(defaultObject).map(module => @@ -95,7 +96,9 @@ async function measure(module: string) { } async function fixImportForLazyModules() { - await Promise.all(LAZY_MODULES.map(async module => { + // firebase-lazy/memory is special-case, make sure to also cover that as we make changes + await Promise.all(LAZY_MODULES.map(async ([module, _sdk]) => { + const sdk = _sdk || module; const packageJson = JSON.parse((await readFile(dest(module, 'package.json'))).toString()); const entries = Array.from(new Set(Object.values(packageJson).filter(v => typeof v === 'string' && v.endsWith('.js')))) as string[]; // TODO don't hardcode esm2015 here, perhaps we should scan all the entry directories @@ -106,16 +109,41 @@ async function fixImportForLazyModules() { let newSource: string; if (path.endsWith('.umd.js')) { // in the UMD for lazy modules replace the dyanamic import - newSource = source.replace(`import('firebase/${module}')`, 'rxjs.of(undefined)'); + newSource = source.replace(`import('firebase/${sdk}')`, 'rxjs.of(undefined)'); } else { // in everything else get rid of the global side-effect import - newSource = source.replace(new RegExp(`^import 'firebase/${module}'.+$`, 'gm'), ''); + newSource = source.replace(new RegExp(`^import 'firebase/${sdk}'.+$`, 'gm'), ''); } await writeFile(dest(module, path), newSource); })); })); } +async function fixFirestoreLazyMemoryModule() { + const module = 'firestore-lazy/memory'; + const packageJson = JSON.parse((await readFile(dest(module, 'package.json'))).toString()); + const entries = Array.from(new Set(Object.values(packageJson).filter(v => typeof v === 'string' && v.endsWith('.js')))) as string[]; + // TODO don't hardcode esm2015 here, perhaps we should scan all the entry directories + // e.g, if ng-packagr starts building other non-flattened entries we'll lose the dynamic import + entries.push(`../../esm2015/${module}/public_api.js`); // the import isn't pulled into the ESM public_api + entries.push(`../../esm2015/${module}/firestore.js`); + await Promise.all(entries.map(async path => { + const source = (await readFile(dest(module, path))).toString(); + let newSource: string; + if (path.endsWith('.umd.js')) { + // in the UMD for lazy modules replace the dyanamic import + newSource = source.replace('import(\'firebase/firestore\')', 'rxjs.of(undefined)') + .replace('require(\'firebase/firestore\')', 'require(\'firebase/firestore/memory\')') + .replace(', \'firebase/firestore\',', ', \'firebase/firestore/memory\','); + } else { + // in everything else get rid of the global side-effect import + newSource = source.replace(/^import 'firebase\/firestore'.+$/gm, '') + .replace('import(\'firebase/firestore\')', 'import(\'firebase/firestore/memory\')'); + } + await writeFile(dest(module, path), newSource); + })); +} + async function buildLibrary() { await proxyPolyfillCompat(); await spawnPromise('npx', ['ng', 'build']); @@ -127,6 +155,7 @@ async function buildLibrary() { replacePackageJsonVersions(), replacePackageCoreVersion(), fixImportForLazyModules(), + fixFirestoreLazyMemoryModule(), ]); } diff --git a/tsconfig.base.json b/tsconfig.base.json index f60094014..0245d92f5 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -29,6 +29,7 @@ "@angular/fire/database-deprecated": ["dist/packages-dist/database-deprecated"], "@angular/fire/firebase-node": ["dist/packages-dist/firebase-node"], "@angular/fire/firestore": ["dist/packages-dist/firestore"], + "@angular/fire/firestore-lazy": ["dist/packages-dist/firestore-lazy"], "@angular/fire/functions": ["dist/packages-dist/functions"], "@angular/fire/messaging": ["dist/packages-dist/messaging"], "@angular/fire/performance": ["dist/packages-dist/performance"], From e955f45c951e747f2fca0b1c7c182577e7542331 Mon Sep 17 00:00:00 2001 From: James Daniels Date: Thu, 26 Nov 2020 03:43:53 -0500 Subject: [PATCH 08/11] Storage pipe uses transfer state --- .../src/app/firestore/firestore.component.ts | 24 +++++----------- sample/src/app/upboats/upboats.component.ts | 28 ++++++++----------- src/storage/pipes/storageUrl.pipe.ts | 12 ++++++-- 3 files changed, 28 insertions(+), 36 deletions(-) diff --git a/sample/src/app/firestore/firestore.component.ts b/sample/src/app/firestore/firestore.component.ts index 0421313fa..52206e802 100644 --- a/sample/src/app/firestore/firestore.component.ts +++ b/sample/src/app/firestore/firestore.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { AngularFirestore } from '../../firestore'; -import { from, Observable } from 'rxjs'; -import { map, startWith, switchMap, tap } from 'rxjs/operators'; +import { Observable } from 'rxjs'; +import { startWith, tap } from 'rxjs/operators'; import { makeStateKey, TransferState } from '@angular/platform-browser'; import { trace } from '@angular/fire/performance'; @@ -10,31 +10,21 @@ import { trace } from '@angular/fire/performance'; template: `

Firestore! {{ testDocValue$ | async | json }} - {{ persistenceEnabled$ | async }} - {{ (persistenceProvider | async) || 'unknown (mangled)' }}

`, styles: [``] }) export class FirestoreComponent implements OnInit { - public readonly persistenceEnabled$: Observable; public readonly testDocValue$: Observable; - public readonly persistenceProvider: any; constructor(state: TransferState, firestore: AngularFirestore) { - this.persistenceProvider = from((firestore as any)._persistenceProvider).pipe(map(it => it?.constructor.name)); const doc = firestore.doc('test/1'); - this.testDocValue$ = from(doc.ref).pipe( - switchMap(ref => { - const key = makeStateKey(ref.path); - const existing = state.get(key, undefined); - return doc.valueChanges().pipe( - trace('firestore'), - existing ? startWith(existing) : tap(it => state.set(key, it)) - ); - }) + const key = makeStateKey('test/1'); + const existing = state.get(key, undefined); + this.testDocValue$ = doc.valueChanges().pipe( + trace('firestore'), + existing ? startWith(existing) : tap(it => state.set(key, it)) ); - this.persistenceEnabled$ = firestore.persistenceEnabled$; } ngOnInit(): void { diff --git a/sample/src/app/upboats/upboats.component.ts b/sample/src/app/upboats/upboats.component.ts index 2bcc58354..daec0227d 100644 --- a/sample/src/app/upboats/upboats.component.ts +++ b/sample/src/app/upboats/upboats.component.ts @@ -1,6 +1,6 @@ import { Component, OnInit } from '@angular/core'; -import { from, Observable } from 'rxjs'; -import { map, startWith, switchMap, tap } from 'rxjs/operators'; +import { Observable } from 'rxjs'; +import { map, startWith, tap } from 'rxjs/operators'; import firebase from 'firebase/app'; import { makeStateKey, TransferState } from '@angular/platform-browser'; import { trace } from '@angular/fire/performance'; @@ -21,20 +21,16 @@ export class UpboatsComponent implements OnInit { const collection = firestore.collection('animals', ref => ref.orderBy('upboats', 'desc').orderBy('updatedAt', 'desc') ); - this.animals = from(collection.ref).pipe( - switchMap(ref => { - const key = makeStateKey(ref.path); - const existing = state.get(key, undefined); - return collection.snapshotChanges().pipe( - trace('animals'), - map(it => it.map(change => ({ - ...change.payload.doc.data(), - id: change.payload.doc.id, - hasPendingWrites: change.payload.doc.metadata.hasPendingWrites - }))), - existing ? startWith(existing) : tap(it => state.set(key, it)) - ); - }) + const key = makeStateKey('animals'); + const existing = state.get(key, undefined); + this.animals = collection.snapshotChanges().pipe( + trace('animals'), + map(it => it.map(change => ({ + ...change.payload.doc.data(), + id: change.payload.doc.id, + hasPendingWrites: change.payload.doc.metadata.hasPendingWrites + }))), + existing ? startWith(existing) : tap(it => state.set(key, it)) ); } diff --git a/src/storage/pipes/storageUrl.pipe.ts b/src/storage/pipes/storageUrl.pipe.ts index 1aaf2caeb..9dafc9eac 100644 --- a/src/storage/pipes/storageUrl.pipe.ts +++ b/src/storage/pipes/storageUrl.pipe.ts @@ -1,6 +1,8 @@ import { AsyncPipe } from '@angular/common'; import { ChangeDetectorRef, NgModule, OnDestroy, Pipe, PipeTransform } from '@angular/core'; -import { Observable } from 'rxjs'; +import { makeStateKey, TransferState } from '@angular/platform-browser'; +import { Observable, of } from 'rxjs'; +import { startWith, tap } from 'rxjs/operators'; import { AngularFireStorage } from '../storage'; /** to be used with in combination with | async */ @@ -14,14 +16,18 @@ export class GetDownloadURLPipe implements PipeTransform, OnDestroy { private path: string; private downloadUrl$: Observable; - constructor(private storage: AngularFireStorage, cdr: ChangeDetectorRef) { + constructor(private storage: AngularFireStorage, cdr: ChangeDetectorRef, private state: TransferState) { this.asyncPipe = new AsyncPipe(cdr); } transform(path: string) { if (path !== this.path) { this.path = path; - this.downloadUrl$ = this.storage.ref(path).getDownloadURL(); + const key = makeStateKey(`|getDownloadURL|${path}`); + const existing = this.state.get(key, undefined); + this.downloadUrl$ = existing ? of(existing) : this.storage.ref(path).getDownloadURL().pipe( + tap(it => this.state.set(key, it)) + ); } return this.asyncPipe.transform(this.downloadUrl$); } From 87f4b1736e3a5e75e8fbd1c1f12088965b52b8c8 Mon Sep 17 00:00:00 2001 From: James Daniels Date: Thu, 26 Nov 2020 04:48:35 -0500 Subject: [PATCH 09/11] Adding storage-lazy --- sample/src/app/app.module.ts | 2 +- sample/src/app/storage/storage.component.ts | 22 +- src/storage-lazy/interfaces.ts | 10 + .../observable/fromTask.ts | 1 + src/storage-lazy/package.json | 12 + .../pipes/storageUrl.pipe.ts | 2 +- src/storage-lazy/public_api.ts | 9 + src/storage-lazy/ref.ts | 51 ++++ src/storage-lazy/storage.module.ts | 9 + src/storage-lazy/storage.spec.ts | 231 ++++++++++++++++++ src/storage-lazy/storage.ts | 96 ++++++++ src/storage-lazy/task.ts | 31 +++ src/storage/public_api.ts | 3 +- src/storage/ref.ts | 2 +- src/storage/storage.module.ts | 2 +- src/storage/storage.ts | 6 +- src/storage/task.ts | 2 +- tools/build.ts | 5 +- 18 files changed, 463 insertions(+), 33 deletions(-) create mode 100644 src/storage-lazy/interfaces.ts rename src/{storage => storage-lazy}/observable/fromTask.ts (95%) create mode 100644 src/storage-lazy/package.json rename src/{storage => storage-lazy}/pipes/storageUrl.pipe.ts (96%) create mode 100644 src/storage-lazy/public_api.ts create mode 100644 src/storage-lazy/ref.ts create mode 100644 src/storage-lazy/storage.module.ts create mode 100644 src/storage-lazy/storage.spec.ts create mode 100644 src/storage-lazy/storage.ts create mode 100644 src/storage-lazy/task.ts diff --git a/sample/src/app/app.module.ts b/sample/src/app/app.module.ts index c1ce6630f..82f530291 100644 --- a/sample/src/app/app.module.ts +++ b/sample/src/app/app.module.ts @@ -21,7 +21,7 @@ import { import { FirestoreComponent } from './firestore/firestore.component'; import { AngularFireDatabaseModule, USE_EMULATOR as USE_DATABASE_EMULATOR } from '@angular/fire/database'; import { USE_EMULATOR as USE_FIRESTORE_EMULATOR, SETTINGS as FIRESTORE_SETTINGS } from '../firestore'; -import { AngularFireStorageModule } from '@angular/fire/storage'; +import { AngularFireStorageModule } from '@angular/fire/storage-lazy'; import { AngularFireAuthModule, USE_DEVICE_LANGUAGE, USE_EMULATOR as USE_AUTH_EMULATOR } from '@angular/fire/auth'; import { AngularFireMessagingModule, SERVICE_WORKER, VAPID_KEY } from '@angular/fire/messaging'; import { AngularFireFunctionsModule, USE_EMULATOR as USE_FUNCTIONS_EMULATOR, ORIGIN as FUNCTIONS_ORIGIN, NEW_ORIGIN_BEHAVIOR } from '@angular/fire/functions'; diff --git a/sample/src/app/storage/storage.component.ts b/sample/src/app/storage/storage.component.ts index 2dc184ef1..5122c1745 100644 --- a/sample/src/app/storage/storage.component.ts +++ b/sample/src/app/storage/storage.component.ts @@ -1,37 +1,19 @@ import { Component, OnInit } from '@angular/core'; -import { AngularFireStorage } from '@angular/fire/storage'; -import { Observable, of } from 'rxjs'; -import { startWith, tap } from 'rxjs/operators'; -import { makeStateKey, TransferState } from '@angular/platform-browser'; -import { trace } from '@angular/fire/performance'; - -const TRANSPARENT_PNG - = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII='; @Component({ selector: 'app-storage', template: `

Storage! - -
{{ 'google-g.png' | getDownloadURL | json }} +

`, styles: [] }) export class StorageComponent implements OnInit { - public readonly downloadUrl$: Observable; - constructor(storage: AngularFireStorage, state: TransferState) { - const icon = storage.ref('google-g.png'); - const key = makeStateKey('google-icon-url'); - const existing = state.get(key, undefined); - this.downloadUrl$ = existing ? of(existing) : icon.getDownloadURL().pipe( - trace('storage'), - tap(it => state.set(key, it)), - startWith(TRANSPARENT_PNG) - ); + constructor() { } ngOnInit(): void { diff --git a/src/storage-lazy/interfaces.ts b/src/storage-lazy/interfaces.ts new file mode 100644 index 000000000..1f1265065 --- /dev/null +++ b/src/storage-lazy/interfaces.ts @@ -0,0 +1,10 @@ +import firebase from 'firebase/app'; + +export type UploadTask = firebase.storage.UploadTask; +export type UploadTaskSnapshot = firebase.storage.UploadTaskSnapshot; +export type UploadMetadata = firebase.storage.UploadMetadata; + +export type SettableMetadata = firebase.storage.SettableMetadata; +export type Reference = firebase.storage.Reference; +export type StringFormat = firebase.storage.StringFormat; +export type ListResult = firebase.storage.ListResult; diff --git a/src/storage/observable/fromTask.ts b/src/storage-lazy/observable/fromTask.ts similarity index 95% rename from src/storage/observable/fromTask.ts rename to src/storage-lazy/observable/fromTask.ts index ae4d8ec94..f93b09d65 100644 --- a/src/storage/observable/fromTask.ts +++ b/src/storage-lazy/observable/fromTask.ts @@ -6,6 +6,7 @@ export function fromTask(task: UploadTask) { const progress = (snap: UploadTaskSnapshot) => subscriber.next(snap); const error = e => subscriber.error(e); const complete = () => subscriber.complete(); + progress(task.snapshot); task.on('state_changed', progress, (e) => { progress(task.snapshot); error(e); diff --git a/src/storage-lazy/package.json b/src/storage-lazy/package.json new file mode 100644 index 000000000..252f86ad2 --- /dev/null +++ b/src/storage-lazy/package.json @@ -0,0 +1,12 @@ +{ + "$schema": "../../node_modules/ng-packagr/package.schema.json", + "ngPackage": { + "lib": { + "entryFile": "public_api.ts", + "umdModuleIds": { + "firebase/app": "firebase", + "@firebase/storage": "firebase-storage" + } + } + } +} diff --git a/src/storage/pipes/storageUrl.pipe.ts b/src/storage-lazy/pipes/storageUrl.pipe.ts similarity index 96% rename from src/storage/pipes/storageUrl.pipe.ts rename to src/storage-lazy/pipes/storageUrl.pipe.ts index 9dafc9eac..03731965f 100644 --- a/src/storage/pipes/storageUrl.pipe.ts +++ b/src/storage-lazy/pipes/storageUrl.pipe.ts @@ -2,7 +2,7 @@ import { AsyncPipe } from '@angular/common'; import { ChangeDetectorRef, NgModule, OnDestroy, Pipe, PipeTransform } from '@angular/core'; import { makeStateKey, TransferState } from '@angular/platform-browser'; import { Observable, of } from 'rxjs'; -import { startWith, tap } from 'rxjs/operators'; +import { tap } from 'rxjs/operators'; import { AngularFireStorage } from '../storage'; /** to be used with in combination with | async */ diff --git a/src/storage-lazy/public_api.ts b/src/storage-lazy/public_api.ts new file mode 100644 index 000000000..33fc87ea1 --- /dev/null +++ b/src/storage-lazy/public_api.ts @@ -0,0 +1,9 @@ + +import 'firebase/storage'; // trimmed out by build script + +export * from './ref'; +export * from './storage'; +export * from './task'; +export * from './observable/fromTask'; +export * from './storage.module'; +export * from './pipes/storageUrl.pipe'; diff --git a/src/storage-lazy/ref.ts b/src/storage-lazy/ref.ts new file mode 100644 index 000000000..c0bc80a71 --- /dev/null +++ b/src/storage-lazy/ref.ts @@ -0,0 +1,51 @@ +import { ListResult, Reference, SettableMetadata, StringFormat, UploadMetadata } from './interfaces'; +import { AngularFireUploadTask, createUploadTask } from './task'; +import { from, Observable, of } from 'rxjs'; +import { ɵAngularFireSchedulers } from '@angular/fire'; +import { map, observeOn, switchMap } from 'rxjs/operators'; + +export interface AngularFireStorageReference { + getDownloadURL(): Observable; + getMetadata(): Observable; + delete(): Observable; + child(path: string): AngularFireStorageReference; + updateMetadata(meta: SettableMetadata): Observable; + put(data: any, metadata?: UploadMetadata | undefined): AngularFireUploadTask; + putString(data: string, format?: string | undefined, metadata?: UploadMetadata | undefined): AngularFireUploadTask; + listAll(): Observable; +} + +/** + * Create an AngularFire wrapped Storage Reference. This object + * creates observable methods from promise based methods. + */ +export function createStorageRef( + ref$: Observable, + schedulers: ɵAngularFireSchedulers, + keepUnstableUntilFirst: (obs$: Observable) => Observable +): AngularFireStorageReference { + return { + getDownloadURL: () => ref$.pipe( + observeOn(schedulers.outsideAngular), + switchMap(ref => ref.getDownloadURL()), + keepUnstableUntilFirst + ), + getMetadata: () => ref$.pipe( + observeOn(schedulers.outsideAngular), + switchMap(ref => ref.getMetadata()), + keepUnstableUntilFirst + ), + delete: () => ref$.pipe(switchMap(ref => ref.delete())), + child: (path: string) => createStorageRef(ref$.pipe(map(ref => ref.child(path))), schedulers, keepUnstableUntilFirst), + updateMetadata: (meta: SettableMetadata) => ref$.pipe(switchMap(ref => ref.updateMetadata(meta))), + put: (data: any, metadata?: UploadMetadata) => { + const task = ref$.pipe(map(ref => ref.put(data, metadata))); + return createUploadTask(task); + }, + putString: (data: string, format?: StringFormat, metadata?: UploadMetadata) => { + const task = ref$.pipe(map(ref => ref.putString(data, format, metadata))); + return createUploadTask(task); + }, + listAll: () => ref$.pipe(switchMap(ref => ref.listAll())) + }; +} diff --git a/src/storage-lazy/storage.module.ts b/src/storage-lazy/storage.module.ts new file mode 100644 index 000000000..c6181645f --- /dev/null +++ b/src/storage-lazy/storage.module.ts @@ -0,0 +1,9 @@ +import { NgModule } from '@angular/core'; +import { GetDownloadURLPipeModule } from './pipes/storageUrl.pipe'; +import { AngularFireStorage } from './storage'; + +@NgModule({ + exports: [ GetDownloadURLPipeModule ], + providers: [ AngularFireStorage ] +}) +export class AngularFireStorageModule { } diff --git a/src/storage-lazy/storage.spec.ts b/src/storage-lazy/storage.spec.ts new file mode 100644 index 000000000..2f11fde08 --- /dev/null +++ b/src/storage-lazy/storage.spec.ts @@ -0,0 +1,231 @@ +import { forkJoin, from } from 'rxjs'; +import { mergeMap, tap } from 'rxjs/operators'; +import { TestBed } from '@angular/core/testing'; +import { AngularFireModule, FIREBASE_APP_NAME, FIREBASE_OPTIONS, FirebaseApp } from '@angular/fire'; +import { AngularFireStorage, AngularFireStorageModule, AngularFireUploadTask, BUCKET } from './public_api'; +import { COMMON_CONFIG } from '../test-config'; +import { rando } from '../firestore/utils.spec'; +import { GetDownloadURLPipe } from './pipes/storageUrl.pipe'; +import { ChangeDetectorRef } from '@angular/core'; +import 'firebase/storage'; + +if (typeof XMLHttpRequest === 'undefined') { + globalThis.XMLHttpRequest = require('xhr2'); +} + +const blobOrBuffer = (data: string, options: {}) => { + if (typeof Blob === 'undefined') { + return Buffer.from(data, 'utf8'); + } else { + return new Blob([JSON.stringify(data)], options); + } +}; + +describe('AngularFireStorage', () => { + let app: FirebaseApp; + let afStorage: AngularFireStorage; + let cdr: ChangeDetectorRef; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + AngularFireModule.initializeApp(COMMON_CONFIG, rando()), + AngularFireStorageModule, + ], + providers: [ + ChangeDetectorRef + ] + }); + + app = TestBed.inject(FirebaseApp); + afStorage = TestBed.inject(AngularFireStorage); + cdr = TestBed.inject(ChangeDetectorRef); + }); + + afterEach(() => { + app.delete(); + }); + + it('should exist', () => { + expect(afStorage instanceof AngularFireStorage).toBe(true); + }); + + it('should have the Firebase storage instance', () => { + expect(afStorage.storage).toBeDefined(); + }); + + it('should have an initialized Firebase app', () => { + expect(afStorage.storage.app).toBeDefined(); + }); + + describe('upload task', () => { + + it('should upload and delete a file', (done) => { + const data = { angular: 'fire' }; + const blob = blobOrBuffer(JSON.stringify(data), { type: 'application/json' }); + const ref = afStorage.ref('af.json'); + const task = ref.put(blob); + task.snapshotChanges() + .subscribe( + snap => { + expect(snap).toBeDefined(); + }, + done.fail, + () => { + ref.delete().subscribe(done, done.fail); + }); + }); + + it('should upload a file and observe the download url', (done) => { + const data = { angular: 'fire' }; + const blob = blobOrBuffer(JSON.stringify(data), { type: 'application/json' }); + const ref = afStorage.ref('af.json'); + ref.put(blob).then(() => { + const url$ = ref.getDownloadURL(); + url$.subscribe( + url => { + expect(url).toBeDefined(); + }, + done.fail, + () => { + ref.delete().subscribe(done, done.fail); + } + ); + }); + }); + + it('should resolve the task as a promise', (done) => { + const data = { angular: 'promise' }; + const blob = blobOrBuffer(JSON.stringify(data), { type: 'application/json' }); + const ref = afStorage.ref('af.json'); + const task: AngularFireUploadTask = ref.put(blob); + task.then(snap => { + expect(snap).toBeDefined(); + done(); + }).catch(done.fail); + }); + + }); + + describe('reference', () => { + + it('it should upload, download, and delete', (done) => { + const data = { angular: 'fire' }; + const blob = blobOrBuffer(JSON.stringify(data), { type: 'application/json' }); + const ref = afStorage.ref('af.json'); + const task = ref.put(blob); + // Wait for the upload + forkJoin([task.snapshotChanges()]) + .pipe( + // get the url download + mergeMap(() => ref.getDownloadURL()), + // assert the URL + tap(url => expect(url).toBeDefined()), + // Delete the file + mergeMap(() => ref.delete()) + ) + // finish the test + .subscribe(done, done.fail); + }); + + it('should upload, get metadata, and delete', (done) => { + const data = { angular: 'fire' }; + const blob = blobOrBuffer(JSON.stringify(data), { type: 'application/json' }); + const ref = afStorage.ref('af.json'); + const task = ref.put(blob, { customMetadata: { blah: 'blah' } }); + // Wait for the upload + forkJoin([task.snapshotChanges()]) + .pipe( + // get the metadata download + mergeMap(() => ref.getMetadata()), + // assert the URL + tap(meta => expect(meta.customMetadata).toEqual({ blah: 'blah' })), + // Delete the file + mergeMap(() => ref.delete()) + ) + // finish the test + .subscribe(done, done.fail); + }); + + }); + +}); + +describe('AngularFireStorage w/options', () => { + let app: FirebaseApp; + let afStorage: AngularFireStorage; + let firebaseAppName: string; + let storageBucket: string; + + beforeEach(() => { + firebaseAppName = rando(); + storageBucket = 'angularfire2-test2'; + TestBed.configureTestingModule({ + imports: [ + AngularFireModule.initializeApp(COMMON_CONFIG, rando()), + AngularFireStorageModule + ], + providers: [ + { provide: FIREBASE_APP_NAME, useValue: firebaseAppName }, + { provide: FIREBASE_OPTIONS, useValue: COMMON_CONFIG }, + { provide: BUCKET, useValue: storageBucket } + ] + }); + + app = TestBed.inject(FirebaseApp); + afStorage = TestBed.inject(AngularFireStorage); + }); + + afterEach(() => { + app.delete(); + }); + + describe('', () => { + + it('should exist', () => { + expect(afStorage instanceof AngularFireStorage).toBe(true); + }); + + it('should have the Firebase storage instance', () => { + expect(afStorage.storage).toBeDefined(); + }); + + it('should have an initialized Firebase app', () => { + expect(afStorage.storage.app).toBeDefined(); + }); + + it('should be hooked up the right app', () => { + expect(afStorage.storage.app.name).toEqual(firebaseAppName); + }); + + it('storage be pointing towards a different bucket', () => { + expect(afStorage.storage.ref().toString()).toEqual(`gs://${storageBucket}/`); + }); + + // TODO tests for Node? + if (typeof Blob !== 'undefined') { + + it('it should upload, download, and delete', (done) => { + const data = { angular: 'fire' }; + const blob = blobOrBuffer(JSON.stringify(data), { type: 'application/json' }); + const ref = afStorage.ref('af.json'); + const task = ref.put(blob); + // Wait for the upload + forkJoin([task.snapshotChanges()]) + .pipe( + // get the url download + mergeMap(() => ref.getDownloadURL()), + // assert the URL + tap(url => expect(url).toMatch(new RegExp(`https:\\/\\/firebasestorage\\.googleapis\\.com\\/v0\\/b\\/${storageBucket}\\/o\\/af\\.json`))), + // Delete the file + mergeMap(() => ref.delete()) + ) + // finish the test + .subscribe(done, done.fail); + }); + + } + + }); + +}); diff --git a/src/storage-lazy/storage.ts b/src/storage-lazy/storage.ts new file mode 100644 index 000000000..47bc48211 --- /dev/null +++ b/src/storage-lazy/storage.ts @@ -0,0 +1,96 @@ +import { Inject, Injectable, InjectionToken, NgZone, Optional, PLATFORM_ID } from '@angular/core'; +import { AngularFireStorageReference, createStorageRef } from './ref'; +import { Observable, of } from 'rxjs'; +import { + FIREBASE_APP_NAME, + FIREBASE_OPTIONS, + FirebaseAppConfig, + FirebaseOptions, + ɵAngularFireSchedulers, + ɵfetchInstance, + ɵfirebaseAppFactory, + ɵkeepUnstableUntilFirstFactory, + ɵlazySDKProxy, + ɵapplyMixins, + ɵPromiseProxy +} from '@angular/fire'; +import { UploadMetadata } from './interfaces'; +import firebase from 'firebase/app'; +import { map, observeOn, switchMap } from 'rxjs/operators'; +import { AngularFireUploadTask } from './task'; +import { proxyPolyfillCompat } from './base'; + +export const BUCKET = new InjectionToken('angularfire2.storageBucket'); +export const MAX_UPLOAD_RETRY_TIME = new InjectionToken('angularfire2.storage.maxUploadRetryTime'); +export const MAX_OPERATION_RETRY_TIME = new InjectionToken('angularfire2.storage.maxOperationRetryTime'); + +export interface AngularFireStorage extends Omit<ɵPromiseProxy, 'ref' | 'refFromURL'> {} + +/** + * AngularFireStorage Service + * + * This service is the main entry point for this feature module. It provides + * an API for uploading and downloading binary files from Cloud Storage for + * Firebase. + */ +@Injectable({ + providedIn: 'any' +}) +export class AngularFireStorage { + + public readonly keepUnstableUntilFirst: (obs: Observable) => Observable; + public readonly schedulers: ɵAngularFireSchedulers; + + public readonly ref: (path: string) => AngularFireStorageReference; + public readonly refFromURL: (url: string) => AngularFireStorageReference; + public readonly upload: (path: string, data: any, metadata?: UploadMetadata) => AngularFireUploadTask; + + constructor( + @Inject(FIREBASE_OPTIONS) options: FirebaseOptions, + @Optional() @Inject(FIREBASE_APP_NAME) nameOrConfig: string | FirebaseAppConfig | null | undefined, + @Optional() @Inject(BUCKET) storageBucket: string | null, + // tslint:disable-next-line:ban-types + @Inject(PLATFORM_ID) platformId: Object, + zone: NgZone, + @Optional() @Inject(MAX_UPLOAD_RETRY_TIME) maxUploadRetryTime: number | any, + @Optional() @Inject(MAX_OPERATION_RETRY_TIME) maxOperationRetryTime: number | any, + ) { + this.schedulers = new ɵAngularFireSchedulers(zone); + this.keepUnstableUntilFirst = ɵkeepUnstableUntilFirstFactory(this.schedulers); + + const storage = of(undefined).pipe( + observeOn(this.schedulers.outsideAngular), + switchMap(() => zone.runOutsideAngular(() => import('firebase/storage'))), + map(() => ɵfirebaseAppFactory(options, zone, nameOrConfig)), + map(app => + ɵfetchInstance(`${app.name}.storage.${storageBucket}`, 'AngularFireStorage', app, () => { + const storage = zone.runOutsideAngular(() => app.storage(storageBucket || undefined)); + if (maxUploadRetryTime) { + storage.setMaxUploadRetryTime(maxUploadRetryTime); + } + if (maxOperationRetryTime) { + storage.setMaxOperationRetryTime(maxOperationRetryTime); + } + return storage; + }, [maxUploadRetryTime, maxOperationRetryTime]) + ) + ); + + this.ref = (path) => createStorageRef(storage.pipe(map(it => it.ref(path))), this.schedulers, this.keepUnstableUntilFirst); + + this.refFromURL = (path) => + createStorageRef(storage.pipe(map(it => it.refFromURL(path))), this.schedulers, this.keepUnstableUntilFirst); + + this.upload = (path, data, metadata?) => { + const storageRef = storage.pipe(map(it => it.ref(path))); + const ref = createStorageRef(storageRef, this.schedulers, this.keepUnstableUntilFirst); + return ref.put(data, metadata); + }; + + return ɵlazySDKProxy(this, storage, zone); + + } + +} + +ɵapplyMixins(AngularFireStorage, [proxyPolyfillCompat]); diff --git a/src/storage-lazy/task.ts b/src/storage-lazy/task.ts new file mode 100644 index 000000000..e66ef8534 --- /dev/null +++ b/src/storage-lazy/task.ts @@ -0,0 +1,31 @@ +import { UploadTask, UploadTaskSnapshot } from './interfaces'; +import { fromTask } from './observable/fromTask'; +import { Observable } from 'rxjs'; +import { map, shareReplay, switchMap } from 'rxjs/operators'; + +export interface AngularFireUploadTask { + snapshot: Observable; + progress: Observable; + pause(): Promise; + cancel(): Promise; + resume(): Promise; +} + +/** + * Create an AngularFireUploadTask from a regular UploadTask from the Storage SDK. + * This method creates an observable of the upload and returns on object that provides + * multiple methods for controlling and monitoring the file upload. + */ +export function createUploadTask(task: Observable): AngularFireUploadTask { + const task$ = task.pipe(shareReplay({ refCount: false, bufferSize: 1 })); + const snapshot = task.pipe(switchMap(fromTask)); + return { + pause: () => task$.toPromise().then(it => it.pause()), + cancel: () => task$.toPromise().then(it => it.cancel()), + resume: () => task$.toPromise().then(it => it.resume()), + snapshot, + progress: snapshot.pipe( + map(s => s.bytesTransferred / s.totalBytes * 100) + ) + }; +} diff --git a/src/storage/public_api.ts b/src/storage/public_api.ts index 460348fa1..cdbe823ef 100644 --- a/src/storage/public_api.ts +++ b/src/storage/public_api.ts @@ -1,6 +1,5 @@ export * from './ref'; export * from './storage'; export * from './task'; -export * from './observable/fromTask'; export * from './storage.module'; -export * from './pipes/storageUrl.pipe'; +export { GetDownloadURLPipe, fromTask } from '@angular/fire/storage-lazy'; diff --git a/src/storage/ref.ts b/src/storage/ref.ts index 06ef4862c..300c7666b 100644 --- a/src/storage/ref.ts +++ b/src/storage/ref.ts @@ -8,7 +8,7 @@ export interface AngularFireStorageReference { getDownloadURL(): Observable; getMetadata(): Observable; delete(): Observable; - child(path: string): any; + child(path: string): AngularFireStorageReference; updateMetadata(meta: SettableMetadata): Observable; put(data: any, metadata?: UploadMetadata | undefined): AngularFireUploadTask; putString(data: string, format?: string | undefined, metadata?: UploadMetadata | undefined): AngularFireUploadTask; diff --git a/src/storage/storage.module.ts b/src/storage/storage.module.ts index c6181645f..e9d75d7e9 100644 --- a/src/storage/storage.module.ts +++ b/src/storage/storage.module.ts @@ -1,5 +1,5 @@ import { NgModule } from '@angular/core'; -import { GetDownloadURLPipeModule } from './pipes/storageUrl.pipe'; +import { GetDownloadURLPipeModule } from '@angular/fire/storage-lazy'; import { AngularFireStorage } from './storage'; @NgModule({ diff --git a/src/storage/storage.ts b/src/storage/storage.ts index e5e906acf..85f96df32 100644 --- a/src/storage/storage.ts +++ b/src/storage/storage.ts @@ -14,10 +14,8 @@ import { import { UploadMetadata } from './interfaces'; import 'firebase/storage'; import firebase from 'firebase/app'; - -export const BUCKET = new InjectionToken('angularfire2.storageBucket'); -export const MAX_UPLOAD_RETRY_TIME = new InjectionToken('angularfire2.storage.maxUploadRetryTime'); -export const MAX_OPERATION_RETRY_TIME = new InjectionToken('angularfire2.storage.maxOperationRetryTime'); +import { BUCKET, MAX_UPLOAD_RETRY_TIME, MAX_OPERATION_RETRY_TIME } from '@angular/fire/storage-lazy'; +export { BUCKET, MAX_UPLOAD_RETRY_TIME, MAX_OPERATION_RETRY_TIME }; /** * AngularFireStorage Service diff --git a/src/storage/task.ts b/src/storage/task.ts index bccc7154c..3587dff1e 100644 --- a/src/storage/task.ts +++ b/src/storage/task.ts @@ -1,5 +1,5 @@ import { UploadTask, UploadTaskSnapshot } from './interfaces'; -import { fromTask } from './observable/fromTask'; +import { fromTask } from '@angular/fire/storage-lazy'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; diff --git a/tools/build.ts b/tools/build.ts index cea1d7d64..13ac9063c 100644 --- a/tools/build.ts +++ b/tools/build.ts @@ -10,9 +10,9 @@ import firebase from 'firebase/app'; const MODULES = [ 'core', 'analytics', 'auth', 'auth-guard', 'database', 'firestore', 'firestore-lazy', 'functions', 'remote-config', - 'storage', 'messaging', 'performance' + 'storage', 'messaging', 'performance', 'storage-lazy' ]; -const LAZY_MODULES = [['analytics'], ['auth'], ['functions'], ['firestore-lazy', 'firestore'], ['messaging'], ['remote-config']]; +const LAZY_MODULES = [['analytics'], ['auth'], ['functions'], ['firestore-lazy', 'firestore'], ['messaging'], ['remote-config'], ['storage-lazy', 'storage']]; const UMD_NAMES = MODULES.map(m => m === 'core' ? 'angular-fire' : `angular-fire-${m}`); const ENTRY_NAMES = MODULES.map(m => m === 'core' ? '@angular/fire' : `@angular/fire/${m}`); @@ -25,6 +25,7 @@ function proxyPolyfillCompat() { performance: tsKeys(), 'remote-config': tsKeys(), 'firestore-lazy': tsKeys(), + 'storage-lazy': tsKeys(), }; return Promise.all(Object.keys(defaultObject).map(module => From dbf06a181565f87433782fd24be90e76b814c602 Mon Sep 17 00:00:00 2001 From: James Daniels Date: Thu, 26 Nov 2020 06:55:40 -0500 Subject: [PATCH 10/11] Lazy-database and cleanup --- sample/package.json | 2 + sample/src/app/app.component.ts | 8 +- sample/src/app/app.module.ts | 2 +- sample/src/app/database/database.component.ts | 5 +- sample/src/app/storage/storage.component.ts | 2 +- sample/yarn.lock | 19 ++ src/database-lazy/database.module.ts | 7 + src/database-lazy/database.spec.ts | 121 ++++++++ src/database-lazy/database.ts | 118 ++++++++ src/database-lazy/interfaces.ts | 71 +++++ src/database-lazy/list/audit-trail.spec.ts | 64 +++++ src/database-lazy/list/audit-trail.ts | 62 ++++ src/database-lazy/list/changes.spec.ts | 146 ++++++++++ src/database-lazy/list/changes.ts | 90 ++++++ src/database-lazy/list/create-reference.ts | 54 ++++ src/database-lazy/list/data-operation.ts | 15 + src/database-lazy/list/remove.ts | 17 ++ .../list/snapshot-changes.spec.ts | 142 +++++++++ src/database-lazy/list/snapshot-changes.ts | 13 + src/database-lazy/list/state-changes.spec.ts | 64 +++++ src/database-lazy/list/state-changes.ts | 10 + src/database-lazy/list/utils.ts | 8 + src/database-lazy/object/create-reference.ts | 23 ++ src/database-lazy/object/snapshot-changes.ts | 9 + src/database-lazy/observable/fromRef.spec.ts | 271 ++++++++++++++++++ src/database-lazy/observable/fromRef.ts | 60 ++++ src/database-lazy/package.json | 12 + src/database-lazy/public_api.ts | 11 + src/database-lazy/utils.spec.ts | 26 ++ src/database-lazy/utils.ts | 41 +++ tools/build.ts | 6 +- 31 files changed, 1490 insertions(+), 9 deletions(-) create mode 100644 src/database-lazy/database.module.ts create mode 100644 src/database-lazy/database.spec.ts create mode 100644 src/database-lazy/database.ts create mode 100644 src/database-lazy/interfaces.ts create mode 100644 src/database-lazy/list/audit-trail.spec.ts create mode 100644 src/database-lazy/list/audit-trail.ts create mode 100644 src/database-lazy/list/changes.spec.ts create mode 100644 src/database-lazy/list/changes.ts create mode 100644 src/database-lazy/list/create-reference.ts create mode 100644 src/database-lazy/list/data-operation.ts create mode 100644 src/database-lazy/list/remove.ts create mode 100644 src/database-lazy/list/snapshot-changes.spec.ts create mode 100644 src/database-lazy/list/snapshot-changes.ts create mode 100644 src/database-lazy/list/state-changes.spec.ts create mode 100644 src/database-lazy/list/state-changes.ts create mode 100644 src/database-lazy/list/utils.ts create mode 100644 src/database-lazy/object/create-reference.ts create mode 100644 src/database-lazy/object/snapshot-changes.ts create mode 100644 src/database-lazy/observable/fromRef.spec.ts create mode 100644 src/database-lazy/observable/fromRef.ts create mode 100644 src/database-lazy/package.json create mode 100644 src/database-lazy/public_api.ts create mode 100644 src/database-lazy/utils.spec.ts create mode 100644 src/database-lazy/utils.ts diff --git a/sample/package.json b/sample/package.json index bc0b2860f..a42aa2b2e 100644 --- a/sample/package.json +++ b/sample/package.json @@ -46,6 +46,8 @@ "@angular/language-service": "~11.0.0", "@firebase/app-types": "^0.6.1", "@nguniversal/builders": "^10.1.0", + "@types/express": "^4.17.9", + "@types/express-serve-static-core": "^4.17.14", "@types/jasmine": "~3.5.0", "@types/jasminewd2": "~2.0.3", "codelyzer": "^6.0.0", diff --git a/sample/src/app/app.component.ts b/sample/src/app/app.component.ts index 250f33e56..7869cf5df 100644 --- a/sample/src/app/app.component.ts +++ b/sample/src/app/app.component.ts @@ -1,5 +1,6 @@ -import { ApplicationRef, Component, isDevMode } from '@angular/core'; +import { ApplicationRef, Component, Inject, isDevMode, Optional } from '@angular/core'; import { FirebaseApp } from '@angular/fire'; +import { RESPONSE } from '@nguniversal/express-engine/tokens'; @Component({ selector: 'app-root', @@ -24,9 +25,12 @@ import { FirebaseApp } from '@angular/fire'; styles: [``] }) export class AppComponent { - constructor(public readonly firebaseApp: FirebaseApp, appRef: ApplicationRef) { + constructor(public readonly firebaseApp: FirebaseApp, appRef: ApplicationRef, @Optional() @Inject(RESPONSE) response: any) { if (isDevMode()) { appRef.isStable.subscribe(it => console.log('isStable', it)); } + if (response) { + response.setHeader('Cache-Control', 'public, max-age=600'); + } } } diff --git a/sample/src/app/app.module.ts b/sample/src/app/app.module.ts index 82f530291..0f6e34f93 100644 --- a/sample/src/app/app.module.ts +++ b/sample/src/app/app.module.ts @@ -19,7 +19,7 @@ import { } from '@angular/fire/analytics'; import { FirestoreComponent } from './firestore/firestore.component'; -import { AngularFireDatabaseModule, USE_EMULATOR as USE_DATABASE_EMULATOR } from '@angular/fire/database'; +import { AngularFireDatabaseModule, USE_EMULATOR as USE_DATABASE_EMULATOR } from '@angular/fire/database-lazy'; import { USE_EMULATOR as USE_FIRESTORE_EMULATOR, SETTINGS as FIRESTORE_SETTINGS } from '../firestore'; import { AngularFireStorageModule } from '@angular/fire/storage-lazy'; import { AngularFireAuthModule, USE_DEVICE_LANGUAGE, USE_EMULATOR as USE_AUTH_EMULATOR } from '@angular/fire/auth'; diff --git a/sample/src/app/database/database.component.ts b/sample/src/app/database/database.component.ts index cf1955a60..c91bbea8c 100644 --- a/sample/src/app/database/database.component.ts +++ b/sample/src/app/database/database.component.ts @@ -1,10 +1,9 @@ import { Component, Inject, OnInit, PLATFORM_ID } from '@angular/core'; -import { AngularFireDatabase } from '@angular/fire/database'; -import { EMPTY, Observable } from 'rxjs'; +import { AngularFireDatabase } from '@angular/fire/database-lazy'; +import { Observable } from 'rxjs'; import { makeStateKey, TransferState } from '@angular/platform-browser'; import { startWith, tap } from 'rxjs/operators'; import { trace } from '@angular/fire/performance'; -import { isPlatformServer } from '@angular/common'; @Component({ selector: 'app-database', diff --git a/sample/src/app/storage/storage.component.ts b/sample/src/app/storage/storage.component.ts index 5122c1745..5f8706a14 100644 --- a/sample/src/app/storage/storage.component.ts +++ b/sample/src/app/storage/storage.component.ts @@ -5,7 +5,7 @@ import { Component, OnInit } from '@angular/core'; template: `

Storage! - +

`, styles: [] diff --git a/sample/yarn.lock b/sample/yarn.lock index 68d3ad3eb..23465e6c4 100644 --- a/sample/yarn.lock +++ b/sample/yarn.lock @@ -1758,6 +1758,15 @@ "@types/qs" "*" "@types/range-parser" "*" +"@types/express-serve-static-core@^4.17.14": + version "4.17.14" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.14.tgz#cabf91debeeb3cb04b798e2cff908864e89b6106" + integrity sha512-uFTLwu94TfUFMToXNgRZikwPuZdOtDgs3syBtAIr/OXorL1kJqUJT9qCLnRZ5KBOWfZQikQ2xKgR2tnDj1OgDA== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + "@types/express@4.17.3": version "4.17.3" resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.3.tgz#38e4458ce2067873b09a73908df488870c303bd9" @@ -1767,6 +1776,16 @@ "@types/express-serve-static-core" "*" "@types/serve-static" "*" +"@types/express@^4.17.9": + version "4.17.9" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.9.tgz#f5f2df6add703ff28428add52bdec8a1091b0a78" + integrity sha512-SDzEIZInC4sivGIFY4Sz1GG6J9UObPwCInYJjko2jzOf/Imx/dlpume6Xxwj1ORL82tBbmN4cPDIDkLbWHk9hw== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "*" + "@types/qs" "*" + "@types/serve-static" "*" + "@types/fs-extra@^8.0.1": version "8.1.1" resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-8.1.1.tgz#1e49f22d09aa46e19b51c0b013cb63d0d923a068" diff --git a/src/database-lazy/database.module.ts b/src/database-lazy/database.module.ts new file mode 100644 index 000000000..ea183f8ec --- /dev/null +++ b/src/database-lazy/database.module.ts @@ -0,0 +1,7 @@ +import { NgModule } from '@angular/core'; +import { AngularFireDatabase } from './database'; + +@NgModule({ + providers: [ AngularFireDatabase ] +}) +export class AngularFireDatabaseModule { } diff --git a/src/database-lazy/database.spec.ts b/src/database-lazy/database.spec.ts new file mode 100644 index 000000000..3ec1c7ea9 --- /dev/null +++ b/src/database-lazy/database.spec.ts @@ -0,0 +1,121 @@ +import { AngularFireModule, FIREBASE_APP_NAME, FIREBASE_OPTIONS, FirebaseApp } from '@angular/fire'; +import { AngularFireDatabase, AngularFireDatabaseModule, URL } from './public_api'; +import { TestBed } from '@angular/core/testing'; +import { COMMON_CONFIG } from '../test-config'; +import { NgZone } from '@angular/core'; +import 'firebase/database'; +import { rando } from '../firestore/utils.spec'; + +describe('AngularFireDatabase', () => { + let app: FirebaseApp; + let db: AngularFireDatabase; + let zone: NgZone; + let firebaseAppName: string; + + beforeEach(() => { + firebaseAppName = rando(); + TestBed.configureTestingModule({ + imports: [ + AngularFireModule.initializeApp(COMMON_CONFIG, firebaseAppName), + AngularFireDatabaseModule + ], + providers: [ + { provide: URL, useValue: 'http://localhost:9000' } + ] + }); + + app = TestBed.inject(FirebaseApp); + db = TestBed.inject(AngularFireDatabase); + zone = TestBed.inject(NgZone); + }); + + afterEach(() => { + app.delete(); + }); + + describe('', () => { + + it('should be an AngularFireDatabase type', () => { + expect(db instanceof AngularFireDatabase).toEqual(true); + }); + + it('should have an initialized Firebase app', () => { + expect(db.database.app).toBeDefined(); + }); + + it('should accept a Firebase App in the constructor', (done) => { + const database = new AngularFireDatabase(app.options, rando(), undefined, {}, zone, undefined, undefined); + expect(database instanceof AngularFireDatabase).toEqual(true); + database.database.app.delete().then(done, done); + }); + + it('should have an initialized Firebase app instance member', () => { + expect(db.database.app.name).toEqual(firebaseAppName); + }); + + }); + +}); + +describe('AngularFireDatabase w/options', () => { + let app: FirebaseApp; + let db: AngularFireDatabase; + let firebaseAppName: string; + let url: string; + let query: string; + + beforeEach(() => { + query = rando(); + firebaseAppName = rando(); + url = `http://localhost:${Math.floor(Math.random() * 9999)}`; + TestBed.configureTestingModule({ + imports: [ + AngularFireModule.initializeApp(COMMON_CONFIG, rando()), + AngularFireDatabaseModule + ], + providers: [ + { provide: FIREBASE_APP_NAME, useValue: firebaseAppName }, + { provide: FIREBASE_OPTIONS, useValue: COMMON_CONFIG }, + { provide: URL, useValue: url } + ] + }); + + app = TestBed.inject(FirebaseApp); + db = TestBed.inject(AngularFireDatabase); + }); + + afterEach(() => { + app.delete(); + }); + + describe('', () => { + + it('should be an AngularFireDatabase type', () => { + expect(db instanceof AngularFireDatabase).toEqual(true); + }); + + it('should have an initialized Firebase app', () => { + expect(db.database.app).toBeDefined(); + }); + + it('should have an initialized Firebase app instance member', () => { + expect(db.database.app.name).toEqual(firebaseAppName); + }); + + /* INVESTIGATE database(url) does not seem to be working + + it('database be pointing to the provided DB instance', () => { + expect(db.database.ref().toString()).toEqual(url); + }); + + it('list should be using the provided DB instance', () => { + expect(db.list(query).query.toString()).toEqual(`${url}/${query}`); + }); + + it('object should be using the provided DB instance', () => { + expect(db.object(query).query.toString()).toEqual(`${url}/${query}`); + }); + */ + }); + +}); diff --git a/src/database-lazy/database.ts b/src/database-lazy/database.ts new file mode 100644 index 000000000..1567e4271 --- /dev/null +++ b/src/database-lazy/database.ts @@ -0,0 +1,118 @@ +import { Inject, Injectable, InjectionToken, NgZone, Optional, PLATFORM_ID } from '@angular/core'; +import { AngularFireList, AngularFireObject, PathReference, QueryFn } from './interfaces'; +import { getRef } from './utils'; +import { createListReference } from './list/create-reference'; +import { createObjectReference } from './object/create-reference'; +import { + FIREBASE_APP_NAME, + FIREBASE_OPTIONS, + FirebaseAppConfig, + FirebaseOptions, + ɵAngularFireSchedulers, + ɵfirebaseAppFactory, + ɵkeepUnstableUntilFirstFactory, + ɵlazySDKProxy, + ɵapplyMixins, + ɵPromiseProxy, +} from '@angular/fire'; +import { Observable, of } from 'rxjs'; +import { USE_EMULATOR as USE_AUTH_EMULATOR } from '@angular/fire/auth'; +import { ɵfetchInstance } from '@angular/fire'; +import { map, observeOn, switchMap } from 'rxjs/operators'; +import { proxyPolyfillCompat } from './base'; +import firebase from 'firebase/app'; + +export const URL = new InjectionToken('angularfire2.realtimeDatabaseURL'); + +// SEMVER(7): use Parameters to detirmine the useEmulator arguments +// TODO(jamesdaniels): don't hardcode, but having tyepscript issues with firebase.database.Database +// type UseEmulatorArguments = Parameters; +type UseEmulatorArguments = [string, number]; +export const USE_EMULATOR = new InjectionToken('angularfire2.database.use-emulator'); + + +export interface AngularFireDatabase extends ɵPromiseProxy {} + +@Injectable({ + providedIn: 'any' +}) +export class AngularFireDatabase { + + public readonly schedulers: ɵAngularFireSchedulers; + public readonly keepUnstableUntilFirst: (obs$: Observable) => Observable; + + public readonly list: (pathOrRef: PathReference, queryFn?: QueryFn) => AngularFireList; + public readonly object: (pathOrRef: PathReference) => AngularFireObject; + public readonly createPushId: () => Promise; + + constructor( + @Inject(FIREBASE_OPTIONS) options: FirebaseOptions, + @Optional() @Inject(FIREBASE_APP_NAME) nameOrConfig: string | FirebaseAppConfig | null | undefined, + @Optional() @Inject(URL) databaseURL: string | null, + // tslint:disable-next-line:ban-types + @Inject(PLATFORM_ID) platformId: Object, + zone: NgZone, + @Optional() @Inject(USE_EMULATOR) _useEmulator: any, // tuple isn't working here + @Optional() @Inject(USE_AUTH_EMULATOR) useAuthEmulator: any, + ) { + this.schedulers = new ɵAngularFireSchedulers(zone); + this.keepUnstableUntilFirst = ɵkeepUnstableUntilFirstFactory(this.schedulers); + + const useEmulator: UseEmulatorArguments | null = _useEmulator; + + const database$ = of(undefined).pipe( + observeOn(this.schedulers.outsideAngular), + switchMap(() => zone.runOutsideAngular(() => import('firebase/database'))), + map(() => ɵfirebaseAppFactory(options, zone, nameOrConfig)), + map(app => + ɵfetchInstance(`${app.name}.database.${databaseURL}`, 'AngularFireDatabase', app, () => { + const database = zone.runOutsideAngular(() => app.database(databaseURL || undefined)); + if (useEmulator) { + database.useEmulator(...useEmulator); + } + return database; + }, [useEmulator]) + ) + ); + + this.list = (pathOrRef: PathReference, queryFn: QueryFn = ((fn) => fn)) => { + const query$ = database$.pipe(map(database => { + const ref = this.schedulers.ngZone.runOutsideAngular(() => getRef(database, pathOrRef)); + return queryFn(ref); + })); + return createListReference(query$, this); + }; + + this.object = (pathOrRef: PathReference) => { + const ref$ = database$.pipe(map(database => + this.schedulers.ngZone.runOutsideAngular(() => getRef(database, pathOrRef)) + )); + return createObjectReference(ref$, this); + }; + + this.createPushId = () => database$.pipe( + map(database => this.schedulers.ngZone.runOutsideAngular(() => database.ref())), + map(ref => ref.push().key), + ).toPromise(); + + return ɵlazySDKProxy(this, database$, zone); + + } + +} + +ɵapplyMixins(AngularFireDatabase, [proxyPolyfillCompat]); + + +export { + PathReference, + DatabaseSnapshot, + ChildEvent, + ListenEvent, + QueryFn, + AngularFireList, + AngularFireObject, + AngularFireAction, + Action, + SnapshotAction +} from './interfaces'; diff --git a/src/database-lazy/interfaces.ts b/src/database-lazy/interfaces.ts new file mode 100644 index 000000000..d7a85b93b --- /dev/null +++ b/src/database-lazy/interfaces.ts @@ -0,0 +1,71 @@ +import { Observable } from 'rxjs'; +import firebase from 'firebase/app'; + +export type FirebaseOperation = string | firebase.database.Reference | firebase.database.DataSnapshot; + +export interface AngularFireList { + query: Promise; + valueChanges(events?: ChildEvent[], options?: {}): Observable; + valueChanges(events?: ChildEvent[], options?: {idField: K}): Observable<(T & {[T in K]?: string})[]>; + snapshotChanges(events?: ChildEvent[]): Observable[]>; + stateChanges(events?: ChildEvent[]): Observable>; + auditTrail(events?: ChildEvent[]): Observable[]>; + update(item: FirebaseOperation, data: Partial): Promise; + set(item: FirebaseOperation, data: T): Promise; + push(data: T): Observable; + remove(item?: FirebaseOperation): Promise; +} + +export interface AngularFireObject { + query: Promise; + valueChanges(): Observable; + snapshotChanges(): Observable>; + update(data: Partial): Promise; + set(data: T): Promise; + remove(): Promise; +} + +export interface FirebaseOperationCases { + stringCase: () => Promise; + firebaseCase?: () => Promise; + snapshotCase?: () => Promise; + unwrappedSnapshotCase?: () => Promise; +} + +export type QueryFn = (ref: DatabaseReference) => DatabaseQuery; +export type ChildEvent = 'child_added' | 'child_removed' | 'child_changed' | 'child_moved'; +export type ListenEvent = 'value' | ChildEvent; + +export interface Action { + type: ListenEvent; + payload: T; +} + +export interface AngularFireAction extends Action { + prevKey: string | null | undefined; + key: string | null; +} + +export type SnapshotAction = AngularFireAction>; + +export type Primitive = number | string | boolean; + +export interface DatabaseSnapshotExists extends firebase.database.DataSnapshot { + exists(): true; + val(): T; + forEach(action: (a: DatabaseSnapshot) => boolean): boolean; +} + +export interface DatabaseSnapshotDoesNotExist extends firebase.database.DataSnapshot { + exists(): false; + val(): null; + forEach(action: (a: DatabaseSnapshot) => boolean): boolean; +} + +export type DatabaseSnapshot = DatabaseSnapshotExists | DatabaseSnapshotDoesNotExist; + +export type DatabaseReference = firebase.database.Reference; +export type DatabaseQuery = firebase.database.Query; +export type DataSnapshot = firebase.database.DataSnapshot; +export type QueryReference = DatabaseReference | DatabaseQuery; +export type PathReference = QueryReference | string; diff --git a/src/database-lazy/list/audit-trail.spec.ts b/src/database-lazy/list/audit-trail.spec.ts new file mode 100644 index 000000000..c866417a5 --- /dev/null +++ b/src/database-lazy/list/audit-trail.spec.ts @@ -0,0 +1,64 @@ +import { DatabaseReference } from '../interfaces'; +import { AngularFireModule, FirebaseApp } from '@angular/fire'; +import { AngularFireDatabase, AngularFireDatabaseModule, auditTrail, ChildEvent, URL } from '../public_api'; +import { TestBed } from '@angular/core/testing'; +import { COMMON_CONFIG } from '../../test-config'; +import { skip } from 'rxjs/operators'; +import 'firebase/database'; +import { rando } from '../../firestore/utils.spec'; + +describe('auditTrail', () => { + let app: FirebaseApp; + let db: AngularFireDatabase; + let createRef: (path: string) => DatabaseReference; + let batch = {}; + const items = [{ name: 'zero' }, { name: 'one' }, { name: 'two' }].map((item, i) => ({ key: i.toString(), ...item })); + Object.keys(items).forEach((key, i) => { + batch[i] = items[key]; + }); + // make batch immutable to preserve integrity + batch = Object.freeze(batch); + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + AngularFireModule.initializeApp(COMMON_CONFIG, rando()), + AngularFireDatabaseModule + ], + providers: [ + { provide: URL, useValue: 'http://localhost:9000' } + ] + }); + + app = TestBed.inject(FirebaseApp); + db = TestBed.inject(AngularFireDatabase); + createRef = (path: string) => db.database.ref(path); + }); + + afterEach(() => { + app.delete(); + }); + + function prepareAuditTrail(opts: { events?: ChildEvent[], skipnumber: number } = { skipnumber: 0 }) { + const { events, skipnumber } = opts; + const aref = createRef(rando()); + aref.set(batch); + const changes = auditTrail(aref, events); + return { + changes: changes.pipe(skip(skipnumber)), + ref: aref + }; + } + + it('should listen to all events by default', (done) => { + + const { changes } = prepareAuditTrail(); + changes.subscribe(actions => { + const data = actions.map(a => a.payload.val()); + expect(data).toEqual(items); + done(); + }); + + }); + +}); diff --git a/src/database-lazy/list/audit-trail.ts b/src/database-lazy/list/audit-trail.ts new file mode 100644 index 000000000..1ead7342b --- /dev/null +++ b/src/database-lazy/list/audit-trail.ts @@ -0,0 +1,62 @@ +import { AngularFireAction, ChildEvent, DatabaseQuery, DataSnapshot, SnapshotAction } from '../interfaces'; +import { stateChanges } from './state-changes'; +import { Observable, SchedulerLike } from 'rxjs'; +import { fromRef } from '../observable/fromRef'; + +import { map, scan, skipWhile, withLatestFrom } from 'rxjs/operators'; + +export function auditTrail(query: DatabaseQuery, events?: ChildEvent[], scheduler?: SchedulerLike): Observable[]> { + const auditTrail$ = stateChanges(query, events) + .pipe( + scan((current, action) => [...current, action], []) + ); + return waitForLoaded(query, auditTrail$, scheduler); +} + +interface LoadedMetadata { + data: AngularFireAction; + lastKeyToLoad: any; +} + +function loadedData(query: DatabaseQuery, scheduler?: SchedulerLike): Observable { + // Create an observable of loaded values to retrieve the + // known dataset. This will allow us to know what key to + // emit the "whole" array at when listening for child events. + return fromRef(query, 'value', 'on', scheduler) + .pipe( + map(data => { + // Store the last key in the data set + let lastKeyToLoad; + // Loop through loaded dataset to find the last key + data.payload.forEach(child => { + lastKeyToLoad = child.key; return false; + }); + // return data set and the current last key loaded + return { data, lastKeyToLoad }; + }) + ); +} + +function waitForLoaded(query: DatabaseQuery, action$: Observable[]>, scheduler?: SchedulerLike) { + const loaded$ = loadedData(query, scheduler); + return loaded$ + .pipe( + withLatestFrom(action$), + // Get the latest values from the "loaded" and "child" datasets + // We can use both datasets to form an array of the latest values. + map(([loaded, actions]) => { + // Store the last key in the data set + const lastKeyToLoad = loaded.lastKeyToLoad; + // Store all child keys loaded at this point + const loadedKeys = actions.map(snap => snap.key); + return { actions, lastKeyToLoad, loadedKeys }; + }), + // This is the magical part, only emit when the last load key + // in the dataset has been loaded by a child event. At this point + // we can assume the dataset is "whole". + skipWhile(meta => meta.loadedKeys.indexOf(meta.lastKeyToLoad) === -1), + // Pluck off the meta data because the user only cares + // to iterate through the snapshots + map(meta => meta.actions) + ); +} diff --git a/src/database-lazy/list/changes.spec.ts b/src/database-lazy/list/changes.spec.ts new file mode 100644 index 000000000..ae87b837f --- /dev/null +++ b/src/database-lazy/list/changes.spec.ts @@ -0,0 +1,146 @@ +import firebase from 'firebase/app'; +import { AngularFireModule, FirebaseApp } from '@angular/fire'; +import { AngularFireDatabase, AngularFireDatabaseModule, listChanges, URL } from '../public_api'; +import { TestBed } from '@angular/core/testing'; +import { COMMON_CONFIG } from '../../test-config'; +import { skip, take } from 'rxjs/operators'; +import 'firebase/database'; +import { rando } from '../../firestore/utils.spec'; + +describe('listChanges', () => { + let app: FirebaseApp; + let db: AngularFireDatabase; + let ref: (path: string) => firebase.database.Reference; + let batch = {}; + const items = [{ name: 'zero' }, { name: 'one' }, { name: 'two' }].map((item, i) => ({ key: i.toString(), ...item })); + Object.keys(items).forEach((key, i) => { + batch[i] = items[key]; + }); + // make batch immutable to preserve integrity + batch = Object.freeze(batch); + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + AngularFireModule.initializeApp(COMMON_CONFIG, rando()), + AngularFireDatabaseModule + ], + providers: [ + { provide: URL, useValue: 'http://localhost:9000' } + ] + }); + + app = TestBed.inject(FirebaseApp); + db = TestBed.inject(AngularFireDatabase); + ref = (path: string) => db.database.ref(path); + }); + + afterEach(() => { + app.delete(); + }); + + describe('events', () => { + + it('should stream value at first', (done) => { + const someRef = ref(rando()); + const obs = listChanges(someRef, ['child_added']); + obs.pipe(take(1)).subscribe(changes => { + const data = changes.map(change => change.payload.val()); + expect(data).toEqual(items); + }).add(done); + someRef.set(batch); + }); + + it('should process a new child_added event', done => { + const aref = ref(rando()); + const obs = listChanges(aref, ['child_added']); + obs.pipe(skip(1), take(1)).subscribe(changes => { + const data = changes.map(change => change.payload.val()); + expect(data[3]).toEqual({ name: 'anotha one' }); + }).add(done); + aref.set(batch); + aref.push({ name: 'anotha one' }); + }); + + it('should stream in order events', (done) => { + const aref = ref(rando()); + const obs = listChanges(aref.orderByChild('name'), ['child_added']); + obs.pipe(take(1)).subscribe(changes => { + const names = changes.map(change => change.payload.val().name); + expect(names[0]).toEqual('one'); + expect(names[1]).toEqual('two'); + expect(names[2]).toEqual('zero'); + }).add(done); + aref.set(batch); + }); + + it('should stream in order events w/child_added', (done) => { + const aref = ref(rando()); + const obs = listChanges(aref.orderByChild('name'), ['child_added']); + obs.pipe(skip(1), take(1)).subscribe(changes => { + const names = changes.map(change => change.payload.val().name); + expect(names[0]).toEqual('anotha one'); + expect(names[1]).toEqual('one'); + expect(names[2]).toEqual('two'); + expect(names[3]).toEqual('zero'); + }).add(done); + aref.set(batch); + aref.push({ name: 'anotha one' }); + }); + + it('should stream events filtering', (done) => { + const aref = ref(rando()); + const obs = listChanges(aref.orderByChild('name').equalTo('zero'), ['child_added']); + obs.pipe(skip(1), take(1)).subscribe(changes => { + const names = changes.map(change => change.payload.val().name); + expect(names[0]).toEqual('zero'); + expect(names[1]).toEqual('zero'); + }).add(done); + aref.set(batch); + aref.push({ name: 'zero' }); + }); + + + /* FLAKES? aref.set not fufilling + + it('should process a new child_removed event', done => { + const aref = ref(rando()); + const obs = listChanges(aref, ['child_added','child_removed']); + aref.set(batch).then(() => { + const sub = obs.pipe(skip(1),take(1)).subscribe(changes => { + const data = changes.map(change => change.payload.val()); + expect(data.length).toEqual(items.length - 1); + }).add(done); + aref.child(items[0].key).remove(); + }); + }); + + it('should process a new child_changed event', (done) => { + const aref = ref(rando()); + const obs = listChanges(aref, ['child_added','child_changed']) + aref.set(batch).then(() => { + const sub = obs.pipe(skip(1),take(1)).subscribe(changes => { + const data = changes.map(change => change.payload.val()); + expect(data[1].name).toEqual('lol'); + }).add(done); + aref.child(items[1].key).update({ name: 'lol'}); + }); + }); + + it('should process a new child_moved event', (done) => { + const aref = ref(rando()); + const obs = listChanges(aref, ['child_added','child_moved']) + aref.set(batch).then(() => { + const sub = obs.pipe(skip(1),take(1)).subscribe(changes => { + const data = changes.map(change => change.payload.val()); + // We moved the first item to the last item, so we check that + // the new result is now the last result + expect(data[data.length - 1]).toEqual(items[0]); + }).add(done); + aref.child(items[0].key).setPriority('a', () => {}); + }); + });*/ + + }); + +}); diff --git a/src/database-lazy/list/changes.ts b/src/database-lazy/list/changes.ts new file mode 100644 index 000000000..cb37d0694 --- /dev/null +++ b/src/database-lazy/list/changes.ts @@ -0,0 +1,90 @@ +import { fromRef } from '../observable/fromRef'; +import { merge, Observable, of, SchedulerLike } from 'rxjs'; + +import { ChildEvent, DatabaseQuery, SnapshotAction } from '../interfaces'; +import { isNil } from '../utils'; + +import { distinctUntilChanged, scan, switchMap } from 'rxjs/operators'; + +export function listChanges(ref: DatabaseQuery, events: ChildEvent[], scheduler?: SchedulerLike): Observable[]> { + return fromRef(ref, 'value', 'once', scheduler).pipe( + switchMap(snapshotAction => { + const childEvent$ = [of(snapshotAction)]; + events.forEach(event => childEvent$.push(fromRef(ref, event, 'on', scheduler))); + return merge(...childEvent$).pipe(scan(buildView, [])); + }), + distinctUntilChanged() + ); +} + +function positionFor(changes: SnapshotAction[], key) { + const len = changes.length; + for (let i = 0; i < len; i++) { + if (changes[i].payload.key === key) { + return i; + } + } + return -1; +} + +function positionAfter(changes: SnapshotAction[], prevKey?: string) { + if (isNil(prevKey)) { + return 0; + } else { + const i = positionFor(changes, prevKey); + if (i === -1) { + return changes.length; + } else { + return i + 1; + } + } +} + +function buildView(current, action) { + const { payload, prevKey, key } = action; + const currentKeyPosition = positionFor(current, key); + const afterPreviousKeyPosition = positionAfter(current, prevKey); + switch (action.type) { + case 'value': + if (action.payload && action.payload.exists()) { + let prevKey = null; + action.payload.forEach(payload => { + const action = { payload, type: 'value', prevKey, key: payload.key }; + prevKey = payload.key; + current = [...current, action]; + return false; + }); + } + return current; + case 'child_added': + if (currentKeyPosition > -1) { + // check that the previouskey is what we expect, else reorder + const previous = current[currentKeyPosition - 1]; + if ((previous && previous.key || null) !== prevKey) { + current = current.filter(x => x.payload.key !== payload.key); + current.splice(afterPreviousKeyPosition, 0, action); + } + } else if (prevKey == null) { + return [action, ...current]; + } else { + current = current.slice(); + current.splice(afterPreviousKeyPosition, 0, action); + } + return current; + case 'child_removed': + return current.filter(x => x.payload.key !== payload.key); + case 'child_changed': + return current.map(x => x.payload.key === key ? action : x); + case 'child_moved': + if (currentKeyPosition > -1) { + const data = current.splice(currentKeyPosition, 1)[0]; + current = current.slice(); + current.splice(afterPreviousKeyPosition, 0, data); + return current; + } + return current; + // default will also remove null results + default: + return current; + } +} diff --git a/src/database-lazy/list/create-reference.ts b/src/database-lazy/list/create-reference.ts new file mode 100644 index 000000000..2dcd1ee14 --- /dev/null +++ b/src/database-lazy/list/create-reference.ts @@ -0,0 +1,54 @@ +import { AngularFireList, ChildEvent, DatabaseQuery } from '../interfaces'; +import { snapshotChanges } from './snapshot-changes'; +import { stateChanges } from './state-changes'; +import { auditTrail } from './audit-trail'; +import { createDataOperationMethod } from './data-operation'; +import { createRemoveMethod } from './remove'; +import { AngularFireDatabase } from '../database'; +import { map, shareReplay, switchMap } from 'rxjs/operators'; +import { Observable } from 'rxjs'; + +export function createListReference(query$: Observable, afDatabase: AngularFireDatabase): AngularFireList { + const outsideAngularScheduler = afDatabase.schedulers.outsideAngular; + const ref$ = query$.pipe(map(query => afDatabase.schedulers.ngZone.run(() => query.ref))); + return { + query: query$.toPromise(), + update: createDataOperationMethod>(ref$, 'update'), + set: createDataOperationMethod(ref$, 'set'), + push: (data: T) => { + // this should be a hot observable + const obs = ref$.pipe(map(ref => ref.push(data)), shareReplay({ bufferSize: 1, refCount: false })); + obs.subscribe(); + return obs; + }, + remove: createRemoveMethod(ref$), + snapshotChanges: (events?: ChildEvent[]) => query$.pipe( + switchMap(query => snapshotChanges(query, events, outsideAngularScheduler)), + afDatabase.keepUnstableUntilFirst, + ), + stateChanges: (events?: ChildEvent[]) => query$.pipe( + switchMap(query => stateChanges(query, events, outsideAngularScheduler)), + afDatabase.keepUnstableUntilFirst, + ), + auditTrail: (events?: ChildEvent[]) => query$.pipe( + switchMap(query => auditTrail(query, events, outsideAngularScheduler)), + afDatabase.keepUnstableUntilFirst + ), + valueChanges: (events?: ChildEvent[], options?: {idField?: K}) => query$.pipe( + switchMap(query => snapshotChanges(query, events, outsideAngularScheduler)), + map(actions => actions.map(a => { + if (options && options.idField) { + return { + ...a.payload.val() as T, + ...{ + [options.idField]: a.key + } + }; + } else { + return a.payload.val() as T; + } + })), + afDatabase.keepUnstableUntilFirst + ), + }; +} diff --git a/src/database-lazy/list/data-operation.ts b/src/database-lazy/list/data-operation.ts new file mode 100644 index 000000000..93ae54149 --- /dev/null +++ b/src/database-lazy/list/data-operation.ts @@ -0,0 +1,15 @@ +import { Observable } from 'rxjs'; +import { switchMap } from 'rxjs/operators'; +import { DatabaseReference, DatabaseSnapshot, FirebaseOperation } from '../interfaces'; +import { checkOperationCases } from '../utils'; + +export function createDataOperationMethod(ref$: Observable, operation: string) { + return function dataOperation(item: FirebaseOperation, value: T) { + return checkOperationCases(item, { + // TODO fix the typing here, rather than lean on any + stringCase: () => ref$.pipe(switchMap(ref => ref.child(item as string)[operation](value))).toPromise() as any, + firebaseCase: () => (item as DatabaseReference)[operation](value), + snapshotCase: () => (item as DatabaseSnapshot).ref[operation](value) + }); + }; +} diff --git a/src/database-lazy/list/remove.ts b/src/database-lazy/list/remove.ts new file mode 100644 index 000000000..1b61daf89 --- /dev/null +++ b/src/database-lazy/list/remove.ts @@ -0,0 +1,17 @@ +import { Observable } from 'rxjs'; +import { switchMap } from 'rxjs/operators'; +import { DatabaseReference, DatabaseSnapshot, FirebaseOperation } from '../interfaces'; +import { checkOperationCases } from '../utils'; + +// TODO(davideast): Find out why TS thinks this returns firebase.Primise +// instead of Promise. +export function createRemoveMethod(ref$: Observable) { + return function remove(item?: FirebaseOperation): any { + if (!item) { return ref$.pipe(switchMap(ref => ref.remove())).toPromise(); } + return checkOperationCases(item, { + stringCase: () => ref$.pipe(switchMap(ref => ref.child(item as string).remove())).toPromise(), + firebaseCase: () => (item as DatabaseReference).remove(), + snapshotCase: () => (item as DatabaseSnapshot).ref.remove() + }); + }; +} diff --git a/src/database-lazy/list/snapshot-changes.spec.ts b/src/database-lazy/list/snapshot-changes.spec.ts new file mode 100644 index 000000000..5dfce960e --- /dev/null +++ b/src/database-lazy/list/snapshot-changes.spec.ts @@ -0,0 +1,142 @@ +import firebase from 'firebase/app'; +import { AngularFireModule, FirebaseApp } from '@angular/fire'; +import { AngularFireDatabase, AngularFireDatabaseModule, ChildEvent, snapshotChanges, URL } from '../public_api'; +import { TestBed } from '@angular/core/testing'; +import { COMMON_CONFIG } from '../../test-config'; +import { BehaviorSubject } from 'rxjs'; +import { skip, switchMap, take } from 'rxjs/operators'; +import 'firebase/database'; +import { rando } from '../../firestore/utils.spec'; + +describe('snapshotChanges', () => { + let app: FirebaseApp; + let db: AngularFireDatabase; + let createRef: (path: string) => firebase.database.Reference; + let batch = {}; + const items = [{ name: 'zero' }, { name: 'one' }, { name: 'two' }].map((item, i) => ({ key: i.toString(), ...item })); + Object.keys(items).forEach((key, i) => { + batch[i] = items[key]; + }); + // make batch immutable to preserve integrity + batch = Object.freeze(batch); + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + AngularFireModule.initializeApp(COMMON_CONFIG, rando()), + AngularFireDatabaseModule + ], + providers: [ + { provide: URL, useValue: 'http://localhost:9000' } + ] + }); + + app = TestBed.inject(FirebaseApp); + db = TestBed.inject(AngularFireDatabase); + createRef = (path: string) => db.database.ref(path); + }); + + afterEach(() => { + app.delete(); + }); + + function prepareSnapshotChanges(opts: { events?: ChildEvent[], skipnumber: number } = { skipnumber: 0 }) { + const { events, skipnumber } = opts; + const aref = createRef(rando()); + const snapChanges = snapshotChanges(aref, events); + return { + snapChanges: snapChanges.pipe(skip(skipnumber)), + ref: aref + }; + } + + it('should listen to all events by default', (done) => { + const { snapChanges, ref } = prepareSnapshotChanges(); + snapChanges.pipe(take(1)).subscribe(actions => { + const data = actions.map(a => a.payload.val()); + expect(data).toEqual(items); + }).add(done); + ref.set(batch); + }); + + it('should handle multiple subscriptions (hot)', (done) => { + const { snapChanges, ref } = prepareSnapshotChanges(); + const sub = snapChanges.subscribe(() => { + }).add(done); + snapChanges.pipe(take(1)).subscribe(actions => { + const data = actions.map(a => a.payload.val()); + expect(data).toEqual(items); + }).add(sub); + ref.set(batch); + }); + + it('should handle multiple subscriptions (warm)', done => { + const { snapChanges, ref } = prepareSnapshotChanges(); + snapChanges.pipe(take(1)).subscribe(() => { + }).add(() => { + snapChanges.pipe(take(1)).subscribe(actions => { + const data = actions.map(a => a.payload.val()); + expect(data).toEqual(items); + }).add(done); + }); + ref.set(batch); + }); + + it('should listen to only child_added events', (done) => { + const { snapChanges, ref } = prepareSnapshotChanges({ events: ['child_added'], skipnumber: 0 }); + snapChanges.pipe(take(1)).subscribe(actions => { + const data = actions.map(a => a.payload.val()); + expect(data).toEqual(items); + }).add(done); + ref.set(batch); + }); + + /* FLAKE? set promise not fufilling + it('should listen to only child_added, child_changed events', (done) => { + const { snapChanges, ref } = prepareSnapshotChanges({ + events: ['child_added', 'child_changed'], + skipnumber: 1 + }); + const name = 'ligatures'; + snapChanges.pipe(take(1)).subscribe(actions => { + const data = actions.map(a => a.payload!.val());; + const copy = [...items]; + copy[0].name = name; + expect(data).toEqual(copy); + }).add(done); + ref.set(batch).then(() => { + ref.child(items[0].key).update({ name }) + }); + });*/ + + it('should handle empty sets', done => { + const aref = createRef(rando()); + aref.set({}); + snapshotChanges(aref).pipe(take(1)).subscribe(data => { + expect(data.length).toEqual(0); + }).add(done); + }); + + it('should handle dynamic queries that return empty sets', done => { + let count = 0; + const namefilter$ = new BehaviorSubject(null); + const aref = createRef(rando()); + aref.set(batch); + namefilter$.pipe(switchMap(name => { + const filteredRef = name ? aref.child('name').equalTo(name) : aref; + return snapshotChanges(filteredRef); + }), take(2)).subscribe(data => { + count = count + 1; + // the first time should all be 'added' + if (count === 1) { + expect(Object.keys(data).length).toEqual(3); + namefilter$.next(-1); + } + // on the second round, we should have filtered out everything + if (count === 2) { + expect(Object.keys(data).length).toEqual(0); + } + }).add(done); + }); + +}); diff --git a/src/database-lazy/list/snapshot-changes.ts b/src/database-lazy/list/snapshot-changes.ts new file mode 100644 index 000000000..7422c65bd --- /dev/null +++ b/src/database-lazy/list/snapshot-changes.ts @@ -0,0 +1,13 @@ +import { Observable, SchedulerLike } from 'rxjs'; +import { listChanges } from './changes'; +import { ChildEvent, DatabaseQuery, SnapshotAction } from '../interfaces'; +import { validateEventsArray } from './utils'; + +export function snapshotChanges( + query: DatabaseQuery, + events?: ChildEvent[], + scheduler?: SchedulerLike +): Observable[]> { + events = validateEventsArray(events); + return listChanges(query, events, scheduler); +} diff --git a/src/database-lazy/list/state-changes.spec.ts b/src/database-lazy/list/state-changes.spec.ts new file mode 100644 index 000000000..bbb5a9e76 --- /dev/null +++ b/src/database-lazy/list/state-changes.spec.ts @@ -0,0 +1,64 @@ +import firebase from 'firebase/app'; +import { AngularFireModule, FirebaseApp } from '@angular/fire'; +import { AngularFireDatabase, AngularFireDatabaseModule, ChildEvent, stateChanges, URL } from '../public_api'; +import { TestBed } from '@angular/core/testing'; +import { COMMON_CONFIG } from '../../test-config'; +import { skip } from 'rxjs/operators'; +import 'firebase/database'; +import { rando } from '../../firestore/utils.spec'; + +describe('stateChanges', () => { + let app: FirebaseApp; + let db: AngularFireDatabase; + let createRef: (path: string) => firebase.database.Reference; + let batch = {}; + const items = [{ name: 'zero' }, { name: 'one' }, { name: 'two' }].map((item, i) => ({ key: i.toString(), ...item })); + Object.keys(items).forEach((key, i) => { + batch[i] = items[key]; + }); + // make batch immutable to preserve integrity + batch = Object.freeze(batch); + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + AngularFireModule.initializeApp(COMMON_CONFIG, rando()), + AngularFireDatabaseModule + ], + providers: [ + { provide: URL, useValue: 'http://localhost:9000' } + ] + }); + + app = TestBed.inject(FirebaseApp); + db = TestBed.inject(AngularFireDatabase); + createRef = (path: string) => db.database.ref(path); + }); + + afterEach(() => { + app.delete(); + }); + + function prepareStateChanges(opts: { events?: ChildEvent[], skipnumber: number } = { skipnumber: 0 }) { + const { events, skipnumber } = opts; + const aref = createRef(rando()); + aref.set(batch); + const changes = stateChanges(aref, events); + return { + changes: changes.pipe(skip(skipnumber)), + ref: aref + }; + } + + it('should listen to all events by default', (done) => { + + const { changes } = prepareStateChanges({ skipnumber: 2 }); + changes.subscribe(action => { + expect(action.key).toEqual('2'); + expect(action.payload.val()).toEqual(items[items.length - 1]); + done(); + }); + + }); + +}); diff --git a/src/database-lazy/list/state-changes.ts b/src/database-lazy/list/state-changes.ts new file mode 100644 index 000000000..192043e3b --- /dev/null +++ b/src/database-lazy/list/state-changes.ts @@ -0,0 +1,10 @@ +import { ChildEvent, DatabaseQuery } from '../interfaces'; +import { fromRef } from '../observable/fromRef'; +import { validateEventsArray } from './utils'; +import { merge, SchedulerLike } from 'rxjs'; + +export function stateChanges(query: DatabaseQuery, events?: ChildEvent[], scheduler?: SchedulerLike) { + events = validateEventsArray(events); + const childEvent$ = events.map(event => fromRef(query, event, 'on', scheduler)); + return merge(...childEvent$); +} diff --git a/src/database-lazy/list/utils.ts b/src/database-lazy/list/utils.ts new file mode 100644 index 000000000..35404600c --- /dev/null +++ b/src/database-lazy/list/utils.ts @@ -0,0 +1,8 @@ +import { isNil } from '../utils'; + +export function validateEventsArray(events?: any[]) { + if (isNil(events) || events.length === 0) { + events = ['child_added', 'child_removed', 'child_changed', 'child_moved']; + } + return events; +} diff --git a/src/database-lazy/object/create-reference.ts b/src/database-lazy/object/create-reference.ts new file mode 100644 index 000000000..8848cb073 --- /dev/null +++ b/src/database-lazy/object/create-reference.ts @@ -0,0 +1,23 @@ +import { map, switchMap } from 'rxjs/operators'; +import { AngularFireObject, DatabaseQuery } from '../interfaces'; +import { createObjectSnapshotChanges } from './snapshot-changes'; +import { AngularFireDatabase } from '../database'; +import { Observable } from 'rxjs'; + +export function createObjectReference(query$: Observable, afDatabase: AngularFireDatabase): AngularFireObject { + return { + query: query$.toPromise(), + snapshotChanges: () => query$.pipe( + switchMap(query => createObjectSnapshotChanges(query, afDatabase.schedulers.outsideAngular)()), + afDatabase.keepUnstableUntilFirst + ), + update: (data: Partial) => query$.pipe(switchMap(query => query.ref.update(data as any))).toPromise(), + set: (data: T) => query$.pipe(switchMap(query => query.ref.set(data))).toPromise(), + remove: () => query$.pipe(switchMap(query => query.ref.remove())).toPromise(), + valueChanges: () => query$.pipe( + switchMap(query => createObjectSnapshotChanges(query, afDatabase.schedulers.outsideAngular)()), + afDatabase.keepUnstableUntilFirst, + map(action => action.payload.exists() ? action.payload.val() as T : null) + ), + }; +} diff --git a/src/database-lazy/object/snapshot-changes.ts b/src/database-lazy/object/snapshot-changes.ts new file mode 100644 index 000000000..66ae6ef3c --- /dev/null +++ b/src/database-lazy/object/snapshot-changes.ts @@ -0,0 +1,9 @@ +import { Observable, SchedulerLike } from 'rxjs'; +import { fromRef } from '../observable/fromRef'; +import { DatabaseQuery, SnapshotAction } from '../interfaces'; + +export function createObjectSnapshotChanges(query: DatabaseQuery, scheduler?: SchedulerLike) { + return function snapshotChanges(): Observable> { + return fromRef(query, 'value', 'on', scheduler); + }; +} diff --git a/src/database-lazy/observable/fromRef.spec.ts b/src/database-lazy/observable/fromRef.spec.ts new file mode 100644 index 000000000..e7a1f966e --- /dev/null +++ b/src/database-lazy/observable/fromRef.spec.ts @@ -0,0 +1,271 @@ +import { DatabaseReference } from '../interfaces'; +import { AngularFireModule, FirebaseApp, ɵZoneScheduler } from '@angular/fire'; +import { AngularFireDatabase, AngularFireDatabaseModule, fromRef } from '../public_api'; +import { TestBed } from '@angular/core/testing'; +import { COMMON_CONFIG } from '../../test-config'; +import { take } from 'rxjs/operators'; +import { TestScheduler } from 'rxjs/testing'; +import { rando } from '../../firestore/utils.spec'; + +describe('fromRef', () => { + let app: FirebaseApp; + let db: AngularFireDatabase; + let ref: (path: string) => DatabaseReference; + let batch = {}; + const items = [{ name: 'one' }, { name: 'two' }, { name: 'three' }].map(item => ({ key: rando(), ...item })); + Object.keys(items).forEach((key) => { + const itemValue = items[key]; + batch[itemValue.key] = itemValue; + }); + // make batch immutable to preserve integrity + batch = Object.freeze(batch); + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + AngularFireModule.initializeApp(COMMON_CONFIG, rando()), + AngularFireDatabaseModule + ], + providers: [ + { provide: URL, useValue: 'http://localhost:9000' } + ] + }); + + app = TestBed.inject(FirebaseApp); + db = TestBed.inject(AngularFireDatabase); + ref = (path: string) => db.database.ref(path); + }); + + afterEach(() => { + app.delete(); + }); + + it('it should be async by default', (done) => { + const itemRef = ref(rando()); + itemRef.set(batch); + const obs = fromRef(itemRef, 'value'); + let count = 0; + expect(count).toEqual(0); + const sub = obs.subscribe(() => { + count = count + 1; + expect(count).toEqual(1); + sub.unsubscribe(); + done(); + }); + expect(count).toEqual(0); + }); + + it('should take a scheduler', done => { + const itemRef = ref(rando()); + itemRef.set(batch); + + const testScheduler = new TestScheduler((actual, expected) => { + expect(actual).toEqual(expected); + }); + spyOn(testScheduler, 'schedule').and.callThrough(); + + const obs = fromRef(itemRef, 'value', 'once', testScheduler); + expect(testScheduler.schedule).not.toHaveBeenCalled(); + + obs.subscribe(() => { + expect(testScheduler.schedule).toHaveBeenCalled(); + done(); + }, err => { + console.error(err); + expect(false).toEqual(true, 'Shouldnt error'); + done(); + }, () => { + expect(testScheduler.schedule).toHaveBeenCalled(); + done(); + }); + testScheduler.flush(); + }); + + it('should schedule completed and error correctly', done => { + const testScheduler = new TestScheduler((actual, expected) => { + expect(actual).toEqual(expected); + }); + spyOn(testScheduler, 'schedule').and.callThrough(); + + // Error + const errorObservable = fromRef({ + once: (event, snap, err) => err() + } as any, + 'value', + 'once', + testScheduler + ); + errorObservable.subscribe(() => { + fail('Should not emit'); + }, () => { + expect(testScheduler.schedule).toHaveBeenCalled(); + }, () => { + fail('Should not complete'); + }); + + testScheduler.flush(); + + // Completed + const itemRef = ref(rando()); + itemRef.set(batch); + + const scheduler = new ɵZoneScheduler(Zone.current.fork({ + name: 'ExpectedZone' + })); + const completeObservable = fromRef( + itemRef, + 'value', + 'once', + scheduler + ); + completeObservable.subscribe( + () => { + }, + () => fail('Should not error'), + () => expect(Zone.current.name).toEqual('ExpectedZone') + ); + testScheduler.flush(); + done(); + }); + + + it('it should should handle non-existence', (done) => { + const itemRef = ref(rando()); + itemRef.set({}); + const obs = fromRef(itemRef, 'value'); + obs.pipe(take(1)).subscribe(change => { + expect(change.payload.exists()).toEqual(false); + expect(change.payload.val()).toEqual(null); + }).add(done); + }); + + it('once should complete', (done) => { + const itemRef = ref(rando()); + itemRef.set(batch); + const obs = fromRef(itemRef, 'value', 'once'); + obs.subscribe(() => { + }, () => { + }, done); + }); + + it('it should listen and then unsubscribe', (done) => { + const itemRef = ref(rando()); + itemRef.set(batch); + const obs = fromRef(itemRef, 'value'); + let count = 0; + const sub = obs.subscribe(() => { + count = count + 1; + // hard coding count to one will fail if the unsub + // doesn't actually unsub + expect(count).toEqual(1); + done(); + sub.unsubscribe(); + itemRef.push({ name: 'anotha one' }); + }); + }); + + describe('events', () => { + + it('should stream back a child_added event', async (done: any) => { + const itemRef = ref(rando()); + itemRef.set(batch); + const obs = fromRef(itemRef, 'child_added'); + let count = 0; + const sub = obs.subscribe(change => { + count = count + 1; + const { type, payload } = change; + expect(type).toEqual('child_added'); + expect(payload.val()).toEqual(batch[payload.key]); + if (count === items.length) { + done(); + sub.unsubscribe(); + expect(sub.closed).toEqual(true); + } + }); + }); + + it('should stream back a child_changed event', async (done: any) => { + const itemRef = ref(rando()); + itemRef.set(batch); + const obs = fromRef(itemRef, 'child_changed'); + const name = 'look at what you made me do'; + const key = items[0].key; + const sub = obs.subscribe(change => { + const { type, payload } = change; + expect(type).toEqual('child_changed'); + expect(payload.key).toEqual(key); + expect(payload.val()).toEqual({ key, name }); + sub.unsubscribe(); + done(); + }); + itemRef.child(key).update({ name }); + }); + + it('should stream back a child_removed event', async (done: any) => { + const itemRef = ref(rando()); + itemRef.set(batch); + const obs = fromRef(itemRef, 'child_removed'); + const key = items[0].key; + const name = items[0].name; + const sub = obs.subscribe(change => { + const { type, payload } = change; + expect(type).toEqual('child_removed'); + expect(payload.key).toEqual(key); + expect(payload.val()).toEqual({ key, name }); + sub.unsubscribe(); + done(); + }); + itemRef.child(key).remove(); + }); + + it('should stream back a child_moved event', async (done: any) => { + const itemRef = ref(rando()); + itemRef.set(batch); + const obs = fromRef(itemRef, 'child_moved'); + const key = items[2].key; + const name = items[2].name; + const sub = obs.subscribe(change => { + const { type, payload } = change; + expect(type).toEqual('child_moved'); + expect(payload.key).toEqual(key); + expect(payload.val()).toEqual({ key, name }); + sub.unsubscribe(); + done(); + }); + itemRef.child(key).setPriority(-100, () => { + }); + }); + + it('should stream back a value event', (done: any) => { + const itemRef = ref(rando()); + itemRef.set(batch); + const obs = fromRef(itemRef, 'value'); + const sub = obs.subscribe(change => { + const { type, payload } = change; + expect(type).toEqual('value'); + expect(payload.val()).toEqual(batch); + done(); + sub.unsubscribe(); + expect(sub.closed).toEqual(true); + }); + }); + + it('should stream back query results', (done: any) => { + const itemRef = ref(rando()); + itemRef.set(batch); + const query = itemRef.orderByChild('name').equalTo(items[0].name); + const obs = fromRef(query, 'value'); + obs.subscribe(change => { + let child = null; + change.payload.forEach(snap => { + child = snap.val(); + return true; + }); + expect(child).toEqual(items[0]); + done(); + }); + }); + + }); + +}); diff --git a/src/database-lazy/observable/fromRef.ts b/src/database-lazy/observable/fromRef.ts new file mode 100644 index 000000000..d08283235 --- /dev/null +++ b/src/database-lazy/observable/fromRef.ts @@ -0,0 +1,60 @@ +import { AngularFireAction, DatabaseQuery, DatabaseSnapshot, ListenEvent } from '../interfaces'; +import { asyncScheduler, Observable, SchedulerLike } from 'rxjs'; +import { map, share } from 'rxjs/operators'; + +interface SnapshotPrevKey { + snapshot: DatabaseSnapshot; + prevKey: string | null | undefined; +} + +/** + * Create an observable from a Database Reference or Database Query. + * @param ref Database Reference + * @param event Listen event type ('value', 'added', 'changed', 'removed', 'moved') + * @param listenType 'on' or 'once' + * @param scheduler - Rxjs scheduler + */ +export function fromRef(ref: DatabaseQuery, + event: ListenEvent, + listenType = 'on', + scheduler: SchedulerLike = asyncScheduler +): Observable>> { + return new Observable>(subscriber => { + let fn: any | null = null; + fn = ref[listenType](event, (snapshot, prevKey) => { + scheduler.schedule(() => { + subscriber.next({ snapshot, prevKey }); + }); + if (listenType === 'once') { + scheduler.schedule(() => subscriber.complete()); + } + }, err => { + scheduler.schedule(() => subscriber.error(err)); + }); + + if (listenType === 'on') { + return { + unsubscribe() { + if (fn != null) { + ref.off(event, fn); + } + } + }; + } else { + return { + unsubscribe() { + } + }; + } + }).pipe( + map(payload => { + const { snapshot, prevKey } = payload; + let key: string | null = null; + if (snapshot.exists()) { + key = snapshot.key; + } + return { type: event, payload: snapshot, prevKey, key }; + }), + share() + ); +} diff --git a/src/database-lazy/package.json b/src/database-lazy/package.json new file mode 100644 index 000000000..10e70bb74 --- /dev/null +++ b/src/database-lazy/package.json @@ -0,0 +1,12 @@ +{ + "$schema": "../../node_modules/ng-packagr/package.schema.json", + "ngPackage": { + "lib": { + "umdModuleIds": { + "firebase/app": "firebase", + "@firebase/database": "firebase-database" + }, + "entryFile": "public_api.ts" + } + } +} diff --git a/src/database-lazy/public_api.ts b/src/database-lazy/public_api.ts new file mode 100644 index 000000000..f79e8fabf --- /dev/null +++ b/src/database-lazy/public_api.ts @@ -0,0 +1,11 @@ + +import 'firebase/database'; // strip out in the build process + +export * from './database'; +export * from './list/changes'; +export * from './list/create-reference'; +export * from './list/snapshot-changes'; +export * from './list/state-changes'; +export * from './list/audit-trail'; +export * from './observable/fromRef'; +export * from './database.module'; diff --git a/src/database-lazy/utils.spec.ts b/src/database-lazy/utils.spec.ts new file mode 100644 index 000000000..b437b0700 --- /dev/null +++ b/src/database-lazy/utils.spec.ts @@ -0,0 +1,26 @@ +import * as utils from './utils'; + +describe('utils', () => { + + describe('isString', () => { + + it('should be able to properly detect a string', () => { + const str = 'oh hai'; + const notStr = 101; + const bool = true; + const nul = null; + const obj = {}; + const fn = () => { }; + const undef = undefined; + expect(utils.isString(str)).toBe(true); + expect(utils.isString(notStr)).toBe(false); + expect(utils.isString(bool)).toBe(false); + expect(utils.isString(nul)).toBe(false); + expect(utils.isString(obj)).toBe(false); + expect(utils.isString(fn)).toBe(false); + expect(utils.isString(undef)).toBe(false); + }); + + }); + +}); diff --git a/src/database-lazy/utils.ts b/src/database-lazy/utils.ts new file mode 100644 index 000000000..56c7d9043 --- /dev/null +++ b/src/database-lazy/utils.ts @@ -0,0 +1,41 @@ +import { DatabaseReference, FirebaseOperation, FirebaseOperationCases, PathReference } from './interfaces'; +import firebase from 'firebase/app'; + +export function isString(value: any): boolean { + return typeof value === 'string'; +} + +export function isFirebaseDataSnapshot(value: any): boolean { + return typeof value.exportVal === 'function'; +} + +export function isNil(obj: any): boolean { + return obj === undefined || obj === null; +} + +export function isFirebaseRef(value: any): boolean { + return typeof value.set === 'function'; +} + +/** + * Returns a database reference given a Firebase App and an + * absolute or relative path. + * @param database - Firebase Database + * @param pathRef - Database path, relative or absolute + */ +export function getRef(database: firebase.database.Database, pathRef: PathReference): DatabaseReference { + // if a db ref was passed in, just return it + return isFirebaseRef(pathRef) ? pathRef as DatabaseReference + : database.ref(pathRef as string); +} + +export function checkOperationCases(item: FirebaseOperation, cases: FirebaseOperationCases): Promise { + if (isString(item)) { + return cases.stringCase(); + } else if (isFirebaseRef(item)) { + return cases.firebaseCase(); + } else if (isFirebaseDataSnapshot(item)) { + return cases.snapshotCase(); + } + throw new Error(`Expects a string, snapshot, or reference. Got: ${typeof item}`); +} diff --git a/tools/build.ts b/tools/build.ts index 13ac9063c..79d7c10c4 100644 --- a/tools/build.ts +++ b/tools/build.ts @@ -10,9 +10,10 @@ import firebase from 'firebase/app'; const MODULES = [ 'core', 'analytics', 'auth', 'auth-guard', 'database', 'firestore', 'firestore-lazy', 'functions', 'remote-config', - 'storage', 'messaging', 'performance', 'storage-lazy' + 'storage', 'messaging', 'performance', 'storage-lazy', + 'database-lazy', // 'firestore/memory', 'firestore-lazy/memory', ]; -const LAZY_MODULES = [['analytics'], ['auth'], ['functions'], ['firestore-lazy', 'firestore'], ['messaging'], ['remote-config'], ['storage-lazy', 'storage']]; +const LAZY_MODULES = [['analytics'], ['auth'], ['functions'], ['firestore-lazy', 'firestore'], ['messaging'], ['remote-config'], ['storage-lazy', 'storage'], ['database-lazy', 'database']]; const UMD_NAMES = MODULES.map(m => m === 'core' ? 'angular-fire' : `angular-fire-${m}`); const ENTRY_NAMES = MODULES.map(m => m === 'core' ? '@angular/fire' : `@angular/fire/${m}`); @@ -26,6 +27,7 @@ function proxyPolyfillCompat() { 'remote-config': tsKeys(), 'firestore-lazy': tsKeys(), 'storage-lazy': tsKeys(), + 'database-lazy': tsKeys(), }; return Promise.all(Object.keys(defaultObject).map(module => From dc4ea43506ce73aadf0df3e3e85505b3ffa8d378 Mon Sep 17 00:00:00 2001 From: James Daniels Date: Thu, 26 Nov 2020 07:34:44 -0500 Subject: [PATCH 11/11] Add preboot to perfservice --- sample/package.json | 1 + sample/yarn.lock | 5 +++++ src/performance/performance.service.ts | 11 +++++++++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/sample/package.json b/sample/package.json index a42aa2b2e..34a48e813 100644 --- a/sample/package.json +++ b/sample/package.json @@ -32,6 +32,7 @@ "core-js": "^3.6.5", "firebase": "^8.0.0", "first-input-delay": "^0.1.3", + "preboot": "^7.0.0", "proxy-polyfill": "^0.3.2", "rxjs": "~6.6.3", "tslib": "^2.0.1", diff --git a/sample/yarn.lock b/sample/yarn.lock index 23465e6c4..95c8b3f0f 100644 --- a/sample/yarn.lock +++ b/sample/yarn.lock @@ -9690,6 +9690,11 @@ postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.27, postcss@^7.0.3 source-map "^0.6.1" supports-color "^6.1.0" +preboot@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/preboot/-/preboot-7.0.0.tgz#a06e9ec5d60b0f0a0143981e89983173510459b9" + integrity sha512-moGFdwpdY91Hr7L1OdwpMWPLwJmijUdynZkP7zJzpIgTqCShisVVU5AMVHLdetu1EvOpMo9Hy7WPMH1mDk19hQ== + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" diff --git a/src/performance/performance.service.ts b/src/performance/performance.service.ts index 94c532884..913204b0c 100644 --- a/src/performance/performance.service.ts +++ b/src/performance/performance.service.ts @@ -2,12 +2,12 @@ import { ApplicationRef, Injectable, OnDestroy } from '@angular/core'; import { Subscription } from 'rxjs'; import { first, tap } from 'rxjs/operators'; -const IS_STABLE_START_MARK = '_isStableStart'; +const IS_STABLE_START_MARK = 'Zone'; // use Zone.js's mark const IS_STABLE_END_MARK = '_isStableEnd'; +const PREBOOT_COMPLETE_END_MARK = '_prebootComplete'; function markStarts() { if (typeof(window) !== 'undefined' && window.performance) { - window.performance.mark(IS_STABLE_START_MARK); return true; } else { return false; @@ -23,6 +23,7 @@ export class PerformanceMonitoringService implements OnDestroy { constructor(appRef: ApplicationRef) { if (started) { + this.disposable = appRef.isStable.pipe( first(it => it), tap(() => { @@ -30,7 +31,13 @@ export class PerformanceMonitoringService implements OnDestroy { window.performance.measure('isStable', IS_STABLE_START_MARK, IS_STABLE_END_MARK); }) ).subscribe(); + + window.document.addEventListener('PrebootComplete', () => { + window.performance.mark(PREBOOT_COMPLETE_END_MARK); + window.performance.measure('prebootComplete', IS_STABLE_START_MARK, PREBOOT_COMPLETE_END_MARK); + }); } + } ngOnDestroy() {