Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions packages/firebase-functions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,41 @@ firebase()
});
```

## Regional Cloud Functions
Cloud Functions are _regional_, which means the infrastructure that runs your Cloud Function is located in specific regions.

By default, functions run in the _us-central1_ region. View the [supported regions](https://firebase.google.com/docs/functions/locations).

To run functions in a different region, after initializing Firebase App set the region using _firebase().app().functions(region)_.

Regional function endpoint example (using _europe-west2_ region ):
```ts
// Deployed HTTPS callable
exports.listProducts = functions.region("europe-west2").https.onCall(() => {
return [
/* ... */
// Return some data
];
});
```

To access the regional function endpoint:
```ts
import { firebase } from '@nativescript/firebase-core';
import '@nativescript/firebase-functions';

firebase().initializeApp();
firebase().app().functions("europe-west2");

firebase()
.functions()
.httpsCallable('listProducts')()
.then((response) => {
setProducts(response.data);
setLoading(false);
});
```

## Using an emulator

Whilst developing your application with Cloud Functions, it is possible to run the functions inside of a local emulator.
Expand Down
40 changes: 35 additions & 5 deletions packages/firebase-functions/index.android.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@ import {
HttpsCallable,
HttpsCallableOptions,
HttpsErrorCode,
IFunctions,
IFunctions
} from "./common";
import {deserialize, firebase, FirebaseApp, serialize} from "@nativescript/firebase-core";


let defaultFunctions: Functions;

const fb = firebase();
Expand All @@ -24,6 +23,31 @@ Object.defineProperty(fb, 'functions', {
},
writable: false,
});
/**
Firebase Functions Region - Region for which to run HttpsCallable method
Set parameter using firebase().app().functions(regionOrCustomDomain: string)
@see https://firebase.google.com/docs/reference/android/com/google/firebase/functions/FirebaseFunctions
@note If not set, default region is used ("us-central1")
*/
let defaultRegionOrCustomDomain: string;
/**
Add 'functions' method to FirebaseApp class
@see https://firebase.google.com/docs/reference/node/firebase.app.App
@see https://firebase.google.com/docs/functions/locations
@param regionOrCustomDomain(string)(Optional): Name of the region for which to Functions results
@return Functions
*/
const fbApp = FirebaseApp;
Object.defineProperty(fbApp.prototype, 'functions', {
value: (regionOrCustomDomain?: string) => {
defaultRegionOrCustomDomain = regionOrCustomDomain;
if (!defaultFunctions) {
defaultFunctions = new Functions();
}
return defaultFunctions;
},
writable: false,
});


function errorToCode(error: com.google.firebase.functions.FirebaseFunctionsException.Code) {
Expand Down Expand Up @@ -130,13 +154,19 @@ export class Functions implements IFunctions {

constructor(app?: FirebaseApp) {
if (app?.native) {
this.#native = com.google.firebase.functions.FirebaseFunctions.getInstance(app.native);
this.#native = defaultRegionOrCustomDomain
? com.google.firebase.functions.FirebaseFunctions.getInstance(app.native, defaultRegionOrCustomDomain)
: com.google.firebase.functions.FirebaseFunctions.getInstance(app.native);
} else {
if(defaultFunctions){
return defaultFunctions;
}
defaultFunctions = this;
this.#native = com.google.firebase.functions.FirebaseFunctions.getInstance();
// If defaultRegionOrCustomDomain is set, get FirebaseFunctions instance using that parameter
// @see https://firebase.google.com/docs/functions/locations#client-side_location_selection_for_callable_functions
this.#native = defaultRegionOrCustomDomain
? com.google.firebase.functions.FirebaseFunctions.getInstance(defaultRegionOrCustomDomain)
: com.google.firebase.functions.FirebaseFunctions.getInstance();
}
}

Expand All @@ -162,7 +192,7 @@ export class Functions implements IFunctions {
}

useEmulator(host: string, port: number) {
this.native.useEmulator(host, port);
this.native.useEmulator(host === 'localhost' ? '10.0.2.2' : host, port);
}

get native() {
Expand Down
13 changes: 13 additions & 0 deletions packages/firebase-functions/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,22 @@ export declare class Functions implements IFunctions {
}

declare module '@nativescript/firebase-core' {

export interface Firebase extends FirebaseFunctions {}
// Add 'functions' method to FirebaseApp
export interface FirebaseApp extends FirebaseFunctionsApp {}
}

export interface FirebaseFunctions {
static functions(app?: FirebaseApp): Functions;
}
/**
Add Region (Android & iOS) or Custom Domain (iOS only) to Firebase Functions HTTPS call
@param regionOrCustomDomain (string) (optional): Region (Android or iOS) or Custom Domain (iOS only)
@return Functions
@see Supported Regions: https://firebase.google.com/docs/functions/locations
@example firebase().app().functions("us-central1")
*/
export interface FirebaseFunctionsApp {
static functions(regionOrCustomDomain?: string): Functions;
}
67 changes: 64 additions & 3 deletions packages/firebase-functions/index.ios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
HttpsCallable,
HttpsCallableOptions,
HttpsErrorCode,
IFunctions,
IFunctions
} from "./common";
import {deserialize, firebase, FirebaseApp, serialize} from "@nativescript/firebase-core";

Expand All @@ -23,6 +23,34 @@ Object.defineProperty(fb, 'functions', {
},
writable: false,
});
/**
Firebase Functions Region - Region for which to run HttpsCallable method
Set parameter using firebase().app().functions(regionOrCustomDomain: string)
@link https://firebase.google.com/docs/reference/node/firebase.app.App
@link https://firebase.google.com/docs/reference/ios/firebasefunctions/api/reference/Classes/FIRFunctions
@note If not set, default region is used ('us-central1')
*/
let defaultRegionOrCustomDomain: string;
/**
Add 'functions' method to FirebaseApp class
@param regionOrCustomDomain(string)(Optional): Name of the Region or Custom Domain for which to Functions results
@return Functions
@see FirebaseFunctions
@link https://firebase.google.com/docs/reference/ios/firebasefunctions/api/reference/Classes/FIRFunctions
@see Supported Regions
@see https://firebase.google.com/docs/functions/locations
*/
const fbApp = FirebaseApp;
Object.defineProperty(fbApp.prototype, 'functions', {
value: (regionOrCustomDomain?: string) => {
defaultRegionOrCustomDomain = regionOrCustomDomain;
if (!defaultFunctions) {
defaultFunctions = new Functions();
}
return defaultFunctions;
},
writable: false,
});

function errorToCode(error: NSError) {
let code = HttpsErrorCode.UNKNOWN;
Expand Down Expand Up @@ -115,13 +143,29 @@ export class Functions implements IFunctions {

constructor(app?: FirebaseApp) {
if (app?.native) {
this.#native = FIRFunctions.functionsForApp(app.native);
if(defaultRegionOrCustomDomain){
this.#native = isRegion(defaultRegionOrCustomDomain) // Check whether a Region has been set
? FIRFunctions.functionsForAppRegion(app.native, defaultRegionOrCustomDomain) // @see https://firebase.google.com/docs/reference/ios/firebasefunctions/api/reference/Classes/FIRFunctions#+functionsforapp:region:
: isCustomDomain(defaultRegionOrCustomDomain) // Check whether using a Custom Domain has been set
? FIRFunctions.functionsForAppCustomDomain(app.native, defaultRegionOrCustomDomain) // @see https://firebase.google.com/docs/reference/ios/firebasefunctions/api/reference/Classes/FIRFunctions#+functionsforapp:customdomain:
: FIRFunctions.functionsForApp(app.native); // @see https://firebase.google.com/docs/reference/ios/firebasefunctions/api/reference/Classes/FIRFunctions#+functionsforapp:
} else {
this.#native = FIRFunctions.functionsForApp(app.native); // @see https://firebase.google.com/docs/reference/ios/firebasefunctions/api/reference/Classes/FIRFunctions#+functionsforapp:
}
} else {
if(defaultFunctions){
return defaultFunctions;
}
defaultFunctions = this;
this.#native = FIRFunctions.functions();
if(defaultRegionOrCustomDomain){
this.#native = isRegion(defaultRegionOrCustomDomain) // Check whether a Region has been set
? FIRFunctions.functionsForRegion(defaultRegionOrCustomDomain) // @see https://firebase.google.com/docs/reference/ios/firebasefunctions/api/reference/Classes/FIRFunctions#+functionsforregion:
: isCustomDomain(defaultRegionOrCustomDomain) // Check whether using a Custom Domain has been set
? FIRFunctions.functionsForCustomDomain(defaultRegionOrCustomDomain) // @see https://firebase.google.com/docs/reference/ios/firebasefunctions/api/reference/Classes/FIRFunctions#+functionsforcustomdomain:
: FIRFunctions.functions(); // @see https://firebase.google.com/docs/reference/ios/firebasefunctions/api/reference/Classes/FIRFunctions#+functions
} else {
this.#native = FIRFunctions.functions(); // @see https://firebase.google.com/docs/reference/ios/firebasefunctions/api/reference/Classes/FIRFunctions#+functions
}
}
}

Expand Down Expand Up @@ -178,3 +222,20 @@ export class Functions implements IFunctions {
return this.#app;
}
}
/**
Check whether a regionOrCustomDomain string is a Region for the http trigger, such as “us-central1”.
@param regionOrCustomDomain(string): Text to parse
@return boolean: TRUE if a Region; FALSE if not
*/
function isRegion(regionOrCustomDomain: string): boolean{
const elems = regionOrCustomDomain.split('.');
return elems.length === 1 ? true : false;
}
/**
Check whether a regionOrCustomDomain string is a Custom Domain for the http trigger, such as “https://mydomain.com”
@param regionOrCustomDomain(string): Text to parse
@return boolean: TRUE if a CustomDomain; FALSE if not
*/
function isCustomDomain(regionOrCustomDomain: string): boolean{
return !isRegion(regionOrCustomDomain);
}