flamingo 0.2.1

Flamingo #

Flamingo is a firebase firestore model framework library.

https://pub.dev/packages/flamingo

日本語ドキュメント

Example code #

See the example directory for a complete sample app using flamingo.

https://github.com/hukusuke1007/flamingo/tree/master/example

Installation #

Add this to your package's pubspec.yaml file:

dependencies:
  flamingo:

Setup #

Please check Setup of cloud_firestore.
https://pub.dev/packages/cloud_firestore

Usage #

Adding a configure code to main.dart.

Initialize #

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flamingo/flamingo.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  
  final firestore = Firestore.instance;
  final root = firestore.collection('version').document('1');
  Flamingo.configure(firestore: firestore, storage: FirebaseStorage.instance, root: root);
  ...
}

Also be able to set app to firebase instance.

final app = await FirebaseApp.configure(
  name: 'appName',
  options: const FirebaseOptions(
    googleAppID: '1:1234567890:ios:42424242424242',
    gcmSenderID: '1234567890',
  ),
);
final firestore = Firestore(app: app);
final storage = FirebaseStorage(app: app);
final root = firestore.collection('version').document('1');
Flamingo.configure(firestore: firestore, storage: storage, root: root);

Create class that inherited Document. And add json mapping code into override functions.

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flamingo/flamingo.dart';

class User extends Document<User> {
  User({
    String id,
    DocumentSnapshot snapshot,
    Map<String, dynamic> values,
  }): super(id: id, snapshot: snapshot, values: values);

  String name;

  // For save data
  @override
  Map<String, dynamic> toData() {
    final data = <String, dynamic>{};
    writeNotNull(data, 'name', name);
    return data;
  }

  // For load data
  @override
  void fromData(Map<String, dynamic> data) {
    name = valueFromKey<String>(data, 'name');
  }
  
  // Call after create, update, delete.
  @override
  void onCompleted(ExecuteType executeType) {
    print('$executeType');
  }
}

Initialization #

final user = User();
print(user.id); // id: Create document id;

final user = User(id: '0000');
print(user.id); // id: '0000'

CRUD #

Using DocumentAccessor or Batch or Transaction in order to CRUD.

final user = User()
      ..name = 'hoge';

DocumentAccessor documentAccessor = DocumentAccessor();

// save
await documentAccessor.save(user);

// update
await documentAccessor.update(user);

// delete
await documentAccessor.delete(user);

// Batch
final batch = Batch()
  ..save(user)
  ..update(user);
  ..delete(user);
await batch.commit();

If save a document, please check firestore console.

Get a document.

// get
final user = User(id: '0000');  // need to 'id'.
final hoge = await documentAccessor.load<User>(user);

Get documents in collection.

final path = Document.path<User>();
final snapshot = await firestoreInstance().collection(path).getDocuments();

// from snapshot
final listA = snapshot.documents.map((item) => User(snapshot: item)).toList()
  ..forEach((user) {
    print(user.id); // user model.
  });

// from values.
final listB = snapshot.documents.map((item) => User(id: item.documentID, values: item.data)).toList()
  ..forEach((user) {
    print(user.id); // user model.
  });

Model of map object #

Example, Owner's document object is the following json.

{
  "name": "owner",
  "address": {
    "postCode": "0000",
    "country": "japan"
  },
  "medals": [
    {"name": "gold"},
    {"name": "silver"},
    {"name": "bronze"}
  ]
}

Owner that inherited Document has model of map object.

class Owner extends Document<Owner> {
  Owner({
    String id,
    DocumentSnapshot snapshot,
    Map<String, dynamic> values,
  }): super(id: id, snapshot: snapshot, values: values);

  String name;

  // Model of map object
  Address address;
  List<Medal> medals;

  /// For save data
  @override
  Map<String, dynamic> toData() {
    final data = <String, dynamic>{};
    writeNotNull(data, 'name', name);
    writeModelNotNull(data, 'address', address);  // For model.
    writeModelListNotNull(data, 'medals', medals); // For model list.
    return data;
  }

  /// For load data
  @override
  void fromData(Map<String, dynamic> data) {
    name = valueFromKey<String>(data, 'name');
    address = Address(values: valueMapFromKey<String, String>(data, 'address')); // For model
    medals = valueMapListFromKey<String, String>(data, 'medals') // For model list.
        .where((d) => d != null)
        .map((d) => Medal(values: d))
        .toList();
  }
}

