Skip to content

Instantly share code, notes, and snippets.

@sgr-ksmt
Created September 20, 2024 05:06
Show Gist options
  • Save sgr-ksmt/29a0cd8968f7d38723b518705672fb3b to your computer and use it in GitHub Desktop.
Save sgr-ksmt/29a0cd8968f7d38723b518705672fb3b to your computer and use it in GitHub Desktop.
Dart Macros x Firestore
import 'dart:async';
import 'package:macros/macros.dart';
macro class FirestoreModel implements ClassDeclarationsMacro {
const FirestoreModel(this.collectionPath);
final String collectionPath;
@override
FutureOr<void> buildDeclarationsForClass(ClassDeclaration clazz, MemberDeclarationBuilder builder) async {
final firestore = Uri.parse('package:cloud_firestore/cloud_firestore.dart');
builder.declareInLibrary(
DeclarationCode.fromParts([
'import \'${firestore.toString()}\';',
]),
);
final className = clazz.identifier.name;
final fields = await builder.fieldsOf(clazz);
builder.debugPrint("className: $className");
builder.debugPrint("fields: ${fields.map((f) => f.identifier.name).join(', ')}");
builder.declareInType(
DeclarationCode.fromParts(
[
'''
static CollectionReference<$className> collectionRef() => FirebaseFirestore.instance.collection('$collectionPath').withConverter(
fromFirestore: (snapshot, options) {
final data = snapshot.data()!;
data['id'] = snapshot.id;
return User.fromJson(data);
},
toFirestore: (user, options) {
return user.toJson();
},
);
''',
'''
static DocumentReference<$className> docRef(String id) => collectionRef().doc(id);
''',
],
),
);
}
}
extension MemberDeclarationBuilderEx on MemberDeclarationBuilder {
void debugPrint(String message) {
declareInLibrary(
DeclarationCode.fromParts([
'// $message',
]),
);
}
}
@JsonCodable()
@FirestoreModel('users')
class User {
final String id;
final String name;
final int age;
User({
required this.id,
required this.name,
required this.age,
});
}
part of 'package:flutter_firebase_macros/user.dart';
import 'dart:core' as prefix0;
import 'package:cloud_firestore/cloud_firestore.dart';
augment class User {
static CollectionReference<User> collectionRef() => FirebaseFirestore.instance.collection('users').withConverter(
fromFirestore: (snapshot, options) {
final data = snapshot.data()!;
data['id'] = snapshot.id;
return User.fromJson(data);
},
toFirestore: (user, options) {
return user.toJson();
},
);
static DocumentReference<User> docRef(String id) => collectionRef().doc(id);
external User.fromJson(prefix0.Map<prefix0.String, prefix0.Object?> json);
external prefix0.Map<prefix0.String, prefix0.Object?> toJson();
augment User.fromJson(prefix0.Map<prefix0.String, prefix0.Object?> json, )
: this.id = json[r'id'] as prefix0.String,
this.name = json[r'name'] as prefix0.String,
this.age = json[r'age'] as prefix0.int;
augment prefix0.Map<prefix0.String, prefix0.Object?> toJson() {
final json = <prefix0.String, prefix0.Object?>{};
json[r'id'] = this.id;
json[r'name'] = this.name;
json[r'age'] = this.age;
return json;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment