diff --git a/CHANGELOG.md b/CHANGELOG.md index ab72d1f3c..0cace6d49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,22 @@ +<a name="5.2.0"></a> +# [5.2.0](https://github.com/angular/angularfire2/compare/5.1.3...5.2.0) (2019-05-24) + +### Bug Fixes + +* **firestore:** Fix for builds targeting Node ([#2079](https://github.com/angular/angularfire2/issues/2079)) ([8a33826](https://github.com/angular/angularfire2/commit/8a33826)) +* **storage:** Typo in updateMetadata method ([#2029](https://github.com/angular/angularfire2/issues/2029)) ([6133296](https://github.com/angular/angularfire2/commit/6133296)) + +### Features + +* **performance:** AngularFire Performance Monitoring ([#2064](https://github.com/angular/angularfire2/issues/2064)) +* **auth-guard:** AngularFire Auth Guards ([#2016](https://github.com/angular/angularfire2/issues/2016)) ([e32164d](https://github.com/angular/angularfire2/commit/e32164d)) +* **firestore:** Added option to include document IDs on valueChanges() ([#1976](https://github.com/angular/angularfire2/issues/1976)) ([7108875](https://github.com/angular/angularfire2/commit/7108875)) +* **firestore:** Support Firestore Collection Group Queries ([#2066](https://github.com/angular/angularfire2/issues/2066)) ([c34c0f3](https://github.com/angular/angularfire2/commit/c34c0f3)) +* **functions:** Allow configuration of Functions Emulator Origin ([#2017](https://github.com/angular/angularfire2/issues/2017)) ([d12b4c5](https://github.com/angular/angularfire2/commit/d12b4c5)) +* **schematics:** ng deploy schematic ([#2046](https://github.com/angular/angularfire2/issues/2046)) ([be0a1fb](https://github.com/angular/angularfire2/commit/be0a1fb)) + + + <a name="5.1.2"></a> # [5.1.2](https://github.com/angular/angularfire2/compare/5.1.1...5.1.2) (2019-03-11) diff --git a/README.md b/README.md index dcc8bd114..2b8446404 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,10 @@ Firebase offers two cloud-based, client-accessible database solutions that suppo - [Getting started with Firebase Messaging](docs/messaging/messaging.md) +### Monitor your application performance in production + +- [Getting started with Performance Monitoring](docs/performance/getting-started.md) + ### Directly call Cloud Functions - [Getting started with Callable Functions](docs/functions/functions.md) diff --git a/cloudbuild.yaml b/cloudbuild.yaml index 866bd6dc4..fc52bd244 100644 --- a/cloudbuild.yaml +++ b/cloudbuild.yaml @@ -4,19 +4,19 @@ # @next `gcloud builds submit --substitutions=TAG_NAME="v1.2.3-rc.1"` # @latest `gcloud builds submit --substitutions=TAG_NAME="v1.2.3"` steps: -- name: 'gcr.io/cloud-builders/yarn' - entrypoint: 'bash' +- name: node:lts + entrypoint: bash args: ["./tools/build.sh"] env: - 'TAG_NAME=$TAG_NAME' - 'SHORT_SHA=$SHORT_SHA' -- name: 'gcr.io/cloud-builders/yarn' - entrypoint: 'bash' +- name: node:lts + entrypoint: bash args: ["./tools/test.sh"] -- name: 'gcr.io/cloud-builders/npm' - entrypoint: 'bash' +- name: node:lts + entrypoint: bash env: ['TAG_NAME=$TAG_NAME'] args: ["./tools/release.sh"] secretEnv: ['NPM_TOKEN'] @@ -24,4 +24,6 @@ steps: secrets: - kmsKeyName: projects/angularfire/locations/global/keyRings/cloud-build/cryptoKeys/cloud-build secretEnv: - NPM_TOKEN: CiQAwtE8WoPa1sNqAQJZ1WMODuJooVmO6zihz2hAZOfUmDsgogUSTQCq8yp8qgltY+8jWpAR9GuS1JaVhd+fTVRilqLtdi2yXSdiDPTzLhZ+30bMlAOcoc0PxhCBn3JOpn8H1xshX+mG8yK7xog2Uq+CLVx/ \ No newline at end of file + NPM_TOKEN: CiQAwtE8WoPa1sNqAQJZ1WMODuJooVmO6zihz2hAZOfUmDsgogUSTQCq8yp8qgltY+8jWpAR9GuS1JaVhd+fTVRilqLtdi2yXSdiDPTzLhZ+30bMlAOcoc0PxhCBn3JOpn8H1xshX+mG8yK7xog2Uq+CLVx/ + +timeout: 1200s \ No newline at end of file diff --git a/docs/performance/getting-started.md b/docs/performance/getting-started.md new file mode 100644 index 000000000..e38abd933 --- /dev/null +++ b/docs/performance/getting-started.md @@ -0,0 +1,145 @@ +# Getting started with Performance Monitoring + +## Automatic page load tracing + +Understand your Angular application's real-world performance with [Firebase Performance Monitoring](https://firebase.google.com/docs/perf-mon). Performance Monitoring automatically provides a trace for **page load** when you add `AngularFirePerformanceModule` into your App Module's imports. + +```ts +import { AngularFireModule } from '@angular/fire'; +import { AngularFirePerformanceModule } from '@angular/fire/performance'; +import { environment } from '../environments/environment'; + +@NgModule({ + imports: [ + BrowserModule, + AngularFireModule.initializeApp(environment.firebase), + AngularFirePerformanceModule, + ... + ], + declarations: [ AppComponent ], + bootstrap: [ AppComponent ] +}) +export class AppModule {} +``` + +The page load trace breaks down into the following default metrics: + +* [first paint traces](https://firebase.google.com/docs/perf-mon/automatic-web#first-paint) — measure the time between when the user navigates to a page and when any visual change happens +* [first contentful paint traces](https://firebase.google.com/docs/perf-mon/automatic-web#contentful-paint) — measure the time between when a user navigates to a page and when meaningful content displays, like an image or text +* [domInteractive traces](https://firebase.google.com/docs/perf-mon/automatic-web#domInteractive) — measure the time between when the user navigates to a page and when the page is considered interactive for the user +* [domContentLoadedEventEnd traces](https://firebase.google.com/docs/perf-mon/automatic-web#domContentLoaded) — measure the time between when the user navigates to a page and when the initial HTML document is completely loaded and parsed +* [loadEventEnd traces](https://firebase.google.com/docs/perf-mon/automatic-web#loadEventEnd) — measure the time between when the user navigates to the page and when the current document's load event completes +* [first input delay traces](https://firebase.google.com/docs/perf-mon/automatic-web#input-delay) — measure the time between when the user interacts with a page and when the browser is able to respond to that input +* **Angular specific traces** - measure the time needed for `ApplicationRef.isStable` to be true, an important metric to track if you're concerned about solving Zone.js issues for proper functionality of NGSW and Server Side Rendering + +## Manual traces + +You can inject `AngularFirePerformance` to perform manual traces on Observables. + +```ts +constructor(private afp: AngularFirePerformance, private afs: AngularFirestore) {} + +ngOnInit() { + this.articles = afs.collection('articles') + .collection('articles', ref => ref.orderBy('publishedAt', 'desc')) + .snapshotChanges() + .pipe( + // measure the amount of time between the Observable being subscribed to and first emission (or completion) + this.afp.trace('getArticles'), + map(articles => ...) + ); +} +``` + +### `trace(name:string)` + +The most basic operator, `trace` will measure the amount of time it takes for your observable to either complete or emit its first value. Beyond the basic trace there are several other operators: + +### `traceUntil(name:string, test: (T) => Boolean)` + +Trace the observable until the first emission that passes the provided test. + +### `traceWhile(name:string, test: (T) => Boolean)` + +Trace the observable until the first emission that fails the provided test. + +### `traceUntilLast(name:string)` + +Trace the observable until completion. + +### `traceUntilFirst(name: string)` + +Traces the observable until the first emission. + +## Advanced usage + +### Configuration via Dependency Injection + +By default, `AngularFirePerformanceModule` traces your Angular application's time to `ApplicationRef.isStable`. `isStable` is an important metric to track if you're concerned about proper functionality of NGSW and Server Side Rendering. If you want to opt-out of the tracing of this metric use the `AUTOMATICALLY_TRACE_CORE_NG_METRICS` injection token: + +```ts +import { NgModule } from '@angular/core'; +import { AngularFirePerformanceModule, AUTOMATICALLY_TRACE_CORE_NG_METRICS } from '@angular/fire/functions'; + +@NgModule({ + imports: [ + ... + AngularFirePerformanceModule, + ... + ], + ... + providers: [ + { provide: AUTOMATICALLY_TRACE_CORE_NG_METRICS, useValue: false } + ] +}) +export class AppModule {} +``` + +Similarly, setting `INSTRUMENTATION_ENABLED` or `DATA_COLLECTION_ENABLED` to false disable all automatic and custom traces respectively. + +### Get at an observable form of trace + +`trace$(name:string)` provides an observable version of `firebase/perf`'s `.trace` method; the basis for `AngularFirePerfomance`'s pipes. + +`.subscribe()` is equivalent to calling `.start()` +`.unsubscribe()` is equivalent to calling `.stop()` + +### Using `TraceOptions` to collect additional metrics + +`TraceOptions` can be provided to the aformentioned operators to collect custom metrics and attributes on your traces: + +```ts +type TraceOptions = { + metrics?: { [key:string]: number }, + attributes?: { [key:string]: string }, + attribute$?: { [key:string]: Observable<string> }, + incrementMetric$: { [key:string]: Observable<number|void|null|undefined> }, + metric$?: { [key:string]: Observable<number> } +}; +``` + +#### Usage: + +```ts +const articleLength$ = this.articles.pipe( + map(actions => actions.length) +); + +const articleSize$ = this.articles.pipe( + map(actions => actions.reduce((sum, a) => sum += JSON.stringify(a.payload.doc.data()).length)) +) + +this.articles = afs.collection('articles') + .collection('articles', ref => ref.orderBy('publishedAt', 'desc')) + .snapshotChanges() + .pipe( + this.afp.trace('getArticles', { + attributes: { gitSha: '1d277f823ad98dd739fb86e9a6c440aa8237ff3a' }, + metrics: { something: 42 }, + metrics$: { count: articleLength$, size: articleSize$ }, + attributes$: { user: this.afAuth.user }, + incrementMetric$: { buttonClicks: fromEvent(button, 'click') } + }), + share() + ); +``` \ No newline at end of file diff --git a/karma.conf.js b/karma.conf.js index 741435dd8..5ab48f0da 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -30,6 +30,7 @@ module.exports = function(config) { 'node_modules/firebase/firebase-database.js', 'node_modules/firebase/firebase-firestore.js', 'node_modules/firebase/firebase-functions.js', + 'node_modules/firebase/firebase-performance.js', 'node_modules/firebase/firebase-storage.js', 'dist/packages-dist/bundles/core.umd.{js,map}', 'dist/packages-dist/bundles/auth.umd.{js,map}', @@ -38,6 +39,7 @@ module.exports = function(config) { 'dist/packages-dist/bundles/firestore.umd.{js,map}', 'dist/packages-dist/bundles/functions.umd.{js,map}', 'dist/packages-dist/bundles/storage.umd.{js,map}', + 'dist/packages-dist/bundles/performance.umd.{js,map}', 'dist/packages-dist/bundles/database-deprecated.umd.{js,map}', 'dist/packages-dist/bundles/test.umd.{js,map}', ], diff --git a/package.json b/package.json index 0a500276f..2322578a1 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "angularfire2", + "name": "@angular/fire", "version": "5.2.0", "description": "The official library of Firebase and Angular.", "private": true, @@ -33,7 +33,7 @@ }, "homepage": "https://github.com/angular/angularfire2#readme", "dependencies": { - "@angular-devkit/architect": "^0.800.0-rc.4", + "@angular-devkit/architect": "^0.800.0-rc.4 || >=8.0.0 <9 || 9.0.0-0", "@angular-devkit/core": ">=6.0.0 <9 || 9.0.0-0", "@angular-devkit/schematics": ">=6.0.0 <9 || 9.0.0-0", "@angular/common": ">=6.0.0 <9 || 9.0.0-0", diff --git a/src/core/firebase.app.module.ts b/src/core/firebase.app.module.ts index 72b195969..ed35ff51d 100644 --- a/src/core/firebase.app.module.ts +++ b/src/core/firebase.app.module.ts @@ -25,6 +25,7 @@ export class FirebaseApp { auth: () => FirebaseAuth; database: (databaseURL?: string) => FirebaseDatabase; messaging: () => FirebaseMessaging; + performance: () => any; // SEMVER: once >= 6 import performance.Performance storage: (storageBucket?: string) => FirebaseStorage; delete: () => Promise<void>; firestore: () => FirebaseFirestore; diff --git a/src/performance/index.spec.ts b/src/performance/index.spec.ts new file mode 100644 index 000000000..bf7cd6401 --- /dev/null +++ b/src/performance/index.spec.ts @@ -0,0 +1 @@ +export * from './performance.spec'; diff --git a/src/performance/index.ts b/src/performance/index.ts new file mode 100644 index 000000000..4aaf8f92e --- /dev/null +++ b/src/performance/index.ts @@ -0,0 +1 @@ +export * from './public_api'; diff --git a/src/performance/package.json b/src/performance/package.json new file mode 100644 index 000000000..67c354cbd --- /dev/null +++ b/src/performance/package.json @@ -0,0 +1,30 @@ +{ + "name": "@angular/fire/performance", + "version": "ANGULARFIRE2_VERSION", + "description": "The performance monitoring module", + "main": "../bundles/performance.umd.js", + "module": "index.js", + "es2015": "./es2015/index.js", + "keywords": [ + "angular", + "firebase", + "rxjs" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/angular/angularfire2.git" + }, + "author": "angular,firebase", + "license": "MIT", + "peerDependencies": { + "@angular/fire": "ANGULARFIRE2_VERSION", + "@angular/common": "ANGULAR_VERSION", + "@angular/core": "ANGULAR_VERSION", + "@angular/platform-browser": "ANGULAR_VERSION", + "@angular/platform-browser-dynamic": "ANGULAR_VERSION", + "firebase": "FIREBASE_VERSION", + "rxjs": "RXJS_VERSION", + "zone.js": "ZONEJS_VERSION" + }, + "typings": "index.d.ts" +} diff --git a/src/performance/performance.module.ts b/src/performance/performance.module.ts new file mode 100644 index 000000000..c167877fc --- /dev/null +++ b/src/performance/performance.module.ts @@ -0,0 +1,9 @@ +import { NgModule } from '@angular/core'; +import { AngularFirePerformance } from './performance'; + +import 'firebase/performance'; + +@NgModule({ + providers: [ AngularFirePerformance ] +}) +export class AngularFirePerformanceModule { } diff --git a/src/performance/performance.spec.ts b/src/performance/performance.spec.ts new file mode 100644 index 000000000..f610feeeb --- /dev/null +++ b/src/performance/performance.spec.ts @@ -0,0 +1,36 @@ +import { TestBed, inject } from '@angular/core/testing'; +import { FirebaseApp, AngularFireModule } from '@angular/fire'; +import { AngularFirePerformance, AngularFirePerformanceModule } from '@angular/fire/performance'; +import { COMMON_CONFIG } from './test-config'; + +describe('AngularFirePerformance', () => { + let app: FirebaseApp; + let afp: AngularFirePerformance; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + AngularFireModule.initializeApp(COMMON_CONFIG), + AngularFirePerformanceModule + ] + }); + inject([FirebaseApp, AngularFirePerformance], (app_: FirebaseApp, _perf: AngularFirePerformance) => { + app = app_; + afp = _perf; + })(); + }); + + afterEach(done => { + app.delete(); + done(); + }); + + it('should be exist', () => { + expect(afp instanceof AngularFirePerformance).toBe(true); + }); + + it('should have the Performance instance', () => { + expect(afp.performance).toBeDefined(); + }); + +}); \ No newline at end of file diff --git a/src/performance/performance.ts b/src/performance/performance.ts new file mode 100644 index 000000000..f1c909565 --- /dev/null +++ b/src/performance/performance.ts @@ -0,0 +1,123 @@ +import { Injectable, NgZone, ApplicationRef, InjectionToken, Inject, Optional } from '@angular/core'; +import { Observable } from 'rxjs'; +import { first, tap } from 'rxjs/operators'; +import { performance } from 'firebase/app'; + +export const AUTOMATICALLY_TRACE_CORE_NG_METRICS = new InjectionToken<boolean>('angularfire2.performance.auto_trace'); +export const INSTRUMENTATION_ENABLED = new InjectionToken<boolean>('angularfire2.performance.instrumentationEnabled'); +export const DATA_COLLECTION_ENABLED = new InjectionToken<boolean>('angularfire2.performance.dataCollectionEnabled'); + +export type TraceOptions = { + metrics?: {[key:string]: number}, + attributes?: {[key:string]:string}, + attribute$?: {[key:string]:Observable<string>}, + incrementMetric$?: {[key:string]: Observable<number|void|null|undefined>}, + metric$?: {[key:string]: Observable<number>} +}; + +@Injectable() +export class AngularFirePerformance { + + performance: performance.Performance; + + constructor( + @Optional() @Inject(AUTOMATICALLY_TRACE_CORE_NG_METRICS) automaticallyTraceCoreNgMetrics:boolean|null, + @Optional() @Inject(INSTRUMENTATION_ENABLED) instrumentationEnabled:boolean|null, + @Optional() @Inject(DATA_COLLECTION_ENABLED) dataCollectionEnabled:boolean|null, + appRef: ApplicationRef, + private zone: NgZone + ) { + + this.performance = zone.runOutsideAngular(() => performance()); + + if (instrumentationEnabled == false) { this.performance.instrumentationEnabled = false } + if (dataCollectionEnabled == false) { this.performance.dataCollectionEnabled = false } + + if (automaticallyTraceCoreNgMetrics != false) { + + // TODO determine more built in metrics + appRef.isStable.pipe( + this.traceUntilLast('isStable'), + first(it => it) + ).subscribe(); + + } + + } + + trace$ = (name:string, options?: TraceOptions) => new Observable<void>(emitter => + this.zone.runOutsideAngular(() => { + const trace = this.performance.trace(name); + options && options.metrics && Object.keys(options.metrics).forEach(metric => { + trace.putMetric(metric, options!.metrics![metric]) + }); + options && options.attributes && Object.keys(options.attributes).forEach(attribute => { + trace.putAttribute(attribute, options!.attributes![attribute]) + }); + const attributeSubscriptions = options && options.attribute$ ? Object.keys(options.attribute$).map(attribute => + options!.attribute$![attribute].subscribe(next => trace.putAttribute(attribute, next)) + ) : []; + const metricSubscriptions = options && options.metric$ ? Object.keys(options.metric$).map(metric => + options!.metric$![metric].subscribe(next => trace.putMetric(metric, next)) + ) : []; + const incrementOnSubscriptions = options && options.incrementMetric$ ? Object.keys(options.incrementMetric$).map(metric => + options!.incrementMetric$![metric].subscribe(next => trace.incrementMetric(metric, next || undefined)) + ) : []; + emitter.next(trace.start()); + return { unsubscribe: () => { + trace.stop(); + metricSubscriptions.forEach(m => m.unsubscribe()); + incrementOnSubscriptions.forEach(m => m.unsubscribe()); + attributeSubscriptions.forEach(m => m.unsubscribe()); + }}; + }) + ); + + traceUntil = <T=any>(name:string, test: (a:T) => boolean, options?: TraceOptions) => (source$: Observable<T>) => { + const traceSubscription = this.trace$(name, options).subscribe(); + return source$.pipe( + tap(a => { if (test(a)) { traceSubscription.unsubscribe() }}) + ) + }; + + traceWhile = <T=any>(name:string, test: (a:T) => boolean, options?: TraceOptions) => (source$: Observable<T>) => { + const traceSubscription = this.trace$(name, options).subscribe(); + return source$.pipe( + tap(a => { if (!test(a)) { traceSubscription.unsubscribe() }}) + ) + }; + + traceUntilLast= <T=any>(name:string, options?: TraceOptions) => (source$: Observable<T>) => { + const traceSubscription = this.trace$(name, options).subscribe(); + return source$.pipe( + tap( + () => {}, + () => {}, + () => traceSubscription.unsubscribe() + ) + ) + }; + + traceUntilFirst = <T=any>(name:string, options?: TraceOptions) => (source$: Observable<T>) => { + const traceSubscription = this.trace$(name, options).subscribe(); + return source$.pipe( + tap( + () => traceSubscription.unsubscribe(), + () => {}, + () => {} + ) + ) + }; + + trace = <T=any>(name:string, options?: TraceOptions) => (source$: Observable<T>) => { + const traceSubscription = this.trace$(name, options).subscribe(); + return source$.pipe( + tap( + () => traceSubscription.unsubscribe(), + () => {}, + () => traceSubscription.unsubscribe() + ) + ) + }; + +} diff --git a/src/performance/public_api.ts b/src/performance/public_api.ts new file mode 100644 index 000000000..620865da9 --- /dev/null +++ b/src/performance/public_api.ts @@ -0,0 +1,2 @@ +export * from './performance'; +export * from './performance.module'; diff --git a/src/performance/test-config.ts b/src/performance/test-config.ts new file mode 100644 index 000000000..e134426d4 --- /dev/null +++ b/src/performance/test-config.ts @@ -0,0 +1,10 @@ + +export const COMMON_CONFIG = { + apiKey: "AIzaSyBVSy3YpkVGiKXbbxeK0qBnu3-MNZ9UIjA", + authDomain: "angularfire2-test.firebaseapp.com", + databaseURL: "https://angularfire2-test.firebaseio.com", + projectId: "angularfire2-test", + storageBucket: "angularfire2-test.appspot.com", + messagingSenderId: "920323787688", + appId: "1:920323787688:web:2253a0e5eb5b9a8b" +}; diff --git a/src/performance/tsconfig-build.json b/src/performance/tsconfig-build.json new file mode 100644 index 000000000..aa254cafe --- /dev/null +++ b/src/performance/tsconfig-build.json @@ -0,0 +1,33 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "module": "es2015", + "target": "es2015", + "noImplicitAny": false, + "outDir": "../../dist/packages-dist/performance/es2015", + "rootDir": ".", + "sourceMap": true, + "inlineSources": true, + "declaration": false, + "removeComments": true, + "strictNullChecks": true, + "lib": ["es2015", "dom", "es2015.promise", "es2015.collection", "es2015.iterable"], + "skipLibCheck": true, + "moduleResolution": "node", + "paths": { + "@angular/fire": ["../../dist/packages-dist"] + } + }, + "files": [ + "index.ts", + "../../node_modules/zone.js/dist/zone.js.d.ts" + ], + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableSummariesForJit": false + } +} + diff --git a/src/performance/tsconfig-esm.json b/src/performance/tsconfig-esm.json new file mode 100644 index 000000000..4dd3842af --- /dev/null +++ b/src/performance/tsconfig-esm.json @@ -0,0 +1,19 @@ +{ + "extends": "./tsconfig-build.json", + "compilerOptions": { + "target": "es5", + "outDir": "../../dist/packages-dist/performance", + "declaration": true + }, + "files": [ + "public_api.ts", + "../../node_modules/zone.js/dist/zone.js.d.ts" + ], + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableSummariesForJit": false, + "flatModuleOutFile": "index.js", + "flatModuleId": "@angular/fire/performance" + } +} diff --git a/src/performance/tsconfig-test.json b/src/performance/tsconfig-test.json new file mode 100644 index 000000000..f6ca2b3c2 --- /dev/null +++ b/src/performance/tsconfig-test.json @@ -0,0 +1,13 @@ +{ + "extends": "./tsconfig-esm.json", + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@angular/fire": ["../../dist/packages-dist"] + } + }, + "files": [ + "index.spec.ts", + "../../node_modules/zone.js/dist/zone.js.d.ts" + ] +} diff --git a/src/root.spec.js b/src/root.spec.js index a44c7a68b..2819c3a0e 100644 --- a/src/root.spec.js +++ b/src/root.spec.js @@ -15,6 +15,7 @@ export * from './packages-dist/database/list/snapshot-changes.spec'; export * from './packages-dist/database/list/state-changes.spec'; export * from './packages-dist/database/list/audit-trail.spec'; export * from './packages-dist/storage/storage.spec'; +export * from './packages-dist/performance/performance.spec'; //export * from './packages-dist/messaging/messaging.spec'; // // Since this a deprecated API, we run on it on manual tests only diff --git a/src/tsconfig.json b/src/tsconfig.json index 42b5cd977..6978e6669 100644 --- a/src/tsconfig.json +++ b/src/tsconfig.json @@ -18,6 +18,7 @@ "@angular/fire/functions": ["./functions"], "@angular/fire/storage": ["./storage"], "@angular/fire/messaging": ["./messaging"], + "@angular/fire/performance": ["./performance"], "@angular/fire/database-deprecated": ["./database-deprecated"] }, "rootDir": ".", diff --git a/tools/build.js b/tools/build.js index 41c8bfcc4..0fe66ccb9 100644 --- a/tools/build.js +++ b/tools/build.js @@ -27,6 +27,7 @@ const GLOBALS = { 'firebase/messaging': 'firebase', 'firebase/firestore': 'firebase', 'firebase/functions': 'firebase', + 'firebase/performance': 'firebase', 'firebase/storage': 'firebase', '@angular/fire': 'angularfire2', '@angular/fire/auth': 'angularfire2.auth', @@ -37,6 +38,7 @@ const GLOBALS = { '@angular/fire/functions': 'angularfire2.functions', '@angular/fire/storage': 'angularfire2.storage', '@angular/fire/messaging': 'angularfire2.messaging', + '@angular/fire/performance': 'angularfire2.performance', 'fs': 'node.fs', 'path': 'node.path', 'inquirer': 'inquirer' @@ -72,6 +74,7 @@ const MODULE_NAMES = { schematics: 'angularfire2.schematics', storage: 'angularfire2.storage', messaging: 'angularfire2.messaging', + performance: 'angularfire2.performance' }; const ENTRIES = { @@ -85,6 +88,7 @@ const ENTRIES = { schematics: `${process.cwd()}/dist/packages-dist/schematics/index.js`, storage: `${process.cwd()}/dist/packages-dist/storage/index.js`, messaging: `${process.cwd()}/dist/packages-dist/messaging/index.js`, + performance: `${process.cwd()}/dist/packages-dist/performance/index.js` }; const SRC_PKG_PATHS = { @@ -98,6 +102,7 @@ const SRC_PKG_PATHS = { functions: `${process.cwd()}/src/functions/package.json`, storage: `${process.cwd()}/src/storage/package.json`, messaging: `${process.cwd()}/src/messaging/package.json`, + performance: `${process.cwd()}/src/performance/package.json` }; const DEST_PKG_PATHS = { @@ -111,6 +116,7 @@ const DEST_PKG_PATHS = { functions: `${process.cwd()}/dist/packages-dist/functions/package.json`, storage: `${process.cwd()}/dist/packages-dist/storage/package.json`, messaging: `${process.cwd()}/dist/packages-dist/messaging/package.json`, + performance: `${process.cwd()}/dist/packages-dist/performance/package.json` }; // Constants for running typescript commands @@ -295,6 +301,7 @@ function getVersions() { getDestPackageFile('functions'), getDestPackageFile('storage'), getDestPackageFile('messaging'), + getDestPackageFile('performance'), getDestPackageFile('database-deprecated') ]; return paths @@ -336,6 +343,7 @@ function buildModules(globals) { const schematics$ = buildModule('schematics', globals); const storage$ = buildModule('storage', globals); const messaging$ = buildModule('messaging', globals); + const performance$ = buildModule('performance', globals); const dbdep$ = buildModule('database-deprecated', globals); return forkJoin(core$, from(copyRootTest())).pipe( switchMapTo(schematics$), @@ -346,6 +354,7 @@ function buildModules(globals) { switchMapTo(functions$), switchMapTo(storage$), switchMapTo(messaging$), + switchMapTo(performance$), switchMapTo(dbdep$) ); } @@ -369,6 +378,7 @@ function buildLibrary(globals) { const functionsStats = measure('functions'); const storageStats = measure('storage'); const messagingStats = measure('messaging'); + const performanceStats = measure('performance'); const dbdepStats = measure('database-deprecated'); console.log(` core.umd.js - ${coreStats.size}, ${coreStats.gzip} @@ -379,6 +389,7 @@ firestore.umd.js - ${fsStats.size}, ${fsStats.gzip} functions.umd.js - ${functionsStats.size}, ${functionsStats.gzip} storage.umd.js - ${storageStats.size}, ${storageStats.gzip} messaging.umd.js - ${messagingStats.size}, ${messagingStats.gzip} +performance.umd.js - ${performanceStats.size}, ${performanceStats.gzip} database-deprecated.umd.js - ${dbdepStats.size}, ${dbdepStats.gzip} `); verifyVersions(); diff --git a/yarn.lock b/yarn.lock index 398dd46a5..010be29a0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,7 +2,7 @@ # yarn lockfile v1 -"@angular-devkit/architect@^0.800.0-rc.4": +"@angular-devkit/architect@^0.800.0-rc.4 || >=8.0.0 <9 || 9.0.0-0": version "0.800.0-rc.4" resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.800.0-rc.4.tgz#ca0bb9b7b62663caf7bf76f8f0afb2ec5ac32db1" integrity sha512-R+LxKHuGKawzAtSBL7fQ9oYEQfzAEX5DNMvDVC1f+INmyA03vcTKPNf1JzgzetKAN4Y3rt4zpv4OSLiuhjvFwg==