hukusuke1007 / flamingo Goto Github PK
View Code? Open in Web Editor NEW[Flutter Library] Flamingo is a firebase firestore model framework library. ๐ค
Home Page: https://pub.dev/packages/flamingo
License: MIT License
[Flutter Library] Flamingo is a firebase firestore model framework library. ๐ค
Home Page: https://pub.dev/packages/flamingo
License: MIT License
Can you show how to save the model id as a database field .
I wand to be able to do something like this:
List ids = ['someid','someid','someid2','someid3'];
StreamBuilder(
stream: Item().collectionRef.where('id', whereIn: ids).snapshots(),
builder: (context,snap) {
// some code
}
);
thank you.
We have a collection, let's say "Users" and we'd like any user to be able to query list of all user names but not other fields. In firestore we can set restriction rule to specific fields but running query just queries all fields.
We get an error:
Unhandled Exception: [cloud_firestore/permission-denied] The caller does not have permission to execute the specified operation.
I think if Document.onRelease() is executed before the commit(), then the data could be corrupted(because it does incrementValue = null;
Also, I sometime wants to access to Document.value after the increment, so maybe there should be some field like Document.promisedValue which return the value after the commit() beforehand.
int get promisedValue => {
if (incrementValue != null) {
final _value =
value != null ? value! + incrementValue! : incrementValue;
result = Increment<T>(value: _value! as T);
} else {
result = Increment<T>(value: value);
}
return result.value
}
collectionPaging = CollectionPaging<WallpagersDoc>(
query: WallpagersDoc()
.collectionRef
.orderBy(documentUpdatedAtKey, descending: true),
limit: 200,
decode: (
snap,
) =>
WallpagersDoc(snapshot: snap),
);
how to get all document WallpagersDoc ?
Hi!
Is there currently no way to use enums?
enum Role { admin, editor, user }
class Profile extends Document<Profile> {
// ...
@Field()
Role role;
}
[VERBOSE-2:ui_dart_state.cc(166)] Unhandled Exception: type 'String' is not a subtype of type 'Role' in type cast
#0 _AppState.build.<anonymous closure>
package:approach_builder/main.dart:107
#1 _streamStartListening.<anonymous closure>.<anonymous closure>
package:provider/src/async_provider.dart:30
#2 _rootRunUnary (dart:async/zone.dart:1198:47)
#3 _CustomZone.runUnary (dart:async/zone.dart:1100:19)
#4 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1005:7)
#5 _BufferingStreamSubscription._sendError.sendError (dart:async/stream_impl.dart:378:15)
#6 _BufferingStreamSubscription._sendError (dart:async/stream_impl.dart:394:16)
#7 _BufferingStreamSubscription._addError (dart:async/stream_impl.dart:294:7)
#8 _SyncBroadcastStreamController._sendError.<anonymous closure> (dart:async/broadcast_stream_controller.dart:400:20)
#9 _BroadcastStreamController._forEachListener (dart:async/broadcast_stream_controller.dart:330:15)
This is actually related to #1.
But since it is close already I am creating new one here.
final root = firestore.collection('version').document('1');
My questions may be dumb, but I am trying to understand the reason behind this. I am sure you have a good reason for this.
Hi,
Can you please show how to get items in a streambuilder and be able to update changes in realtime?
here is an example of this without using flamingo:
StreamBuilder(
stream: db.collection('chats').orderBy('updated_at').snapshots(),
builder: (context, snapshot) {
//....
// snapshots changes loaded in realtime
},
)
Kindly help.
Even if we have following in pubspec.yaml
flamingo_generator|field_value_generator:
generate_for:
include:
- lib/models/*.dart
the generator reports warnings about other files such as:
[WARNING] flamingo_generator:field_value_generator on lib/screens/project_editor_screen.dart:
project_editor_screen.flamingo.dart must be included as a part directive in the input library with:
part 'project_editor_screen.flamingo.dart';
This is reported when there is a previous error with some misspelled file name. Looks like the generator then goes over all files.
Every time we save model it also updates createdAt and updatedAt field. We'd expect the createdAt field would not be updated for future object updates.
Code sample:
final batch = Batch()
..save(existingObject);
await batch.commit();
We can use Batch()..update()
but the behavior is different. It will update just updatedAt
field but on the device it will set createdAt field to null. Is this expected behavior?
final batch = Batch()
..update(existingObject);
await batch.commit();
debugPrint("New Val: ${existingObject.createdAt}"); // here createdAt is null
We believe the issue is here, where createdAt will be set to null:
flamingo/flamingo/lib/src/model/document.dart
Line 144 in af8836d
here is my model:
import 'some/packages;
part 'user.flamingo.dart';
class AppUser extends Document<AppUser> {
@Field()
String name;
@Field()
String username;
@Field()
String firstName;
@Field()
String lastName;
@Field()
String email;
@Field()
String phoneNumber;
@Field()
String photoUrl;
@Field()
Increment<int> newMessagesCount;
@SubCollection()
Collection<Token> tokens;
AppUser(
{String id,
DocumentSnapshot snapshot,
Map<String, dynamic> values})
: super(
id: id,
snapshot: snapshot,
values: values,
collectionRef: Flamingo.instance.rootReference.collection('users')) {
tokens = Collection(this, AppUserKey.tokens.value);
newMessagesCount = Increment(AppUserKey.newMessagesCount.value);
}
@override
Map<String, dynamic> toData() => _$toData(this);
@override
void fromData(Map<String, dynamic> data) => _$fromData(this, data);
/// Call after create, update, delete.
@override
void onCompleted(ExecuteType executeType) {
newMessagesCount = newMessagesCount.onRefresh();
}
}
and here is some stacktraces:
I/flutter (19763): โโโก EXCEPTION CAUGHT BY WIDGETS LIBRARY โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
I/flutter (19763): The following NoSuchMethodError was thrown building StreamBuilder<DocumentSnapshot>(dirty, state:
I/flutter (19763): _StreamBuilderBaseState<DocumentSnapshot, AsyncSnapshot<DocumentSnapshot>>#7e0eb):
I/flutter (19763): The getter 'fieldName' was called on null.
I/flutter (19763): Receiver: null
I/flutter (19763): Tried calling: fieldName
I/flutter (19763):
I/flutter (19763): The relevant error-causing widget was:
I/flutter (19763): StreamBuilder<DocumentSnapshot>
I/flutter (19763): file:///.../../file.dart:151:16
I/flutter (19763):
I/flutter (19763): When the exception was thrown, this was the stack:
I/flutter (19763): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
I/flutter (19763): #1 _$fromData (package:app/models/user.flamingo.dart:75:65)
I/flutter (19763): #2 AppUser.fromData (package:app/models/user.dart:60:47)
I/flutter (19763): #3 Document.setSnapshot (package:flamingo/src/model/document.dart:125:7)
I/flutter (19763): #4 new Document (package:flamingo/src/model/document.dart:48:9)
I/flutter (19763): #5 new AppUser (package:app/models/user.dart:37:9)
I/flutter (19763): #6 _ChatScreenState.build.<anonymous closure> (package:app/widgets/screens/main/chats/chat_screen.dart:157:29)
I/flutter (19763): #7 StreamBuilder.build (package:flutter/src/widgets/async.dart:525:81)
I/flutter (19763): #8 _StreamBuilderBaseState.build (package:flutter/src/widgets/async.dart:129:48)
I/flutter (19763): #9 StatefulElement.build (package:flutter/src/widgets/framework.dart:4744:28)
I/flutter (19763): #10 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4627:15)
I/flutter (19763): #11 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4800:11)
I/flutter (19763): #12 Element.rebuild (package:flutter/src/widgets/framework.dart:4343:5)
I/flutter (19763): #13 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2730:33)
I/flutter (19763): #14 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:913:20)
I/flutter (19763): #15 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:302:5)
I/flutter (19763): #16 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1117:15)
I/flutter (19763): #17 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1055:9)
I/flutter (19763): #18 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:971:5)
I/flutter (19763): #22 _invoke (dart:ui/hooks.dart:251:10)
I/flutter (19763): #23 _drawFrame (dart:ui/hooks.dart:209:3)
I/flutter (19763): (elided 3 frames from dart:async)
I/flutter (19763):
I/flutter (19763): โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
I/flutter (19763): id: null, changeType: DocumentChangeType.added, oldIndex: -1, newIndex: 0 cache: true
I/flutter (19763): id: null, changeType: DocumentChangeType.added, oldIndex: -1, newIndex: 1 cache: true
I/flutter (19763): id: null, changeType: DocumentChangeType.added, oldIndex: -1, newIndex: 2 cache: true
I/flutter (19763): โโโก EXCEPTION CAUGHT BY WIDGETS LIBRARY โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
I/flutter (19763): The following NoSuchMethodError was thrown building StreamBuilder<DocumentSnapshot>(dirty, state:
I/flutter (19763): _StreamBuilderBaseState<DocumentSnapshot, AsyncSnapshot<DocumentSnapshot>>#7e0eb):
I/flutter (19763): The getter 'fieldName' was called on null.
I/flutter (19763): Receiver: null
I/flutter (19763): Tried calling: fieldName
I/flutter (19763):
I/flutter (19763): The relevant error-causing widget was:
I/flutter (19763): StreamBuilder<DocumentSnapshot>
I/flutter (19763): file:///.../../file.dart:151:16
I/flutter (19763):
I/flutter (19763): When the exception was thrown, this was the stack:
I/flutter (19763): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
I/flutter (19763): #1 _$fromData (package:app/models/user.flamingo.dart:75:65)
I/flutter (19763): #2 AppUser.fromData (package:app/models/user.dart:60:47)
I/flutter (19763): #3 Document.setSnapshot (package:flamingo/src/model/document.dart:125:7)
I/flutter (19763): #4 new Document (package:flamingo/src/model/document.dart:48:9)
I/flutter (19763): #5 new AppUser (package:app/models/user.dart:37:9)
I/flutter (19763): #6 _ChatScreenState.build.<anonymous closure> (package:app/widgets/screens/main/chats/chat_screen.dart:157:29)
I/flutter (19763): #7 StreamBuilder.build (package:flutter/src/widgets/async.dart:525:81)
I/flutter (19763): #8 _StreamBuilderBaseState.build (package:flutter/src/widgets/async.dart:129:48)
I/flutter (19763): #9 StatefulElement.build (package:flutter/src/widgets/framework.dart:4744:28)
I/flutter (19763): #10 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4627:15)
I/flutter (19763): #11 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4800:11)
I/flutter (19763): #12 Element.rebuild (package:flutter/src/widgets/framework.dart:4343:5)
I/flutter (19763): #13 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2730:33)
I/flutter (19763): #14 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:913:20)
I/flutter (19763): #15 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:302:5)
I/flutter (19763): #16 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1117:15)
I/flutter (19763): #17 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1055:9)
I/flutter (19763): #18 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:971:5)
I/flutter (19763): #22 _invoke (dart:ui/hooks.dart:251:10)
I/flutter (19763): #23 _drawFrame (dart:ui/hooks.dart:209:3)
I/flutter (19763): (elided 3 frames from dart:async)
I/flutter (19763):
I/flutter (19763): โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Nice to meet you, my name is kyuji.
We are evaluating flamingo, but if the field increases in the model, refer to the data before the increase.
I get the error "Expected a value of type'String', but got one of type'Null'".
It seems to occur when there is no corresponding Field in Helper.valueFromKey in _ $ fromData (this, data).
Is it possible to set Null when there is no Field?
Or is it used incorrectly?
-- Japaneseใ--
flamingoใฎ่ฉไพกใใใฆใใใพใใใmodelใซFieldใๅขใใๅ ดๅใๅขใใๅใฎใใผใฟใๅ็
งใใใจ
ใExpected a value of type 'String', but got one of type 'Null'ใใฎใจใฉใผใ็บ็ใใพใใ
_$fromData(this, data)ๅ
ใฎใHelper.valueFromKeyใงใ่ฉฒๅฝFieldใใชใๆใซ็บ็ใใใใใงใใ
Fieldใใชใๅ ดๅใซใNullใ่จญๅฎใใไบใฏๅฏ่ฝใงใใใใใ
ใใใจใใไฝฟ็จๆนๆณใ้้ใฃใฆใใพใใงใใใใใ
ไปฅไธใๅฎใใใ้กใ่ดใใพใใ
I think Document.onCompleted() is called twice for each documents.
flamingo/flamingo/lib/src/batch.dart
Line 126 in 7437db4
Perhaps it should be called once for each documents after batch.commit() is completed?
We have following field which has no value in Firestore. If we fetch this model we get an error. We do not want to add bool?
since we take this value as default if it's not present.
// Field Definition
@Field()
bool requireSomeField = false;
2021-07-28 11:09:24.547 25564-25650/eu.app E/flutter: [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: type 'Null' is not a subtype of type 'bool' in type cast
#0 Helper.valueFromKey (package:flamingo/src/helper/helper.dart:214:18)
Since flamingo is a very useful library, I want to use it for Flutter web.
Do you have any plans to support Flutter web?
I'm so glad if it will be supported.
The example shown in readme is not clear about how rootReference is going to be created.
import 'package:flamingo/flamingo.dart';
void main() {
Flamingo.configure(rootName: 'version', version: 1);
...
}
My suggestion is to add this snippet or a text describing that rootName will be a collection and version a document:
instance.rootReference =
instance.firestore.collection('${rootName != null ? rootName : 'version'}')
.document('${version != null ? version.toString() : '1'}');
Also, would it be possible to not have this structure and just use Firestore's default "/" root?
We'd like to customize the collection name which model class uses. For example we use file name user_model.dart
with UserModel class
inside. We'd like the collection to be named users
.
It would be handy to specify collection name using class annotation.
Description:
The updated version allows me to deleted all the images from a list but changes the dataType to null
due to which further query to add to list cannot be done.
The dataType getting changed to null instead of array when all elements of a list are deleted
code snippets :
//in flamingo (UserDocument)
writeStorageList(data, "subProfileImages", subProfileImages);
//To fetch user Document
final document = await DocumentAccessor() .load<UserDocument>(social.UserDocument(id: userId));
Steps to reproduce:
when updating document.subProfileImages = []
In Firebase:
when images are present:
when the entire list is deleted(updated):
subProfileImages becomes null due to which no further query can be made.
@hukusuke1007
Hi ! I've been struggling to find a good approach to modeling firebase data. I started with functional_data
and then looked at this library but was discouraged by mutability and then I settled on freezed
. However with the new null safety, I've been trying to solve one problem. Having everything be non-null. This includes the references
, id
s and so on of a document. One thing I've come to realize is that this would need two separate classes. Take for example a user
. One class is the base implementation. Nothing to do with firebase. The second (generated) class would be the one after we've associated it with a firebase document. Its reference would never null.
I came up with a close approximation of what it'd look like here:
/// @Flamingo(options) will set the collection ref
/// $User provides immutable `copyWith` implementation or lenses.
@Flamingo(path: 'path/to/users', collectionRef: myCollectionRef)
class User extends $User {
const User({
required this.name,
required this.email,
});
final String name;
final String email;
UserDoc toDocument(DocumentSnapshot snapshot) => _$toDocument(snapshot);
}
/// This class will be auto generated and be kept inside the part file.
/// $UserDoc will also create `copyWith` and/or lenses.
class UserDoc extends $UserDoc with Document<UserDoc>, Snapshot {
UserDoc({
required this.name,
required this.email,
required this.reference,
required this.metadata,
required this.id,
required this.exists,
});
final String name;
final String email;
final DocumentReference reference;
final SnapshotMetadata metadata;
final String id;
final bool exists;
factory UserDoc.fromSnapshot(DocumentSnapshot snapshot) =>
_$fromSnapshot(snapshot);
@override
Map<String, dynamic> toData() => _$toData(this);
}
// In a separate file
abstract class Document<T> {
// Sort of the implementation as previously
}
// In a separate file
abstract class Snapshot {
DocumentReference get reference;
SnapshotMetadata get metadata;
String get id;
bool get exists;
}
One thing I really like about this is that nothing is nullable. If something is we'd have a @nullable annotation or something otherwise we'll throw a parse error.
To update a value for example we could:
// You could either create a user and then attach it to a do
// Or create a UserDoc from non empty a snapshot
final user = User(name: 'kilo', email: '[email protected]');
final userDoc = User.toDocument(CollectionRef.doc());
await documentAccessor.save(userDoc.copyWith(name: 'Kilo'));
If this is something you'd be interested in, I could try for a PR or be glad to keep discussing
Hi,
First of all, thank you for building Flamingo.
I'm currently having the following problem:
For example:
Let's say i have a document called Cart. The cart document will contain an array with objects
Cart Document
import 'package:flamingo/flamingo.dart';
import 'package:flamingo_annotation/flamingo_annotation.dart';
import 'cart_product.dart';
part 'cart.flamingo.dart';
class Cart extends Document<Cart> {
Cart({
String id,
DocumentSnapshot snapshot,
Map<String, dynamic> values,
}) : super(id: id, snapshot: snapshot, values: values);
@ModelField()
List<CartProduct> products = [];
@override
Map<String, dynamic> toData() => _$toData(this);
@override
void fromData(Map<String, dynamic> data) => _$fromData(this, data);
}
CartProduct Model
import 'package:flamingo/flamingo.dart';
import 'package:flamingo_annotation/flamingo_annotation.dart';
import 'package:{hidden}/models/product.dart';
part 'cart_product.flamingo.dart';
class CartProduct extends Model {
CartProduct({
this.product,
this.quantity,
Map<String, dynamic> values,
}) : super(values: values);
@Field()
Product product; // This is not going to work
@Field()
double quantity;
@override
Map<String, dynamic> toData() => _$toData(this);
@override
void fromData(Map<String, dynamic> data) => _$fromData(this, data);
}
Product Document
import 'package:flamingo/flamingo.dart';
import 'package:flamingo_annotation/flamingo_annotation.dart';
part 'product.flamingo.dart';
class Product extends Document<Product> {
Product({
String id,
DocumentSnapshot snapshot,
Map<String, dynamic> values,
}) : super(id: id, snapshot: snapshot, values: values);
@Field()
String name;
@override
Map<String, dynamic> toData() => _$toData(this);
@override
void fromData(Map<String, dynamic> data) => _$fromData(this, data);
}
I've seen a similar issue #6 but it looks like i am having a different issue.
My goal is to load a Cart with a list of CartProduct that contain the product.
This is a really nice project but it has no LICENSE attached so it's not clear if/how others can use it. Please add a LICENSE, ideally Apache-2.0 or MIT.
Thank you for providing this library.
I'm a new user of it, and relatively new to firestore.
Could you please confirm the best way to deal with references todocuments like in the image below ("ref" in "carts" (in the parent document) refers to another document in "shopper" (child document))
Should i use the child Document's id as the reference?
If so, it seems ok to save the document with the reference it contains as a String with writeNotNull in the overriden toData method.
But when loading the document containing the reference from firestore, what is the best way to trigger also the loading of the child document refered to by the parent document?
Thanks in advance for your help
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.