Create class that inherited Model.

class Address extends Model {
  Address({
    this.postCode,
    this.country,
    Map<String, dynamic> values,
  }): super(values: values);

  String postCode;
  String country;

  /// For save data
  @override
  Map<String, dynamic> toData() {
    final data = <String, dynamic>{};
    writeNotNull(data, 'postCode', postCode);
    writeNotNull(data, 'country', country);
    return data;
  }

  /// For load data
  @override
  void fromData(Map<String, dynamic> data) {
    postCode = valueFromKey<String>(data, 'postCode');
    country = valueFromKey<String>(data, 'country');
  }

}
class Medal extends Model {
  Medal({
    this.name,
    Map<String, dynamic> values,
  }): super(values: values);

  String name;

  /// For save data
  @override
  Map<String, dynamic> toData() {
    final data = <String, dynamic>{};
    writeNotNull(data, 'name', name);
    return data;
  }

  /// For load data
  @override
  void fromData(Map<String, dynamic> data) {
    name = valueFromKey<String>(data, 'name');
  }
}

Example of usage.

// save
final owner = Owner()
  ..name = 'owner'
  ..address = Address(
    postCode: '0000',
    country: 'japan',
  )
  ..medals = [
    Medal(name: 'gold',),
    Medal(name: 'silver',),
    Medal(name: 'bronze',),
  ];

await documentAccessor.save(owner);

// load
final _owner = await documentAccessor.load<Owner>(Owner(id: owner.id));
print('id: ${_owner.id}, name: ${_owner.name}');
print('address: ${_owner.id} ${_owner.address.postCode} ${_owner.address.country}');
print('medals: ${_owner.medals.map((d) => d.name)}');

Snapshot Listener #

Listen snapshot of document.

// Listen
final user = User(id: '0')
  ..name = 'hoge';

final dispose = user.reference.snapshots().listen((snap) {
  final user = User(snapshot: snap);
  print('${user.id}, ${user.name}');
});

// Save, update, delete
DocumentAccessor documentAccessor = DocumentAccessor();
await documentAccessor.save(user);

user.name = 'fuga';
await documentAccessor.update(user);

await documentAccessor.delete(user);

await dispose.cancel();

Listen snapshot of collection documents.

Need to import cloud_firestore.

import 'package:cloud_firestore/cloud_firestore.dart';
// Listen
final path = Document.path<User>();
final query = firestoreInstance().collection(path).limit(20);
final dispose = query.snapshots().listen((querySnapshot) {
  for (var change in querySnapshot.documentChanges) {
    if (change.type == DocumentChangeType.added ) {
      print('added ${change.document.documentID}');
    }
    if (change.type == DocumentChangeType.modified) {
      print('modified ${change.document.documentID}');
    }
    if (change.type == DocumentChangeType.removed) {
      print('removed ${change.document.documentID}');
    }
  }
  final _ = querySnapshot.documents.map((item) => User(snapshot: item)).toList()
    ..forEach((item) => print('${item.id}, ${item.name}'));
});

// Save, update, delete
final user = User(id: '0')
  ..name = 'hoge';

DocumentAccessor documentAccessor = DocumentAccessor();
await documentAccessor.save(user);

user.name = 'fuga';
await documentAccessor.update(user);

await documentAccessor.delete(user);

await dispose.cancel();

Sub Collection #

For example, ranking document has count collection.

Ranking model #

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flamingo/flamingo.dart';
import 'count.dart';

class Ranking extends Document<Ranking> {
  Ranking({
    String id,
    DocumentSnapshot snapshot,
    Map<String, dynamic> values,
  }): super(id: id, snapshot: snapshot, values: values) {
    // Must be create instance of Collection and set collection name.
    count = Collection(this, 'count');
  }

  String title;
  Collection<Count> count;

  /// For save data
  @override
  Map<String, dynamic> toData() {
    final data = <String, dynamic>{};
    writeNotNull(data, 'name', title);
    return data;
  }

  /// For load data
  @override
  void fromData(Map<String, dynamic> data) {
    title = valueFromKey<String>(data, 'title');
  }
}

