From dc86ba2a22983131582d7fb5b8e7be161f32bc4d Mon Sep 17 00:00:00 2001 From: Jonah Walker Date: Wed, 12 May 2021 12:29:59 -0400 Subject: [PATCH] NNBD and Code Cleanup --- CHANGELOG.md | 6 + README.md | 4 +- example/main.dart | 2 +- lib/firebase_admin_interop.dart | 2 +- lib/src/admin.dart | 28 ++- lib/src/app.dart | 18 +- lib/src/auth.dart | 9 +- lib/src/bindings.dart | 378 ++++++++++++++++---------------- lib/src/database.dart | 103 +++++---- lib/src/firestore.dart | 302 ++++++++++++------------- lib/src/firestore_bindings.dart | 89 ++++---- lib/src/messaging.dart | 14 +- lib/src/storage_bindings.dart | 14 +- pubspec.yaml | 24 +- test/admin_test.dart | 2 +- test/auth_test.dart | 14 +- test/database_test.dart | 16 +- test/firestore_test.dart | 228 +++++++++---------- test/setup.dart | 5 +- 19 files changed, 629 insertions(+), 629 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 078eb41..6d925e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ + +## 3.0.0 + +Non Nullable By Default (NNBD) +Bump sdk to 2.12.0 + ## 2.1.0 Upgraded to support firebase-admin Messaging features to send cloud message payloads to device, topic, all, multicast, and subscribe/unsubscribe from topic. diff --git a/README.md b/README.md index 9b74a44..dbe655f 100644 --- a/README.md +++ b/README.md @@ -90,8 +90,8 @@ dev dependencies to your `pubspec.yaml`: ```yaml dev_dependencies: - build_runner: ^1.0.0 - build_node_compilers: ^0.2.0 + build_runner: ^2.0.0 + build_node_compilers: ^1.0.0 ``` Next, create `build.yaml` file with following contents: diff --git a/example/main.dart b/example/main.dart index 002001e..7b7e0b6 100644 --- a/example/main.dart +++ b/example/main.dart @@ -4,7 +4,7 @@ main() async { final serviceAccountKeyFilename = '/absolute/path/to/service-account.json'; final admin = FirebaseAdmin.instance; final cert = admin.certFromPath(serviceAccountKeyFilename); - final app = admin.initializeApp(new AppOptions( + final app = admin.initializeApp(AppOptions( credential: cert, databaseURL: "YOUR_DB_URL", )); diff --git a/lib/firebase_admin_interop.dart b/lib/firebase_admin_interop.dart index 22f74c0..0066bdf 100644 --- a/lib/firebase_admin_interop.dart +++ b/lib/firebase_admin_interop.dart @@ -23,7 +23,7 @@ /// Future main() async { /// var admin = FirebaseAdmin.instance; /// var cert = admin.certFromPath(serviceAccountKeyFilename); -/// var app = admin.initializeApp(new AppOptions( +/// var app = admin.initializeApp(AppOptions( /// credential: cert, /// databaseUrl: "YOUR_DB_URL", /// )); diff --git a/lib/src/admin.dart b/lib/src/admin.dart index f917c7f..b62aa9c 100644 --- a/lib/src/admin.dart +++ b/lib/src/admin.dart @@ -1,8 +1,6 @@ // Copyright (c) 2017, Anatoly Pulyaevskiy. All rights reserved. Use of this source code // is governed by a BSD-style license that can be found in the LICENSE file. -import 'package:meta/meta.dart'; - import 'app.dart'; import 'bindings.dart' as js; @@ -12,10 +10,10 @@ import 'bindings.dart' as js; /// with [initializeApp] method. class FirebaseAdmin { final js.FirebaseAdmin _admin; - final Map _apps = new Map(); + final Map _apps = {}; - static FirebaseAdmin get instance => _instance ??= new FirebaseAdmin._(); - static FirebaseAdmin _instance; + static FirebaseAdmin get instance => _instance ??= FirebaseAdmin._(); + static FirebaseAdmin? _instance; FirebaseAdmin._() : _admin = js.admin; @@ -38,7 +36,7 @@ class FirebaseAdmin { /// privateKey: 'your-private-key', /// ); /// var app = FirebaseAdmin.instance.initializeApp( - /// new AppOptions( + /// AppOptions( /// credential: certificate, /// databaseURL: 'https://your-database.firebase.io') /// ); @@ -47,30 +45,30 @@ class FirebaseAdmin { /// * [App] /// * [cert] /// * [certFromPath] - App initializeApp([js.AppOptions options, String name]) { + App initializeApp([js.AppOptions? options, String? name]) { if (options == null && name == null) { // Special case for default app with Application Default Credentials. name = js.defaultAppName; if (!_apps.containsKey(name)) { - _apps[name] = new App(_admin.initializeApp()); + _apps[name] = App(_admin.initializeApp()); } - return _apps[name]; + return _apps[name]!; } name ??= js.defaultAppName; if (!_apps.containsKey(name)) { - _apps[name] = new App(_admin.initializeApp(options, name)); + _apps[name] = App(_admin.initializeApp(options, name)); } - return _apps[name]; + return _apps[name]!; } /// Creates [App] certificate. js.Credential cert({ - @required String projectId, - @required String clientEmail, - @required String privateKey, + required String projectId, + required String clientEmail, + required String privateKey, }) { - return _admin.credential.cert(new js.ServiceAccountConfig( + return _admin.credential.cert(js.ServiceAccountConfig( project_id: projectId, client_email: clientEmail, private_key: privateKey, diff --git a/lib/src/app.dart b/lib/src/app.dart index 0da67a7..1371d20 100644 --- a/lib/src/app.dart +++ b/lib/src/app.dart @@ -29,23 +29,21 @@ class App { js.AppOptions get options => nativeInstance.options; /// Gets the [Auth] service for this application. - Auth auth() => _auth ??= new Auth(nativeInstance.auth()); - Auth _auth; + Auth auth() => _auth ??= Auth(nativeInstance.auth()); + Auth? _auth; /// Gets Realtime [Database] client for this application. Database database() => - _database ??= new Database(this.nativeInstance.database(), this); - Database _database; + _database ??= Database(this.nativeInstance.database(), this); + Database? _database; /// Gets [Firestore] client for this application. - Firestore firestore() => - _firestore ??= new Firestore(nativeInstance.firestore()); - Firestore _firestore; + Firestore firestore() => _firestore ??= Firestore(nativeInstance.firestore()); + Firestore? _firestore; /// Gets [Messaging] client for this application. - Messaging messaging() => - _messaging ??= new Messaging(nativeInstance.messaging()); - Messaging _messaging; + Messaging messaging() => _messaging ??= Messaging(nativeInstance.messaging()); + Messaging? _messaging; /// Renders this app unusable and frees the resources of all associated /// services. diff --git a/lib/src/auth.dart b/lib/src/auth.dart index 7b77e6d..e646fdb 100644 --- a/lib/src/auth.dart +++ b/lib/src/auth.dart @@ -39,9 +39,10 @@ class Auth { /// Returns a [Future] containing a custom token string for the provided [uid] /// and payload. Future createCustomToken(String uid, - [Map developerClaims]) => + [Map? developerClaims]) => promiseToFuture( - nativeInstance.createCustomToken(uid, jsify(developerClaims))); + nativeInstance.createCustomToken(uid, jsify(developerClaims as Object)), + ); /// Creates a new user. Future createUser(CreateUserRequest properties) => @@ -67,7 +68,7 @@ class Auth { /// and starting from the offset as specified by [pageToken]. /// /// This is used to retrieve all the users of a specified project in batches. - Future listUsers([num maxResults, String pageToken]) { + Future listUsers([num? maxResults, String? pageToken]) { if (pageToken != null && maxResults != null) { return promiseToFuture(nativeInstance.listUsers(maxResults, pageToken)); } else if (maxResults != null) { @@ -120,7 +121,7 @@ class Auth { /// of [DecodedIdToken]; otherwise, the future is completed with an error. /// An optional flag can be passed to additionally check whether the ID token /// was revoked. - Future verifyIdToken(String idToken, [bool checkRevoked]) { + Future verifyIdToken(String idToken, [bool? checkRevoked]) { if (checkRevoked != null) { return promiseToFuture( nativeInstance.verifyIdToken(idToken, checkRevoked)); diff --git a/lib/src/bindings.dart b/lib/src/bindings.dart index ca3204b..d6e2665 100644 --- a/lib/src/bindings.dart +++ b/lib/src/bindings.dart @@ -21,7 +21,7 @@ final FirebaseAdmin admin = require('firebase-admin'); @anonymous abstract class FirebaseAdmin { /// Creates and initializes a Firebase app instance. - external App initializeApp([options, String name]); + external App initializeApp([AppOptions? options, String? name]); /// The current SDK version. external String get SDK_VERSION; @@ -36,7 +36,7 @@ abstract class FirebaseAdmin { /// /// An exception is thrown if the app being retrieved has not yet been /// initialized. - external App app([String name]); + external App app([String? name]); /// Gets the [Auth] service for the default app or a given [app]. external Auth auth([App app]); @@ -106,7 +106,7 @@ abstract class ServiceAccountConfig { external String get private_key; external factory ServiceAccountConfig( - {String project_id, String client_email, String private_key}); + {String? project_id, String? client_email, String? private_key}); } /// Interface which provides Google OAuth2 access tokens used to authenticate @@ -188,10 +188,10 @@ abstract class AppOptions { /// Creates new instance of [AppOptions]. external factory AppOptions({ - Credential credential, - String databaseURL, - String projectId, - String storageBucket, + Credential? credential, + String? databaseURL, + String? projectId, + String? storageBucket, }); } @@ -248,7 +248,7 @@ abstract class Auth { /// /// Returns a promise that resolves with the current batch of downloaded users /// and the next page token as an instance of [ListUsersResult]. - external Promise listUsers([num maxResults, String pageToken]); + external Promise listUsers([num? maxResults, String? pageToken]); /// Revokes all refresh tokens for an existing user. /// @@ -289,7 +289,7 @@ abstract class Auth { /// If the token is valid, the returned promise is fulfilled with an instance of /// [DecodedIdToken]; otherwise, the promise is rejected. An optional flag can /// be passed to additionally check whether the ID token was revoked. - external Promise verifyIdToken(String idToken, [bool checkRevoked]); + external Promise verifyIdToken(String idToken, [bool? checkRevoked]); } @JS() @@ -305,14 +305,14 @@ abstract class CreateUserRequest { external String get uid; external factory CreateUserRequest({ - bool disabled, - String displayName, - String email, - bool emailVerified, - String password, - String phoneNumber, - String photoURL, - String uid, + bool? disabled, + String? displayName, + String? email, + bool? emailVerified, + String? password, + String? phoneNumber, + String? photoURL, + String? uid, }); } @@ -328,13 +328,13 @@ abstract class UpdateUserRequest { external String get photoURL; external factory UpdateUserRequest({ - bool disabled, - String displayName, - String email, - bool emailVerified, - String password, - String phoneNumber, - String photoURL, + bool? disabled, + String? displayName, + String? email, + bool? emailVerified, + String? password, + String? phoneNumber, + String? photoURL, }); } @@ -555,27 +555,27 @@ abstract class Messaging { /// /// Returns Promise fulfilled with a unique message ID string after the /// message has been successfully handed off to the FCM service for delivery - external Promise send(FcmMessage message, [bool dryRun]); + external Promise send(FcmMessage message, [bool? dryRun]); /// Sends all the messages in the given array via Firebase Cloud Messaging. /// /// Returns Promise fulfilled with an object representing the /// result of the send operation. - external Promise sendAll(List messages, [bool dryRun]); + external Promise sendAll(List messages, [bool? dryRun]); /// Sends the given multicast message to all the FCM registration tokens /// specified in it. /// /// Returns Promise fulfilled with an object representing the /// result of the send operation. - external Promise sendMulticast(MulticastMessage message, [bool dryRun]); + external Promise sendMulticast(MulticastMessage message, [bool? dryRun]); /// Sends an FCM message to a condition. /// /// Returns Promise fulfilled with the server's /// response after the message has been sent. external Promise sendToCondition(String condition, MessagingPayload payload, - [MessagingOptions options]); + [MessagingOptions? options]); /// Sends an FCM message to a single device corresponding to the provided /// registration token. @@ -584,7 +584,7 @@ abstract class Messaging { /// response after the message has been sent. external Promise sendToDevice( String registrationToken, MessagingPayload payload, - [MessagingOptions options]); + [MessagingOptions? options]); /// Sends an FCM message to a device group corresponding to the provided /// notification key. @@ -593,14 +593,14 @@ abstract class Messaging { /// response after the message has been sent. external Promise sendToDeviceGroup( String notificationKey, MessagingPayload payload, - [MessagingOptions options]); + [MessagingOptions? options]); /// Sends an FCM message to a topic. /// /// Returns Promise fulfilled with the server's /// response after the message has been sent. external Promise sendToTopic(String topic, MessagingPayload payload, - [MessagingOptions options]); + [MessagingOptions? options]); /// Subscribes a device to an FCM topic. /// @@ -624,9 +624,9 @@ abstract class FcmMessage { external String get token; external factory FcmMessage({ - String data, - Notification notification, - String token, + String? data, + Notification? notification, + String? token, }); } @@ -645,14 +645,14 @@ abstract class TopicMessage { external WebpushConfig get webpush; external factory TopicMessage({ - AndroidConfig android, - ApnsConfig apns, + AndroidConfig? android, + ApnsConfig? apns, dynamic data, - String key, - FcmOptions fcmOptions, - Notification notification, - String topic, - WebpushConfig webpush, + String? key, + FcmOptions? fcmOptions, + Notification? notification, + String? topic, + WebpushConfig? webpush, }); } @@ -671,14 +671,14 @@ abstract class TokenMessage { external WebpushConfig get webpush; external factory TokenMessage({ - AndroidConfig android, - ApnsConfig apns, + AndroidConfig? android, + ApnsConfig? apns, dynamic data, - String key, - FcmOptions fcmOptions, - Notification notification, - String token, - WebpushConfig webpush, + String? key, + FcmOptions? fcmOptions, + Notification? notification, + String? token, + WebpushConfig? webpush, }); } @@ -697,14 +697,14 @@ abstract class ConditionMessage { external WebpushConfig get webpush; external factory ConditionMessage({ - AndroidConfig android, - ApnsConfig apns, - String condition, + AndroidConfig? android, + ApnsConfig? apns, + String? condition, dynamic data, - String key, - FcmOptions fcmOptions, - Notification notification, - WebpushConfig webpush, + String? key, + FcmOptions? fcmOptions, + Notification? notification, + WebpushConfig? webpush, }); } @@ -723,14 +723,14 @@ abstract class MulticastMessage { external WebpushConfig get webpush; external factory MulticastMessage({ - AndroidConfig android, - ApnsConfig apns, + AndroidConfig? android, + ApnsConfig? apns, dynamic data, - String key, - FcmOptions fcmOptions, - Notification notification, - List tokens, - WebpushConfig webpush, + String? key, + FcmOptions? fcmOptions, + Notification? notification, + List? tokens, + WebpushConfig? webpush, }); } @@ -748,9 +748,9 @@ abstract class Notification { external String get title; external factory Notification({ - String body, - String imageUrl, - String title, + String? body, + String? imageUrl, + String? title, }); } @@ -816,21 +816,21 @@ abstract class WebpushNotification { external num get vibrate; external factory WebpushNotification({ - List actions, - String badge, - String body, + List? actions, + String? badge, + String? body, dynamic data, - String dir, - String icon, - String image, - String lang, - bool renotify, - bool requireInteraction, - bool silent, - String tag, - num timestamp, - String title, - num vibrate, + String? dir, + String? icon, + String? image, + String? lang, + bool? renotify, + bool? requireInteraction, + bool? silent, + String? tag, + num? timestamp, + String? title, + num? vibrate, }); } @@ -853,9 +853,9 @@ abstract class WebpushConfig { external factory WebpushConfig({ dynamic data, - FcmOptions fcmOptions, + FcmOptions? fcmOptions, dynamic headers, - WebpushNotification notification, + WebpushNotification? notification, }); } @@ -869,7 +869,7 @@ abstract class WebpushFcmOptions { external String get link; external factory WebpushFcmOptions({ - String link, + String? link, }); } @@ -881,7 +881,7 @@ abstract class FcmOptions { external String get analyticsLabel; external factory FcmOptions({ - String analyticsLabel, + String? analyticsLabel, }); } @@ -897,8 +897,8 @@ abstract class MessagingPayload { external NotificationMessagePayload get notification; external factory MessagingPayload({ - DataMessagePayload data, - NotificationMessagePayload notification, + DataMessagePayload? data, + NotificationMessagePayload? notification, }); } @@ -915,7 +915,7 @@ abstract class DataMessagePayload { external dynamic get value; external factory DataMessagePayload({ - String key, + String? key, dynamic value, }); } @@ -979,19 +979,19 @@ abstract class NotificationMessagePayload { external String get titleLocKey; external factory NotificationMessagePayload({ - List actions, - String badge, - String body, - String bodyLocArgs, - String bodyLocKey, - String clickAction, - String color, - String icon, - String sound, - String tag, - String title, - String titleLocArgs, - String titleLocKey, + List? actions, + String? badge, + String? body, + String? bodyLocArgs, + String? bodyLocKey, + String? clickAction, + String? color, + String? icon, + String? sound, + String? tag, + String? title, + String? titleLocArgs, + String? titleLocKey, }); } @@ -1043,13 +1043,13 @@ abstract class MessagingOptions { external num get timeToLive; external factory MessagingOptions({ - String collapseKey, - bool contentAvailable, - bool dryRun, - bool mutableContent, - String priority, - String restrictedPackageName, - num timeToLive, + String? collapseKey, + bool? contentAvailable, + bool? dryRun, + bool? mutableContent, + String? priority, + String? restrictedPackageName, + num? timeToLive, }); } @@ -1089,13 +1089,13 @@ abstract class AndroidConfig { external num get ttl; external factory AndroidConfig({ - String collapseKey, + String? collapseKey, dynamic data, - AndroidFcmOptions fcmOptions, - AndroidNotification notification, - String priority, - String restrictedPackageName, - num ttl, + AndroidFcmOptions? fcmOptions, + AndroidNotification? notification, + String? priority, + String? restrictedPackageName, + num? ttl, }); } @@ -1107,7 +1107,7 @@ abstract class AndroidFcmOptions { external String get analyticsLabel; external factory AndroidFcmOptions({ - String analyticsLabel, + String? analyticsLabel, }); } @@ -1170,19 +1170,19 @@ abstract class AndroidNotification { external String get titleLocKey; external factory AndroidNotification({ - String body, - List bodyLocArgs, - String bodyLocKey, - String channelId, - String clickAction, - String color, - String icon, - String imageUrl, - String sound, - String tag, - String title, - List titleLocArgs, - String titleLocKey, + String? body, + List? bodyLocArgs, + String? bodyLocKey, + String? channelId, + String? clickAction, + String? color, + String? icon, + String? imageUrl, + String? sound, + String? tag, + String? title, + List? titleLocArgs, + String? titleLocKey, }); } @@ -1201,9 +1201,9 @@ abstract class ApnsConfig { external ApnsPayload get payload; external factory ApnsConfig({ - ApnsFcmOptions fcmOptions, + ApnsFcmOptions? fcmOptions, dynamic headers, - ApnsPayload payload, + ApnsPayload? payload, }); } @@ -1217,7 +1217,7 @@ abstract class ApnsFcmOptions { /// URL of an image to be displayed in the notification. external String get imageUrl; - external factory ApnsFcmOptions({String analyticsLabel, String imageUrl}); + external factory ApnsFcmOptions({String? analyticsLabel, String? imageUrl}); } /// Represents options for features provided by the FCM SDK for iOS. @@ -1228,7 +1228,7 @@ abstract class ApnsPayload { external Aps get aps; external factory ApnsPayload({ - Aps aps, + Aps? aps, }); } @@ -1263,12 +1263,12 @@ abstract class Aps { external String get threadId; external factory Aps({ - String alert, - num badge, - String category, - bool contentAvailable, - bool mutableContent, - String sound, + String? alert, + num? badge, + String? category, + bool? contentAvailable, + bool? mutableContent, + String? sound, }); } @@ -1288,17 +1288,17 @@ abstract class ApsAlert { external String get titleLocKey; external factory ApsAlert({ - String actionLocKey, - String body, - String launchImage, - List locArgs, - String locKey, - String subtitle, - List subtitleLocArgs, - String subtitleLocKey, - String title, - List titleLocArgs, - String titleLocKey, + String? actionLocKey, + String? body, + String? launchImage, + List? locArgs, + String? locKey, + String? subtitle, + List? subtitleLocArgs, + String? subtitleLocKey, + String? title, + List? titleLocArgs, + String? titleLocKey, }); } @@ -1322,9 +1322,9 @@ abstract class CriticalSound { external num get volume; external factory CriticalSound({ - bool critical, - String name, - num volume, + bool? critical, + String? name, + num? volume, }); } @@ -1343,9 +1343,9 @@ abstract class BatchResponse { external num get successCount; external factory BatchResponse({ - num failureCount, - List responses, - num successCount, + num? failureCount, + List? responses, + num? successCount, }); } @@ -1369,9 +1369,9 @@ abstract class SendResponse { external bool get success; external factory SendResponse({ - FirebaseError error, - String messageId, - bool success, + FirebaseError? error, + String? messageId, + bool? success, }); } @@ -1385,7 +1385,7 @@ abstract class MessagingConditionResponse { external num get messageId; external factory MessagingConditionResponse({ - num messageId, + num? messageId, }); } @@ -1404,9 +1404,9 @@ abstract class MessagingDeviceGroupResponse { external num get successCount; external factory MessagingDeviceGroupResponse({ - List failedRegistrationTokens, - num failureCount, - num successCount, + List? failedRegistrationTokens, + num? failureCount, + num? successCount, }); } @@ -1429,9 +1429,9 @@ abstract class MessagingDeviceResult { external String get messageId; external factory MessagingDeviceResult({ - String canonicalRegistrationToken, - FirebaseError error, - String messageId, + String? canonicalRegistrationToken, + FirebaseError? error, + String? messageId, }); } @@ -1468,11 +1468,11 @@ abstract class MessagingDevicesResponse { external num get successCount; external factory MessagingDevicesResponse({ - num canonicalRegistrationTokenCount, - num failureCount, - num multicastId, - List results, - num successCount, + num? canonicalRegistrationTokenCount, + num? failureCount, + num? multicastId, + List? results, + num? successCount, }); } @@ -1486,7 +1486,7 @@ abstract class MessagingTopicResponse { external num get messageId; external factory MessagingTopicResponse({ - num messageId, + num? messageId, }); } @@ -1510,9 +1510,9 @@ abstract class MessagingTopicManagementResponse { external num get successCount; external factory MessagingTopicManagementResponse({ - List errors, - num failureCount, - num successCount, + List? errors, + num? failureCount, + num? successCount, }); } @@ -1525,7 +1525,7 @@ abstract class DatabaseService { // external Database call([App app]); /// Logs debugging information to the console. - external enableLogging([dynamic loggerOrBool, bool persistent]); + external enableLogging([dynamic loggerOrBool, bool? persistent]); external ServerValues get ServerValue; } @@ -1557,7 +1557,7 @@ abstract class Database { /// Returns a [Reference] representing the location in the Database /// corresponding to the provided [path]. If no path is provided, the /// Reference will point to the root of the Database. - external Reference ref([String path]); + external Reference ref([String? path]); /// Returns a Reference representing the location in the Database /// corresponding to the provided Firebase URL. @@ -1609,7 +1609,7 @@ abstract class Reference extends Query { /// so the resulting list of items will be chronologically sorted. The keys /// are also designed to be unguessable (they contain 72 random bits of /// entropy). - external ThenableReference push([value, onComplete(JsError error)]); + external ThenableReference push([value, onComplete(JsError error)?]); /// Removes the data at this Database location. /// @@ -1620,7 +1620,7 @@ abstract class Reference extends Query { /// Firebase servers will also be started, and the returned [Promise] will /// resolve when complete. If provided, the [onComplete] callback will be /// called asynchronously after synchronization has finished. - external Promise remove([onComplete(JsError error)]); + external Promise remove([onComplete(JsError error)?]); /// Writes data to this Database location. /// @@ -1644,7 +1644,7 @@ abstract class Reference extends Query { /// /// A single [set] will generate a single "value" event at the location where /// the `set()` was performed. - external Promise set(value, [onComplete(JsError error)]); + external Promise set(value, [onComplete(JsError error)?]); /// Sets a priority for the data at this Database location. /// @@ -1653,7 +1653,7 @@ abstract class Reference extends Query { /// /// See also: /// - [Sorting and filtering data](https://firebase.google.com/docs/database/web/lists-of-data#sorting_and_filtering_data) - external Promise setPriority(priority, [onComplete(JsError error)]); + external Promise setPriority(priority, [onComplete(JsError error)?]); /// Writes data the Database location. Like [set] but also specifies the /// [priority] for that data. @@ -1664,7 +1664,7 @@ abstract class Reference extends Query { /// See also: /// - [Sorting and filtering data](https://firebase.google.com/docs/database/web/lists-of-data#sorting_and_filtering_data) external Promise setWithPriority(value, priority, - [onComplete(JsError error)]); + [onComplete(JsError error)?]); /// Atomically modifies the data at this location. /// @@ -1720,7 +1720,7 @@ abstract class Reference extends Query { /// [transaction] to modify the same data. /// /// Passing `null` to [update] will remove the data at this location. - external Promise update(values, [onComplete(JsError error)]); + external Promise update(values, [onComplete(JsError error)?]); } @JS() @@ -1764,7 +1764,7 @@ abstract class OnDisconnect { /// Optional [onComplete] function that will be called when synchronization to /// the server has completed. The callback will be passed a single parameter: /// `null` for success, or a [JsError] object indicating a failure. - external Promise cancel([onComplete(JsError error)]); + external Promise cancel([onComplete(JsError error)?]); /// Ensures the data at this location is deleted when the client is /// disconnected (due to closing the browser, navigating to a new page, or @@ -1773,7 +1773,7 @@ abstract class OnDisconnect { /// Optional [onComplete] function that will be called when synchronization to /// the server has completed. The callback will be passed a single parameter: /// `null` for success, or a [JsError] object indicating a failure. - external Promise remove([onComplete(JsError error)]); + external Promise remove([onComplete(JsError error)?]); /// Ensures the data at this location is set to the specified [value] when the /// client is disconnected (due to closing the browser, navigating to a new @@ -1789,13 +1789,13 @@ abstract class OnDisconnect { /// /// See also: /// - [Enabling Offline Capabilities in JavaScript](https://firebase.google.com/docs/database/web/offline-capabilities) - external Promise set(value, [onComplete(JsError error)]); + external Promise set(value, [onComplete(JsError error)?]); /// Ensures the data at this location is set to the specified [value] and /// [priority] when the client is disconnected (due to closing the browser, /// navigating to a new page, or network issues). external Promise setWithPriority(value, priority, - [onComplete(JsError error)]); + [onComplete(JsError error)?]); /// Writes multiple [values] at this location when the client is disconnected /// (due to closing the browser, navigating to a new page, or network issues). @@ -1811,7 +1811,7 @@ abstract class OnDisconnect { /// /// See [Reference.update] for examples of using the connected version of /// update. - external Promise update(values, [onComplete(JsError error)]); + external Promise update(values, [onComplete(JsError error)?]); } /// Sorts and filters the data at a [Database] location so only a subset of the @@ -1852,7 +1852,7 @@ abstract class Query { /// Optional [key] is only allowed if ordering by priority and defines the /// child key to end at, among the children with the previously specified /// priority. - external Query endAt(dynamic value, [String key]); + external Query endAt(dynamic value, [String? key]); /// Creates a [Query] that includes children that match the specified value. /// @@ -1867,7 +1867,7 @@ abstract class Query { /// query. If it is specified, then children that have exactly the specified /// value must also have exactly the specified key as their key name. This can /// be used to filter result sets with many matches for the same value. - external Query equalTo(dynamic value, [String key]); + external Query equalTo(dynamic value, [String? key]); /// Returns `true` if this and [other] query are equal. /// @@ -1916,7 +1916,7 @@ abstract class Query { /// If a [callback] is not specified, all callbacks for the specified /// [eventType] will be removed. Similarly, if no [eventType] or [callback] is /// specified, all callbacks for the [Reference] will be removed. - external void off([String eventType, callback, context]); + external void off([String? eventType, callback, context]); /// Listens for data changes at a particular location. /// @@ -1978,7 +1978,7 @@ abstract class Query { /// /// See also: /// - [Filtering data](https://firebase.google.com/docs/database/web/lists-of-data#filtering_data) - external Query startAt(dynamic value, [String key]); + external Query startAt(dynamic value, [String? key]); /// Returns a JSON-serializable representation of this object. external dynamic toJSON(); diff --git a/lib/src/database.dart b/lib/src/database.dart index 0a87d95..c124044 100644 --- a/lib/src/database.dart +++ b/lib/src/database.dart @@ -32,12 +32,11 @@ class Database { /// Returns a [Reference] representing the location in the Database /// corresponding to the provided [path]. If no path is provided, the /// Reference will point to the root of the Database. - Reference ref([String path]) => new Reference(nativeInstance.ref(path)); + Reference ref([String? path]) => Reference(nativeInstance.ref(path)); /// Returns a [Reference] representing the location in the Database /// corresponding to the provided Firebase URL. - Reference refFromUrl(String url) => - new Reference(nativeInstance.refFromURL(url)); + Reference refFromUrl(String url) => Reference(nativeInstance.refFromURL(url)); } /// List of event types supported in [Query.on] and [Query.off]. @@ -123,8 +122,8 @@ class Query { Query(this.nativeInstance); /// Returns a [Reference] to the [Query]'s location. - Reference get ref => _ref ??= new Reference(nativeInstance.ref); - Reference _ref; + Reference get ref => _ref ??= Reference(nativeInstance.ref); + Reference? _ref; /// Creates a [Query] with the specified ending point. /// @@ -143,11 +142,11 @@ class Query { /// Optional [key] is only allowed if ordering by priority and defines the /// child key to end at, among the children with the previously specified /// priority. - Query endAt(value, [String key]) { + Query endAt(value, [String? key]) { if (key == null) { - return new Query(nativeInstance.endAt(value)); + return Query(nativeInstance.endAt(value)); } - return new Query(nativeInstance.endAt(value, key)); + return Query(nativeInstance.endAt(value, key)); } /// Creates a [Query] that includes children that match the specified value. @@ -163,11 +162,11 @@ class Query { /// query. If it is specified, then children that have exactly the specified /// value must also have exactly the specified key as their key name. This can /// be used to filter result sets with many matches for the same value. - Query equalTo(value, [String key]) { + Query equalTo(value, [String? key]) { if (key == null) { - return new Query(nativeInstance.equalTo(value)); + return Query(nativeInstance.equalTo(value)); } - return new Query(nativeInstance.equalTo(value, key)); + return Query(nativeInstance.equalTo(value, key)); } /// Returns `true` if this and [other] query are equal. @@ -191,8 +190,7 @@ class Query { /// the first 100 ordered messages. As items change, we will receive /// child_removed events for each item that drops out of the active list so /// that the total number stays at 100. - Query limitToFirst(int limit) => - new Query(nativeInstance.limitToFirst(limit)); + Query limitToFirst(int limit) => Query(nativeInstance.limitToFirst(limit)); /// Generates a new [Query] limited to the last specific number of children. /// @@ -204,13 +202,13 @@ class Query { /// the last 100 ordered messages. As items change, we will receive /// child_removed events for each item that drops out of the active list so /// that the total number stays at 100. - Query limitToLast(int limit) => new Query(nativeInstance.limitToLast(limit)); + Query limitToLast(int limit) => Query(nativeInstance.limitToLast(limit)); /// Listens for exactly one event of the specified [eventType], and then stops /// listening. Future> once(String eventType) { return promiseToFuture(nativeInstance.once(eventType)) - .then((snapshot) => new DataSnapshot(snapshot)); + .then((snapshot) => DataSnapshot(snapshot)); } /// Cancels previously created subscription with [on]. @@ -225,7 +223,7 @@ class Query { /// specified, [eventType] must be one of [EventType] constants. /// /// To unsubscribe a specific callback, use [QuerySubscription.cancel]. - void off([String eventType]) { + void off([String? eventType]) { if (eventType != null) { nativeInstance.off(eventType); } else { @@ -244,8 +242,8 @@ class Query { /// Returns [QuerySubscription] which can be used to cancel the subscription. QuerySubscription on( String eventType, Function(DataSnapshot snapshot) callback, - [Function() cancelCallback]) { - var fn = allowInterop((snapshot) => callback(new DataSnapshot(snapshot))); + [Function()? cancelCallback]) { + var fn = allowInterop((snapshot) => callback(DataSnapshot(snapshot))); if (cancelCallback != null) { nativeInstance.on(eventType, fn, allowInterop(cancelCallback)); } else { @@ -258,8 +256,7 @@ class Query { /// /// Queries can only order by one key at a time. Calling [orderByChild] /// multiple times on the same query is an error. - Query orderByChild(String path) => - new Query(nativeInstance.orderByChild(path)); + Query orderByChild(String path) => Query(nativeInstance.orderByChild(path)); /// Generates a new [Query] object ordered by key. /// @@ -267,7 +264,7 @@ class Query { /// /// See also: /// - [Sort data](https://firebase.google.com/docs/database/web/lists-of-data#sort_data) - Query orderByKey() => new Query(nativeInstance.orderByKey()); + Query orderByKey() => Query(nativeInstance.orderByKey()); /// Generates a new [Query] object ordered by priority. /// @@ -276,7 +273,7 @@ class Query { /// /// See also: /// - [Sort data](https://firebase.google.com/docs/database/web/lists-of-data#sort_data) - Query orderByPriority() => new Query(nativeInstance.orderByPriority()); + Query orderByPriority() => Query(nativeInstance.orderByPriority()); /// Generates a new [Query] object ordered by value. /// @@ -285,7 +282,7 @@ class Query { /// /// See also: /// - [Sort data](https://firebase.google.com/docs/database/web/lists-of-data#sort_data) - Query orderByValue() => new Query(nativeInstance.orderByValue()); + Query orderByValue() => Query(nativeInstance.orderByValue()); /// Creates a [Query] with the specified starting point. /// @@ -299,11 +296,11 @@ class Query { /// /// See also: /// - [Filtering data](https://firebase.google.com/docs/database/web/lists-of-data#filtering_data) - Query startAt(value, [String key]) { + Query startAt(value, [String? key]) { if (key == null) { - return new Query(nativeInstance.startAt(value)); + return Query(nativeInstance.startAt(value)); } - return new Query(nativeInstance.startAt(value, key)); + return Query(nativeInstance.startAt(value, key)); } // Note: intentionally not following JS convention and using Dart convention instead. @@ -330,7 +327,7 @@ class Reference extends Query { @override @protected - js.Reference get nativeInstance => super.nativeInstance; + js.Reference get nativeInstance => super.nativeInstance as js.Reference; /// The last part of this Reference's path. /// @@ -341,25 +338,25 @@ class Reference extends Query { /// The parent location of this Reference. /// /// The parent of a root Reference is `null`. - Reference get parent => _parent ??= new Reference(nativeInstance.parent); - Reference _parent; + Reference get parent => _parent ??= Reference(nativeInstance.parent); + Reference? _parent; /// The root [Reference] of the [Database]. - Reference get root => _root ??= new Reference(nativeInstance.root); - Reference _root; + Reference get root => _root ??= Reference(nativeInstance.root); + Reference? _root; /// Gets a [Reference] for the location at the specified relative [path]. /// /// The relative [path] can either be a simple child name (for example, "ada") /// or a deeper slash-separated path (for example, "ada/name/first"). - Reference child(String path) => new Reference(nativeInstance.child(path)); + Reference child(String path) => Reference(nativeInstance.child(path)); /// Returns an [OnDisconnect] object. /// /// For more information on how to use it see /// [Enabling Offline Capabilities in JavaScript](https://firebase.google.com/docs/database/web/offline-capabilities). dynamic onDisconnect() { - throw new UnimplementedError(); + throw UnimplementedError(); } /// Generates a new child location using a unique key and returns its @@ -376,16 +373,16 @@ class Reference extends Query { /// so the resulting list of items will be chronologically sorted. The keys /// are also designed to be unguessable (they contain 72 random bits of /// entropy). - FutureReference push([T value]) { + FutureReference push([T? value]) { if (value != null) { var futureRef = nativeInstance.push(jsify(value)); - return new FutureReference(futureRef, promiseToFuture(futureRef)); + return FutureReference(futureRef, promiseToFuture(futureRef)); } else { // JS side returns regular Reference if value is not provided, but // we still convert it to FutureReference to be consistent with declared // return type. var newRef = nativeInstance.push(); - return new FutureReference(newRef, new Future.value()); + return FutureReference(newRef, Future.value()); } } @@ -421,7 +418,7 @@ class Reference extends Query { /// A single [setValue] will generate a single "value" event at the location /// where the `setValue()` was performed. Future setValue(T value) { - return promiseToFuture(nativeInstance.set(jsify(value))); + return promiseToFuture(nativeInstance.set(jsify(value!))); } /// Sets a priority for the data at this Database location. @@ -444,7 +441,7 @@ class Reference extends Query { /// - [Sorting and filtering data](https://firebase.google.com/docs/database/web/lists-of-data#sorting_and_filtering_data) Future setWithPriority(T value, priority) { return promiseToFuture( - nativeInstance.setWithPriority(jsify(value), priority)); + nativeInstance.setWithPriority(jsify(value!), priority)); } /// Atomically modifies the data at this location. @@ -489,15 +486,16 @@ class Reference extends Query { DatabaseTransactionHandler handler, [bool applyLocally = true]) { var promise = nativeInstance.transaction( - allowInterop(_createTransactionHandler(handler)), + allowInterop( + _createTransactionHandler(handler) as dynamic Function(dynamic)), allowInterop(_onComplete), applyLocally, ); return promiseToFuture(promise).then( (result) { final jsResult = result as js.TransactionResult; - return new DatabaseTransaction( - jsResult.committed, new DataSnapshot(jsResult.snapshot)); + return DatabaseTransaction( + jsResult.committed, DataSnapshot(jsResult.snapshot)); }, ); } @@ -510,12 +508,9 @@ class Reference extends Query { return (currentData) { final data = dartify(currentData); final result = handler(data); - assert( - result != null, - 'Transaction handler returned null and this is not allowed. ' - 'Make sure to always return an instance of TransactionResult.'); + if (result.aborted) return undefined; - return jsify(result.data); + return jsify(result.data!); }; } @@ -562,9 +557,9 @@ class TransactionResult { final bool aborted; final T data; - static TransactionResult abort = new TransactionResult._(true, null); + static TransactionResult abort = TransactionResult._(true, null); static TransactionResult success(T data) => - new TransactionResult._(false, data); + TransactionResult._(false, data); } /// Firebase Realtime Database transaction result returned from @@ -612,7 +607,7 @@ class DataSnapshot { String get key => nativeInstance.key; /// The [Reference] for the location that generated this [DataSnapshot]. - Reference get ref => new Reference(nativeInstance.ref); + Reference get ref => Reference(nativeInstance.ref); /// Gets [DataSnapshot] for the location at the specified relative [path]. /// @@ -621,7 +616,7 @@ class DataSnapshot { /// child location has no data, an empty DataSnapshot (that is, a /// DataSnapshot whose value is `null`) is returned. DataSnapshot child(String path) => - new DataSnapshot(nativeInstance.child(path)); + DataSnapshot(nativeInstance.child(path)); /// Returns `true` if this DataSnapshot contains any data. /// @@ -638,7 +633,7 @@ class DataSnapshot { /// by priority). bool forEach(bool action(DataSnapshot child)) { bool wrapper(js.DataSnapshot child) { - return action(new DataSnapshot(child)); + return action(DataSnapshot(child)); } return nativeInstance.forEach(allowInterop(wrapper)); @@ -646,12 +641,12 @@ class DataSnapshot { bool hasChild(String path) => nativeInstance.hasChild(path); bool hasChildren() => nativeInstance.hasChildren(); - int numChildren() => nativeInstance.numChildren(); + int numChildren() => nativeInstance.numChildren() as int; - T _value; + T? _value; /// Returns value stored in this data snapshot. - T val() { + T? val() { if (_value != null) return _value; if (!exists()) return null; // Don't attempt to dartify empty snapshot. diff --git a/lib/src/firestore.dart b/lib/src/firestore.dart index 406cc7d..57b5c4c 100644 --- a/lib/src/firestore.dart +++ b/lib/src/firestore.dart @@ -7,6 +7,7 @@ import 'dart:typed_data'; import 'package:js/js.dart'; import 'package:meta/meta.dart'; +import 'package:firebase_admin_interop/src/firestore_bindings.dart' as binding; import 'package:node_interop/js.dart'; import 'package:node_interop/node.dart'; import 'package:node_interop/util.dart'; @@ -19,17 +20,17 @@ js.GeoPoint createGeoPoint(num latitude, num longitude) => _createJsGeoPoint(latitude, longitude); js.GeoPoint _createJsGeoPoint(num latitude, num longitude) { - final proto = new js.GeoPointProto(latitude: latitude, longitude: longitude); + final proto = js.GeoPointProto(latitude: latitude, longitude: longitude); return js.admin.firestore.GeoPoint.fromProto(proto); } -js.Timestamp _createJsTimestamp(Timestamp ts) { +js.Timestamp? _createJsTimestamp(Timestamp ts) { return callConstructor( js.admin.firestore.Timestamp, jsify([ts.seconds, ts.nanoseconds])); } @Deprecated('This function will be hidden from public API in future versions.') -js.FieldPath createFieldPath(List fieldNames) { +js.FieldPath? createFieldPath(List fieldNames) { return callConstructor(js.admin.firestore.FieldPath, jsify(fieldNames)); } @@ -72,8 +73,7 @@ class Firestore { /// Gets a [CollectionReference] for the specified Firestore path. CollectionReference collection(String path) { - assert(path != null); - return new CollectionReference(nativeInstance.collection(path), this); + return CollectionReference(nativeInstance.collection(path), this); } /// Creates and returns a new Query that includes all documents in the @@ -84,15 +84,12 @@ class Firestore { /// or subcollection with this ID as the last segment of its path will be /// included. Cannot contain a slash. DocumentQuery collectionGroup(String collectionId) { - assert(collectionId != null); - return new DocumentQuery( - nativeInstance.collectionGroup(collectionId), this); + return DocumentQuery(nativeInstance.collectionGroup(collectionId), this); } /// Gets a [DocumentReference] for the specified Firestore path. DocumentReference document(String path) { - assert(path != null); - return new DocumentReference(nativeInstance.doc(path), this); + return DocumentReference(nativeInstance.doc(path), this); } /// Executes the given [updateFunction] and commits the changes applied within @@ -108,12 +105,11 @@ class Firestore { /// with the same error. Future runTransaction( Future updateFunction(Transaction transaction)) { - assert(updateFunction != null); Function jsUpdateFunction = (js.Transaction transaction) { - return futureToPromise(updateFunction(new Transaction(transaction))); + return futureToPromise(updateFunction(Transaction(transaction))); }; - return promiseToFuture( - nativeInstance.runTransaction(allowInterop(jsUpdateFunction))); + return promiseToFuture(nativeInstance.runTransaction(allowInterop( + jsUpdateFunction as Promise Function(binding.Transaction)))); } /// Fetches the root collections that are associated with this Firestore @@ -126,7 +122,7 @@ class Firestore { /// Creates a write batch, used for performing multiple writes as a single /// atomic operation. - WriteBatch batch() => new WriteBatch(nativeInstance.batch()); + WriteBatch batch() => WriteBatch(nativeInstance.batch()); /// Retrieves multiple documents from Firestore. Future> getAll(List refs) async { @@ -151,14 +147,15 @@ class CollectionReference extends DocumentQuery { @override @protected - js.CollectionReference get nativeInstance => super.nativeInstance; + js.CollectionReference? get nativeInstance => + super.nativeInstance as binding.CollectionReference?; /// For subcollections, parent returns the containing DocumentReference. /// /// For root collections, null is returned. - DocumentReference get parent { - return (nativeInstance.parent != null) - ? new DocumentReference(nativeInstance.parent, firestore) + DocumentReference? get parent { + return (nativeInstance?.parent != null) + ? DocumentReference(nativeInstance!.parent, firestore) : null; } @@ -168,10 +165,10 @@ class CollectionReference extends DocumentQuery { /// /// The unique key generated is prefixed with a client-generated timestamp /// so that the resulting list will be chronologically-sorted. - DocumentReference document([String path]) { + DocumentReference document([String? path]) { final docRef = - (path == null) ? nativeInstance.doc() : nativeInstance.doc(path); - return new DocumentReference(docRef, firestore); + (path == null) ? nativeInstance!.doc() : nativeInstance!.doc(path); + return DocumentReference(docRef, firestore); } /// Returns a `DocumentReference` with an auto-generated ID, after @@ -180,16 +177,16 @@ class CollectionReference extends DocumentQuery { /// The unique key generated is prefixed with a client-generated timestamp /// so that the resulting list will be chronologically-sorted. Future add(DocumentData data) { - return promiseToFuture(nativeInstance.add(data.nativeInstance)) - .then((jsRef) => new DocumentReference(jsRef, firestore)); + return promiseToFuture(nativeInstance!.add(data.nativeInstance)) + .then((jsRef) => DocumentReference(jsRef, firestore)); } /// The last path element of the referenced collection. - String get id => nativeInstance.id; + String get id => nativeInstance!.id; /// A string representing the path of the referenced collection (relative to /// the root of the database). - String get path => nativeInstance.path; + String get path => nativeInstance!.path; } /// A [DocumentReference] refers to a document location in a Firestore database @@ -212,13 +209,13 @@ class DocumentReference { String get documentID => nativeInstance.id; CollectionReference get parent { - return new CollectionReference(nativeInstance.parent, firestore); + return CollectionReference(nativeInstance.parent, firestore); } /// Writes to the document referred to by this [DocumentReference]. If the /// document does not yet exist, it will be created. If you pass [SetOptions], /// the provided data will be merged into an existing document. - Future setData(DocumentData data, [js.SetOptions options]) { + Future setData(DocumentData data, [js.SetOptions? options]) { final docData = data.nativeInstance; if (options != null) { return promiseToFuture(nativeInstance.set(docData, options)); @@ -239,7 +236,7 @@ class DocumentReference { /// If no document exists, the read will return null. Future get() { return promiseToFuture(nativeInstance.get()) - .then((jsSnapshot) => new DocumentSnapshot(jsSnapshot, firestore)); + .then((jsSnapshot) => DocumentSnapshot(jsSnapshot, firestore)); } /// Deletes the document referred to by this [DocumentReference]. @@ -248,20 +245,20 @@ class DocumentReference { /// Returns the reference of a collection contained inside of this /// document. CollectionReference collection(String path) => - new CollectionReference(nativeInstance.collection(path), firestore); + CollectionReference(nativeInstance.collection(path), firestore); /// Notifies of documents at this location. Stream get snapshots { - Function cancelCallback; + late Function cancelCallback; // It's fine to let the StreamController be garbage collected once all the // subscribers have cancelled; this analyzer warning is safe to ignore. - StreamController controller; // ignore: close_sinks + late StreamController controller; // ignore: close_sinks void _onNextSnapshot(js.DocumentSnapshot jsSnapshot) { - controller.add(new DocumentSnapshot(jsSnapshot, firestore)); + controller.add(DocumentSnapshot(jsSnapshot, firestore)); } - controller = new StreamController.broadcast( + controller = StreamController.broadcast( onListen: () { cancelCallback = nativeInstance.onSnapshot(allowInterop(_onNextSnapshot)); @@ -309,7 +306,7 @@ class DocumentChange { /// The type of change that occurred (added, modified, or removed). /// /// Can be `null` if this document change was returned from [DocumentQuery.get]. - DocumentChangeType get type { + DocumentChangeType? get type { if (_type != null) return _type; if (nativeInstance.type == 'added') { _type = DocumentChangeType.added; @@ -321,7 +318,7 @@ class DocumentChange { return _type; } - DocumentChangeType _type; + DocumentChangeType? _type; /// The index of the changed document in the result set immediately prior to /// this [DocumentChange] (i.e. supposing that all prior DocumentChange objects @@ -339,8 +336,8 @@ class DocumentChange { /// The document affected by this change. DocumentSnapshot get document => - _document ??= new DocumentSnapshot(nativeInstance.doc, firestore); - DocumentSnapshot _document; + _document ??= DocumentSnapshot(nativeInstance.doc, firestore); + DocumentSnapshot? _document; } class DocumentSnapshot { @@ -352,12 +349,12 @@ class DocumentSnapshot { /// The reference that produced this snapshot DocumentReference get reference => - _reference ??= new DocumentReference(nativeInstance.ref, firestore); - DocumentReference _reference; + _reference ??= DocumentReference(nativeInstance.ref, firestore); + DocumentReference? _reference; /// Contains all the data of this snapshot - DocumentData get data => _data ??= new DocumentData(nativeInstance.data()); - DocumentData _data; + DocumentData get data => _data ??= DocumentData(nativeInstance.data()); + DocumentData? _data; /// Returns `true` if the document exists. bool get exists => nativeInstance.exists; @@ -367,10 +364,10 @@ class DocumentSnapshot { /// The time the document was created. Not set for documents that don't /// exist. - Timestamp get createTime { + Timestamp? get createTime { final ts = nativeInstance.createTime; if (ts == null) return null; - return new Timestamp(ts.seconds, ts.nanoseconds); + return Timestamp(ts.seconds, ts.nanoseconds); } /// The time the document was last updated (at the time the snapshot was @@ -378,15 +375,15 @@ class DocumentSnapshot { /// /// Note that this value includes nanoseconds and can not be represented /// by a [DateTime] object with expected accuracy when used in [Transaction]. - Timestamp get updateTime { + Timestamp? get updateTime { final ts = nativeInstance.updateTime; if (ts == null) return null; - return new Timestamp(ts.seconds, ts.nanoseconds); + return Timestamp(ts.seconds, ts.nanoseconds); } } class _FirestoreData { - _FirestoreData([Object nativeInstance]) + _FirestoreData([Object? nativeInstance]) : nativeInstance = nativeInstance ?? newObject(); @protected final dynamic nativeInstance; @@ -425,33 +422,34 @@ class _FirestoreData { } else if (value is FieldValue) { setFieldValue(key, value); } else if (value is Map) { - setNestedData( - key, new DocumentData.fromMap(value.cast())); + setNestedData(key, DocumentData.fromMap(value.cast())); } else { - throw new ArgumentError.value( + throw ArgumentError.value( value, key, 'Unsupported value type for Firestore.'); } } - String getString(String key) => (getProperty(nativeInstance, key) as String); + String? getString(String key) => + (getProperty(nativeInstance, key) as String?); void setString(String key, String value) { setProperty(nativeInstance, key, value); } - int getInt(String key) => (getProperty(nativeInstance, key) as int); + int? getInt(String key) => (getProperty(nativeInstance, key) as int?); - void setInt(String key, int value) { + void setInt(String key, int? value) { setProperty(nativeInstance, key, value); } - double getDouble(String key) => (getProperty(nativeInstance, key) as double); + double? getDouble(String key) => + (getProperty(nativeInstance, key) as double?); void setDouble(String key, double value) { setProperty(nativeInstance, key, value); } - bool getBool(String key) => (getProperty(nativeInstance, key) as bool); + bool? getBool(String key) => (getProperty(nativeInstance, key) as bool?); void setBool(String key, bool value) { setProperty(nativeInstance, key, value); @@ -461,70 +459,63 @@ class _FirestoreData { bool has(String key) => hasProperty(nativeInstance, key); @Deprecated('Migrate to using Firestore Timestamps and "getTimestamp()".') - DateTime getDateTime(String key) { - final Date value = getProperty(nativeInstance, key); + DateTime? getDateTime(String key) { + final Date? value = getProperty(nativeInstance, key); if (value == null) return null; assert(_isDate(value), 'Tried to get Date and got $value'); - return new DateTime.fromMillisecondsSinceEpoch(value.getTime()); + return DateTime.fromMillisecondsSinceEpoch(value.getTime()); } - Timestamp getTimestamp(String key) { - js.Timestamp ts = getProperty(nativeInstance, key); + Timestamp? getTimestamp(String key) { + js.Timestamp? ts = getProperty(nativeInstance, key); if (ts == null) return null; assert(_isTimestamp(ts), 'Tried to get Timestamp and got $ts.'); - return new Timestamp(ts.seconds, ts.nanoseconds); + return Timestamp(ts.seconds, ts.nanoseconds); } @Deprecated('Migrate to using Firestore Timestamps and "setTimestamp()".') - void setDateTime(String key, DateTime value) { - assert(key != null); - final data = - (value != null) ? new Date(value.millisecondsSinceEpoch) : null; + void setDateTime(String key, DateTime? value) { + final data = (value != null) ? Date(value.millisecondsSinceEpoch) : null; setProperty(nativeInstance, key, data); } - void setTimestamp(String key, Timestamp value) { - assert(key != null); + void setTimestamp(String key, Timestamp? value) { final ts = (value != null) ? _createJsTimestamp(value) : null; setProperty(nativeInstance, key, ts); } - GeoPoint getGeoPoint(String key) { - js.GeoPoint value = getProperty(nativeInstance, key); + GeoPoint? getGeoPoint(String key) { + js.GeoPoint? value = getProperty(nativeInstance, key); if (value == null) return null; assert(_isGeoPoint(value), 'Invalid value provided to $runtimeType.getGeoPoint().'); - return new GeoPoint(value.latitude.toDouble(), value.longitude.toDouble()); + return GeoPoint(value.latitude.toDouble(), value.longitude.toDouble()); } - Blob getBlob(String key) { + Blob? getBlob(String key) { var value = getProperty(nativeInstance, key); if (value == null) return null; assert(_isBlob(value), 'Invalid value provided to $runtimeType.getBlob().'); - return new Blob(value); + return Blob(value); } - void setGeoPoint(String key, GeoPoint value) { - assert(key != null); + void setGeoPoint(String key, GeoPoint? value) { final data = (value != null) ? _createJsGeoPoint(value.latitude, value.longitude) : null; setProperty(nativeInstance, key, data); } - void setBlob(String key, Blob value) { - assert(key != null); + void setBlob(String key, Blob? value) { final data = (value != null) ? value.data : null; setProperty(nativeInstance, key, data); } void setFieldValue(String key, FieldValue value) { - assert(key != null); - setProperty(nativeInstance, key, value?._jsify()); + setProperty(nativeInstance, key, value._jsify()); } void setNestedData(String key, DocumentData value) { - assert(key != null); setProperty(nativeInstance, key, value.nativeInstance); } @@ -535,13 +526,13 @@ class _FirestoreData { value is String || value is bool; - List getList(String key) { + List? getList(String key) { final data = getProperty(nativeInstance, key); if (data == null) return null; if (data is! List) { - throw new StateError('Expected list but got ${data.runtimeType}.'); + throw StateError('Expected list but got ${data.runtimeType}.'); } - final result = new List(); + final result = []; for (var item in data) { item = _dartify(item); result.add(item); @@ -549,8 +540,7 @@ class _FirestoreData { return result; } - void setList(String key, List value) { - assert(key != null); + void setList(String key, List? value) { if (value == null) { setProperty(nativeInstance, key, value); return; @@ -562,18 +552,17 @@ class _FirestoreData { setProperty(nativeInstance, key, data); } - DocumentReference getReference(String key) { - js.DocumentReference ref = getProperty(nativeInstance, key); + DocumentReference? getReference(String key) { + js.DocumentReference? ref = getProperty(nativeInstance, key); if (ref == null) return null; assert(_isReference(ref), 'Invalid value provided to $runtimeType.getReference().'); js.Firestore firestore = ref.firestore; - return new DocumentReference(ref, new Firestore(firestore)); + return DocumentReference(ref, Firestore(firestore)); } - void setReference(String key, DocumentReference value) { - assert(key != null); + void setReference(String key, DocumentReference? value) { final data = (value != null) ? value.nativeInstance : null; setProperty(nativeInstance, key, data); } @@ -634,7 +623,7 @@ class _FirestoreData { return blob.data; } else if (item is DateTime) { DateTime date = item; - return new Date(date.millisecondsSinceEpoch); + return Date(date.millisecondsSinceEpoch); } else if (item is Timestamp) { return _createJsTimestamp(item); } else if (item is FieldValue) { @@ -642,7 +631,7 @@ class _FirestoreData { } else if (item is List) { return _jsifyList(item); } else if (item is Map) { - return DocumentData.fromMap(item?.cast()).nativeInstance; + return DocumentData.fromMap(item.cast()).nativeInstance; } else { throw UnsupportedError( 'Value of type ${item.runtimeType} is not supported by Firestore.'); @@ -682,7 +671,7 @@ class _FirestoreData { } else if (_isReference(item)) { js.DocumentReference ref = item; js.Firestore firestore = ref.firestore; - return DocumentReference(ref, new Firestore(firestore)); + return DocumentReference(ref, Firestore(firestore)); } else if (_isBlob(item)) { return Blob(item); } else if (_isTimestamp(item)) { @@ -737,18 +726,18 @@ class _FirestoreData { /// - [UpdateData] which is used to update a part of a document and follows /// different pattern for handling nested fields. class DocumentData extends _FirestoreData { - DocumentData([js.DocumentData nativeInstance]) : super(nativeInstance); + DocumentData([js.DocumentData? nativeInstance]) : super(nativeInstance); factory DocumentData.fromMap(Map data) { - final doc = new DocumentData(); + final doc = DocumentData(); data.forEach(doc._setField); return doc; } - DocumentData getNestedData(String key) { + DocumentData? getNestedData(String key) { final data = getProperty(nativeInstance, key); if (data == null) return null; - return new DocumentData(data); + return DocumentData(data); } /// List of keys in this document data. @@ -775,19 +764,19 @@ class DocumentData extends _FirestoreData { /// /// // Using DocumentData with "profile" field which itself contains /// // "name" field: -/// DocumentData profile = new DocumentData(); +/// DocumentData profile = DocumentData(); /// profile.setString("name", "John"); -/// DocumentData doc = new DocumentData(); +/// DocumentData doc = DocumentData(); /// doc.setNestedData("profile", profile); /// /// // Using UpdateData to update profile name: -/// UpdateData data = new UpdateData(); +/// UpdateData data = UpdateData(); /// data.setString("profile.name", "John"); class UpdateData extends _FirestoreData { - UpdateData([js.UpdateData nativeInstance]) : super(nativeInstance); + UpdateData([js.UpdateData? nativeInstance]) : super(nativeInstance); factory UpdateData.fromMap(Map data) { - final doc = new UpdateData(); + final doc = UpdateData(); data.forEach(doc._setField); return doc; } @@ -825,7 +814,7 @@ class Timestamp { } DateTime toDateTime() { - return new DateTime.fromMicrosecondsSinceEpoch(microsecondsSinceEpoch); + return DateTime.fromMicrosecondsSinceEpoch(microsecondsSinceEpoch); } } @@ -857,10 +846,10 @@ class GeoPoint { class Blob { final Uint8List _data; - /// Creates new blob from list of bytes in [data]. - Blob(List data) : _data = new Uint8List.fromList(data); + /// Creates blob from list of bytes in [data]. + Blob(List data) : _data = Uint8List.fromList(data); - /// Creates new blob from list of bytes in [Uint8List]. + /// Creates blob from list of bytes in [Uint8List]. Blob.fromUint8List(this._data); /// List of bytes contained in this blob. @@ -883,32 +872,32 @@ class QuerySnapshot { bool get isNotEmpty => !isEmpty; /// Gets a list of all the documents included in this snapshot - List get documents { + List? get documents { if (isEmpty) return const []; - _documents ??= new List.from(nativeInstance.docs) - .map((jsDoc) => new DocumentSnapshot(jsDoc, firestore)) + _documents ??= List.from(nativeInstance.docs) + .map((jsDoc) => DocumentSnapshot(jsDoc, firestore)) .toList(growable: false); return _documents; } - List _documents; + List? _documents; /// An array of the documents that changed since the last snapshot. If this /// is the first snapshot, all documents will be in the list as Added changes. - List get documentChanges { + List? get documentChanges { if (_changes == null) { if (nativeInstance.docChanges() == null) { _changes = const []; } else { - _changes = new List.from(nativeInstance.docChanges()) - .map((jsChange) => new DocumentChange(jsChange, firestore)) + _changes = List.from(nativeInstance.docChanges()!) + .map((jsChange) => DocumentChange(jsChange, firestore)) .toList(growable: false); } } return _changes; } - List _changes; + List? _changes; } /// Represents a query over the data at a particular location. @@ -916,34 +905,34 @@ class DocumentQuery { DocumentQuery(this.nativeInstance, this.firestore); @protected - final js.DocumentQuery nativeInstance; + final js.DocumentQuery? nativeInstance; final Firestore firestore; Future get() { - return promiseToFuture(nativeInstance.get()) - .then((jsSnapshot) => new QuerySnapshot(jsSnapshot, firestore)); + return promiseToFuture(nativeInstance!.get()) + .then((jsSnapshot) => QuerySnapshot(jsSnapshot, firestore)); } /// Notifies of query results at this location. Stream get snapshots { // It's fine to let the StreamController be garbage collected once all the // subscribers have cancelled; this analyzer warning is safe to ignore. - StreamController controller; // ignore: close_sinks + late StreamController controller; // ignore: close_sinks void onSnapshot(js.QuerySnapshot snapshot) { - controller.add(new QuerySnapshot(snapshot, firestore)); + controller.add(QuerySnapshot(snapshot, firestore)); } void onError(error) { controller.addError(error); } - Function unsubscribe; + late Function unsubscribe; - controller = new StreamController.broadcast( + controller = StreamController.broadcast( onListen: () { - unsubscribe = nativeInstance.onSnapshot( - allowInterop(onSnapshot), allowInterop(onError)); + unsubscribe = nativeInstance! + .onSnapshot(allowInterop(onSnapshot), allowInterop(onError)); }, onCancel: () { unsubscribe(); @@ -965,12 +954,12 @@ class DocumentQuery { dynamic isGreaterThan, dynamic isGreaterThanOrEqualTo, dynamic arrayContains, - bool isNull, + bool? isNull, }) { - js.DocumentQuery query = nativeInstance; + js.DocumentQuery? query = nativeInstance; void addCondition(String field, String opStr, dynamic value) { - query = query.where(field, opStr, _FirestoreData._jsify(value)); + query = query!.where(field, opStr, _FirestoreData._jsify(value)); } if (isEqualTo != null) addCondition(field, '==', isEqualTo); @@ -991,15 +980,14 @@ class DocumentQuery { addCondition(field, '==', null); } - return new DocumentQuery(query, firestore); + return DocumentQuery(query, firestore); } /// Creates and returns a new [DocumentQuery] that's additionally sorted by the specified /// [field]. DocumentQuery orderBy(String field, {bool descending: false}) { String direction = descending ? 'desc' : 'asc'; - return new DocumentQuery( - nativeInstance.orderBy(field, direction), firestore); + return DocumentQuery(nativeInstance!.orderBy(field, direction), firestore); } /// Takes a [snapshot] or a list of [values], creates and returns a new [DocumentQuery] @@ -1009,8 +997,9 @@ class DocumentQuery { /// The [values] must be in order of [orderBy] filters. /// /// Cannot be used in combination with [startAt]. - DocumentQuery startAfter({DocumentSnapshot snapshot, List values}) { - return new DocumentQuery( + DocumentQuery startAfter( + {DocumentSnapshot? snapshot, List? values}) { + return DocumentQuery( _wrapPaginatingFunctionCall("startAfter", snapshot, values), firestore); } @@ -1021,8 +1010,8 @@ class DocumentQuery { /// The [values] must be in order of [orderBy] filters. /// /// Cannot be used in combination with [startAfter]. - DocumentQuery startAt({DocumentSnapshot snapshot, List values}) { - return new DocumentQuery( + DocumentQuery startAt({DocumentSnapshot? snapshot, List? values}) { + return DocumentQuery( _wrapPaginatingFunctionCall("startAt", snapshot, values), firestore); } @@ -1033,8 +1022,8 @@ class DocumentQuery { /// The [values] must be in order of [orderBy] filters. /// /// Cannot be used in combination with [endBefore]. - DocumentQuery endAt({DocumentSnapshot snapshot, List values}) { - return new DocumentQuery( + DocumentQuery endAt({DocumentSnapshot? snapshot, List? values}) { + return DocumentQuery( _wrapPaginatingFunctionCall("endAt", snapshot, values), firestore); } @@ -1045,40 +1034,38 @@ class DocumentQuery { /// The [values] must be in order of [orderBy] filters. /// /// Cannot be used in combination with [endAt]. - DocumentQuery endBefore({DocumentSnapshot snapshot, List values}) { - return new DocumentQuery( + DocumentQuery endBefore({DocumentSnapshot? snapshot, List? values}) { + return DocumentQuery( _wrapPaginatingFunctionCall("endBefore", snapshot, values), firestore); } /// Creates and returns a new Query that's additionally limited to only return up /// to the specified number of documents. DocumentQuery limit(int length) { - assert(length != null); - return new DocumentQuery(nativeInstance.limit(length), firestore); + return DocumentQuery(nativeInstance!.limit(length), firestore); } /// Specifies the offset of the returned results. DocumentQuery offset(int offset) { - assert(offset != null); - return new DocumentQuery(nativeInstance.offset(offset), firestore); + return DocumentQuery(nativeInstance!.offset(offset), firestore); } /// Calls js paginating [method] with [DocumentSnapshot] or List of [values]. /// We need to call this method in all paginating methods to fix that Dart /// doesn't support varargs - we need to use [List] to call js function. - js.DocumentQuery _wrapPaginatingFunctionCall( - String method, DocumentSnapshot snapshot, List values) { + js.DocumentQuery? _wrapPaginatingFunctionCall( + String method, DocumentSnapshot? snapshot, List? values) { if (snapshot == null && values == null) { - throw new ArgumentError( + throw ArgumentError( "Please provide either snapshot or values parameter."); } else if (snapshot != null && values != null) { - throw new ArgumentError( + throw ArgumentError( 'Cannot provide both snapshot and values parameters.'); } List args = (snapshot != null) ? [snapshot.nativeInstance] - : values.map(_FirestoreData._jsify).toList(); - return callMethod(nativeInstance, method, args); + : values!.map(_FirestoreData._jsify).toList(); + return callMethod(nativeInstance!, method, args); } /// Creates and returns a new Query instance that applies a field mask @@ -1086,10 +1073,9 @@ class DocumentQuery { /// You can specify a list of field paths to return, or use an empty /// list to only return the references of matching documents. DocumentQuery select(List fieldPaths) { - assert(fieldPaths != null); // Dart doesn't support varargs - return new DocumentQuery( - callMethod(nativeInstance, "select", fieldPaths), firestore); + return DocumentQuery( + callMethod(nativeInstance!, "select", fieldPaths), firestore); } } @@ -1106,8 +1092,8 @@ class Transaction { /// Holds a pessimistic lock on the returned document. Future get(DocumentReference documentRef) { final nativeRef = documentRef.nativeInstance; - return promiseToFuture(nativeInstance.get(nativeRef)).then((jsSnapshot) => - new DocumentSnapshot(jsSnapshot, documentRef.firestore)); + return promiseToFuture(nativeInstance.get(nativeRef)).then( + (jsSnapshot) => DocumentSnapshot(jsSnapshot, documentRef.firestore)); } /// Retrieves a query result. Holds a pessimistic lock on the returned @@ -1115,7 +1101,7 @@ class Transaction { Future getQuery(DocumentQuery query) { final nativeQuery = query.nativeInstance; return promiseToFuture(nativeInstance.get(nativeQuery)) - .then((jsSnapshot) => new QuerySnapshot(jsSnapshot, query.firestore)); + .then((jsSnapshot) => QuerySnapshot(jsSnapshot, query.firestore)); } /// Create the document referred to by the provided [documentRef]. @@ -1145,7 +1131,7 @@ class Transaction { /// [DocumentSnapshot.updateTime]. The update will be accepted only if /// update time on the server is equal to this value. void update(DocumentReference documentRef, UpdateData data, - {Timestamp lastUpdateTime}) { + {Timestamp? lastUpdateTime}) { final docData = data.nativeInstance; final nativeRef = documentRef.nativeInstance; if (lastUpdateTime != null) { @@ -1162,7 +1148,7 @@ class Transaction { /// delete. This argument, if specified, must contain value of /// [DocumentSnapshot.updateTime]. The delete will be accepted only if /// update time on the server is equal to this value. - void delete(DocumentReference documentRef, {Timestamp lastUpdateTime}) { + void delete(DocumentReference documentRef, {Timestamp? lastUpdateTime}) { final nativeRef = documentRef.nativeInstance; if (lastUpdateTime != null) { nativeInstance.delete(nativeRef, _getNativePrecondition(lastUpdateTime)); @@ -1190,7 +1176,7 @@ class WriteBatch { /// If the document does not exist yet, it will be created. If you pass /// [options], the provided data can be merged into the existing document. void setData(DocumentReference documentRef, DocumentData data, - [js.SetOptions options]) { + [js.SetOptions? options]) { final docData = data.nativeInstance; final nativeRef = documentRef.nativeInstance; if (options != null) { @@ -1220,9 +1206,8 @@ class WriteBatch { /// Using Preconditions, these calls can be restricted to only apply to /// documents that match the specified restrictions. js.Precondition _getNativePrecondition(Timestamp lastUpdateTime) { - assert(lastUpdateTime != null, 'Precontition lastUpdateTime can`t be null'); final ts = _createJsTimestamp(lastUpdateTime); - return new js.Precondition(lastUpdateTime: ts); + return js.Precondition(lastUpdateTime: ts); } /// An options object that configures the behavior of [set] calls in @@ -1230,8 +1215,7 @@ js.Precondition _getNativePrecondition(Timestamp lastUpdateTime) { /// configured to perform granular merges instead of overwriting the target /// documents in their entirety by providing a [SetOptions] with [merge]: true. js.SetOptions _getNativeSetOptions(bool merge) { - assert(merge != null, 'SetOption merge can`t be null'); - return new js.SetOptions(merge: merge); + return js.SetOptions(merge: merge); } class _FieldValueDelete implements FieldValue { diff --git a/lib/src/firestore_bindings.dart b/lib/src/firestore_bindings.dart index 8fe5858..f341af3 100644 --- a/lib/src/firestore_bindings.dart +++ b/lib/src/firestore_bindings.dart @@ -53,7 +53,7 @@ abstract class GeoPointUtil { @JS() @anonymous abstract class GeoPointProto { - external factory GeoPointProto({num latitude, num longitude}); + external factory GeoPointProto({num? latitude, num? longitude}); external num get latitude; external num get longitude; } @@ -96,11 +96,11 @@ abstract class Firestore { /// Retrieves multiple documents from Firestore. /// snapshots. external Promise getAll( - [DocumentReference documentRef1, - DocumentReference documentRef2, - DocumentReference documentRef3, - DocumentReference documentRef4, - DocumentReference documentRef5]); + [DocumentReference? documentRef1, + DocumentReference? documentRef2, + DocumentReference? documentRef3, + DocumentReference? documentRef4, + DocumentReference? documentRef5]); /// Fetches the root collections that are associated with this Firestore /// database. @@ -165,9 +165,9 @@ abstract class FirestoreSettings { external bool get timestampsInSnapshots; external factory FirestoreSettings({ - String projectId, - String keyFilename, - bool timestampsInSnapshots, + String? projectId, + String? keyFilename, + bool? timestampsInSnapshots, }); } @@ -201,13 +201,16 @@ abstract class Transaction { /// Create the document referred to by the provided `DocumentReference`. /// The operation will fail the transaction if a document exists at the /// specified location. - external Transaction create(DocumentReference documentRef, DocumentData data); + external Transaction create( + DocumentReference documentRef, + DocumentData? data, + ); /// Writes to the document referred to by the provided `DocumentReference`. /// If the document does not exist yet, it will be created. If you pass /// `SetOptions`, the provided data can be merged into the existing document. - external Transaction set(DocumentReference documentRef, DocumentData data, - [SetOptions options]); + external Transaction set(DocumentReference documentRef, DocumentData? data, + [SetOptions? options]); /// Updates fields in the document referred to by the provided /// `DocumentReference`. The update will fail if applied to a document that @@ -230,11 +233,11 @@ abstract class Transaction { external Transaction update( DocumentReference documentRef, dynamic /*String|FieldPath*/ data_field, [dynamic /*Precondition|dynamic*/ precondition_value, - List fieldsOrPrecondition]); + List? fieldsOrPrecondition]); /// Deletes the document referred to by the provided `DocumentReference`. external Transaction delete(DocumentReference documentRef, - [Precondition precondition]); + [Precondition? precondition]); } /// A write batch, used to perform multiple writes as a single atomic unit. @@ -257,14 +260,14 @@ abstract class WriteBatch { /// Write to the document referred to by the provided [DocumentReference]. /// If the document does not exist yet, it will be created. If you pass /// [options], the provided data can be merged into the existing document. - external WriteBatch set(DocumentReference documentRef, DocumentData data, - [SetOptions options]); + external WriteBatch set(DocumentReference documentRef, DocumentData? data, + [SetOptions? options]); /// Updates fields in the document referred to by this DocumentReference. /// The update will fail if applied to a document that does not exist. /// /// Nested fields can be updated by providing dot-separated field path strings - external WriteBatch update(DocumentReference documentRef, UpdateData data); + external WriteBatch update(DocumentReference documentRef, UpdateData? data); /// Deletes the document referred to by the provided `DocumentReference`. external WriteBatch delete(DocumentReference documentRef); @@ -284,7 +287,7 @@ abstract class Precondition { /// string). external Timestamp get lastUpdateTime; external set lastUpdateTime(Timestamp v); - external factory Precondition({Timestamp lastUpdateTime}); + external factory Precondition({Timestamp? lastUpdateTime}); } /// An options object that configures the behavior of `set()` calls in @@ -299,7 +302,7 @@ abstract class SetOptions { /// untouched. external bool get merge; external set merge(bool v); - external factory SetOptions({bool merge}); + external factory SetOptions({bool? merge}); } /// A WriteResult wraps the write time set by the Firestore servers on `sets()`, @@ -352,14 +355,14 @@ abstract class DocumentReference { /// Writes to the document referred to by this `DocumentReference`. If the /// document does not yet exist, it will be created. If you pass /// `SetOptions`, the provided data can be merged into an existing document. - external Promise set(DocumentData data, [SetOptions options]); + external Promise set(DocumentData? data, [SetOptions? options]); /// Updates fields in the document referred to by this `DocumentReference`. /// The update will fail if applied to a document that does not exist. /// Nested fields can be updated by providing dot-separated field path /// strings. /// update the document. - external Promise update(UpdateData data, [Precondition precondition]); + external Promise update(UpdateData? data, [Precondition? precondition]); /// Updates fields in the document referred to by this `DocumentReference`. /// The update will fail if applied to a document that does not exist. @@ -375,7 +378,7 @@ abstract class DocumentReference { // List moreFieldsOrPrecondition]); /// Deletes the document referred to by this `DocumentReference`. - external Promise delete([Precondition precondition]); + external Promise delete([Precondition? precondition]); /// Reads the document referred to by this `DocumentReference`. /// current document contents. @@ -386,7 +389,7 @@ abstract class DocumentReference { /// cancelled. No further callbacks will occur. /// the snapshot listener. external Function onSnapshot(void onNext(DocumentSnapshot snapshot), - [void onError(Error error)]); + [void onError(Error error)?]); } /// A `DocumentSnapshot` contains data read from a document in your Firestore @@ -412,13 +415,13 @@ abstract class DocumentSnapshot { /// The time the document was created. Not set for documents that don't /// exist. - external Timestamp get createTime; - external set createTime(Timestamp v); + external Timestamp? get createTime; + external set createTime(Timestamp? v); /// The time the document was last updated (at the time the snapshot was /// generated). Not set for documents that don't exist. - external Timestamp get updateTime; - external set updateTime(Timestamp v); + external Timestamp? get updateTime; + external set updateTime(Timestamp? v); /// The time this snapshot was read. external Timestamp get readTime; @@ -446,12 +449,12 @@ abstract class DocumentSnapshot { abstract class QueryDocumentSnapshot extends DocumentSnapshot { /// The time the document was created. external Timestamp get createTime; - external set createTime(Timestamp v); + external set createTime(Timestamp? v); /// The time the document was last updated (at the time the snapshot was /// generated). external Timestamp get updateTime; - external set updateTime(Timestamp v); + external set updateTime(Timestamp? v); /// Retrieves all fields in the document as an Object. /// @override @@ -488,7 +491,7 @@ abstract class DocumentQuery { /// than modify the existing instance) to impose the order. /// not specified, order will be ascending. external DocumentQuery orderBy(dynamic /*String|FieldPath*/ fieldPath, - [String /*'desc'|'asc'*/ directionStr]); + [String? /*'desc'|'asc'*/ directionStr]); /// Creates and returns a new Query that's additionally limited to only /// return up to the specified number of documents. @@ -597,7 +600,7 @@ abstract class DocumentQuery { /// cancelled. No further callbacks will occur. /// the snapshot listener. external Function onSnapshot(void onNext(QuerySnapshot snapshot), - [void onError(Error error)]); + [void onError(Error error)?]); } /// A `QuerySnapshot` contains zero or more `QueryDocumentSnapshot` objects @@ -616,7 +619,7 @@ abstract class QuerySnapshot { /// An array of the documents that changed since the last snapshot. If this /// is the first snapshot, all documents will be in the list as added /// changes. - external List docChanges(); + external List? docChanges(); /// An array of all the documents in the QuerySnapshot. external List get docs; @@ -668,10 +671,10 @@ abstract class DocumentChange { external num get newIndex; external set newIndex(num v); external factory DocumentChange( - {String /*'added'|'removed'|'modified'*/ type, - QueryDocumentSnapshot doc, - num oldIndex, - num newIndex}); + {String? /*'added'|'removed'|'modified'*/ type, + QueryDocumentSnapshot? doc, + num? oldIndex, + num? newIndex}); } /// A `CollectionReference` object can be used for adding documents, getting @@ -697,12 +700,12 @@ abstract class CollectionReference extends DocumentQuery { /// Get a `DocumentReference` for the document within the collection at the /// specified path. If no path is specified, an automatically-generated /// unique ID will be used for the returned DocumentReference. - external DocumentReference doc([String documentPath]); + external DocumentReference doc([String? documentPath]); /// Add a new document to this collection with the specified data, assigning /// it a document ID automatically. /// newly created document after it has been written to the backend. - external Promise add(DocumentData data); + external Promise add(DocumentData? data); } /// Sentinel values that can be used when writing document fields with set() @@ -759,9 +762,9 @@ abstract class FieldPath { /// Creates a FieldPath from the provided field names. If more than one field /// name is provided, the path will point to a nested field in a document. external factory FieldPath( - [String fieldNames1, - String fieldNames2, - String fieldNames3, - String fieldNames4, - String fieldNames5]); + [String? fieldNames1, + String? fieldNames2, + String? fieldNames3, + String? fieldNames4, + String? fieldNames5]); } diff --git a/lib/src/messaging.dart b/lib/src/messaging.dart index 7043052..6ceaa61 100644 --- a/lib/src/messaging.dart +++ b/lib/src/messaging.dart @@ -64,7 +64,7 @@ class Messaging { /// /// Returns Future fulfilled with a unique message ID string after the /// message has been successfully handed off to the FCM service for delivery - Future send(FcmMessage message, [bool dryRun]) { + Future send(FcmMessage message, [bool? dryRun]) { if (dryRun != null) return promiseToFuture(nativeInstance.send(message, dryRun)); else @@ -75,7 +75,7 @@ class Messaging { /// /// Returns Future fulfilled with an object representing the /// result of the send operation. - Future sendAll(List messages, [bool dryRun]) { + Future sendAll(List messages, [bool? dryRun]) { if (dryRun != null) return promiseToFuture(nativeInstance.sendAll(messages, dryRun)); else @@ -87,7 +87,7 @@ class Messaging { /// /// Returns Future fulfilled with an object representing the /// result of the send operation. - Future sendMulticast(MulticastMessage message, [bool dryRun]) { + Future sendMulticast(MulticastMessage message, [bool? dryRun]) { if (dryRun != null) return promiseToFuture(nativeInstance.sendMulticast(message, dryRun)); else @@ -100,7 +100,7 @@ class Messaging { /// response after the message has been sent. Future sendToCondition( String condition, MessagingPayload payload, - [MessagingOptions options]) { + [MessagingOptions? options]) { if (options != null) return promiseToFuture( nativeInstance.sendToCondition(condition, payload, options)); @@ -116,7 +116,7 @@ class Messaging { /// response after the message has been sent. Future sendToDevice( String registrationToken, MessagingPayload payload, - [MessagingOptions options]) { + [MessagingOptions? options]) { if (options != null) return promiseToFuture( nativeInstance.sendToDevice(registrationToken, payload, options)); @@ -132,7 +132,7 @@ class Messaging { /// response after the message has been sent. Future sendToDeviceGroup( String notificationKey, MessagingPayload payload, - [MessagingOptions options]) { + [MessagingOptions? options]) { if (options != null) return promiseToFuture( nativeInstance.sendToDeviceGroup(notificationKey, payload, options)); @@ -147,7 +147,7 @@ class Messaging { /// response after the message has been sent. Future sendToTopic( String topic, MessagingPayload payload, - [MessagingOptions options]) { + [MessagingOptions? options]) { if (options != null) return promiseToFuture( nativeInstance.sendToTopic(topic, payload, options)); diff --git a/lib/src/storage_bindings.dart b/lib/src/storage_bindings.dart index 343e1b1..b11db9c 100644 --- a/lib/src/storage_bindings.dart +++ b/lib/src/storage_bindings.dart @@ -20,7 +20,7 @@ abstract class Storage { /// /// [name] of the bucket to be retrieved is optional. If [name] is not /// specified, retrieves a reference to the default bucket. - external Bucket bucket([String name]); + external Bucket bucket([String? name]); } @JS() @@ -40,18 +40,18 @@ abstract class Bucket { /// Create a bucket. /// /// Returns promise containing CreateBucketResponse. - external Promise create([CreateBucketRequest metadata, callback]); + external Promise create([CreateBucketRequest? metadata, callback]); /// Checks if the bucket exists. /// /// Returns promise containing list with following values: /// [0] [boolean] - Whether this bucket exists. - external Promise exists([BucketExistsOptions options, callback]); + external Promise exists([BucketExistsOptions? options, callback]); /// Creates a [StorageFile] object. /// /// See [StorageFile] to see for more details. - external StorageFile file(String name, [StorageFileOptions options]); + external StorageFile file(String name, [StorageFileOptions? options]); /// Upload a file to the bucket. This is a convenience method that wraps /// [StorageFile.createWriteStream]. @@ -81,7 +81,7 @@ abstract class CombineOptions { /// The ID of the project which will be billed for the request. external String get userProject; - external factory CombineOptions({String kmsKeyName, String userProject}); + external factory CombineOptions({String? kmsKeyName, String? userProject}); } @JS() @@ -96,7 +96,7 @@ abstract class BucketExistsOptions { /// The ID of the project which will be billed for the request. external String get userProject; - external factory BucketExistsOptions({String userProject}); + external factory BucketExistsOptions({String? userProject}); } @JS() @@ -115,7 +115,7 @@ abstract class StorageFileOptions { external String get kmsKeyName; external factory StorageFileOptions( - {String generation, String encryptionKey, String kmsKeyName}); + {String? generation, String? encryptionKey, String? kmsKeyName}); } @JS() diff --git a/pubspec.yaml b/pubspec.yaml index 733cba1..4093cff 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,20 +1,24 @@ name: firebase_admin_interop description: Firebase Admin SDK for Dart written as a wrapper around official Node.js SDK. -version: 2.1.0 +version: 3.0.0 homepage: https://github.com/pulyaevskiy/firebase-admin-interop author: Anatoly Pulyaevskiy environment: - sdk: '>=2.7.0 <3.0.0' + sdk: '>=2.12.0 <3.0.0' dependencies: - js: ^0.6.1+1 - node_interop: ^1.0.3 - meta: ^1.1.8 - quiver_hashcode: ^2.0.0 + js: ^0.6.3 + node_interop: ^2.0.1 + meta: ^1.3.0 + quiver_hashcode: ^3.0.0+1 dev_dependencies: - test: ^1.12.0 - build_runner: ^1.7.4 - build_node_compilers: ^0.2.4 - build_test: ^0.10.12+1 + test: ^1.17.3 + build_runner: ^2.0.2 + build_node_compilers: + git: # temporary until NNBD approved for main package + url: https://github.com/SupposedlySam/node-interop.git + path: build_node_compilers + # path: ../node-interop/build_node_compilers + build_test: ^2.1.0 diff --git a/test/admin_test.dart b/test/admin_test.dart index 1d65f6f..4dcab72 100644 --- a/test/admin_test.dart +++ b/test/admin_test.dart @@ -9,7 +9,7 @@ import 'setup.dart'; void main() { group('FirebaseAdmin', () { - App app; + late App app; setUpAll(() { app = initFirebaseApp(); diff --git a/test/auth_test.dart b/test/auth_test.dart index 548114e..617e03e 100644 --- a/test/auth_test.dart +++ b/test/auth_test.dart @@ -10,14 +10,20 @@ import 'setup.dart'; void main() { group('Auth', () { - App app; + late App app; setUpAll(() async { app = initFirebaseApp(); - var user = - await app.auth().getUser('testuser').catchError((error) => null); + UserRecord? user; + + try { + user = await app.auth().getUser('testuser'); + } catch (e) { + // Fail gracefully: expected to fail when no user matches + } + if (user == null) { - await app.auth().createUser(new CreateUserRequest(uid: 'testuser')); + await app.auth().createUser(CreateUserRequest(uid: 'testuser')); } }); diff --git a/test/database_test.dart b/test/database_test.dart index 8635e8f..028c1c4 100644 --- a/test/database_test.dart +++ b/test/database_test.dart @@ -32,14 +32,14 @@ void main() { test('querying works', () async { var ref = app.database().ref('/app/users').endAt('Firebase'); var value = await ref.once('value'); - var records = new Map.from(value.val()); + var records = Map.from(value.val()); expect(records, hasLength(2)); }); test('on and off', () async { - var controller = StreamController(); + var controller = StreamController(); final sub = ref.on(EventType.value, (DataSnapshot snapshot) { - controller.add(snapshot.val() as String); + controller.add(snapshot.val() as String?); }); final result = controller.stream.take(3).toList(); @@ -122,7 +122,7 @@ void main() { }); test('transaction abort', () async { - var result = await refUpdate.transaction((currentData) { + var result = await refUpdate.transaction((dynamic currentData) { return TransactionResult.abort; }); expect(result.committed, isFalse); @@ -131,12 +131,12 @@ void main() { test('transaction commit', () async { await refUpdate.update({'num': 23, 'nested/thing': '1984'}); - var tx = await refUpdate.transaction((currentData) { + var tx = await refUpdate.transaction((dynamic currentData) { // Not sure I fully understand why Firebase sends initial `null` value // here, but this should not have anything to do with our Dart code. if (currentData == null) return TransactionResult.success(currentData); - final data = new Map.from(currentData); + final data = Map.from(currentData); data['tx'] = true; return TransactionResult.success(data); }); @@ -148,7 +148,7 @@ void main() { group('DataSnapshot', () { var ref = app.database().ref('/app/users/3/notifications'); - var childKey; + late var childKey; setUp(() async { await ref.remove(); @@ -210,7 +210,7 @@ void main() { test('val()', () async { var snapshot = await ref.once('value'); - var val = snapshot.val(); + var val = snapshot.val()!; expect(val, isMap); expect(val.length, 2); }); diff --git a/test/firestore_test.dart b/test/firestore_test.dart index a075cac..1edc235 100644 --- a/test/firestore_test.dart +++ b/test/firestore_test.dart @@ -22,11 +22,11 @@ void main() { var ref = app.firestore().document('users/23'); setUp(() async { - final data = new DocumentData.fromMap({ + final data = DocumentData.fromMap({ 'name': 'Firestore', 'profile.url': "https://pic.com/123", }); - final nested = new DocumentData.fromMap({'author': 'Unknown'}); + final nested = DocumentData.fromMap({'author': 'Unknown'}); data.setNestedData('nested', nested); // This completely overwrites the whole document. await ref.setData(data); @@ -51,38 +51,38 @@ void main() { expect(data.keys, contains('nested')); expect(data.getString('name'), 'Firestore'); expect(data.getString('profile.url'), 'https://pic.com/123'); - var nested = data.getNestedData('nested'); + var nested = data.getNestedData('nested')!; expect(nested, const TypeMatcher()); expect(nested, hasLength(1)); expect(nested.getString('author'), 'Unknown'); }); test('update value', () async { - await ref.updateData(new UpdateData.fromMap({ + await ref.updateData(UpdateData.fromMap({ 'nested.author': 'Isaac Asimov', })); var snapshot = await ref.get(); var data = snapshot.data; - var nested = data.getNestedData('nested'); + var nested = data.getNestedData('nested')!; expect(nested.getString('author'), 'Isaac Asimov'); }); // test setter and getters and fromMap/toMap round trip for // all types test('get set', () { - var data = new DocumentData(); - DateTime now = new DateTime.now(); + var data = DocumentData(); + DateTime now = DateTime.now(); final tsNow = Timestamp.fromDateTime(now); data.setInt('intVal', 1); data.setDouble('doubleVal', 1.5); data.setBool('boolVal', true); data.setString('stringVal', 'text'); - data.setGeoPoint('geoVal', new GeoPoint(23.03, 19.84)); - data.setBlob('blob', new Blob([1, 2, 3])); + data.setGeoPoint('geoVal', GeoPoint(23.03, 19.84)); + data.setBlob('blob', Blob([1, 2, 3])); data.setReference('refVal', app.firestore().document('users/23')); data.setList('listVal', [23, 84]); data.setTimestamp('tsVal', tsNow); - var nestedData = new DocumentData(); + var nestedData = DocumentData(); nestedData.setString('nestedVal', 'very nested'); data.setNestedData('nestedData', nestedData); data.setFieldValue('serverTimestampFieldValue', @@ -97,13 +97,13 @@ void main() { expect(data.getDouble('doubleVal'), 1.5); expect(data.getBool('boolVal'), true); expect(data.getString('stringVal'), 'text'); - expect(data.getGeoPoint('geoVal'), new GeoPoint(23.03, 19.84)); - expect(data.getBlob('blob').data, [1, 2, 3]); - var documentReference = data.getReference('refVal'); + expect(data.getGeoPoint('geoVal'), GeoPoint(23.03, 19.84)); + expect(data.getBlob('blob')!.data, [1, 2, 3]); + var documentReference = data.getReference('refVal')!; expect(documentReference.path, 'users/23'); expect(data.getList('listVal'), [23, 84]); expect(data.getTimestamp('tsVal'), tsNow); - DocumentData nestedData = data.getNestedData('nestedData'); + DocumentData nestedData = data.getNestedData('nestedData')!; expect(nestedData.keys.length, 1); expect(nestedData.getString('nestedVal'), 'very nested'); // Check the field value (no getter here) @@ -117,14 +117,14 @@ void main() { _check(); // from/to map - data = new DocumentData.fromMap(data.toMap()); + data = DocumentData.fromMap(data.toMap()); _check(); }); test('data types', () async { - var date = new DateTime.now(); + var date = DateTime.now(); var ref = app.firestore().document('tests/data-types'); - var data = new DocumentData.fromMap({ + var data = DocumentData.fromMap({ 'boolVal': true, 'stringVal': 'text', 'intVal': 23, @@ -152,18 +152,18 @@ void main() { expect(result.getString('stringVal'), 'text'); expect(result.getInt('intVal'), 23); expect(result.getDouble('doubleVal'), 19.84); - expect(result.getGeoPoint('geoVal'), new GeoPoint(23.03, 19.84)); - expect(result.getBlob('blobVal').data, [1, 2, 3]); - var docRef = result.getReference('refVal'); + expect(result.getGeoPoint('geoVal'), GeoPoint(23.03, 19.84)); + expect(result.getBlob('blobVal')!.data, [1, 2, 3]); + var docRef = result.getReference('refVal')!; expect(docRef, const TypeMatcher()); expect(docRef.path, 'users/23'); expect(result.getList('listVal'), [23, 84]); expect(result.getTimestamp('tsVal'), Timestamp.fromDateTime(date)); - var nested = result.getNestedData('nestedVal'); + var nested = result.getNestedData('nestedVal')!; expect(nested.getString('nestedKey'), 'much nested'); expect( result.getTimestamp('serverTimestamp'), TypeMatcher()); - var complexVal = result.getNestedData('complexVal'); + var complexVal = result.getNestedData('complexVal')!; expect(complexVal.getList('sub'), [ { 'subList': [1] @@ -172,17 +172,17 @@ void main() { }); test('$DocumentData.toMap', () async { - var date = new DateTime.now(); + var date = DateTime.now(); var ts = Timestamp.fromDateTime(date); var ref = app.firestore().document('tests/data-types-toMap'); - var data = new DocumentData.fromMap({ + var data = DocumentData.fromMap({ 'boolVal': true, 'stringVal': 'text', 'intVal': 23, 'doubleVal': 19.84, - 'geoVal': new GeoPoint(23.03, 19.84), + 'geoVal': GeoPoint(23.03, 19.84), 'refVal': app.firestore().document('users/23'), - 'blobVal': new Blob([4, 5, 6]), + 'blobVal': Blob([4, 5, 6]), 'listVal': [23, 84], 'tsVal': ts, 'mapVal': { @@ -192,15 +192,15 @@ void main() { ] }, }); - var nested = new DocumentData.fromMap({'nestedVal': 'very nested'}); + var nested = DocumentData.fromMap({'nestedVal': 'very nested'}); data.setNestedData('nestedData', nested); - var fakeGeoPoint = new DocumentData.fromMap( + var fakeGeoPoint = DocumentData.fromMap( {'latitude': 23.03, 'longitude': 84.19, 'toString': 'GeoPoint'}); data.setNestedData('fakeGeoPoint', fakeGeoPoint); - var fakeRef = new DocumentData.fromMap( + var fakeRef = DocumentData.fromMap( {'firestore': 'Nope', 'id': 'Nah', 'onSnapshot': 'Function'}); data.setNestedData('fakeRef', fakeRef); - var fakeDate = new DocumentData.fromMap( + var fakeDate = DocumentData.fromMap( {'toDateString': 'date', 'getTime': 'Function'}); data.setNestedData('fakeDate', fakeDate); await ref.setData(data); @@ -211,7 +211,7 @@ void main() { expect(result['stringVal'], 'text'); expect(result['intVal'], 23); expect(result['doubleVal'], 19.84); - expect(result['geoVal'], new GeoPoint(23.03, 19.84)); + expect(result['geoVal'], GeoPoint(23.03, 19.84)); expect((result['blobVal'] as Blob).data, [4, 5, 6]); var docRef = result['refVal']; expect(docRef, const TypeMatcher()); @@ -235,8 +235,9 @@ void main() { test('unsupported data types', () async { var ref = app.firestore().document('tests/unsupported'); - await ref.setData(new DocumentData() - ..setGeoPoint('geoVal', new GeoPoint(23.03, 19.84))); + await ref.setData( + DocumentData()..setGeoPoint('geoVal', GeoPoint(23.03, 19.84)), + ); var snapshot = await ref.get(); var data = snapshot.data; expect(() => data.getList('geoVal'), throwsStateError); @@ -244,7 +245,7 @@ void main() { test('lists with complex types', () async { var ref = app.firestore().document('tests/complex-lists'); - var data = new DocumentData(); + var data = DocumentData(); data.setList('data', [ Timestamp.fromDateTime(DateTime.now()), GeoPoint(1.0, 2.0), @@ -254,7 +255,7 @@ void main() { await ref.setData(data); var snapshot = await ref.get(); - var result = snapshot.data.getList('data'); + var result = snapshot.data.getList('data')!; expect(result, hasLength(4)); expect(result.elementAt(0), const TypeMatcher()); expect(result.elementAt(1), const TypeMatcher()); @@ -269,7 +270,7 @@ void main() { FieldValue fieldValueDelete = Firestore.fieldValues.delete(); // create document - var documentData = new DocumentData(); + var documentData = DocumentData(); documentData.setString("some_key", "some_value"); documentData.setString("other_key", "other_value"); await ref.setData(documentData); @@ -279,7 +280,7 @@ void main() { expect(documentData.getString("some_key"), "some_value"); // delete field - var updateData = new UpdateData(); + var updateData = UpdateData(); updateData.setFieldValue("some_key", fieldValueDelete); await ref.updateData(updateData); @@ -308,7 +309,7 @@ void main() { ]); // create document - var documentData = new DocumentData(); + var documentData = DocumentData(); documentData.setFieldValue("array", fieldValueArrayUnion); documentData.setFieldValue("array2", fieldValueArrayUnion2); documentData.setFieldValue("complex", fieldValueArrayComplex); @@ -329,7 +330,7 @@ void main() { ]); // update and remove some data - var updateData = new UpdateData(); + var updateData = UpdateData(); updateData.setFieldValue( "array", Firestore.fieldValues.arrayUnion([2, 3])); updateData.setFieldValue( @@ -356,16 +357,16 @@ void main() { test('set options', () async { var ref = app.firestore().document('tests/set_options'); - var documentData = new DocumentData(); + var documentData = DocumentData(); documentData.setInt('value1', 1); documentData.setInt('value2', 2); await ref.setData(documentData); - documentData = new DocumentData(); + documentData = DocumentData(); documentData.setInt('value2', 3); // Set with merge, value1 should remain - await ref.setData(documentData, new SetOptions(merge: true)); + await ref.setData(documentData, SetOptions(merge: true)); var readData = (await ref.get()).data; expect(readData.toMap(), {'value1': 1, 'value2': 3}); @@ -441,7 +442,7 @@ void main() { }); test('parent of root collection', () { - final parent = ref.parent; + final parent = ref.parent!; expect(parent, const TypeMatcher()); expect(parent.path, isEmpty); expect(parent.documentID, isNull); @@ -459,8 +460,8 @@ void main() { }); test('add document to collection', () async { - final point = new GeoPoint(37.7991232, -122.4485953); - final data = new DocumentData.fromMap({'name': 'Added Doc'}); + final point = GeoPoint(37.7991232, -122.4485953); + final data = DocumentData.fromMap({'name': 'Added Doc'}); data.setGeoPoint("location", point); final doc = await ref.add(data); expect(doc.documentID, isNotNull); @@ -497,7 +498,7 @@ void main() { // Some test assume that this collection is empty or already contains // one item. On the first ever call, create the item if (snapshot.isEmpty) { - await ref.add(new DocumentData()..setString('name', 'John Doe')); + await ref.add(DocumentData()..setString('name', 'John Doe')); } }); @@ -507,9 +508,9 @@ void main() { expect(snapshot, isNotEmpty); expect(snapshot.documents, hasLength(1)); expect(snapshot.documentChanges, hasLength(1)); - var doc = snapshot.documents.first; + var doc = snapshot.documents!.first; expect(doc.data.getString('name'), 'John Doe'); - var change = snapshot.documentChanges.first; + var change = snapshot.documentChanges!.first; expect(change.type, DocumentChangeType.added); }); @@ -517,8 +518,8 @@ void main() { var collection = app.firestore().collection('tests/query/where-ref'); var doc1 = collection.document(); var doc2 = collection.document(); - await doc2.setData(new DocumentData.fromMap({'name': 'doc2'})); - var data1 = new DocumentData(); + await doc2.setData(DocumentData.fromMap({'name': 'doc2'})); + var data1 = DocumentData(); data1.setReference('ref', doc2); data1.setString('name', 'doc1'); await doc1.setData(data1); @@ -528,7 +529,7 @@ void main() { expect(snapshot, isNotEmpty); expect(snapshot.documents, hasLength(1)); expect(snapshot.documentChanges, hasLength(1)); - var doc = snapshot.documents.first; + var doc = snapshot.documents!.first; expect(doc.data.getString('name'), 'doc1'); expect(doc.data.getReference('ref'), const TypeMatcher()); @@ -553,7 +554,7 @@ void main() { var snapshot = await query.get(); expect(snapshot, isNotEmpty); expect(snapshot.documents, hasLength(1)); - var doc = snapshot.documents.single; + var doc = snapshot.documents!.single; expect(doc.documentID, doc1.documentID); // Test with startAfter @@ -561,7 +562,7 @@ void main() { snapshot = await query.get(); expect(snapshot, isNotEmpty); expect(snapshot.documents, hasLength(1)); - doc = snapshot.documents.single; + doc = snapshot.documents!.single; expect(doc.documentID, doc2.documentID); }); @@ -581,7 +582,7 @@ void main() { var snapshot = await query.get(); expect(snapshot, isNotEmpty); expect(snapshot.documents, hasLength(1)); - var doc = snapshot.documents.single; + var doc = snapshot.documents!.single; expect(doc.documentID, doc1.documentID); // Test with startAfter @@ -589,7 +590,7 @@ void main() { snapshot = await query.get(); expect(snapshot, isNotEmpty); expect(snapshot.documents, hasLength(1)); - doc = snapshot.documents.single; + doc = snapshot.documents!.single; expect(doc.documentID, doc2.documentID); }); @@ -609,7 +610,7 @@ void main() { var snapshot = await query.get(); expect(snapshot, isNotEmpty); expect(snapshot.documents, hasLength(1)); - var doc = snapshot.documents.single; + var doc = snapshot.documents!.single; expect(doc.documentID, doc1.documentID); }); @@ -634,7 +635,7 @@ void main() { })); List _querySnapshotDocIds(QuerySnapshot querySnapshot) { - return querySnapshot.documents + return querySnapshot.documents! .map((snapshot) => snapshot.documentID) .toList(); } @@ -669,7 +670,7 @@ void main() { })); List _querySnapshotDocIds(QuerySnapshot querySnapshot) { - return querySnapshot.documents + return querySnapshot.documents! .map((snapshot) => snapshot.documentID) .toList(); } @@ -703,7 +704,7 @@ void main() { var snapshot = await query.get(); expect(snapshot, isNotEmpty); expect(snapshot.documents, hasLength(1)); - var doc = snapshot.documents.single; + var doc = snapshot.documents!.single; expect(doc.documentID, doc1.documentID); }); @@ -719,7 +720,7 @@ void main() { test('listen for query snapshot updates', () async { var ref = app.firestore().collection('tests/query/docs'); - Completer completer = new Completer(); + Completer completer = Completer(); var subscription = ref.snapshots.listen((event) { completer.complete(event); }); @@ -735,16 +736,16 @@ void main() { // set the content var docRef = collRef.document('one'); - await docRef.setData( - new DocumentData()..setInt('field1', 1)..setInt('field2', 2)); + await docRef + .setData(DocumentData()..setInt('field1', 1)..setInt('field2', 2)); QuerySnapshot querySnapshot = await collRef.select(['field2']).get(); - var documentData = querySnapshot.documents.first.data; + var documentData = querySnapshot.documents!.first.data; expect(documentData.has('field2'), isTrue); expect(documentData.has('field1'), isFalse); querySnapshot = await collRef.select(['field2']).get(); - documentData = querySnapshot.documents.first.data; + documentData = querySnapshot.documents!.first.data; expect(documentData.has('field2'), isTrue); expect(documentData.has('field1'), isFalse); }); @@ -755,59 +756,59 @@ void main() { // Create or update the content var docRefOne = collRef.document('one'); - await docRefOne.setData(new DocumentData()..setInt('value', 1)); + await docRefOne.setData(DocumentData()..setInt('value', 1)); var docRefTwo = collRef.document('two'); - await docRefTwo.setData(new DocumentData()..setInt('value', 2)); + await docRefTwo.setData(DocumentData()..setInt('value', 2)); - List list; + List? list; // limit QuerySnapshot querySnapshot = await collRef.limit(1).get(); list = querySnapshot.documents; - expect(list.length, 1); + expect(list!.length, 1); // offset querySnapshot = await collRef.orderBy('value').offset(1).get(); list = querySnapshot.documents; - expect(list.length, 1); + expect(list!.length, 1); // order by querySnapshot = await collRef.orderBy('value').get(); list = querySnapshot.documents; - expect(list.length, 2); + expect(list!.length, 2); expect(list.first.reference.documentID, "one"); // desc querySnapshot = await collRef.orderBy('value', descending: true).get(); list = querySnapshot.documents; - expect(list.length, 2); + expect(list!.length, 2); expect(list.first.reference.documentID, "two"); // start at querySnapshot = await collRef.orderBy('value').startAt(values: [2]).get(); list = querySnapshot.documents; - expect(list.length, 1); + expect(list!.length, 1); expect(list.first.reference.documentID, "two"); // start after querySnapshot = await collRef.orderBy('value').startAfter(values: [1]).get(); list = querySnapshot.documents; - expect(list.length, 1); + expect(list!.length, 1); expect(list.first.reference.documentID, "two"); // end at querySnapshot = await collRef.orderBy('value').endAt(values: [1]).get(); list = querySnapshot.documents; - expect(list.length, 1); + expect(list!.length, 1); expect(list.first.reference.documentID, "one"); // end before querySnapshot = await collRef.orderBy('value').endBefore(values: [2]).get(); list = querySnapshot.documents; - expect(list.length, 1); + expect(list!.length, 1); expect(list.first.reference.documentID, "one"); // start after using snapshot @@ -816,13 +817,13 @@ void main() { .startAfter(snapshot: list.first) .get(); list = querySnapshot.documents; - expect(list.length, 1); + expect(list!.length, 1); expect(list.first.reference.documentID, "two"); // where querySnapshot = await collRef.where('value', isGreaterThan: 1).get(); list = querySnapshot.documents; - expect(list.length, 1); + expect(list!.length, 1); expect(list.first.reference.documentID, "two"); }); @@ -839,8 +840,8 @@ void main() { final int stepCount = 4; // Create a completer for each step - var completers = new List>>.generate( - stepCount, (_) => new Completer>()); + var completers = List>>.generate( + stepCount, (_) => Completer>()); int stepIndex = 0; var subscription = @@ -858,7 +859,7 @@ void main() { await completers[index++].future; // create it - await docRef.setData(new DocumentData()); + await docRef.setData(DocumentData()); // wait for receiving change data documentChanges = await completers[index++].future; // expect creation @@ -866,7 +867,7 @@ void main() { expect(documentChanges.first.type, DocumentChangeType.added); // modify it - await docRef.setData(new DocumentData()..setInt('value', 1)); + await docRef.setData(DocumentData()..setInt('value', 1)); // wait for receiving change data documentChanges = await completers[index++].future; // expect a modified item @@ -899,11 +900,12 @@ void main() { var doc4Value = 4; await doc1Ref.delete(); - await doc2Ref.setData(new DocumentData()..setInt('value', 2)); - await doc3Ref.setData(new DocumentData()..setInt('value', 3)); - await doc4Ref.setData(new DocumentData()..setInt('value', doc4Value)); + await doc2Ref.setData(DocumentData()..setInt('value', 2)); + await doc3Ref.setData(DocumentData()..setInt('value', 3)); + await doc4Ref.setData(DocumentData()..setInt('value', doc4Value)); - await Future.delayed(Duration(seconds: 1)); // to avoid too much contention errors + await Future.delayed( + Duration(seconds: 1)); // to avoid too much contention errors List list = await app.firestore().runTransaction((Transaction tx) async { @@ -911,16 +913,15 @@ void main() { collRef.orderBy('value').where('value', isGreaterThan: 1)); var list = query.documents; - var doc4 = (await tx.get(doc4Ref)).data.getInt('value'); - tx.create(doc1Ref, new DocumentData()..setInt('value', 1 + doc4)); - tx.update( - doc2Ref, new UpdateData()..setInt('other.value', 22 + doc4)); - tx.set(doc3Ref, new DocumentData()..setInt('value', 3 + doc4)); - tx.set(doc3Ref, new DocumentData()..setInt('other.value', 33 + doc4), + var doc4 = (await tx.get(doc4Ref)).data.getInt('value')!; + tx.create(doc1Ref, DocumentData()..setInt('value', 1 + doc4)); + tx.update(doc2Ref, UpdateData()..setInt('other.value', 22 + doc4)); + tx.set(doc3Ref, DocumentData()..setInt('value', 3 + doc4)); + tx.set(doc3Ref, DocumentData()..setInt('other.value', 33 + doc4), merge: true); tx.delete(doc4Ref); - return list; + return list!; }); expect(list.length, 3); @@ -950,37 +951,40 @@ void main() { // this one will be deleted var doc2Ref = collRef.document('item2'); - await doc1Ref.setData(new DocumentData()..setInt('value', 1)); - await doc2Ref.setData(new DocumentData()..setInt('value', 2)); + await doc1Ref.setData(DocumentData()..setInt('value', 1)); + await doc2Ref.setData(DocumentData()..setInt('value', 2)); var doc1UpdateTime1 = (await doc1Ref.get()).updateTime; var doc2UpdateTime1 = (await doc2Ref.get()).updateTime; - await Future.delayed(Duration(seconds: 1)); // to avoid too much contention errors + await Future.delayed( + Duration(seconds: 1)); // to avoid too much contention errors - await doc1Ref.setData(new DocumentData()..setInt('value', 10)); - await doc2Ref.setData(new DocumentData()..setInt('value', 20)); + await doc1Ref.setData(DocumentData()..setInt('value', 10)); + await doc2Ref.setData(DocumentData()..setInt('value', 20)); var doc1UpdateTime2 = (await doc1Ref.get()).updateTime; var doc2UpdateTime2 = (await doc2Ref.get()).updateTime; - await Future.delayed(Duration(seconds: 1)); // to avoid too much contention errors + await Future.delayed( + Duration(seconds: 1)); // to avoid too much contention errors Future result = app.firestore().runTransaction((Transaction tx) async { var doc2 = (await tx.get(doc2Ref)).data; tx.update( - doc1Ref, new UpdateData()..setInt('value', doc2.getInt('value')), + doc1Ref, UpdateData()..setInt('value', doc2.getInt('value')), lastUpdateTime: doc1UpdateTime1); tx.delete(doc2Ref, lastUpdateTime: doc2UpdateTime1); }); var error = await result.catchError((error) => error); - expect(error.toString(), contains('does not match the required base version')); + expect(error.toString(), + contains('does not match the required base version')); expect((await doc1Ref.get()).data.toMap(), {'value': 10}); expect((await doc2Ref.get()).data.toMap(), {'value': 20}); await app.firestore().runTransaction((Transaction tx) async { var doc2 = (await tx.get(doc2Ref)).data.getInt('value'); - tx.update(doc1Ref, new UpdateData()..setInt('value', doc2), + tx.update(doc1Ref, UpdateData()..setInt('value', doc2), lastUpdateTime: doc1UpdateTime2); tx.delete(doc2Ref, lastUpdateTime: doc2UpdateTime2); }); @@ -995,19 +999,19 @@ void main() { /// ABORTED: Too much contention on these documents. Please try again. var collRef = app.firestore().collection('tests/transaction/async'); var doc1Ref = collRef.document('counter'); - await doc1Ref.setData(new DocumentData()..setInt('value', 1)); + await doc1Ref.setData(DocumentData()..setInt('value', 1)); - List> futures = new List(); - List errors = new List(); - List complete = new List(); + List> futures = >[]; + List errors = []; + List complete = []; var futuresCount = 5; for (int i = 0; i < futuresCount; i++) { var transaction = app.firestore().runTransaction((Transaction tx) async { var doc1 = await tx.get(doc1Ref); - var val = doc1.data.getInt('value') + 1; - tx.set(doc1Ref, new DocumentData()..setInt('value', val)); + var val = doc1.data.getInt('value')! + 1; + tx.set(doc1Ref, DocumentData()..setInt('value', val)); return val; }); futures.add(transaction.then((int val) { @@ -1042,13 +1046,13 @@ void main() { var doc4Ref = collRef.document('item4'); await doc1Ref.delete(); - await doc2Ref.setData(new DocumentData()..setInt('value', 2)); - await doc4Ref.setData(new DocumentData()..setInt('value', 4)); + await doc2Ref.setData(DocumentData()..setInt('value', 2)); + await doc4Ref.setData(DocumentData()..setInt('value', 4)); var batch = app.firestore().batch(); - batch.setData(doc1Ref, new DocumentData()..setInt('value', 1)); - batch.updateData(doc2Ref, new UpdateData()..setInt('other.value', 22)); - batch.setData(doc3Ref, new DocumentData()..setInt('value', 3)); + batch.setData(doc1Ref, DocumentData()..setInt('value', 1)); + batch.updateData(doc2Ref, UpdateData()..setInt('other.value', 22)); + batch.setData(doc3Ref, DocumentData()..setInt('value', 3)); batch.delete(doc4Ref); await batch.commit(); diff --git a/test/setup.dart b/test/setup.dart index 4de992c..8bf6b81 100644 --- a/test/setup.dart +++ b/test/setup.dart @@ -12,7 +12,7 @@ final Map env = dartify(process.env); App initFirebaseApp() { if (!env.containsKey('FIREBASE_CONFIG') || !env.containsKey('FIREBASE_SERVICE_ACCOUNT_JSON')) - throw new StateError('Environment variables are not set.'); + throw StateError('Environment variables are not set.'); Map certConfig = jsonDecode(env['FIREBASE_SERVICE_ACCOUNT_JSON']); final cert = FirebaseAdmin.instance.cert( @@ -23,5 +23,6 @@ App initFirebaseApp() { final Map config = jsonDecode(env['FIREBASE_CONFIG']); final databaseUrl = config['databaseURL']; return FirebaseAdmin.instance.initializeApp( - new AppOptions(credential: cert, databaseURL: databaseUrl)); + AppOptions(credential: cert, databaseURL: databaseUrl), + ); }