Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
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
4 changes: 4 additions & 0 deletions packages/cloud_functions/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.1.1

* Support for regions and multiple apps

## 0.1.0+1

* Log a more detailed warning at build time about the previous AndroidX
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import androidx.annotation.NonNull;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.FirebaseApp;
import com.google.firebase.functions.FirebaseFunctions;
import com.google.firebase.functions.FirebaseFunctionsException;
import com.google.firebase.functions.HttpsCallableReference;
Expand All @@ -32,9 +33,17 @@ public void onMethodCall(MethodCall call, final Result result) {
switch (call.method) {
case "CloudFunctions#call":
String functionName = call.argument("functionName");
HttpsCallableReference httpsCallableReference =
FirebaseFunctions.getInstance().getHttpsCallable(functionName);
Map<String, Object> parameters = call.argument("parameters");
String appName = call.argument("app");
FirebaseApp app = FirebaseApp.getInstance(appName);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if appName is null do we want FirebaseApp.getInstance(), thats for default FirebaseApp as opposed to FirebaseApp.getInstance(null) which might throw? (it's not very clear per docs https://firebase.google.com/docs/reference/android/com/google/firebase/FirebaseApp.html#getInstance(java.lang.String))

Copy link
Contributor Author

@collinjackson collinjackson Feb 21, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think appName cannot be null with the firebase_core plugin that we are depending on. There is an assert(name != null) in firebase_core. The default app is named __FIRAPP_DEFAULT on iOS and [DEFAULT] on Android.

Note that app can't be null either; see the Dart CloudFunctions constructor.

String region = call.argument("region");
FirebaseFunctions functions;
if (region != null) {
functions = FirebaseFunctions.getInstance(app, region);
} else {
functions = FirebaseFunctions.getInstance(app);
}
HttpsCallableReference httpsCallableReference = functions.getHttpsCallable(functionName);
httpsCallableReference
.call(parameters)
.addOnCompleteListener(
Expand Down
68 changes: 39 additions & 29 deletions packages/cloud_functions/ios/Classes/CloudFunctionsPlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -35,36 +35,46 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
if ([@"CloudFunctions#call" isEqualToString:call.method]) {
NSString *functionName = call.arguments[@"functionName"];
NSObject *parameters = call.arguments[@"parameters"];
[[FIRFunctions functions]
callFunction:functionName
withObject:parameters
completion:^(FIRHTTPSCallableResult *callableResult, NSError *error) {
if (error) {
FlutterError *flutterError;
if (error.domain == FIRFunctionsErrorDomain) {
NSDictionary *details = [NSMutableDictionary dictionary];
[details setValue:[self mapFunctionsErrorCodes:error.code] forKey:@"code"];
if (error.localizedDescription != nil) {
[details setValue:error.localizedDescription forKey:@"message"];
}
if (error.userInfo[FIRFunctionsErrorDetailsKey] != nil) {
[details setValue:error.userInfo[FIRFunctionsErrorDetailsKey] forKey:@"details"];
}
NSString *appName = call.arguments[@"app"];
NSString *region = call.arguments[@"region"];
FIRApp *app = [FIRApp appNamed:appName];
FIRFunctions *functions;
if (region != nil) {
functions = [FIRFunctions functionsForApp:app region:region];
} else {
functions = [FIRFunctions functionsForApp:app];
}
[functions callFunction:functionName
withObject:parameters
completion:^(FIRHTTPSCallableResult *callableResult, NSError *error) {
if (error) {
FlutterError *flutterError;
if (error.domain == FIRFunctionsErrorDomain) {
NSDictionary *details = [NSMutableDictionary dictionary];
[details setValue:[self mapFunctionsErrorCodes:error.code] forKey:@"code"];
if (error.localizedDescription != nil) {
[details setValue:error.localizedDescription forKey:@"message"];
}
if (error.userInfo[FIRFunctionsErrorDetailsKey] != nil) {
[details setValue:error.userInfo[FIRFunctionsErrorDetailsKey]
forKey:@"details"];
}

flutterError =
[FlutterError errorWithCode:@"functionsError"
message:@"Firebase function failed with exception."
details:details];
} else {
flutterError = [FlutterError errorWithCode:nil
message:error.localizedDescription
details:nil];
}
result(flutterError);
} else {
result(callableResult.data);
}
}];
flutterError =
[FlutterError errorWithCode:@"functionsError"
message:@"Firebase function failed with exception."
details:details];
} else {
flutterError = [FlutterError
errorWithCode:[NSString stringWithFormat:@"%ld", error.code]
message:error.localizedDescription
details:nil];
}
result(flutterError);
} else {
result(callableResult.data);
}
}];
} else {
result(FlutterMethodNotImplemented);
}
Expand Down
11 changes: 11 additions & 0 deletions packages/cloud_functions/lib/cloud_functions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import 'dart:async';

import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/services.dart';
import 'package:meta/meta.dart';

Expand All @@ -19,13 +20,21 @@ class CloudFunctionsException implements Exception {
///
/// You can get an instance by calling [CloudFunctions.instance].
class CloudFunctions {
CloudFunctions({FirebaseApp app, String region})
: _app = app ?? FirebaseApp.instance,
_region = region;

@visibleForTesting
static const MethodChannel channel = MethodChannel('cloud_functions');

static CloudFunctions _instance = CloudFunctions();

static CloudFunctions get instance => _instance;

final FirebaseApp _app;

final String _region;

/// Executes this Callable HTTPS trigger asynchronously.
///
/// @param functionName The name of the callable function being triggered.
Expand All @@ -38,6 +47,8 @@ class CloudFunctions {
// https://github.com/flutter/flutter/issues/26431
// ignore: strong_mode_implicit_dynamic_method
await channel.invokeMethod('CloudFunctions#call', <String, dynamic>{
'app': _app.name,
'region': _region,
'functionName': functionName,
'parameters': parameters,
});
Expand Down
4 changes: 2 additions & 2 deletions packages/cloud_functions/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: cloud_functions
description: Flutter plugin for Cloud Functions.
version: 0.1.0+1
version: 0.1.1
author: Flutter Team <[email protected]>
homepage: https://github.com/flutter/plugins/tree/master/packages/cloud_functions

Expand All @@ -13,11 +13,11 @@ dependencies:
meta: ^1.1.6
flutter:
sdk: flutter
firebase_core: ^0.3.0

dev_dependencies:
flutter_test:
sdk: flutter
firebase_core: ^0.3.0

environment:
sdk: ">=2.0.0-dev.28.0 <3.0.0"
Expand Down
8 changes: 7 additions & 1 deletion packages/cloud_functions/test/cloud_functions_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.

import 'package:cloud_functions/cloud_functions.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';

Expand All @@ -28,7 +29,8 @@ void main() {

test('call', () async {
await CloudFunctions.instance.call(functionName: 'baz');
await CloudFunctions.instance
await CloudFunctions(
app: const FirebaseApp(name: '1337'), region: 'space')
.call(functionName: 'qux', parameters: <String, dynamic>{
'quux': 'quuz',
});
Expand All @@ -38,13 +40,17 @@ void main() {
isMethodCall(
'CloudFunctions#call',
arguments: <String, dynamic>{
'app': '[DEFAULT]',
'region': null,
'functionName': 'baz',
'parameters': null,
},
),
isMethodCall(
'CloudFunctions#call',
arguments: <String, dynamic>{
'app': '1337',
'region': 'space',
'functionName': 'qux',
'parameters': <String, dynamic>{
'quux': 'quuz',
Expand Down