Count model #

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flamingo/flamingo.dart';

class Count extends Document<Count> {
  Count({
    String id,
    DocumentSnapshot snapshot,
    Map<String, dynamic> values,
    CollectionReference collectionRef,
  }): super(id: id, snapshot: snapshot, values: values, collectionRef: collectionRef);

  String userId;
  int count = 0;

  /// For save data
  @override
  Map<String, dynamic> toData() {
    final data = <String, dynamic>{};
    writeNotNull(data, 'userId', userId);
    writeNotNull(data, 'count', count);
    return data;
  }

  /// For load data
  @override
  void fromData(Map<String, dynamic> data) {
    userId = valueFromKey<String>(data, 'userId');
    count = valueFromKey<int>(data, 'count');
  }
}

Save and Get sub collection. #

final ranking = Ranking(id: '20201007')
  ..title = 'userRanking';

// Save sub collection of ranking document
final countA = Count(collectionRef: ranking.count.ref)
  ..userId = '0'
  ..count = 10;
final countB = Count(collectionRef: ranking.count.ref)
  ..userId = '1'
  ..count = 100;
final batch = Batch()
  ..save(ranking)
  ..save(countA)
  ..save(countB);
await batch.commit();

// Get sub collection
final path = ranking.count.ref.path;
final snapshot = await firestoreInstance().collection(path).getDocuments();
final list = snapshot.documents.map((item) => Count(snapshot: item, collectionRef: ranking.count.ref)).toList()
  ..forEach((count) {
    print(count);
  });

File #

Can operation into Firebase Storage and upload and delete storage file. Using StorageFile and Storage class.

For examople, create post model that have StorageFile.

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flamingo/flamingo.dart';

class Post extends Document<Post> {
  Post({
    String id
  }): super(id: id);

  // Storage
  StorageFile file;
  String folderName = 'file';

  // For save data
  @override
  Map<String, dynamic> toData() {
    final data = <String, dynamic>{};
    writeStorage(data, folderName, file);
    return data;
  }

  // For load data
  @override
  void fromData(Map<String, dynamic> data) {
    file = storageFile(data, folderName);
  }
}

Upload file to Firebase Storage.

final post = Post();
final storage = Storage();
final file = await Helper.getImageFileFromAssets('assets', 'sample.jpg');

// Fetch uploader stream
storage.fetch();

// Checking status
storage.uploader.listen((data){
  print('total: ${data.snapshot.totalByteCount} transferred: ${data.snapshot.bytesTransferred}');
});

// Upload file into firebase storage and save file metadata into firestore
final path = '${post.documentPath}/${post.folderName}';
post.file = await storage.save(path, file, mimeType: mimeTypePng, metadata: {'newPost': 'true'}); // 'mimeType' is defined in master/master.dart
await documentAccessor.save(post);

// Dispose uploader stream
storage.dispose();

Delete storage file.

// delete file in firebase storage and delete file metadata in firestore
final path = '${post.documentPath}/${post.folderName}';
await storage.delete(path, post.file);
await documentAccessor.update(post);

Alternatively, flamingo provide function to operate Cloud Storage and Firestore.

// Save storage and document of storage data.
final storageFile = await storage.saveWithDoc(
    post.reference,
    post.folderName,
    file,
    mimeType: mimeTypePng,
    metadata: {
      'newPost': 'true'
    },
    additionalData: <String, dynamic>{
      'key0': 'key',
      'key1': 10,
      'key2': 0.123,
      'key3': true,
    },
);

// Delete storage and document of storage data.
await storage.deleteWithDoc(post.reference, post.folderName, post.file, isNotNull: true);

Increment #

Example, CreditCard's document has point and score field. Their fields is Increment type.

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flamingo/flamingo.dart';

class CreditCard extends Document<CreditCard> {
  CreditCard({
    String id,
    DocumentSnapshot snapshot,
    Map<String, dynamic> values,
  }): super(id: id, snapshot: snapshot, values: values) {
    point = Increment('point'); // Set field name of point
    score = Increment('score'); // Set field name of score
  }

  Increment<int> point;
  Increment<double> score;

  /// For save data
  @override
  Map<String, dynamic> toData() {
    final data = <String, dynamic>{};
    writeIncrement(data, point);
    writeIncrement(data, score);
    return data;
  }

