Skip to content

Commit 26f3f5f

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

18 files changed

+260
-3
lines changed

karma.conf.js

+1
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

+2
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

+2
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

+8
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

+75
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

+46
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

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import './functions.spec';

src/functions/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './public_api';

src/functions/package.json

+31
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

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './functions';
2+
export * from './functions.module';

src/functions/test-config.ts

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
export const COMMON_CONFIG = {
3+
apiKey: "AIzaSyBVSy3YpkVGiKXbbxeK0qBnu3-MNZ9UIjA",
4+
authDomain: "angularfire2-test.firebaseapp.com",
5+
databaseURL: "https://angularfire2-test.firebaseio.com",
6+
storageBucket: "angularfire2-test.appspot.com",
7+
};

src/functions/tsconfig-build.json

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"compilerOptions": {
3+
"baseUrl": ".",
4+
"experimentalDecorators": true,
5+
"emitDecoratorMetadata": true,
6+
"module": "es2015",
7+
"target": "es2015",
8+
"noImplicitAny": false,
9+
"outDir": "../../dist/packages-dist/functions/es2015",
10+
"rootDir": ".",
11+
"sourceMap": true,
12+
"inlineSources": true,
13+
"declaration": false,
14+
"removeComments": true,
15+
"strictNullChecks": true,
16+
"lib": ["es2015", "dom", "es2015.promise", "es2015.collection", "es2015.iterable"],
17+
"skipLibCheck": true,
18+
"moduleResolution": "node",
19+
"paths": {
20+
"angularfire2": ["../../dist/packages-dist"]
21+
}
22+
},
23+
"files": [
24+
"index.ts",
25+
"../../node_modules/zone.js/dist/zone.js.d.ts"
26+
],
27+
"angularCompilerOptions": {
28+
"skipTemplateCodegen": true,
29+
"strictMetadataEmit": true,
30+
"enableSummariesForJit": false
31+
}
32+
}
33+

src/functions/tsconfig-esm.json

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"extends": "./tsconfig-build.json",
3+
"compilerOptions": {
4+
"target": "es5",
5+
"outDir": "../../dist/packages-dist/functions",
6+
"declaration": true
7+
},
8+
"files": [
9+
"public_api.ts",
10+
"../../node_modules/zone.js/dist/zone.js.d.ts"
11+
],
12+
"angularCompilerOptions": {
13+
"skipTemplateCodegen": true,
14+
"strictMetadataEmit": true,
15+
"enableSummariesForJit": false,
16+
"flatModuleOutFile": "index.js",
17+
"flatModuleId": "angularfire2/functions"
18+
}
19+
}

src/functions/tsconfig-test.json

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"extends": "./tsconfig-esm.json",
3+
"compilerOptions": {
4+
"baseUrl": ".",
5+
"paths": {
6+
"angularfire2": ["../../dist/packages-dist"],
7+
"angularfire2/functions": ["../../dist/packages-dist/functions"]
8+
}
9+
},
10+
"files": [
11+
"index.spec.ts",
12+
"../../node_modules/zone.js/dist/zone.js.d.ts"
13+
]
14+
}

src/root.spec.js

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export * from './packages-dist/auth/auth.spec';
44
export * from './packages-dist/firestore/firestore.spec';
55
export * from './packages-dist/firestore/document/document.spec';
66
export * from './packages-dist/firestore/collection/collection.spec';
7+
export * from './packages-dist/functions/functions.spec';
78
export * from './packages-dist/database/database.spec';
89
export * from './packages-dist/database/utils.spec';
910
export * from './packages-dist/database/observable/fromRef.spec';

src/tsconfig.json

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"angularfire2/auth": ["./auth"],
1515
"angularfire2/database": ["./database"],
1616
"angularfire2/firestore": ["./firestore"],
17+
"angularfire2/functions": ["./functions"],
1718
"angularfire2/storage": ["./storage"],
1819
"angularfire2/database-deprecated": ["./database-deprecated"]
1920
},

0 commit comments

Comments
 (0)