generateDart function
Dart source for the collections of a schema snapshot: per collection a
XRecord extends RecordModel with a getter per field, an XCreate (base
and auth collections) with toJson(), and vb.collections.<name>.
Implementation
String generateDart(List<Map<String, dynamic>> collections,
{String header = '// AUTO-GENERATED by `dart run vaultbase:types`. '
'Do not edit.\n'}) {
final classes = <String>[];
final accessors = <String>[];
final accessorNames = {
'vb',
'hashCode',
'runtimeType',
'toString',
'noSuchMethod'
};
final classNames = {'Vaultbase'};
var usesGeo = false;
var usesGroupDate = false;
// Group classes are named after their collection and field; kept clear of
// every record and create class, and of the library's own.
final typeNames = {
'Vaultbase', 'VaultbaseCollections', 'RecordModel', 'Collection', //
'Singleton',
};
final bases = <Map<String, dynamic>, String>{};
for (final col in collections) {
final name = col['name'];
if (name is! String || !_collectionName.hasMatch(name)) continue;
final base = _unique(_typeBase(name), classNames);
bases[col] = base;
typeNames.addAll(['${base}Record', '${base}Create', '${base}Params']);
}
for (final col in collections) {
final base = bases[col];
if (base == null) continue;
final name = col['name'] as String;
final type = col['type'] as String? ?? 'base';
final fields = [
for (final f in _parseFields(col['fields']))
if (_keepField(f, type)) f
];
for (final f in fields.where((f) => f.type == 'group')) {
final cls = _unique(
'$base${_pascal(f.name)}${f.groupList ? 'Item' : ''}', typeNames);
f.groupClass = cls;
classes.add(_emitGroup(cls, name, f));
usesGroupDate = usesGroupDate || f.subfields.any((s) => s.type == 'date');
}
final names = _fieldNames(
fields, type == 'auth' ? _recordMembers : _recordMembersNoAuth);
usesGeo = usesGeo || fields.any((f) => f.type == 'geoPoint');
final accessor = _unique(_safeIdent(_camel(name)), accessorNames);
classes.add(_emitRecord('${base}Record', name, type, fields, names));
if (type == 'base' || type == 'auth') {
classes.add(_emitCreate(
'${base}Create',
name,
type,
[
for (final f in fields)
if (f.type != 'autodate') f
],
names,
accessor));
}
if (type == 'view') {
final params = _viewParams(col['view_params']);
if (params.isNotEmpty) {
classes.add(_emitParams('${base}Params', name, params, accessor));
}
}
final quoted = _dartString(name);
accessors.add(type == 'singleton'
? ' Singleton<${base}Record> get $accessor =>\n'
' vb.singletonOf($quoted, ${base}Record.fromJson);'
: ' Collection<${base}Record> get $accessor =>\n'
' vb.collectionOf($quoted, ${base}Record.fromJson);');
}
final parts = [
header.trimRight(),
'// ignore_for_file: type=lint',
'',
"import 'package:vaultbase/vaultbase.dart';",
'',
classes.join('\n\n'),
'',
'/// Each collection with its record type: `vb.collections.posts.list()`.',
'class VaultbaseCollections {',
' const VaultbaseCollections(this.vb);',
'',
' final Vaultbase vb;',
if (accessors.isNotEmpty) ...['', accessors.join('\n\n')],
'}',
'',
'extension VaultbaseSchema on Vaultbase {',
' VaultbaseCollections get collections => VaultbaseCollections(this);',
'}',
if (usesGeo) ...[
'',
'({double lat, double lng})? _geoPoint(Object? v) => v is Map &&',
" v['lat'] is num &&",
" v['lng'] is num",
" ? (lat: (v['lat'] as num).toDouble(), "
"lng: (v['lng'] as num).toDouble())",
' : null;',
],
if (usesGroupDate) ...[
'',
'DateTime? _groupDate(Object? v) => v is num',
' ? DateTime.fromMillisecondsSinceEpoch(v.toInt() * 1000, isUtc: true)',
' : null;',
],
'',
];
return parts.join('\n');
}