  /// For load data
  @override
  void fromData(Map<String, dynamic> data) {
    point = valueFromIncrement<int>(data, point.fieldName);
    score = valueFromIncrement<double>(data, score.fieldName);
  }

  /// Call after create, update, delete
  @override
  void onCompleted(ExecuteType executeType) {
    point = point.onRefresh();
    score = score.onRefresh();
  }
}

Increment and decrement of data.


// Increment
final card = CreditCard()
  ..point.incrementValue = 1
  ..score.incrementValue = 1.25;
await documentAccessor.save(card);
print('point ${card.point.value}, score: ${card.score.value}'); // point 1, score 1.25

final _card = await documentAccessor.load<CreditCard>(card);
print('point ${_card.point.value}, score: ${_card.score.value}'); // point 1, score 1.25


// Decrement
card
  ..point.incrementValue = -1
  ..score.incrementValue = -1.00;
await documentAccessor.update(card);
print('point ${card.point.value}, score: ${card.score.value}'); // point 0, score 0.25

final _card = await documentAccessor.load<CreditCard>(card);
print('point ${_card.point.value}, score: ${_card.score.value}'); // point 0, score 0.25


// Clear
card
  ..point.isClearValue = true
  ..score.isClearValue = true;
await documentAccessor.update(card);
print('point ${card.point.value}, score: ${card.score.value}'); // point 0, score 0.0

final _card = await documentAccessor.load<CreditCard>(card);
print('point ${_card.point.value}, score: ${_card.score.value}'); // point 0, score 0.0

Or can be use with increment method of DocumentAccessor.

final card = CreditCard();
final batch = Batch()
  ..save(card);
await batch.commit();

// Increment
card
  ..point = await documentAccessor.increment<int>(card.point, card.reference, value: 10)
  ..score = await documentAccessor.increment<double>(card.score, card.reference, value: 3.5);

// Decrement
card
  ..point = await documentAccessor.increment<int>(card.point, card.reference, value: -5)
  ..score = await documentAccessor.increment<double>(card.score, card.reference, value: -2.5);

// Clear
card
  ..point = await documentAccessor.increment<int>(card.point, card.reference, isClear: true)
  ..score = await documentAccessor.increment<double>(card.score, card.reference, isClear: true);

Attension:

Clear process only set 0 to document and update. It not try transaction process. Do not use except to first set doument

Distributed counter #

Using DistributedCounter and Counter.

For examople, create score model that have Counter.

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flamingo/flamingo.dart';

class Score extends Document<Score> {
  Score({
    String id,
  }): super(id: id) {
    value = Counter(this, 'shards', numShards);
  }

  /// Document
  String userId;

  /// DistributedCounter
  int numShards = 10;
  Counter value;

  /// For save data
  @override
  Map<String, dynamic> toData() {
    final data = <String, dynamic>{};
    writeNotNull(data, 'userId', userId);
    return data;
  }

  /// For load data
  @override
  void fromData(Map<String, dynamic> data) {
    userId = valueFromKey<String>(data, 'userId');
  }
}

Create and increment and load.

/// Create
final score = Score()
  ..userId = '0001';
await documentAccessor.save(score);

final distributedCounter = DistributedCounter();
await distributedCounter.create(score.value);

/// Increment
for (var i = 0; i < 10; i++) {
  await distributedCounter.increment(score.value, count: 1);
}

/// Load
final count = await distributedCounter.load(score.value);
print('count $count ${score.value.count}');

Transaction #

This api is simply wrap transaction function of Firestore.

RunTransaction.scope((transaction) async {
  final hoge = User()
    ..name = 'hoge';

  // save
  await transaction.set(hoge.reference, hoge.toData());

  // update
  final fuge = User(id: '0')
    ..name = 'fuge';
  await transaction.update(fuge.reference, fuge.toData());

  // delete
  await transaction.delete(User(id: '1').reference);
});

Objects for model #

Map objects #

Create the following model class.

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flamingo/flamingo.dart';

class MapSample extends Document<MapSample> {
  MapSample({
    String id,
    DocumentSnapshot snapshot,
    Map<String, dynamic> values,
  }): super(id: id, snapshot: snapshot, values: values);

