Skip to content

Commit 26f3f5f

Browse files
authored
feat(functions): Adding AngularFireFunctions with httpCallable (angular#1532)
1 parent 92f77dc commit 26f3f5f

18 files changed

+260
-3
lines changed

karma.conf.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ module.exports = function(config) {
3030
'dist/packages-dist/bundles/auth.umd.{js,map}',
3131
'dist/packages-dist/bundles/database.umd.{js,map}',
3232
'dist/packages-dist/bundles/firestore.umd.{js,map}',
33+
'dist/packages-dist/bundles/functions.umd.{js,map}',
3334
'dist/packages-dist/bundles/storage.umd.{js,map}',
3435
'dist/packages-dist/bundles/database-deprecated.umd.{js,map}',
3536
'dist/packages-dist/bundles/test.umd.{js,map}',

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
"@firebase/database-types": "^0.3.1",
4343
"@firebase/firestore": "^0.5.2",
4444
"@firebase/firestore-types": "^0.4.1",
45+
"@firebase/functions": "^0.2.2",
46+
"@firebase/functions-types": "^0.1.2",
4547
"@firebase/messaging-types": "^0.2.2",
4648
"@firebase/storage": "^0.2.2",
4749
"@firebase/storage-types": "^0.2.2",

src/core/firebase.app.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { FirebaseDatabase } from '@firebase/database-types';
99
import { FirebaseMessaging } from '@firebase/messaging-types';
1010
import { FirebaseStorage } from '@firebase/storage-types';
1111
import { FirebaseFirestore } from '@firebase/firestore-types';
12+
import { FirebaseFunctions } from '@firebase/functions-types';
1213

1314
export class FirebaseApp implements _FirebaseApp {
1415
name: string;
@@ -20,6 +21,7 @@ export class FirebaseApp implements _FirebaseApp {
2021
storage: (storageBucket?: string) => FirebaseStorage;
2122
delete: () => Promise<void>;
2223
firestore: () => FirebaseFirestore;
24+
functions: () => FirebaseFunctions;
2325
}
2426

2527
export function _firebaseAppFactory(options: FirebaseOptions, nameOrConfig?: string | FirebaseAppConfig) {

src/functions/functions.module.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { NgModule } from '@angular/core';
2+
import { AngularFireFunctions } from './functions';
3+
import '@firebase/functions'
4+
5+
@NgModule({
6+
providers: [ AngularFireFunctions ]
7+
})
8+
export class AngularFireFunctionsModule { }

src/functions/functions.spec.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { ReflectiveInjector, Provider } from '@angular/core';
2+
import { TestBed, inject } from '@angular/core/testing';
3+
import { FirebaseApp, FirebaseOptionsToken, AngularFireModule, FirebaseNameOrConfigToken } from 'angularfire2';
4+
import { AngularFireFunctions, AngularFireFunctionsModule } from 'angularfire2/functions';
5+
import { COMMON_CONFIG } from './test-config';
6+
7+
describe('AngularFireFunctions', () => {
8+
let app: FirebaseApp;
9+
let afFns: AngularFireFunctions;
10+
11+
beforeEach(() => {
12+
TestBed.configureTestingModule({
13+
imports: [
14+
AngularFireModule.initializeApp(COMMON_CONFIG),
15+
AngularFireFunctionsModule
16+
]
17+
});
18+
inject([FirebaseApp, AngularFireFunctions], (app_: FirebaseApp, _fn: AngularFireFunctions) => {
19+
app = app_;
20+
afFns = _fn;
21+
})();
22+
});
23+
24+
afterEach(done => {
25+
app.delete();
26+
done();
27+
});
28+
29+
it('should be exist', () => {
30+
expect(afFns instanceof AngularFireFunctions).toBe(true);
31+
});
32+
33+
it('should have the Firebase Functions instance', () => {
34+
expect(afFns.functions).toBeDefined();
35+
});
36+
37+
});
38+
39+
const FIREBASE_APP_NAME_TOO = (Math.random() + 1).toString(36).substring(7);
40+
41+
describe('AngularFireFunctions with different app', () => {
42+
let app: FirebaseApp;
43+
let afFns: AngularFireFunctions;
44+
45+
beforeEach(() => {
46+
TestBed.configureTestingModule({
47+
imports: [
48+
AngularFireModule.initializeApp(COMMON_CONFIG),
49+
AngularFireFunctionsModule
50+
],
51+
providers: [
52+
{ provide: FirebaseNameOrConfigToken, useValue: FIREBASE_APP_NAME_TOO },
53+
{ provide: FirebaseOptionsToken, useValue: COMMON_CONFIG }
54+
]
55+
});
56+
inject([FirebaseApp, AngularFireFunctions], (app_: FirebaseApp, _fns: AngularFireFunctions) => {
57+
app = app_;
58+
afFns = _fns;
59+
})();
60+
});
61+
62+
afterEach(done => {
63+
app.delete();
64+
done();
65+
});
66+
67+
describe('<constructor>', () => {
68+
69+
it('should be an AngularFireAuth type', () => {
70+
expect(afFns instanceof AngularFireFunctions).toEqual(true);
71+
});
72+
73+
});
74+
75+
});

src/functions/functions.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { FirebaseFunctions } from '@firebase/functions-types';
2+
import { FirebaseOptions, FirebaseAppConfig } from '@firebase/app-types';
3+
import { Injectable, Inject, Optional, NgZone, PLATFORM_ID } from '@angular/core';
4+
import { Observable, from } from 'rxjs';
5+
import { map } from 'rxjs/operators';
6+
7+
import { FirebaseOptionsToken, FirebaseNameOrConfigToken, _firebaseAppFactory, FirebaseZoneScheduler } from 'angularfire2';
8+
9+
@Injectable()
10+
export class AngularFireFunctions {
11+
12+
/**
13+
* Firebase Functions instance
14+
*/
15+
public readonly functions: FirebaseFunctions;
16+
17+
public readonly scheduler: FirebaseZoneScheduler;
18+
19+
constructor(
20+
@Inject(FirebaseOptionsToken) options:FirebaseOptions,
21+
@Optional() @Inject(FirebaseNameOrConfigToken) nameOrConfig:string|FirebaseAppConfig|undefined,
22+
@Inject(PLATFORM_ID) platformId: Object,
23+
zone: NgZone
24+
) {
25+
this.scheduler = new FirebaseZoneScheduler(zone, platformId);
26+
27+
this.functions = zone.runOutsideAngular(() => {
28+
const app = _firebaseAppFactory(options, nameOrConfig);
29+
return app.functions();
30+
});
31+
32+
}
33+
34+
public httpsCallable<T=any, R=any>(name: string) {
35+
const callable = this.functions.httpsCallable(name);
36+
return (data: T) => {
37+
const callable$ = from(callable(data));
38+
return this.scheduler.runOutsideAngular(
39+
callable$.pipe(
40+
map(r => r.data as R)
41+
)
42+
)
43+
}
44+
}
45+
46+
}

src/functions/index.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import './functions.spec';

src/functions/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './public_api';

src/functions/package.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "angularfire2/functions",
3+
"version": "ANGULARFIRE2_VERSION",
4+
"description": "The functions module",
5+
"main": "../bundles/functions.umd.js",
6+
"module": "index.js",
7+
"es2015": "./es2015/index.js",
8+
"keywords": [
9+
"angular",
10+
"firebase",
11+
"rxjs"
12+
],
13+
"repository": {
14+
"type": "git",
15+
"url": "git+https://github.com/angular/angularfire2.git"
16+
},
17+
"author": "angular,firebase",
18+
"license": "MIT",
19+
"peerDependencies": {
20+
"angularfire2": "ANGULARFIRE2_VERSION",
21+
"@angular/common": "ANGULAR_VERSION",
22+
"@angular/core": "ANGULAR_VERSION",
23+
"@angular/platform-browser": "ANGULAR_VERSION",
24+
"@angular/platform-browser-dynamic": "ANGULAR_VERSION",
25+
"@firebase/app": "FIREBASE_APP_VERSION",
26+
"@firebase/functions": "FIREBASE_FUNCTIONS_VERSION",
27+
"rxjs": "RXJS_VERSION",
28+
"zone.js": "ZONEJS_VERSION"
29+
},
30+
"typings": "index.d.ts"
31+
}

src/functions/public_api.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './functions';
2+
export * from './functions.module';

0 commit comments

Comments
 (0)