From c75ffb8cf4b25fa0d555d13ad0a606e297d2c5e5 Mon Sep 17 00:00:00 2001 From: Jonah Walker Date: Wed, 12 May 2021 15:36:32 -0400 Subject: [PATCH 1/2] Upgrade Packages --- functions/pubspec.yaml | 9 +++++++-- pubspec.yaml | 20 +++++++++++++------- test/https_test.dart | 10 +++++----- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/functions/pubspec.yaml b/functions/pubspec.yaml index 170d48a..ad3758a 100644 --- a/functions/pubspec.yaml +++ b/functions/pubspec.yaml @@ -4,6 +4,8 @@ version: 0.0.0 #homepage: https://www.example.com author: Anatoly Pulyaevskiy +publish_to: none + environment: sdk: '>=2.7.0 <3.0.0' @@ -12,5 +14,8 @@ dependencies: path: ../ dev_dependencies: - build_runner: ^1.7.4 - build_node_compilers: ^0.2.4 + build_runner: ^2.0.3 + build_node_compilers: + git: # temporary until NNBD approved for main package + url: https://github.com/SupposedlySam/node-interop.git + path: build_node_compilers diff --git a/pubspec.yaml b/pubspec.yaml index d2119c3..b9a3d88 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,16 +4,22 @@ version: 2.0.0 homepage: https://www.github.com/pulyaevskiy/firebase-functions-interop author: Anatoly Pulyaevskiy +publish_to: none + environment: sdk: '>=2.7.0 <3.0.0' dependencies: - js: ^0.6.1+1 - meta: ^1.1.8 - node_interop: ^1.0.3 - node_io: ^1.0.1+2 - node_http: ^1.0.0 - firebase_admin_interop: ^2.0.0 + js: ^0.6.3 + meta: ^1.3.0 + node_interop: ^2.0.1 + node_io: ^2.0.0 + node_http: + git: # temporary until NNBD approved for main package + url: https://github.com/SupposedlySam/node-interop.git + path: node_http + firebase_admin_interop: + git: git@github.com:SupposedlySam/firebase-admin-interop.git dev_dependencies: - test: ^1.12.0 + test: ^1.17.4 diff --git a/test/https_test.dart b/test/https_test.dart index 115697a..26b777a 100644 --- a/test/https_test.dart +++ b/test/https_test.dart @@ -24,15 +24,15 @@ void main() { }); test('get request', () async { - var response = await http.get('$baseUrl/helloWorld'); + var response = await http.get(Uri.parse('$baseUrl/helloWorld')); expect(response.statusCode, 200); expect(response.body, 'HappyPathTest\n'); }); test('save to database', () async { var time = new DateTime.now().millisecondsSinceEpoch.toString(); - var response = - await http.get('$baseUrl/httpsToDatabase?name=Firebase$time'); + var response = await http + .get(Uri.parse('$baseUrl/httpsToDatabase?name=Firebase$time')); expect(response.statusCode, 200); expect(response.body, 'httpsToDatabase: ok\n'); @@ -44,7 +44,7 @@ void main() { }); test('get json body', () async { - var response = await http.post('$baseUrl/jsonTest', + var response = await http.post(Uri.parse('$baseUrl/jsonTest'), headers: {'Content-Type': 'application/json'}, body: json.encode({"helloJSON": "hi"})); expect(response.statusCode, 200); @@ -52,7 +52,7 @@ void main() { }); test('callable', () async { - var response = await http.post('$callableUrl', + var response = await http.post(Uri.parse('$callableUrl'), headers: {'content-type': 'application/json; charset=utf-8'}, body: jsonEncode( {'data': 'body'}, From eb62be19552a400c7d6f725230ec6381ab1c7dab Mon Sep 17 00:00:00 2001 From: Jonah Walker Date: Wed, 12 May 2021 16:01:21 -0400 Subject: [PATCH 2/2] Support for NNBD --- CHANGELOG.md | 4 +++ example/https_auth.dart | 11 +++++--- example/main.dart | 6 ++--- lib/firebase_functions_interop.dart | 42 ++++++++++++++++++----------- lib/src/bindings.dart | 16 +++++------ lib/src/https.dart | 8 +++--- pubspec.yaml | 4 +-- test/config_test.dart | 2 +- test/https_test.dart | 4 +-- test/pubsub_test.dart | 17 ++++++------ test/setup_admin.dart | 4 +-- 11 files changed, 69 insertions(+), 49 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a8eacc..77c3253 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.0.0 + +- Support for NNBD: Bump sdk to 2.12 + ## 2.0.0 - Update to use firebase_admin_interop `2.0.0` diff --git a/example/https_auth.dart b/example/https_auth.dart index 05cce83..f1fd6f4 100644 --- a/example/https_auth.dart +++ b/example/https_auth.dart @@ -19,15 +19,20 @@ void main() { Future secured(ExpressHttpRequest request) async { try { - String auth = request.headers.value('authorization'); + String? auth = request.headers.value('authorization'); if (auth != null && auth.startsWith('Bearer ')) { print('Authorization header found.'); var admin = FirebaseAdmin.instance; var app = admin.initializeApp(); String idToken = auth.split(' ').last; - DecodedIdToken decodedToken = - await app.auth().verifyIdToken(idToken).catchError((error) => null); + late DecodedIdToken? decodedToken; + try { + decodedToken = await app.auth().verifyIdToken(idToken); + } catch (e) { + // Fail Gracefully: we expect this to fail if the id doesn't exist + } + if (decodedToken == null) { print('Invalid or expired authorization token provided.'); request.response.statusCode = 403; diff --git a/example/main.dart b/example/main.dart index d1fe8ea..cd8762c 100644 --- a/example/main.dart +++ b/example/main.dart @@ -28,7 +28,7 @@ void main() { FutureOr makeUppercase( Change> change, EventContext context) { final DataSnapshot snapshot = change.after; - var original = snapshot.val(); + var original = snapshot.val()!; var pushId = context.params['testId']; print('Uppercasing $original'); var uppercase = pushId.toString() + ': ' + original.toUpperCase(); @@ -42,7 +42,7 @@ FutureOr makeNamesUppercase( // infinite cycle of this function writing, reading and writing again. final snapshot = change.after; if (snapshot.data.getString("uppercasedName") == null) { - var original = snapshot.data.getString("name"); + var original = snapshot.data.getString("name")!; print('Uppercasing $original'); UpdateData newData = new UpdateData(); @@ -83,7 +83,7 @@ Future helloWorld(ExpressHttpRequest request) async { /// Note though that Firebase uses body-parser expressjs middleware which /// decodes request body for some common content-types (json included). /// In such cases use `request.body` which contains decoded body. - String name = request.requestedUri.queryParameters['name']; + String? name = request.requestedUri.queryParameters['name']; if (name != null) { // We can also write to Realtime Database right here: var admin = FirebaseAdmin.instance; diff --git a/lib/firebase_functions_interop.dart b/lib/firebase_functions_interop.dart index abfe5fe..90b536f 100644 --- a/lib/firebase_functions_interop.dart +++ b/lib/firebase_functions_interop.dart @@ -173,8 +173,15 @@ class Change { /// * Authorization of the request that triggered the event, if applicable /// and available. class EventContext { - EventContext._(this.auth, this.authType, this.eventId, this.eventType, - this.params, this.resource, this.timestamp); + EventContext._( + this.auth, + this.authType, + this.eventId, + this.eventType, + this.params, + this.resource, + this.timestamp, + ); factory EventContext(js.EventContext data) { return new EventContext._( @@ -193,12 +200,12 @@ class EventContext { /// For an unauthenticated user, this field is null. For event types that do /// not provide user information (all except Realtime Database) or for /// Firebase admin users, this field will not exist. - final js.EventAuthInfo auth; + final js.EventAuthInfo? auth; /// The level of permissions for a user. /// /// Valid values are: `ADMIN`, `USER`, `UNAUTHENTICATED` and `null`. - final String authType; + final String? authType; /// The event’s unique identifier. final String eventId; @@ -410,14 +417,14 @@ class ScheduleBuilder { ScheduleBuilder._(this.nativeInstance); /// Event handler that fires every time a schedule occurs. - js.CloudFunction onRun(DataEventHandler handler) { + js.CloudFunction onRun(DataEventHandler handler) { dynamic wrapper(js.EventContext jsContext) => _handleEvent(jsContext, handler); return nativeInstance.onRun(allowInterop(wrapper)); } - - dynamic _handleEvent(js.EventContext jsContext, - DataEventHandler handler) { + + dynamic _handleEvent( + js.EventContext jsContext, DataEventHandler handler) { final context = new EventContext(jsContext); var result = handler(null, context); if (result is Future) { @@ -571,7 +578,7 @@ class ObjectMetadata { String get crc32c => nativeInstance.crc32c; /// Customer-supplied encryption key. - CustomerEncryption get customerEncryption { + CustomerEncryption? get customerEncryption { final dartified = dartify(nativeInstance.customerEncryption); if (dartified == null) return null; return new CustomerEncryption( @@ -624,28 +631,31 @@ class ObjectMetadata { String get storageClass => nativeInstance.storageClass; /// The creation time of this object. - DateTime get timeCreated => nativeInstance.timeCreated == null + DateTime? get timeCreated => nativeInstance.timeCreated == null ? null - : DateTime.parse(nativeInstance.timeCreated); + : DateTime.parse(nativeInstance.timeCreated!); /// The deletion time of this object. /// /// Returned only if this version of the object has been deleted. - DateTime get timeDeleted => nativeInstance.timeDeleted == null + DateTime? get timeDeleted => nativeInstance.timeDeleted == null ? null - : DateTime.parse(nativeInstance.timeDeleted); + : DateTime.parse(nativeInstance.timeDeleted!); /// The modification time of this object. - DateTime get updated => nativeInstance.updated == null + DateTime? get updated => nativeInstance.updated == null ? null - : DateTime.parse(nativeInstance.updated); + : DateTime.parse(nativeInstance.updated!); } class CustomerEncryption { final String encryptionAlgorithm; final String keySha256; - CustomerEncryption({this.encryptionAlgorithm, this.keySha256}); + CustomerEncryption({ + required this.encryptionAlgorithm, + required this.keySha256, + }); } /// Namespace for Firebase Authentication functions. diff --git a/lib/src/bindings.dart b/lib/src/bindings.dart index a2d51ec..1716281 100644 --- a/lib/src/bindings.dart +++ b/lib/src/bindings.dart @@ -15,12 +15,13 @@ export 'package:firebase_admin_interop/js.dart'; abstract class RuntimeOptions { /// Timeout for the function in seconds. external int get timeoutSeconds; + /// Amount of memory to allocate to the function. /// /// Valid values are: '128MB', '256MB', '512MB', '1GB', and '2GB'. external String get memory; - external factory RuntimeOptions({int timeoutSeconds, String memory}); + external factory RuntimeOptions({int? timeoutSeconds, String? memory}); } @JS() @@ -107,12 +108,12 @@ abstract class EventContext { /// For an unauthenticated user, this field is null. For event types that do /// not provide user information (all except Realtime Database) or for /// Firebase admin users, this field will not exist. - external EventAuthInfo get auth; + external EventAuthInfo? get auth; /// The level of permissions for a user. /// /// Valid values are: `ADMIN`, `USER`, `UNAUTHENTICATED` and `null`. - external String get authType; + external String? get authType; /// The event’s unique identifier. external String get eventId; @@ -271,8 +272,7 @@ abstract class TopicBuilder { @anonymous abstract class ScheduleBuilder { /// Event handler that fires every time a schedule occurs. - external CloudFunction onRun( - dynamic handler(EventContext context)); + external CloudFunction onRun(dynamic handler(EventContext context)); } /// Interface representing a Google Cloud Pub/Sub message. @@ -428,14 +428,14 @@ abstract class ObjectMetadata { external String get storageClass; /// The creation time of this object in RFC 3339 format. - external String get timeCreated; + external String? get timeCreated; /// The deletion time of the object in RFC 3339 format. Returned only if this /// version of the object has been deleted. - external String get timeDeleted; + external String? get timeDeleted; /// The modification time of this object. - external String get updated; + external String? get updated; } /// Namespace for Firebase Authentication functions. diff --git a/lib/src/https.dart b/lib/src/https.dart index a50ad4f..6057e99 100644 --- a/lib/src/https.dart +++ b/lib/src/https.dart @@ -98,11 +98,11 @@ class HttpsError { class CallableContext { /// The uid from decoding and verifying a Firebase Auth ID token. Value may /// be `null`. - final String authUid; + final String? authUid; /// The result of decoding and verifying a Firebase Auth ID token. Value may /// be `null`. - final DecodedIdToken authToken; + final DecodedIdToken? authToken; /// An unverified token for a Firebase Instance ID. final String instanceIdToken; @@ -149,8 +149,8 @@ class HttpsFunctions { dynamic jsHandler(data, js.CallableContext context) { var auth = context.auth; var ctx = new CallableContext( - auth?.uid, - auth?.token, + auth.uid, + auth.token, context.instanceIdToken, ); try { diff --git a/pubspec.yaml b/pubspec.yaml index b9a3d88..8598d0c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,13 +1,13 @@ name: firebase_functions_interop description: Firebase Cloud Functions SDK for Dart written as a JS interop wrapper for official Node.js SDK. -version: 2.0.0 +version: 3.0.0 homepage: https://www.github.com/pulyaevskiy/firebase-functions-interop author: Anatoly Pulyaevskiy publish_to: none environment: - sdk: '>=2.7.0 <3.0.0' + sdk: '>=2.12.0 <3.0.0' dependencies: js: ^0.6.3 diff --git a/test/config_test.dart b/test/config_test.dart index c1293eb..79ae9c6 100644 --- a/test/config_test.dart +++ b/test/config_test.dart @@ -11,7 +11,7 @@ import 'setup_admin.dart'; void main() { group('Config', () { test('read config', () async { - var baseUrl = env['FIREBASE_HTTP_BASE_URL'] + '/httpsTests'; + var baseUrl = env['FIREBASE_HTTP_BASE_URL']! + '/httpsTests'; var response = await http.get('$baseUrl/config'); expect(response.statusCode, 200); final Map result = json.decode(response.body); diff --git a/test/https_test.dart b/test/https_test.dart index 26b777a..c0aca19 100644 --- a/test/https_test.dart +++ b/test/https_test.dart @@ -14,8 +14,8 @@ import 'setup_admin.dart'; void main() { App app = initFirebaseApp(); NodeClient http = new NodeClient(keepAlive: false); - var baseUrl = env['FIREBASE_HTTP_BASE_URL'] + '/httpsTests'; - var callableUrl = env['FIREBASE_HTTP_BASE_URL'] + '/onCallTests'; + var baseUrl = env['FIREBASE_HTTP_BASE_URL']! + '/httpsTests'; + var callableUrl = env['FIREBASE_HTTP_BASE_URL']! + '/onCallTests'; group('$HttpsFunctions', () { tearDownAll(() async { diff --git a/test/pubsub_test.dart b/test/pubsub_test.dart index c66202e..5e2b525 100644 --- a/test/pubsub_test.dart +++ b/test/pubsub_test.dart @@ -43,15 +43,16 @@ void main() { Future exec(String command) { Completer completer = new Completer(); - childProcess.exec(command, new ExecOptions(), - allowInterop((error, stdout, stderr) { - int result = (error == null) ? 0 : error.code; - print(stdout); - if (error != null) { + childProcess.exec( + command, + new ExecOptions(), + allowInterop((error, stdout, stderr) { + int result = error.code as int; + print(stdout); print(error); print(stderr); - } - completer.complete(result); - })); + completer.complete(result); + }), + ); return completer.future; } diff --git a/test/setup_admin.dart b/test/setup_admin.dart index 3703c7a..ea9986d 100644 --- a/test/setup_admin.dart +++ b/test/setup_admin.dart @@ -16,13 +16,13 @@ App initFirebaseApp() { !env.containsKey('FIREBASE_HTTP_BASE_URL')) throw new StateError('Environment variables are not set.'); - Map certConfig = jsonDecode(env['FIREBASE_SERVICE_ACCOUNT_JSON']); + Map certConfig = jsonDecode(env['FIREBASE_SERVICE_ACCOUNT_JSON']!); final cert = FirebaseAdmin.instance.cert( projectId: certConfig['project_id'], clientEmail: certConfig['client_email'], privateKey: certConfig['private_key'], ); - final Map config = jsonDecode(env['FIREBASE_CONFIG']); + final Map config = jsonDecode(env['FIREBASE_CONFIG']!); final databaseUrl = config['databaseURL']; return FirebaseAdmin.instance.initializeApp( new AppOptions(credential: cert, databaseURL: databaseUrl));