  Map<String, String> strMap;
  Map<String, int> intMap;
  Map<String, double> doubleMap;
  Map<String, bool> boolMap;
  List<Map<String, String>> listStrMap;

  /// For save data
  @override
  Map<String, dynamic> toData() {
    final data = <String, dynamic>{};
    writeNotNull(data, 'strMap', strMap);
    writeNotNull(data, 'intMap', intMap);
    writeNotNull(data, 'doubleMap', doubleMap);
    writeNotNull(data, 'boolMap', boolMap);
    writeNotNull(data, 'listStrMap', listStrMap);
    return data;
  }

  /// For load data
  @override
  void fromData(Map<String, dynamic> data) {
    strMap = valueMapFromKey<String, String>(data, 'strMap');
    intMap = valueMapFromKey<String, int>(data, 'intMap');
    doubleMap = valueMapFromKey<String, double>(data, 'doubleMap');
    boolMap = valueMapFromKey<String, bool>(data, 'boolMap');
    listStrMap = valueMapListFromKey<String, String>(data, 'listStrMap');
  }
}

And save and load documents.

final sample1 = MapSample()
  ..strMap = {'userId1': 'tanaka', 'userId2': 'hanako', 'userId3': 'shohei',}
  ..intMap = {'userId1': 0, 'userId2': 1, 'userId3': 2,}
  ..doubleMap = {'userId1': 1.02, 'userId2': 0.14, 'userId3': 0.89,}
  ..boolMap = {'userId1': true, 'userId2': true, 'userId3': true,}
  ..listStrMap = [
    {'userId1': 'tanaka', 'userId2': 'hanako',},
    {'adminId1': 'shohei', 'adminId2': 'tanigawa',},
    {'managerId1': 'ueno', 'managerId2': 'yoshikawa',},
  ];
await documentAccessor.save(sample1);

final _sample1 = await documentAccessor.load<MapSample>(MapSample(id: sample1.id));

List #

Create the following model class.

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flamingo/flamingo.dart';

class ListSample extends Document<ListSample> {
  ListSample({
    String id,
    DocumentSnapshot snapshot,
    Map<String, dynamic> values,
  }): super(id: id, snapshot: snapshot, values: values);

  List<String> strList;
  List<int> intList;
  List<double> doubleList;
  List<bool> boolList;
  List<StorageFile> files;
  String folderName = 'files';

  /// For save data
  @override
  Map<String, dynamic> toData() {
    final data = <String, dynamic>{};
    writeNotNull(data, 'strList', strList);
    writeNotNull(data, 'intList', intList);
    writeNotNull(data, 'doubleList', doubleList);
    writeNotNull(data, 'boolList', boolList);
    writeStorageList(data, folderName, files);
    return data;
  }

  /// For load data
  @override
  void fromData(Map<String, dynamic> data) {
    strList = valueListFromKey<String>(data, 'strList');
    intList = valueListFromKey<int>(data, 'intList');
    doubleList = valueListFromKey<double>(data, 'doubleList');
    boolList = valueListFromKey<bool>(data, 'boolList');
    files = storageFiles(data, folderName);
  }
}

And save and load documents.

final sample1 = ListSample()
  ..strList = ['userId1', 'userId2', 'userId3',]
  ..intList = [0, 1, 2,]
  ..doubleList = [0.0, 0.1, 0.2,]
  ..boolList = [true, false, true,]
  ..files = [
    StorageFile(name: 'name1', url: 'https://sample1.jpg', mimeType: mimeTypePng),
    StorageFile(name: 'name2', url: 'https://sample2.jpg', mimeType: mimeTypePng),
    StorageFile(name: 'name3', url: 'https://sample3.jpg', mimeType: mimeTypePng),
  ];
await documentAccessor.save(sample1);
sample1.log();

final _sample1 = await documentAccessor.load<ListSample>(ListSample(id: sample1.id));

Reference #

0.2.1 #

Update plugin.

0.2.0+1 #

Deleted unnecessary files.

0.2.0 #

Update plugin and bug fix for collection reference.

0.1.16 #

Bug fix.

0.1.15 #

Bug fix.

0.1.14 #

Bug fix.

0.1.13 #

Modified property access.

0.1.12 #

