From 0dde8ae83b394f56afd8ed570946df3a6d035e70 Mon Sep 17 00:00:00 2001 From: Jeff Cross Date: Thu, 15 Sep 2016 11:17:26 -0700 Subject: [PATCH 1/5] test: add npm artifact build step to Travis --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index d3106af2d..e21e09b5c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,6 +30,8 @@ before_script: script: - npm run build - ./node_modules/.bin/karma start --single-run --browsers Firefox --reporters mocha + # Make sure the build that ships to npm builds without errors + - npm run build_npm # Can't run until https://github.com/angular/protractor/issues/2784 is resolved #- ./node_modules/.bin/protractor protractor.conf.js --browser firefox From 3f2baef3c902b7fe908a285a70c7696e085d4841 Mon Sep 17 00:00:00 2001 From: Jeff Cross Date: Thu, 15 Sep 2016 10:39:57 -0700 Subject: [PATCH 2/5] fix(typescript): use correct ts version and fix promise types Angular's compiler CLI requires typescript@^1.9.0-dev. The built-in Promise typings for that version of TS don't play well with Firebase Promise when using Promise.resolve, so the firebase_sdk_auth_backend has a function that will cast the promises as the correct type. --- package.json | 2 +- src/auth/firebase_sdk_auth_backend.ts | 21 +++++++++++++-------- tsconfig.json | 3 ++- tsconfig.publish.es5.json | 3 ++- tsconfig.publish.es6.json | 4 +++- 5 files changed, 21 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 01ce1faf7..63045db04 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ "traceur": "0.0.96", "tsd": "^0.6.5", "typedoc": "github:jeffbcross/typedoc", - "typescript": "next", + "typescript": "^2.0.2", "typings": "^1.3.2", "zone.js": "^0.6.21" }, diff --git a/src/auth/firebase_sdk_auth_backend.ts b/src/auth/firebase_sdk_auth_backend.ts index 2f42e48e9..d8a42c75f 100644 --- a/src/auth/firebase_sdk_auth_backend.ts +++ b/src/auth/firebase_sdk_auth_backend.ts @@ -34,7 +34,7 @@ export class FirebaseSdkAuthBackend extends AuthBackend { } createUser(creds: EmailPasswordCredentials): Promise { - return Promise.resolve(this._fbAuth.createUserWithEmailAndPassword(creds.email, creds.password)) + return castPromise(this._fbAuth.createUserWithEmailAndPassword(creds.email, creds.password)) .then((user: firebase.User) => authDataToAuthState(user)); } @@ -64,17 +64,17 @@ export class FirebaseSdkAuthBackend extends AuthBackend { } authWithCustomToken(token: string): Promise { - return Promise.resolve(this._fbAuth.signInWithCustomToken(token)) + return castPromise((this._fbAuth.signInWithCustomToken(token))) .then((user: firebase.User) => authDataToAuthState(user)); } authAnonymously(): Promise { - return Promise.resolve(this._fbAuth.signInAnonymously()) + return castPromise(this._fbAuth.signInAnonymously()) .then((user: firebase.User) => authDataToAuthState(user)); } authWithPassword(creds: EmailPasswordCredentials): Promise { - return Promise.resolve(this._fbAuth.signInWithEmailAndPassword(creds.email, creds.password)) + return castPromise(this._fbAuth.signInWithEmailAndPassword(creds.email, creds.password)) .then((user: firebase.User) => authDataToAuthState(user)); } @@ -83,7 +83,7 @@ export class FirebaseSdkAuthBackend extends AuthBackend { if (options.scope) { options.scope.forEach(scope => providerFromFirebase.addScope(scope)); } - return Promise.resolve(this._fbAuth.signInWithPopup(providerFromFirebase)); + return castPromise(this._fbAuth.signInWithPopup(providerFromFirebase)); } /** @@ -92,16 +92,16 @@ export class FirebaseSdkAuthBackend extends AuthBackend { * You should subscribe to the FirebaseAuth object to listen succesful login */ authWithOAuthRedirect(provider: AuthProviders, options?: any): Promise { - return Promise.resolve(this._fbAuth.signInWithRedirect(this._enumToAuthProvider(provider))); + return castPromise(this._fbAuth.signInWithRedirect(this._enumToAuthProvider(provider))); } authWithOAuthToken(credential: firebase.auth.AuthCredential): Promise { - return Promise.resolve(this._fbAuth.signInWithCredential(credential)) + return castPromise(this._fbAuth.signInWithCredential(credential)) .then((user: firebase.User) => authDataToAuthState(user)); } getRedirectResult(): Observable { - return Observable.fromPromise(Promise.resolve(this._fbAuth.getRedirectResult())); + return Observable.fromPromise(castPromise(this._fbAuth.getRedirectResult())); } private _enumToAuthProvider(providerId: AuthProviders): any { @@ -119,3 +119,8 @@ export class FirebaseSdkAuthBackend extends AuthBackend { } } } + +// Cast Firebase promises as Zone-patched Promises +function castPromise(promiseLike: PromiseLike): Promise { + return Promise.resolve(promiseLike) as Promise; +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 1bed18251..bd88bde0f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -33,6 +33,7 @@ "node_modules/zone.js/dist/zone.js.d.ts" ], "angularCompilerOptions": { - "skipTemplateCodegen": true + "skipTemplateCodegen": true, + "strictMetadataEmit": true } } diff --git a/tsconfig.publish.es5.json b/tsconfig.publish.es5.json index 2def0360f..802f5f97a 100644 --- a/tsconfig.publish.es5.json +++ b/tsconfig.publish.es5.json @@ -24,6 +24,7 @@ "node_modules/zone.js/dist/zone.js.d.ts" ], "angularCompilerOptions": { - "skipTemplateCodegen": true + "skipTemplateCodegen": true, + "strictMetadataEmit": true } } diff --git a/tsconfig.publish.es6.json b/tsconfig.publish.es6.json index afe24ffc3..9ee258a88 100644 --- a/tsconfig.publish.es6.json +++ b/tsconfig.publish.es6.json @@ -15,6 +15,7 @@ "es2015", "dom" ], + "skipLibCheck": true, "moduleResolution": "node" }, "files": [ @@ -25,6 +26,7 @@ "node_modules/zone.js/dist/zone.js.d.ts" ], "angularCompilerOptions": { - "skipTemplateCodegen": true + "skipTemplateCodegen": true, + "strictMetadataEmit": true } } From b3b78f43595eb72f053feda90350d00aba48428b Mon Sep 17 00:00:00 2001 From: Jeff Cross Date: Thu, 15 Sep 2016 15:30:52 -0700 Subject: [PATCH 3/5] feat(packaging): add aot-friendly packaging This change introduces a UMD bundle to the published package, and adds ES2015 modules to the root of the project. Some changes were necessary to fix imports and make rollup work correctly. This change should make AngularFire2 ahead-of-time-compilation -friendly. --- karma-test-shim.js | 86 ++------------------------- karma.conf.js | 32 +++++----- package.json | 21 ++++--- rollup-globals.js | 10 ++++ rollup.publish.config.js | 9 +++ rollup.test.config.js | 9 +++ src/auth/firebase_sdk_auth_backend.ts | 2 +- src/database/query_observable.ts | 22 +++---- src/index.ts | 1 + src/test-root.ts | 8 +++ src/utils.ts | 13 ++-- tools/rewrite-published-package.js | 7 +-- tsconfig.json | 17 ++---- tsconfig.publish.es5.json | 30 ---------- tsconfig.publish.es6-deprecated.json | 20 ------- tsconfig.publish.es6.json | 6 +- 16 files changed, 94 insertions(+), 199 deletions(-) create mode 100644 rollup-globals.js create mode 100644 rollup.publish.config.js create mode 100644 rollup.test.config.js create mode 100644 src/index.ts create mode 100644 src/test-root.ts delete mode 100644 tsconfig.publish.es5.json delete mode 100644 tsconfig.publish.es6-deprecated.json diff --git a/karma-test-shim.js b/karma-test-shim.js index d1bf56928..77331c17e 100644 --- a/karma-test-shim.js +++ b/karma-test-shim.js @@ -2,85 +2,7 @@ Error.stackTraceLimit = Infinity; jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; -__karma__.loaded = function () { -}; - - -function isJsFile(path) { - return path.slice(-3) == '.js'; -} - -function isSpecFile(path) { - return path.slice(-7) == 'spec.js'; -} - -function isBuiltFile(path) { - var builtPath = '/base/dist/'; - return isJsFile(path) && (path.substr(0, builtPath.length) == builtPath); -} - -var allSpecFiles = Object.keys(window.__karma__.files) - .filter(isSpecFile) - .filter(isBuiltFile); - -// Load our SystemJS configuration. -System.config({ - baseURL: '/base' -}); - -System.config( -{ - paths: { - // paths serve as alias - 'npm:': 'node_modules/' - }, - map: { - 'app': 'dist', - '@angular/core': 'npm:@angular/core/bundles/core.umd.js', - '@angular/common': 'npm:@angular/common/bundles/common.umd.js', - '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js', - '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js', - '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js', - - // angular testing umd bundles - '@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js', - '@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js', - '@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js', - '@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js', - '@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js', - - // other libraries - 'rxjs': 'npm:rxjs', - 'firebase': 'npm:firebase/firebase.js' - }, - packages: { - 'app': { - defaultExtension: 'js' - }, - 'rxjs': { - main: 'Rx.js', - defaultExtension: 'js' - } - } -}); - -Promise.all([ - System.import('@angular/core/testing'), - System.import('@angular/platform-browser-dynamic/testing') -]).then(function (providers) { - var testing = providers[0]; - var testingBrowser = providers[1]; - - testing.TestBed.initTestEnvironment( - testingBrowser.BrowserDynamicTestingModule, - testingBrowser.platformBrowserDynamicTesting() - ); - -}).then(function() { - // Finally, load all spec files. - // This will run the tests directly. - return Promise.all( - allSpecFiles.map(function (moduleName) { - return System.import(moduleName); - })); -}).then(__karma__.start, __karma__.error); \ No newline at end of file +ng.core.testing.TestBed.initTestEnvironment( + ng.platformBrowserDynamic.testing.BrowserDynamicTestingModule, + ng.platformBrowserDynamic.testing.platformBrowserDynamicTesting() +); diff --git a/karma.conf.js b/karma.conf.js index 36f0bf4d8..7ccc72255 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -12,10 +12,6 @@ module.exports = function(config) { 'node_modules/reflect-metadata/Reflect.js', - // System.js for module loading - 'node_modules/systemjs/dist/system-polyfills.js', - 'node_modules/systemjs/dist/system.src.js', - // Zone.js dependencies 'node_modules/zone.js/dist/zone.js', 'node_modules/zone.js/dist/proxy.js', @@ -24,21 +20,13 @@ module.exports = function(config) { 'node_modules/zone.js/dist/async-test.js', 'node_modules/zone.js/dist/fake-async-test.js', - // RxJs. - { pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false }, - { pattern: 'node_modules/rxjs/**/*.js.map', included: false, watched: false }, - - - { pattern: 'karma-test-shim.js', included: true, watched: true }, + 'node_modules/rxjs/bundles/Rx.{js,map}', - // paths loaded via module imports - // Angular itself - { pattern: 'node_modules/@angular/**/*.js', included: false, watched: true }, - { pattern: 'node_modules/@angular/**/*.js.map', included: false, watched: true }, + ...getAngularFiles(['core','common','compiler','platform-browser','platform-browser-dynamic']), - { pattern: 'node_modules/firebase/firebase.js', included: false, watched: false }, - { pattern: 'dist/**/*.js', included: false, watched: true }, - { pattern: 'dist/**/*.js.map', included: false, watched: false } + 'karma-test-shim.js', + 'node_modules/firebase/firebase.js', + 'dist/bundles/test-root.umd.{js,map}', ], port: 9876, @@ -48,4 +36,12 @@ module.exports = function(config) { browsers: ['Chrome'], singleRun: false }) -}; \ No newline at end of file +}; + +function getAngularFiles(packages) { + return packages.reduce((files, pkg) => { + files.push(`node_modules/@angular/${pkg}/bundles/${pkg}.umd.js`); + files.push(`node_modules/@angular/${pkg}/bundles/${pkg}-testing.umd.js`); + return files; + }, []); +} diff --git a/package.json b/package.json index 63045db04..005fa8133 100644 --- a/package.json +++ b/package.json @@ -2,18 +2,20 @@ "name": "angularfire2", "version": "2.0.0-beta.5", "description": "", - "main": "./dist/angularfire2.js", - "jsnext:main": "./dist/esm/angularfire2.js", + "main": "bundles/angularfire2.umd.js", + "module": "index.js", "scripts": { "test": "npm run build; karma start --single-run", - "test:watch": "karma start", - "build": "rm -rf dist; tsc", - "build:watch": "rm -rf dist && tsc -w", - "build_npm": "rm -rf dist && ngc -p tsconfig.publish.es5.json && ngc -p tsconfig.publish.es6.json && npm run postbuild_npm", + "test:watch": "concurrently 'npm run build:watch' 'npm run delayed_karma'", + "delayed_karma": "sleep 10 && karma start", + "delayed_rollup": "sleep 5 && rollup --watch -c rollup.test.config.js", + "build:watch": "rm -rf dist && concurrently 'tsc -w' 'npm run delayed_rollup'", + "build": "rm -rf dist && tsc && rollup -c rollup.test.config.js", + "build_npm": "rm -rf dist && ngc -p tsconfig.publish.es6.json && rollup -c rollup.publish.config.js && npm run postbuild_npm", + "build_e2e": "rm -rf dist-test && npm run build && tsc -p test/ && cp test/e2e/firebase_object/index.html dist-test/e2e/firebase_object/ && cp test/e2e/firebase_list/index.html dist-test/e2e/firebase_list/ && cp test/e2e/auth/index.html dist-test/e2e/auth/", "postbuild_npm": "cp package.json README.md .npmignore dist/ && npm run rewrite_npm_package", "rewrite_npm_package": "node --harmony_destructuring tools/rewrite-published-package.js", "e2e_test": "webdriver-manager update && npm run build_e2e && protractor", - "build_e2e": "rm -rf dist-test && npm run build && tsc -p test/ && cp test/e2e/firebase_object/index.html dist-test/e2e/firebase_object/ && cp test/e2e/firebase_list/index.html dist-test/e2e/firebase_list/ && cp test/e2e/auth/index.html dist-test/e2e/auth/", "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 1" }, "keywords": [ @@ -44,6 +46,7 @@ "devDependencies": { "@angular/compiler-cli": "^0.5.0", "@angular/platform-server": "^2.0.0-rc.5", + "concurrently": "^2.2.0", "conventional-changelog-cli": "^1.2.0", "es6-module-loader": "^0.17.10", "es6-shim": "^0.35.0", @@ -64,6 +67,8 @@ "parse5": "^1.3.2", "protractor": "3.0.0", "reflect-metadata": "0.1.2", + "rollup": "^0.35.11", + "rollup-watch": "^2.5.0", "systemjs": "^0.19.16", "systemjs-builder": "^0.15.7", "traceur": "0.0.96", @@ -73,5 +78,5 @@ "typings": "^1.3.2", "zone.js": "^0.6.21" }, - "typings": "dist/angularfire2.d.ts" + "typings": "index.d.ts" } diff --git a/rollup-globals.js b/rollup-globals.js new file mode 100644 index 000000000..4fc8e1fe1 --- /dev/null +++ b/rollup-globals.js @@ -0,0 +1,10 @@ +export default (mod) => { + if (mod === 'rxjs') return 'Rx'; + if (mod.indexOf('rxjs/operator') === 0) return `Rx.Observable.prototype`; + if (mod === 'rxjs/scheduler/queue') return 'Rx.Scheduler'; + if (mod.indexOf('rxjs/') === 0) return 'Rx'; + + if (mod === 'firebase') return 'firebase'; + if (mod === '@angular/core') return 'ng.core'; + if (mod === '@angular/core/testing') return 'ng.core.testing'; +} diff --git a/rollup.publish.config.js b/rollup.publish.config.js new file mode 100644 index 000000000..04b2673f3 --- /dev/null +++ b/rollup.publish.config.js @@ -0,0 +1,9 @@ +import globals from './rollup-globals'; + +export default { + entry: 'dist/index.js', + dest: 'dist/bundles/angularFire2.umd.js', + format: 'umd', + moduleName: 'angularFire2', + globals +} diff --git a/rollup.test.config.js b/rollup.test.config.js new file mode 100644 index 000000000..e18879d15 --- /dev/null +++ b/rollup.test.config.js @@ -0,0 +1,9 @@ +import globals from './rollup-globals'; + +export default { + entry: 'dist/test-root.js', + dest: 'dist/bundles/test-root.umd.js', + format: 'umd', + moduleName: 'angularFire2.test', + globals +} diff --git a/src/auth/firebase_sdk_auth_backend.ts b/src/auth/firebase_sdk_auth_backend.ts index d8a42c75f..f6f6b035b 100644 --- a/src/auth/firebase_sdk_auth_backend.ts +++ b/src/auth/firebase_sdk_auth_backend.ts @@ -123,4 +123,4 @@ export class FirebaseSdkAuthBackend extends AuthBackend { // Cast Firebase promises as Zone-patched Promises function castPromise(promiseLike: PromiseLike): Promise { return Promise.resolve(promiseLike) as Promise; -} \ No newline at end of file +} diff --git a/src/database/query_observable.ts b/src/database/query_observable.ts index ea3d25e98..6d7e6abbd 100644 --- a/src/database/query_observable.ts +++ b/src/database/query_observable.ts @@ -1,24 +1,24 @@ import { Observable } from 'rxjs/Observable'; -import { ScalarObservable } from 'rxjs/observable/ScalarObservable'; +import 'rxjs/add/observable/of'; import { Operator } from 'rxjs/Operator'; import { Observer } from 'rxjs/Observer'; import { merge } from 'rxjs/operator/merge'; import { map } from 'rxjs/operator/map'; -import { - Query, - ScalarQuery, - OrderByOptions, - OrderBySelection, - LimitToOptions, - LimitToSelection, - Primitive +import { + Query, + ScalarQuery, + OrderByOptions, + OrderBySelection, + LimitToOptions, + LimitToSelection, + Primitive } from '../interfaces'; import 'rxjs/add/operator/merge'; import 'rxjs/add/operator/combineLatest'; export function observeQuery(query: Query): Observable { if (!isPresent(query)) { - return new ScalarObservable(null); + return Observable.of(null); } return Observable.create((observer: Observer) => { @@ -97,7 +97,7 @@ export function getOrderObservables(query: Query): Observable } else { return new Observable(subscriber => { subscriber.next(null); - }); + }); } } diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 000000000..d0e702904 --- /dev/null +++ b/src/index.ts @@ -0,0 +1 @@ +export * from './angularfire2'; diff --git a/src/test-root.ts b/src/test-root.ts new file mode 100644 index 000000000..3711c1783 --- /dev/null +++ b/src/test-root.ts @@ -0,0 +1,8 @@ +export * from './angularfire2.spec'; +export * from './database/firebase_list_factory.spec'; +export * from './database/firebase_object_factory.spec'; +export * from './database/firebase_list_observable.spec'; +export * from './database/firebase_object_observable.spec'; +export * from './database/query_observable.spec'; +export * from './auth/auth.spec'; +export * from './auth/auth_backend.spec'; diff --git a/src/utils.ts b/src/utils.ts index cdbaf1099..aa9fd2293 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,7 +1,6 @@ import { Subscription } from 'rxjs/Subscription'; -import { QueueScheduler } from 'rxjs/scheduler/QueueScheduler'; -import { QueueAction } from 'rxjs/scheduler/QueueAction'; import { Scheduler } from 'rxjs/Scheduler'; +import { queue } from 'rxjs/scheduler/queue'; import { AFUnwrappedDataSnapshot} from './interfaces'; export function isPresent(obj: any): boolean { @@ -40,7 +39,7 @@ export interface CheckUrlRef { } /** - * Unwraps the data returned in the DataSnapshot. Exposes the DataSnapshot key and exists methods through the $key and $exists properties respectively. If the value is primitive, it is unwrapped using a $value property. The $ properies mean they cannot be saved in the Database as those characters are invalid. + * Unwraps the data returned in the DataSnapshot. Exposes the DataSnapshot key and exists methods through the $key and $exists properties respectively. If the value is primitive, it is unwrapped using a $value property. The $ properies mean they cannot be saved in the Database as those characters are invalid. * @param {DataSnapshot} snapshot - The snapshot to unwrap * @return AFUnwrappedDataSnapshot * @example @@ -95,12 +94,10 @@ export function stripLeadingSlash(value: string): string { * TODO: remove this scheduler once Rx has a more robust story for working * with zones. */ -export class ZoneScheduler extends QueueScheduler { - constructor(public zone: Zone) { - super(QueueAction); - } +export class ZoneScheduler { + constructor(public zone: Zone) {} schedule(...args): Subscription { - return this.zone.run(() => super.schedule.apply(this, args)); + return this.zone.run(() => queue.schedule.apply(queue, args)); } } diff --git a/tools/rewrite-published-package.js b/tools/rewrite-published-package.js index 41d86e605..2f7e3ba31 100644 --- a/tools/rewrite-published-package.js +++ b/tools/rewrite-published-package.js @@ -5,16 +5,15 @@ */ var fs = require('fs'); var srcPackage = require('../package.json'); -var [MAIN, JSNEXT_MAIN] = ['main', 'jsnext:main'].map(k => srcPackage[k].replace('/dist/', '/')); + +delete srcPackage.scripts; var peerDependencies = Object.assign({}, srcPackage.dependencies); // See note about including firebase as dependency delete peerDependencies.firebase; + var outPackage = Object.assign({}, srcPackage, { peerDependencies, - main: MAIN, - typings: "angularfire2.d.ts", - "jsnext:main": JSNEXT_MAIN, dependencies: { /** * Firebase SDK should be a dependency since it's not required that diff --git a/tsconfig.json b/tsconfig.json index bd88bde0f..8041f68a3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "experimentalDecorators": true, "emitDecoratorMetadata": true, - "module": "commonjs", + "module": "es2015", "target": "es5", "noImplicitAny": false, "outDir": "dist", @@ -15,20 +15,11 @@ "es2015", "dom" ], - "skipLibCheck": true + "skipLibCheck": true, + "moduleResolution": "node" }, "files": [ - "src/angularfire2.ts", - "src/angularfire2.spec.ts", - "src/database/index.ts", - "src/database/firebase_list_factory.spec.ts", - "src/database/firebase_object_factory.spec.ts", - "src/database/firebase_list_observable.spec.ts", - "src/database/firebase_object_observable.spec.ts", - "src/database/query_observable.spec.ts", - "src/auth/auth.ts", - "src/auth/auth.spec.ts", - "src/auth/auth_backend.spec.ts", + "src/test-root.ts", "typings/index.d.ts", "node_modules/zone.js/dist/zone.js.d.ts" ], diff --git a/tsconfig.publish.es5.json b/tsconfig.publish.es5.json deleted file mode 100644 index 802f5f97a..000000000 --- a/tsconfig.publish.es5.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "compilerOptions": { - "experimentalDecorators": true, - "emitDecoratorMetadata": true, - "module": "commonjs", - "target": "es5", - "noImplicitAny": false, - "outDir": "dist", - "rootDir": "src", - "sourceMap": true, - "inlineSources": true, - "declaration": true, - "removeComments": true, - "lib": [ - "es2015", - "dom" - ] - }, - "files": [ - "src/angularfire2.ts", - "src/database/index.ts", - "src/auth/auth.ts", - "typings/index.d.ts", - "node_modules/zone.js/dist/zone.js.d.ts" - ], - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true - } -} diff --git a/tsconfig.publish.es6-deprecated.json b/tsconfig.publish.es6-deprecated.json deleted file mode 100644 index 57d87b2f8..000000000 --- a/tsconfig.publish.es6-deprecated.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "compilerOptions": { - "experimentalDecorators": true, - "emitDecoratorMetadata": true, - "target": "es6", - "noImplicitAny": false, - "outDir": "dist/es6", - "rootDir": "src", - "sourceMap": true, - "inlineSources": true, - "declaration": true, - "removeComments": true, - "moduleResolution": "node" - }, - "files": [ - "src/angularfire2.ts", - "manual_typings/firebase3/firebase3.d.ts", - "node_modules/zone.js/dist/zone.js.d.ts" - ] -} diff --git a/tsconfig.publish.es6.json b/tsconfig.publish.es6.json index 9ee258a88..ecff76d76 100644 --- a/tsconfig.publish.es6.json +++ b/tsconfig.publish.es6.json @@ -5,7 +5,7 @@ "module": "es2015", "target": "es5", "noImplicitAny": false, - "outDir": "dist/es6", + "outDir": "dist", "rootDir": "src", "sourceMap": true, "inlineSources": true, @@ -19,9 +19,7 @@ "moduleResolution": "node" }, "files": [ - "src/angularfire2.ts", - "src/database/index.ts", - "src/auth/auth.ts", + "src/index.ts", "typings/index.d.ts", "node_modules/zone.js/dist/zone.js.d.ts" ], From 7921f57cede1afadae89750732265357aa89280d Mon Sep 17 00:00:00 2001 From: Jeff Cross Date: Thu, 15 Sep 2016 17:24:01 -0700 Subject: [PATCH 4/5] refactor(Observable): get rid of side-effects from rxjs throughout src Also removed side-effects from tests to verify that code under test wouldn't accidentally rely on a patched operator. --- rollup-globals.js | 1 + src/angularfire2.spec.ts | 4 -- src/auth/auth.spec.ts | 8 +-- src/auth/auth.ts | 46 ++++++++-------- src/auth/firebase_sdk_auth_backend.ts | 19 +++---- src/database/firebase_list_factory.spec.ts | 54 +++++++++---------- src/database/firebase_list_factory.ts | 9 ++-- src/database/firebase_list_observable.spec.ts | 4 +- src/database/firebase_object_factory.ts | 1 - .../firebase_object_observable.spec.ts | 4 +- src/database/query_observable.ts | 14 ++--- 11 files changed, 78 insertions(+), 86 deletions(-) diff --git a/rollup-globals.js b/rollup-globals.js index 4fc8e1fe1..25813bd9c 100644 --- a/rollup-globals.js +++ b/rollup-globals.js @@ -1,6 +1,7 @@ export default (mod) => { if (mod === 'rxjs') return 'Rx'; if (mod.indexOf('rxjs/operator') === 0) return `Rx.Observable.prototype`; + if (mod.indexOf('rxjs/observable') === 0) return `Rx.Observable`; if (mod === 'rxjs/scheduler/queue') return 'Rx.Scheduler'; if (mod.indexOf('rxjs/') === 0) return 'Rx'; diff --git a/src/angularfire2.spec.ts b/src/angularfire2.spec.ts index d745e2d73..15c38361d 100644 --- a/src/angularfire2.spec.ts +++ b/src/angularfire2.spec.ts @@ -17,10 +17,6 @@ import { } from './angularfire2'; import { Subscription } from 'rxjs/Subscription'; import { COMMON_CONFIG, ANON_AUTH_CONFIG } from './test-config'; -import 'rxjs/add/operator/toPromise'; -import 'rxjs/add/operator/take'; -import 'rxjs/add/operator/do'; -import 'rxjs/add/operator/delay'; describe('angularfire', () => { var subscription:Subscription; diff --git a/src/auth/auth.spec.ts b/src/auth/auth.spec.ts index 89fe0e6f6..885355e17 100644 --- a/src/auth/auth.spec.ts +++ b/src/auth/auth.spec.ts @@ -6,7 +6,7 @@ import { TestBed, inject } from '@angular/core/testing'; -import 'rxjs/add/operator/do'; +import { _do } from 'rxjs/operator/do'; import { defaultFirebase, @@ -97,9 +97,9 @@ describe('Zones', () => { }); ngZone.run(() => { var afAuth = new AngularFireAuth(new FirebaseSdkAuthBackend(app), window.location); - afAuth - .take(1) - .do(_ => { + var authObs = afAuth.take(1); + + _do.call(authObs, _ => { expect(Zone.current.name).toBe('ngZone'); }) .subscribe(() => { diff --git a/src/auth/auth.ts b/src/auth/auth.ts index 30064f156..21157f74b 100644 --- a/src/auth/auth.ts +++ b/src/auth/auth.ts @@ -14,11 +14,9 @@ import { FirebaseAuthState, stripProviderId } from './auth_backend'; -import 'rxjs/add/operator/mergeMap'; -import 'rxjs/add/operator/take'; -import 'rxjs/add/operator/concat'; -import 'rxjs/add/operator/skip'; -import 'rxjs/add/observable/of'; +import { mergeMap } from 'rxjs/operator/mergeMap'; +import { of as observableOf } from 'rxjs/observable/of'; +import { map } from 'rxjs/operator/map'; const kBufferSize = 1; @@ -35,26 +33,26 @@ export class AngularFireAuth extends ReplaySubject { super(kBufferSize); let firstPass = true; - this._authBackend.onAuth() - .mergeMap((authState: FirebaseAuthState) => { - if (firstPass) { - firstPass = false; - if(['http:', 'https:'].indexOf(loc.protocol) > -1) { - // Only call getRedirectResult() in a browser - return this._authBackend.getRedirectResult() - .map((userCredential: firebase.auth.UserCredential) => { - if (userCredential && userCredential.credential) { - authState = attachCredentialToAuthState(authState, userCredential.credential, userCredential.credential.provider); - this._credentialCache[userCredential.credential.provider] = userCredential.credential; - } - return authState; - }); - } - + let onAuth = this._authBackend.onAuth(); + + mergeMap.call(onAuth, (authState: FirebaseAuthState) => { + if (firstPass) { + firstPass = false; + if(['http:', 'https:'].indexOf(loc.protocol) > -1) { + // Only call getRedirectResult() in a browser + return map.call(this._authBackend.getRedirectResult(), (userCredential: firebase.auth.UserCredential) => { + if (userCredential && userCredential.credential) { + authState = attachCredentialToAuthState(authState, userCredential.credential, userCredential.credential.provider); + this._credentialCache[userCredential.credential.provider] = userCredential.credential; + } + return authState; + }); } - return Observable.of(authState); - }) - .subscribe((authData: FirebaseAuthState) => this._emitAuthData(authData)); + + } + return observableOf(authState); + }) + .subscribe((authData: FirebaseAuthState) => this._emitAuthData(authData)); } public login(config?: AuthConfiguration): firebase.Promise; diff --git a/src/auth/firebase_sdk_auth_backend.ts b/src/auth/firebase_sdk_auth_backend.ts index f6f6b035b..b5ba557f5 100644 --- a/src/auth/firebase_sdk_auth_backend.ts +++ b/src/auth/firebase_sdk_auth_backend.ts @@ -20,9 +20,9 @@ const { TwitterAuthProvider } = auth; -import 'rxjs/add/operator/map'; -import 'rxjs/add/observable/fromPromise'; -import 'rxjs/add/operator/observeOn'; +import { map } from 'rxjs/operator/map'; +import { fromPromise } from 'rxjs/observable/fromPromise'; +import { observeOn } from 'rxjs/operator/observeOn'; @Injectable() export class FirebaseSdkAuthBackend extends AuthBackend { @@ -43,20 +43,21 @@ export class FirebaseSdkAuthBackend extends AuthBackend { } onAuth(): Observable { - return Observable.create((observer: Observer) => { + let stateChange = Observable.create((observer: Observer) => { return this._fbAuth.onAuthStateChanged(observer); - }) - .map((user: firebase.User) => { + }); + let authState = map.call(stateChange, (user: firebase.User) => { if (!user) return null; return authDataToAuthState(user, user.providerData[0]); - }) + }); + /** * TODO: since the auth service automatically subscribes to this before * any user, it will run in the Angular zone, instead of the subscription * zone. The auth service should be refactored to capture the subscription * zone and not use a ReplaySubject. **/ - .observeOn(new ZoneScheduler(Zone.current)); + return observeOn.call(authState, new ZoneScheduler(Zone.current)); } unauth(): void { @@ -101,7 +102,7 @@ export class FirebaseSdkAuthBackend extends AuthBackend { } getRedirectResult(): Observable { - return Observable.fromPromise(castPromise(this._fbAuth.getRedirectResult())); + return fromPromise(castPromise(this._fbAuth.getRedirectResult())); } private _enumToAuthProvider(providerId: AuthProviders): any { diff --git a/src/database/firebase_list_factory.spec.ts b/src/database/firebase_list_factory.spec.ts index 946e33b68..a53d71ea8 100644 --- a/src/database/firebase_list_factory.spec.ts +++ b/src/database/firebase_list_factory.spec.ts @@ -24,16 +24,16 @@ import * as utils from '../utils'; import { Query, AFUnwrappedDataSnapshot } from '../interfaces'; import { Subscription, Observable, Subject } from 'rxjs'; import { COMMON_CONFIG, ANON_AUTH_CONFIG } from '../test-config'; -import 'rxjs/add/operator/do'; -import 'rxjs/add/operator/skip'; -import 'rxjs/add/operator/take'; +import { _do } from 'rxjs/operator/do'; +import { skip } from 'rxjs/operator/skip'; +import { take } from 'rxjs/operator/take'; +import { toPromise } from 'rxjs/operator/toPromise'; const rootDatabaseUrl = COMMON_CONFIG.databaseURL; function queryTest(observable: Observable, subject: Subject, done: any) { let nexted = false; - observable - .take(2) + skipAndTake(observable, 2) .subscribe(val => { if (!nexted) { subject.next('2'); @@ -378,7 +378,7 @@ describe('FirebaseListFactory', () => { it('should emit only when the initial data set has been loaded', (done: any) => { (questions)._ref.set([{ initial1: true }, { initial2: true }, { initial3: true }, { initial4: true }]) - .then(() => questions.take(1).toPromise()) + .then(() => toPromise.call(skipAndTake(questions, 1))) .then((val: any[]) => { expect(val.length).toBe(4); }) @@ -389,10 +389,8 @@ describe('FirebaseListFactory', () => { it('should emit a new value when a child moves', (done: any) => { - subscription = questions - .skip(2) - .take(1) - .do((data: any) => { + let question = skipAndTake(questions, 1, 2) + subscription = _do.call(question, (data: any) => { expect(data.length).toBe(2); expect(data[0].push2).toBe(true); expect(data[1].push1).toBe(true); @@ -412,15 +410,13 @@ describe('FirebaseListFactory', () => { it('should emit unwrapped data by default', (done: any) => { ref.remove(() => { ref.push({ unwrapped: true }, () => { - subscription = questions - .take(1) - .do((data: any) => { - expect(data.length).toBe(1); - expect(data[0].unwrapped).toBe(true); - }) - .subscribe(() => { - done(); - }, done.fail); + subscription = _do.call(skipAndTake(questions, 1), (data: any) => { + expect(data.length).toBe(1); + expect(data[0].unwrapped).toBe(true); + }) + .subscribe(() => { + done(); + }, done.fail); }); }); }); @@ -428,14 +424,12 @@ describe('FirebaseListFactory', () => { it('should emit snapshots if preserveSnapshot option is true', (done: any) => { refSnapshotted.push('hello snapshot!', () => { - subscription = questionsSnapshotted - .take(1) - .do((data: any) => { - expect(data[0].val()).toEqual('hello snapshot!'); - }) - .subscribe(() => { - done(); - }, done.fail); + subscription = _do.call(skipAndTake(questionsSnapshotted, 1),(data: any) => { + expect(data[0].val()).toEqual('hello snapshot!'); + }) + .subscribe(() => { + done(); + }, done.fail); }); }); @@ -543,9 +537,13 @@ describe('FirebaseListFactory', () => { expect(unwrappedValueLol.$key).toEqual('key'); expect(unwrappedValueLol.$value).toEqual('lol'); - expect(unwrappedValueLol.$exists()).toEqual(true); + expect(unwrappedValueLol.$exists()).toEqual(true); }); }); }); }); + +function skipAndTake(obs: Observable, takeCount: number = 1, skipCount: number = 0) { + return take.call(skip.call(obs, skipCount), takeCount); +} diff --git a/src/database/firebase_list_factory.ts b/src/database/firebase_list_factory.ts index 539168462..74454bee1 100644 --- a/src/database/firebase_list_factory.ts +++ b/src/database/firebase_list_factory.ts @@ -5,8 +5,8 @@ import { database } from 'firebase'; import { observeQuery } from './query_observable'; import { Query, FirebaseListFactoryOpts } from '../interfaces'; import * as utils from '../utils'; -import 'rxjs/add/operator/mergeMap'; -import 'rxjs/add/operator/map'; +import { mergeMap } from 'rxjs/operator/mergeMap'; +import { map } from 'rxjs/operator/map'; export function FirebaseListFactory ( absoluteUrlOrDbRef:string | @@ -31,7 +31,7 @@ export function FirebaseListFactory ( const queryObs = observeQuery(query); return new FirebaseListObservable(ref, subscriber => { - let sub = queryObs.map(query => { + let sub = mergeMap.call(map.call(queryObs, query => { let queried: firebase.database.Query = ref; // Only apply the populated keys // apply ordering and available querying options @@ -90,8 +90,7 @@ export function FirebaseListFactory ( } return queried; - }) - .mergeMap((queryRef: firebase.database.Reference, ix: number) => { + }), (queryRef: firebase.database.Reference, ix: number) => { return firebaseListObservable(queryRef, { preserveSnapshot }); }) .subscribe(subscriber); diff --git a/src/database/firebase_list_observable.spec.ts b/src/database/firebase_list_observable.spec.ts index b4ca71573..d991d4b36 100644 --- a/src/database/firebase_list_observable.spec.ts +++ b/src/database/firebase_list_observable.spec.ts @@ -1,7 +1,7 @@ import { FirebaseListObservable } from './index'; import { Observer } from 'rxjs/Observer'; import { Observable } from 'rxjs/Observable'; -import 'rxjs/add/operator/map'; +import { map } from 'rxjs/operator/map'; import { database } from 'firebase'; import { unwrapMapFn } from '../utils'; import { @@ -46,7 +46,7 @@ describe('FirebaseObservable', () => { it('should return an instance of FirebaseObservable when calling operators', () => { O = new FirebaseListObservable(ref, (observer:Observer) => { }); - expect(O.map(noop) instanceof FirebaseListObservable).toBe(true); + expect(map.call(O, noop) instanceof FirebaseListObservable).toBe(true); }); describe('push', () => { diff --git a/src/database/firebase_object_factory.ts b/src/database/firebase_object_factory.ts index ea45c8e48..844a9f055 100644 --- a/src/database/firebase_object_factory.ts +++ b/src/database/firebase_object_factory.ts @@ -5,7 +5,6 @@ import * as utils from '../utils'; import { Query } from '../interfaces'; import { observeQuery } from './query_observable'; import { FirebaseObjectFactoryOpts } from '../interfaces'; -import 'rxjs/add/operator/mergeMap'; export function FirebaseObjectFactory ( absoluteUrlOrDbRef: string | firebase.database.Reference, diff --git a/src/database/firebase_object_observable.spec.ts b/src/database/firebase_object_observable.spec.ts index d3ef9d71b..5c4945b5a 100644 --- a/src/database/firebase_object_observable.spec.ts +++ b/src/database/firebase_object_observable.spec.ts @@ -13,7 +13,7 @@ import { import { COMMON_CONFIG, ANON_AUTH_CONFIG } from '../test-config'; import { FirebaseObjectObservable } from './index'; import { Observer } from 'rxjs/Observer'; -import 'rxjs/add/operator/map'; +import { map } from 'rxjs/operator/map'; import { database } from 'firebase'; const rootDatabaseUrl = COMMON_CONFIG.databaseURL; @@ -44,7 +44,7 @@ describe('FirebaseObjectObservable', () => { it('should return an instance of FirebaseObservable when calling operators', () => { var O = new FirebaseObjectObservable((observer:Observer) => {}); - expect(O.map(noop) instanceof FirebaseObjectObservable).toBe(true); + expect(map.call(O, noop) instanceof FirebaseObjectObservable).toBe(true); }); describe('set', () => { diff --git a/src/database/query_observable.ts b/src/database/query_observable.ts index 6d7e6abbd..4f5aec90b 100644 --- a/src/database/query_observable.ts +++ b/src/database/query_observable.ts @@ -1,7 +1,8 @@ import { Observable } from 'rxjs/Observable'; -import 'rxjs/add/observable/of'; +import { of as observableOf } from 'rxjs/observable/of'; import { Operator } from 'rxjs/Operator'; import { Observer } from 'rxjs/Observer'; +import { combineLatest } from 'rxjs/operator/combineLatest'; import { merge } from 'rxjs/operator/merge'; import { map } from 'rxjs/operator/map'; import { @@ -13,18 +14,17 @@ import { LimitToSelection, Primitive } from '../interfaces'; -import 'rxjs/add/operator/merge'; -import 'rxjs/add/operator/combineLatest'; + export function observeQuery(query: Query): Observable { if (!isPresent(query)) { - return Observable.of(null); + return observableOf(null); } return Observable.create((observer: Observer) => { let obs = getOrderObservables(query) as Observable; - obs.combineLatest( + combineLatest.call(obs, getStartAtObservable(query), getEndAtObservable(query), getEqualToObservable(query), @@ -93,7 +93,7 @@ export function getOrderObservables(query: Query): Observable if (observables.length === 1) { return observables[0]; } else if (observables.length > 1) { - return observables[0].merge(observables.slice(1)); + return merge.call(observables[0], observables.slice(1)); } else { return new Observable(subscriber => { subscriber.next(null); @@ -110,7 +110,7 @@ export function getLimitToObservables(query: Query): Observable 1) { - const mergedObs = observables[0].merge(observables.slice(1)); + const mergedObs = merge.call(observables[0], observables.slice(1)); return mergedObs; } else { return new Observable(subscriber => { From 9f93aa0f713af4e6db880ec83ac2f6233595ad78 Mon Sep 17 00:00:00 2001 From: Jeff Cross Date: Fri, 16 Sep 2016 12:36:06 -0700 Subject: [PATCH 5/5] docs(CHANGELOG): add breaking change note about packaging --- CHANGELOG.md | 22 +++++++++++++++++++++- docs/1-install-and-setup.md | 8 ++++---- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12cecfc42..7cdd1696a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,27 @@ * **utils:** Add $exists method to AFUnwrappedSnapshot ([#471](https://github.com/angular/angularfire2/issues/471)) ([f67aab1](https://github.com/angular/angularfire2/commit/f67aab1)) * upgrade to RC7 ([#505](https://github.com/angular/angularfire2/issues/505)) ([2410b2d](https://github.com/angular/angularfire2/commit/2410b2d)) +### BREAKING CHANGES + +The way this project is packaged has changed to be consistent with other Angular packages. +Previously: + + * The project just consisted of CommonJS modules, with `angularfire2.js` as the main entry point. + * The project provided an `es6` directory which contained es2015 modules and es2015 JS + * Package.json included `main` and `jsnext:main` fields, pointing to `angularfire2.js` and `es6/angularfire2.js`, respectively. + +Now: + + * The project ships ES2015 modules with ES5 JS at the root, as well as an ES5 UMD bundle at `bundles/angulafire2.umd.js` + * The `main` field of `package.json` points to `bundles/angularfire2.umd.js`. + * Instead of `jsnext:main`, we're using the `module` field of package.json to point to `index.js`. + * Instead of `angularfire2.js` being the main entry point, an `index.js` has been added (though angulafire2.js hasn't changed significantly). + +If you're using Rollup or Webpack, they should _just work_ with this new setup (please open issues if not). If using SystemJS, you should be able to +add `format: 'esm'` inside of the packages configuration, and it should load and parse the es2015 modules correctly. +The addition of the umd bundle will also make it possible to use AngularFire2 in a `