Renamed to ORM, etc.
This commit is contained in:
parent
87a13fb285
commit
b7aed22d52
18 changed files with 817 additions and 2 deletions
2
.analysis-options
Normal file
2
.analysis-options
Normal file
|
@ -0,0 +1,2 @@
|
|||
analyzer:
|
||||
strong-mode: true
|
44
.gitignore
vendored
44
.gitignore
vendored
|
@ -10,3 +10,47 @@ pubspec.lock
|
|||
# Directory created by dartdoc
|
||||
# If you don't generate documentation locally you can remove this line.
|
||||
doc/api/
|
||||
### JetBrains template
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff:
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/dictionaries
|
||||
|
||||
# Sensitive or high-churn files:
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.xml
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
|
||||
# Gradle:
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# Mongo Explorer plugin:
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
## File-based project format:
|
||||
*.iws
|
||||
|
||||
## Plugin-specific files:
|
||||
|
||||
# IntelliJ
|
||||
/out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
|
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/postgres.iml" filepath="$PROJECT_DIR$/.idea/postgres.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
28
.idea/postgres.iml
Normal file
28
.idea/postgres.iml
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/packages" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/test/models/packages" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/test/packages" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/tool/packages" />
|
||||
</content>
|
||||
<content url="file://$MODULE_DIR$/../serialize">
|
||||
<excludeFolder url="file://$MODULE_DIR$/../serialize/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/../serialize/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/../serialize/packages" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/../serialize/test/models/packages" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/../serialize/test/packages" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/../serialize/tool/packages" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Dart SDK" level="project" />
|
||||
<orderEntry type="library" name="Dart Packages" level="project" />
|
||||
</component>
|
||||
</module>
|
7
.idea/runConfigurations/postgres__build_dart.xml
Normal file
7
.idea/runConfigurations/postgres__build_dart.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="postgres::build.dart" type="DartCommandLineRunConfigurationType" factoryName="Dart Command Line Application" singleton="true">
|
||||
<option name="filePath" value="$PROJECT_DIR$/tool/build.dart" />
|
||||
<option name="workingDirectory" value="$PROJECT_DIR$" />
|
||||
<method />
|
||||
</configuration>
|
||||
</component>
|
7
.idea/runConfigurations/serialize__build_dart.xml
Normal file
7
.idea/runConfigurations/serialize__build_dart.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="serialize::build.dart" type="DartCommandLineRunConfigurationType" factoryName="Dart Command Line Application" singleton="true">
|
||||
<option name="filePath" value="$PROJECT_DIR$/../serialize/tool/build.dart" />
|
||||
<option name="workingDirectory" value="$PROJECT_DIR$/../serialize" />
|
||||
<method />
|
||||
</configuration>
|
||||
</component>
|
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
1
.travis.yml
Normal file
1
.travis.yml
Normal file
|
@ -0,0 +1 @@
|
|||
language: dart
|
85
README.md
85
README.md
|
@ -1,2 +1,83 @@
|
|||
# postgres
|
||||
PostgreSQL-enabled services for the Angel framework.
|
||||
# orm
|
||||
[![Pub](https://img.shields.io/pub/v/angel_orm.svg)](https://pub.dartlang.org/packages/angel_orm)
|
||||
[![build status](https://travis-ci.org/angel-dart/orm.svg)](https://travis-ci.org/angel-dart/orm)
|
||||
|
||||
**This project is currently in the early stages, and may change at any given
|
||||
time without warning.**
|
||||
|
||||
Source-generated ORM for use with the Angel framework. Documentation is coming soon.
|
||||
This ORM can work with virtually any database, thanks to the functionality exposed by
|
||||
`package:query_builder`.
|
||||
|
||||
```dart
|
||||
library angel_orm.test.models.car;
|
||||
|
||||
import 'package:angel_framework/common.dart';
|
||||
import 'package:angel_orm/angel_orm.dart' as orm;
|
||||
import 'package:angel_serialize/angel_serialize.dart';
|
||||
import 'car.postgres.g.dart';
|
||||
part 'car.g.dart';
|
||||
|
||||
@serializable
|
||||
@orm.model
|
||||
class _Car extends Model {
|
||||
@override
|
||||
String id;
|
||||
|
||||
String manufacturer;
|
||||
|
||||
int year;
|
||||
|
||||
@override
|
||||
@Alias('created_at')
|
||||
DateTime createdAt;
|
||||
|
||||
@override
|
||||
@Alias('updated_at')
|
||||
DateTime updatedAt;
|
||||
}
|
||||
```
|
||||
|
||||
After building, you'll have access to a `Repository` class with strongly-typed methods that
|
||||
allow to run asynchronous queries without a headache.
|
||||
You can run complex queries like:
|
||||
|
||||
```dart
|
||||
import 'package:angel_framework/angel_framework.dart';
|
||||
import 'package:postgres/postgres.dart';
|
||||
import 'car.dart';
|
||||
import 'car.orm.g.dart';
|
||||
|
||||
/// Returns an Angel plug-in that connects to a PostgreSQL database, and sets up a controller connected to it...
|
||||
AngelConfigurer connectToCarsTable(PostgreSQL connection) {
|
||||
return (Angel app) async {
|
||||
// Instantiate a Car repository, which is auto-generated. This class helps us build fluent queries easily.
|
||||
var cars = new CarRepository(connection);
|
||||
|
||||
// Register it with Angel's dependency injection system.
|
||||
//
|
||||
// This means that we can use it as a parameter in routes and controllers.
|
||||
app.container.singleton(cars);
|
||||
|
||||
// Attach the controller we create below
|
||||
await app.configure(new CarService(cars));
|
||||
};
|
||||
}
|
||||
|
||||
@Expose('/cars')
|
||||
class CarService extends Controller {
|
||||
/// `manufacturerId` and `CarRepository` in this case would be dependency-injected. :)
|
||||
@Expose('/:manufacturerId/years')
|
||||
getAllYearsForManufacturer(String manufacturerId, CarRepository cars) {
|
||||
return
|
||||
cars
|
||||
.whereManufacturer(manufacturerId)
|
||||
.get()
|
||||
.map((Car car) {
|
||||
// Cars are deserialized automatically, woohoo!
|
||||
return car.year;
|
||||
})
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
```
|
13
lib/angel_orm.dart
Normal file
13
lib/angel_orm.dart
Normal file
|
@ -0,0 +1,13 @@
|
|||
class Model {
|
||||
final String tableName;
|
||||
const Model([this.tableName]);
|
||||
}
|
||||
|
||||
const Model model = const Model();
|
||||
|
||||
class Column {
|
||||
final String name;
|
||||
const Column([this.name]);
|
||||
}
|
||||
|
||||
const Column column = const Column();
|
296
lib/builder.dart
Normal file
296
lib/builder.dart
Normal file
|
@ -0,0 +1,296 @@
|
|||
import 'dart:async';
|
||||
import 'dart:mirrors';
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
import 'package:angel_serialize/angel_serialize.dart';
|
||||
import 'package:build/build.dart';
|
||||
import 'package:code_builder/dart/async.dart';
|
||||
import 'package:code_builder/dart/core.dart';
|
||||
import 'package:code_builder/code_builder.dart';
|
||||
import 'package:inflection/inflection.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:recase/recase.dart';
|
||||
import 'package:source_gen/src/annotation.dart';
|
||||
import 'package:source_gen/source_gen.dart';
|
||||
import 'package:query_builder_sql/query_builder_sql.dart';
|
||||
import 'angel_orm.dart';
|
||||
|
||||
// TODO: whereXLessThan, greaterThan, etc.
|
||||
|
||||
final RegExp _leadingDot = new RegExp(r'^\.+');
|
||||
|
||||
const List<String> QUERY_DO_NOT_OVERRIDE = const ['when'];
|
||||
|
||||
typedef Iterable<ExpressionBuilder> SuperArgumentProvider(
|
||||
Model model, ClassElement clazz);
|
||||
|
||||
class AngelQueryBuilderGenerator extends GeneratorForAnnotation<Model> {
|
||||
ClassMirror _baseRepositoryClassMirror;
|
||||
final List<String> _imports = [
|
||||
'dart:async',
|
||||
'package:query_builder/query_builder.dart'
|
||||
];
|
||||
|
||||
final Map<String, TypeBuilder> _constructorParams = {};
|
||||
SuperArgumentProvider _superArgProvider;
|
||||
|
||||
AngelQueryBuilderGenerator(Type baseRepositoryQueryClass,
|
||||
{Iterable<String> additonalImports: const [],
|
||||
Map<String, TypeBuilder> constructorParams: const {},
|
||||
SuperArgumentProvider superArgProvider}) {
|
||||
_baseRepositoryClassMirror = reflectClass(baseRepositoryQueryClass);
|
||||
_imports.addAll(additonalImports ?? []);
|
||||
_constructorParams.addAll(constructorParams ?? {});
|
||||
_superArgProvider = superArgProvider ??
|
||||
(annotation, clazz) => [
|
||||
literal(annotation.tableName?.isNotEmpty == true
|
||||
? annotation.tableName
|
||||
: pluralize(new ReCase(clazz.name.substring(1)).snakeCase))
|
||||
];
|
||||
}
|
||||
|
||||
factory AngelQueryBuilderGenerator.postgresql() =>
|
||||
new AngelQueryBuilderGenerator(SqlRepositoryQuery, constructorParams: {
|
||||
'connection': new TypeBuilder('PostgreSQLConnection')
|
||||
}, additonalImports: [
|
||||
'package:postgres/postgres.dart',
|
||||
'package:query_builder_sql/query_builder_sql.dart'
|
||||
]);
|
||||
|
||||
@override
|
||||
Future<String> generateForAnnotatedElement(
|
||||
Element element, Model annotation, BuildStep buildStep) async {
|
||||
if (element.kind != ElementKind.CLASS)
|
||||
throw 'Only classes may be annotated with @model.';
|
||||
var lib = generatePostgresLibrary(element, annotation, buildStep.inputId);
|
||||
return prettyToSource(lib.buildAst());
|
||||
}
|
||||
|
||||
LibraryBuilder generatePostgresLibrary(
|
||||
ClassElement clazz, Model annotation, AssetId inputId) {
|
||||
if (!clazz.name.startsWith('_'))
|
||||
throw 'Classes annotated with @model must have names starting with an underscore.';
|
||||
var lib = new LibraryBuilder();
|
||||
lib.addDirectives(_imports.map((p) => new ImportBuilder(p)));
|
||||
lib.addDirective(new ImportBuilder(p.basename(inputId.path)));
|
||||
|
||||
// Find all aliases...
|
||||
Map<String, String> aliases = {};
|
||||
clazz.fields.forEach((field) {
|
||||
var aliasAnnotation = field.metadata
|
||||
.firstWhere((ann) => matchAnnotation(Alias, ann), orElse: () => null);
|
||||
if (aliasAnnotation != null) {
|
||||
var alias = instantiateAnnotation(aliasAnnotation) as Alias;
|
||||
aliases[field.name] = alias.name;
|
||||
}
|
||||
});
|
||||
|
||||
lib.addMember(generateRepositoryClass(clazz, aliases));
|
||||
lib.addMember(generateRepositoryQueryClass(clazz, annotation, aliases));
|
||||
return lib;
|
||||
}
|
||||
|
||||
ClassBuilder generateRepositoryClass(
|
||||
ClassElement clazz, Map<String, String> aliases) {
|
||||
var genClassName = clazz.name.substring(1) + 'Repository';
|
||||
var genQueryClassName = genClassName + 'Query';
|
||||
var genClass = new ClassBuilder(genClassName);
|
||||
var genQueryType = new TypeBuilder(genQueryClassName);
|
||||
|
||||
// Add `connection` field + constructor
|
||||
|
||||
var genConstructor = new ConstructorBuilder();
|
||||
_constructorParams.forEach((name, type) {
|
||||
genClass.addField(varFinal(name, type: type));
|
||||
genConstructor.addPositional(parameter(name), asField: true);
|
||||
});
|
||||
genClass.addConstructor(genConstructor);
|
||||
|
||||
// Add an all method
|
||||
genClass.addMethod(new MethodBuilder('all',
|
||||
returnType: new TypeBuilder(genQueryClassName),
|
||||
returns: new TypeBuilder(genQueryClassName)
|
||||
.newInstance([reference('connection')])));
|
||||
|
||||
// For each field, add a whereX() method...
|
||||
clazz.fields
|
||||
.map((field) => generateWhereFieldMethod(
|
||||
field, reference('all').call([]), genQueryType, aliases))
|
||||
.forEach(genClass.addMethod);
|
||||
return genClass;
|
||||
}
|
||||
|
||||
ClassBuilder generateRepositoryQueryClass(
|
||||
ClassElement clazz, Model annotation, Map<String, String> aliases) {
|
||||
var modelClassName = clazz.name.substring(1);
|
||||
var genClassName = clazz.name.substring(1) + 'RepositoryQuery';
|
||||
var genClass = new ClassBuilder(genClassName,
|
||||
asExtends: new TypeBuilder(
|
||||
MirrorSystem.getName(_baseRepositoryClassMirror.simpleName),
|
||||
genericTypes: [new TypeBuilder(modelClassName)]));
|
||||
var genQueryType = new TypeBuilder(genClassName);
|
||||
|
||||
// Add `connection` field + constructor
|
||||
|
||||
var genConstructor = new ConstructorBuilder(
|
||||
invokeSuper: _superArgProvider(annotation, clazz));
|
||||
_constructorParams.forEach((name, type) {
|
||||
genClass.addField(varFinal(name, type: type));
|
||||
genConstructor.addPositional(parameter(name), asField: true);
|
||||
});
|
||||
genClass.addConstructor(genConstructor);
|
||||
|
||||
// For each field, add a whereX() method...
|
||||
clazz.fields
|
||||
.map((field) => generateWhereFieldMethod(
|
||||
field, explicitThis, genQueryType, aliases))
|
||||
.forEach(genClass.addMethod);
|
||||
|
||||
// Add orWhereX()
|
||||
clazz.fields
|
||||
.map((f) => generateOrWhereFieldMethod(genQueryType, f))
|
||||
.forEach(genClass.addMethod);
|
||||
|
||||
// Override any query methods
|
||||
_baseRepositoryClassMirror.instanceMembers.forEach((sym, method) {
|
||||
// Skip setters, etc.
|
||||
if (!method.isRegularMethod) return;
|
||||
|
||||
// Only if return type contains 'RepositoryQuery'
|
||||
var methodName = MirrorSystem.getName(sym);
|
||||
|
||||
if (QUERY_DO_NOT_OVERRIDE.contains(methodName)) return;
|
||||
|
||||
var returnTypeName = MirrorSystem.getName(method.returnType.simpleName);
|
||||
|
||||
if (returnTypeName.contains('RepositoryQuery')) {
|
||||
var overriddenMethod =
|
||||
new MethodBuilder(methodName, returnType: genQueryType);
|
||||
// Add @override
|
||||
overriddenMethod.addAnnotation(lib$core.override);
|
||||
|
||||
// Find all positional and named args
|
||||
List<String> args = [];
|
||||
List<String> named = [];
|
||||
|
||||
method.parameters.forEach((param) {
|
||||
var paramName = MirrorSystem.getName(param.simpleName);
|
||||
var typeName = MirrorSystem.getName(param.type.simpleName);
|
||||
var paramType = new TypeBuilder(typeName);
|
||||
var genParam = parameter(paramName, [paramType]);
|
||||
|
||||
if (!param.isNamed) {
|
||||
args.add(paramName);
|
||||
overriddenMethod.addPositional(
|
||||
param.isOptional ? genParam.asOptional() : genParam);
|
||||
} else {
|
||||
overriddenMethod.addNamed(genParam);
|
||||
named.add(paramName);
|
||||
}
|
||||
});
|
||||
|
||||
// Invoke super
|
||||
overriddenMethod.addStatement(reference('super')
|
||||
.invoke(methodName, args.map(reference),
|
||||
namedArguments: named.fold<Map<String, ExpressionBuilder>>(
|
||||
{}, (out, k) => out..[k] = reference(k)))
|
||||
.asReturn());
|
||||
|
||||
genClass.addMethod(overriddenMethod);
|
||||
}
|
||||
});
|
||||
|
||||
// Override toSql to put keys in desired order
|
||||
// TODO: Override toSql
|
||||
|
||||
// Add get()
|
||||
genClass.addMethod(generateGetMethod(clazz, modelClassName, aliases));
|
||||
|
||||
return genClass;
|
||||
}
|
||||
|
||||
MethodBuilder generateGetMethod(
|
||||
ClassElement clazz, String modelClassName, Map<String, String> aliases) {
|
||||
var meth = new MethodBuilder('get')..addAnnotation(lib$core.override);
|
||||
|
||||
// Map rows to model...
|
||||
var mapRowsToModel = new MethodBuilder.closure()
|
||||
..addPositional(parameter('rows'));
|
||||
|
||||
// First, figure out which rows we fetched...
|
||||
//
|
||||
// var requestedKeys = whereFields.keys.isNotEmpty ? whereFields.keys : [<all fields...>];
|
||||
|
||||
var allModelFields = clazz.fields
|
||||
.map((f) => aliases.containsKey(f.name) ? aliases[f.name] : f.name);
|
||||
var whereFieldsKeys = reference('whereFields').property('keys');
|
||||
|
||||
// return new Stream<>.fromFuture(...)
|
||||
meth.addStatement(lib$async.Stream.newInstance([
|
||||
reference('connection')
|
||||
.invoke('query', [reference('toSql').call([])]).invoke(
|
||||
'then', [mapRowsToModel])
|
||||
], constructor: 'fromFuture').asReturn());
|
||||
|
||||
return meth;
|
||||
}
|
||||
|
||||
MethodBuilder generateWhereFieldMethod(
|
||||
FieldElement field,
|
||||
ExpressionBuilder baseQuery,
|
||||
TypeBuilder returnType,
|
||||
Map<String, String> aliases) {
|
||||
var rc = new ReCase(field.name);
|
||||
var whereMethod =
|
||||
new MethodBuilder('where${rc.pascalCase}', returnType: returnType);
|
||||
var columnName =
|
||||
aliases.containsKey(field.name) ? aliases[field.name] : field.name;
|
||||
whereMethod.addPositional(
|
||||
parameter(field.name, [new TypeBuilder(field.type.displayName)]));
|
||||
|
||||
if (field.type.name == 'DateTime') {
|
||||
// Add named `{time: true}`
|
||||
whereMethod.addNamed(
|
||||
parameter('time', [lib$core.bool]).asOptional(literal(true)));
|
||||
// return all().whereDate('x', x, time: time != false);
|
||||
// return all().where('x', x);
|
||||
whereMethod.addStatement(baseQuery.invoke('whereDate', [
|
||||
literal(columnName),
|
||||
reference(field.name)
|
||||
], namedArguments: {
|
||||
'time': reference('time').notEquals(literal(false))
|
||||
}).asReturn());
|
||||
} else {
|
||||
// return all().where('x', x);
|
||||
whereMethod.addStatement(baseQuery.invoke(
|
||||
'where', [literal(columnName), reference(field.name)]).asReturn());
|
||||
}
|
||||
|
||||
return whereMethod;
|
||||
}
|
||||
|
||||
MethodBuilder generateOrWhereFieldMethod(
|
||||
TypeBuilder genQueryClassType, FieldElement field) {
|
||||
var rc = new ReCase(field.name);
|
||||
var orWhereMethod = new MethodBuilder('orWhere' + rc.pascalCase,
|
||||
returnType: genQueryClassType);
|
||||
orWhereMethod.addPositional(
|
||||
parameter(field.name, [new TypeBuilder(field.type.displayName)]));
|
||||
|
||||
if (field.type.name == 'DateTime') {
|
||||
orWhereMethod.addNamed(parameter('time', [lib$core.bool]));
|
||||
orWhereMethod.addStatement(reference('or').call([
|
||||
reference('where' + rc.pascalCase).call([
|
||||
reference(field.name)
|
||||
], namedArguments: {
|
||||
'time': reference('time').notEquals(literal(false))
|
||||
})
|
||||
]).asReturn());
|
||||
} else {
|
||||
orWhereMethod.addStatement(reference('or').call([
|
||||
reference('where' + rc.pascalCase).call([reference(field.name)])
|
||||
]).asReturn());
|
||||
}
|
||||
|
||||
return orWhereMethod;
|
||||
}
|
||||
}
|
22
pubspec.yaml
Normal file
22
pubspec.yaml
Normal file
|
@ -0,0 +1,22 @@
|
|||
name: angel_orm
|
||||
version: 0.0.0
|
||||
description: Source-generated ORM for use with the Angel framework.
|
||||
author: Tobe O <thosakwe@gmail.com>
|
||||
homepage: https://github.com/angel-dart/angel_mongo
|
||||
dependencies:
|
||||
angel_framework: ">=1.0.0-dev < 2.0.0"
|
||||
code_builder: ^1.0.0
|
||||
id: ^1.0.0
|
||||
inflection: ^0.4.1
|
||||
postgres: ">=0.9.5 <1.0.0"
|
||||
query_builder_sql: ^1.0.0-alpha
|
||||
recase: ^1.0.0
|
||||
source_gen: ^0.5.8
|
||||
dev_dependencies:
|
||||
angel_diagnostics: ">=1.0.0 <2.0.0"
|
||||
angel_serialize:
|
||||
path: ../serialize
|
||||
angel_test: ">=1.0.0 <2.0.0"
|
||||
build_runner: ^0.3.0
|
||||
http: ">= 0.11.3 < 0.12.0"
|
||||
test: ">= 0.12.13 < 0.13.0"
|
22
test/models/car.dart
Normal file
22
test/models/car.dart
Normal file
|
@ -0,0 +1,22 @@
|
|||
library angel_orm.test.models.car;
|
||||
|
||||
import 'package:angel_framework/common.dart';
|
||||
import 'package:angel_orm/angel_orm.dart' as orm;
|
||||
import 'package:angel_serialize/angel_serialize.dart';
|
||||
import 'car.postgres.g.dart';
|
||||
part 'car.g.dart';
|
||||
|
||||
@serializable
|
||||
@orm.model
|
||||
class _Car extends Model {
|
||||
@override
|
||||
String id;
|
||||
|
||||
@override
|
||||
@Alias('created_at')
|
||||
DateTime createdAt;
|
||||
|
||||
@override
|
||||
@Alias('updated_at')
|
||||
DateTime updatedAt;
|
||||
}
|
44
test/models/car.g.dart
Normal file
44
test/models/car.g.dart
Normal file
|
@ -0,0 +1,44 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of angel_orm.test.models.car;
|
||||
|
||||
// **************************************************************************
|
||||
// Generator: JsonModelGenerator
|
||||
// Target: class _Car
|
||||
// **************************************************************************
|
||||
|
||||
class Car extends _Car {
|
||||
@override
|
||||
String id;
|
||||
|
||||
@override
|
||||
DateTime createdAt;
|
||||
|
||||
@override
|
||||
DateTime updatedAt;
|
||||
|
||||
Car({this.id, this.createdAt, this.updatedAt});
|
||||
|
||||
factory Car.fromJson(Map data) {
|
||||
return new Car(
|
||||
id: data['id'],
|
||||
createdAt: data['created_at'] is DateTime
|
||||
? data['created_at']
|
||||
: (data['created_at'] is String
|
||||
? DateTime.parse(data['created_at'])
|
||||
: null),
|
||||
updatedAt: data['updated_at'] is DateTime
|
||||
? data['updated_at']
|
||||
: (data['updated_at'] is String
|
||||
? DateTime.parse(data['updated_at'])
|
||||
: null));
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'id': id,
|
||||
'created_at': createdAt == null ? null : createdAt.toIso8601String(),
|
||||
'updated_at': updatedAt == null ? null : updatedAt.toIso8601String()
|
||||
};
|
||||
|
||||
static Car parse(Map map) => new Car.fromJson(map);
|
||||
}
|
212
test/models/car.orm.g.dart
Normal file
212
test/models/car.orm.g.dart
Normal file
|
@ -0,0 +1,212 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
// **************************************************************************
|
||||
// Generator: AngelQueryBuilderGenerator
|
||||
// Target: class _Car
|
||||
// **************************************************************************
|
||||
|
||||
import 'dart:async';
|
||||
import 'package:query_builder/query_builder.dart';
|
||||
import 'package:postgres/postgres.dart';
|
||||
import 'package:query_builder_sql/query_builder_sql.dart';
|
||||
import 'car.dart';
|
||||
|
||||
class CarRepository {
|
||||
final PostgreSQLConnection connection;
|
||||
|
||||
CarRepository(this.connection);
|
||||
|
||||
CarRepositoryQuery all() => new CarRepositoryQuery(connection);
|
||||
|
||||
CarRepositoryQuery whereId(String id) {
|
||||
return all().where('id', id);
|
||||
}
|
||||
|
||||
CarRepositoryQuery whereCreatedAt(DateTime createdAt, {bool time: true}) {
|
||||
return all().whereDate('created_at', createdAt, time: time != false);
|
||||
}
|
||||
|
||||
CarRepositoryQuery whereUpdatedAt(DateTime updatedAt, {bool time: true}) {
|
||||
return all().whereDate('updated_at', updatedAt, time: time != false);
|
||||
}
|
||||
}
|
||||
|
||||
class CarRepositoryQuery extends SqlRepositoryQuery<Car> {
|
||||
final PostgreSQLConnection connection;
|
||||
|
||||
CarRepositoryQuery(this.connection) : super('cars');
|
||||
|
||||
CarRepositoryQuery whereId(String id) {
|
||||
return this.where('id', id);
|
||||
}
|
||||
|
||||
CarRepositoryQuery whereCreatedAt(DateTime createdAt, {bool time: true}) {
|
||||
return this.whereDate('created_at', createdAt, time: time != false);
|
||||
}
|
||||
|
||||
CarRepositoryQuery whereUpdatedAt(DateTime updatedAt, {bool time: true}) {
|
||||
return this.whereDate('updated_at', updatedAt, time: time != false);
|
||||
}
|
||||
|
||||
CarRepositoryQuery orWhereId(String id) {
|
||||
return or(whereId(id));
|
||||
}
|
||||
|
||||
CarRepositoryQuery orWhereCreatedAt(DateTime createdAt, {bool time}) {
|
||||
return or(whereCreatedAt(createdAt, time: time != false));
|
||||
}
|
||||
|
||||
CarRepositoryQuery orWhereUpdatedAt(DateTime updatedAt, {bool time}) {
|
||||
return or(whereUpdatedAt(updatedAt, time: time != false));
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery latest([String fieldName]) {
|
||||
return super.latest(fieldName);
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery oldest([String fieldName]) {
|
||||
return super.oldest(fieldName);
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery where(String fieldName, dynamic value) {
|
||||
return super.where(fieldName, value);
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery whereNot(String fieldName, dynamic value) {
|
||||
return super.whereNot(fieldName, value);
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery whereNull(String fieldName) {
|
||||
return super.whereNull(fieldName);
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery whereNotNull(String fieldName) {
|
||||
return super.whereNotNull(fieldName);
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery distinct(Iterable fieldNames) {
|
||||
return super.distinct(fieldNames);
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery groupBy(String fieldName) {
|
||||
return super.groupBy(fieldName);
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery inRandomOrder() {
|
||||
return super.inRandomOrder();
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery orderBy(String fieldName, [OrderBy orderBy]) {
|
||||
return super.orderBy(fieldName, orderBy);
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery select(Iterable selectors) {
|
||||
return super.select(selectors);
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery skip(int count) {
|
||||
return super.skip(count);
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery take(int count) {
|
||||
return super.take(count);
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery join(
|
||||
String otherTable, String nearColumn, String farColumn,
|
||||
[JoinType joinType]) {
|
||||
return super.join(otherTable, nearColumn, farColumn, joinType);
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery union(RepositoryQuery other, [UnionType type]) {
|
||||
return super.union(other, type);
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery whereBetween(
|
||||
String fieldName, dynamic lower, dynamic upper) {
|
||||
return super.whereBetween(fieldName, lower, upper);
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery whereDate(String fieldName, DateTime date, {bool time}) {
|
||||
return super.whereDate(fieldName, date, time: time);
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery whereDay(String fieldName, int day) {
|
||||
return super.whereDay(fieldName, day);
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery whereEquality(
|
||||
String fieldName, dynamic value, Equality equality) {
|
||||
return super.whereEquality(fieldName, value, equality);
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery whereIn(String fieldName, Iterable values) {
|
||||
return super.whereIn(fieldName, values);
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery whereLike(String fieldName, dynamic value) {
|
||||
return super.whereLike(fieldName, value);
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery whereMonth(String fieldName, int month) {
|
||||
return super.whereMonth(fieldName, month);
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery whereNotBetween(
|
||||
String fieldName, dynamic lower, dynamic upper) {
|
||||
return super.whereNotBetween(fieldName, lower, upper);
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery whereNotIn(String fieldName, Iterable values) {
|
||||
return super.whereNotIn(fieldName, values);
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery whereYear(String fieldName, int year) {
|
||||
return super.whereYear(fieldName, year);
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery selfJoin(String t1, String t2) {
|
||||
return super.selfJoin(t1, t2);
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery or(RepositoryQuery other) {
|
||||
return super.or(other);
|
||||
}
|
||||
|
||||
@override
|
||||
CarRepositoryQuery not(RepositoryQuery other) {
|
||||
return super.not(other);
|
||||
}
|
||||
|
||||
@override
|
||||
get() {
|
||||
return new Stream.fromFuture(connection.query(toSql()).then((rows) {}));
|
||||
}
|
||||
}
|
4
tool/build.dart
Normal file
4
tool/build.dart
Normal file
|
@ -0,0 +1,4 @@
|
|||
import 'package:build_runner/build_runner.dart';
|
||||
import 'phases.dart';
|
||||
|
||||
main() => build(PHASES, deleteFilesByDefault: true);
|
14
tool/phases.dart
Normal file
14
tool/phases.dart
Normal file
|
@ -0,0 +1,14 @@
|
|||
import 'package:build_runner/build_runner.dart';
|
||||
import 'package:source_gen/source_gen.dart';
|
||||
import 'package:angel_orm/builder.dart';
|
||||
import 'package:angel_serialize/builder.dart';
|
||||
|
||||
final PhaseGroup PHASES = new PhaseGroup()
|
||||
..addPhase(new Phase()
|
||||
..addAction(new GeneratorBuilder([const JsonModelGenerator()]),
|
||||
new InputSet('angel_orm', const ['test/models/*.dart'])))
|
||||
..addPhase(new Phase()
|
||||
..addAction(
|
||||
new GeneratorBuilder([new AngelQueryBuilderGenerator.postgresql()],
|
||||
isStandalone: true, generatedExtension: '.orm.g.dart'),
|
||||
new InputSet('angel_orm', const ['test/models/*.dart'])));
|
4
tool/watch.dart
Normal file
4
tool/watch.dart
Normal file
|
@ -0,0 +1,4 @@
|
|||
import 'package:build_runner/build_runner.dart';
|
||||
import 'phases.dart';
|
||||
|
||||
main() => watch(PHASES, deleteFilesByDefault: true);
|
Loading…
Reference in a new issue