Modified mapping timestamp for algolia.

0.1.11 #

Remove dependency on json_annotation #2

0.1.10+1 #

Update example's pubspec.yaml.

0.1.10 #

Update environment version.

0.1.9 #

Rename function. saveStorageAndDoc => saveWithDoc, deleteStorageAndDoc => deleteWithDoc.

0.1.8 #

Add function of raw values for document. Add function to save and delete storage and document.

0.1.7 #

Update firestore plugin.

0.1.6 #

Update environment sdk.

0.1.5 #

Update dependence plugin.

0.1.4 #

Modified batch.

0.1.3 #

Bug fix.

0.1.2 #

Add function of raw values for batch. Add Increment model. Add override method of onCompleted.

0.1.1+2 #

Modified pubspec.yaml.

0.1.1+1 #

Updated document.

0.1.1 #

Rename transaction interface.

0.1.0+1 #

Updated document.

0.1.0 #

Format source code.

0.0.10 #

Add model class of map object. Updated and README.

0.0.9 #

Updated load of DocumentAccessor and README.

0.0.8 #

Added write function. Added path parameter of storage file. Updated firebase packages. Updated README.

0.0.7+1 #

Added additionalData parameter of storage file.

0.0.7 #

Added function for mapping list and modified mapping json of storage file.

0.0.6 #

Added function for mapping map objects and added metadata to storage file.

0.0.5 #

Update initialize spec.

0.0.4+1 #

Update document.

0.0.4 #

Update plugin of firebase.

0.0.3+2 #

Update CHANGELOG.md.

0.0.3+1 #

Update README.md.

0.0.3 #

Bug fix for Android.

0.0.2 #

Bug fix.

0.0.1 #

First release.

example/README.md

flamingo_example #

Demonstrates how to use the flamingo plugin.

Getting Started #

This project is a starting point for a Flutter application.

A few resources to get you started if this is your first Flutter project:

For help getting started with Flutter, view our online documentation, which offers tutorials, samples, guidance on mobile development, and a full API reference.

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  flamingo: ^0.2.1

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:flamingo/flamingo.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
76
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
88
Learn more about scoring.

We analyzed this package on Feb 21, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.7.1
  • pana: 0.13.5
  • Flutter: 1.12.13+hotfix.7

Health suggestions

Format lib/base.dart.

Run flutter format to format lib/base.dart.

Format lib/batch.dart.

Run flutter format to format lib/batch.dart.

Format lib/document_accessor.dart.

Run flutter format to format lib/document_accessor.dart.

Fix additional 6 files with analysis or formatting issues.

Additional issues in the following files:

  • lib/enum/execute_type.dart (Run flutter format to format lib/enum/execute_type.dart.)
  • lib/flamingo.dart (Run flutter format to format lib/flamingo.dart.)
  • lib/model/increment.dart (Run flutter format to format lib/model/increment.dart.)
  • lib/run_transaction.dart (Run flutter format to format lib/run_transaction.dart.)
  • lib/storage.dart (Run flutter format to format lib/storage.dart.)
  • lib/type/type.dart (Run flutter format to format lib/type/type.dart.)

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.7.0 <3.0.0
cloud_firestore ^0.13.3 0.13.3
firebase_core ^0.4.4 0.4.4
firebase_storage ^3.1.1 3.1.1
flutter 0.0.0
path_provider ^1.6.0 1.6.1
Transitive dependencies
async 2.4.0
charcode 1.1.3
cloud_firestore_platform_interface 1.0.0
cloud_firestore_web 0.1.0+3
collection 1.14.11 1.14.12
firebase 7.2.1
firebase_core_platform_interface 1.0.2
firebase_core_web 0.1.1+2
flutter_web_plugins 0.0.0
http 0.12.0+4
http_parser 3.1.3
js 0.6.1+1
matcher 0.12.6
meta 1.1.8
path 1.6.4
pedantic 1.9.0
platform 2.2.1
plugin_platform_interface 1.0.2
quiver 2.1.2+1
sky_engine 0.0.99
source_span 1.6.0
stack_trace 1.9.3
string_scanner 1.0.5
term_glyph 1.1.0
typed_data 1.1.6
vector_math 2.0.8
Dev dependencies
flutter_test
pedantic_mono any