platform-cli/lib/src/commands/service.dart

238 lines
7 KiB
Dart
Raw Normal View History

2016-12-21 17:34:15 +00:00
import 'dart:io';
import 'package:args/command_runner.dart';
2017-02-23 02:48:08 +00:00
import 'package:code_builder/code_builder.dart';
2016-12-21 17:34:15 +00:00
import 'package:console/console.dart';
2017-02-23 02:48:08 +00:00
import 'package:inflection/inflection.dart';
2017-02-19 12:54:29 +00:00
import 'package:recase/recase.dart';
2017-02-23 02:48:08 +00:00
import 'service_generators/service_generators.dart';
2016-12-31 16:50:35 +00:00
import 'init.dart' show preBuild;
2016-09-14 04:33:28 +00:00
2017-02-23 02:48:08 +00:00
const List<ServiceGenerator> GENERATORS = const [
const MapServiceGenerator(),
const MongoServiceGenerator(),
const RethinkServiceGenerator(),
const CustomServiceGenerator()
];
2016-09-14 04:33:28 +00:00
class ServiceCommand extends Command {
final TextPen _pen = new TextPen();
2016-11-24 00:35:40 +00:00
@override
2016-12-21 17:34:15 +00:00
String get name => 'service';
2016-09-14 04:33:28 +00:00
2016-11-24 00:35:40 +00:00
@override
2016-12-21 17:34:15 +00:00
String get description => 'Creates a new service within the given project.';
2016-09-14 04:33:28 +00:00
@override
run() async {
2016-12-21 17:34:15 +00:00
var name = await readInput('Name of Service (not plural): ');
2017-02-23 02:48:08 +00:00
var chooser = new Chooser<String>(
GENERATORS.map<String>((g) => g.name).toList(),
2016-12-21 17:34:15 +00:00
message: 'What type of service would you like to create? ');
2016-09-14 04:33:28 +00:00
var type = await chooser.choose();
2017-02-23 02:48:08 +00:00
print('Wrap this service in a TypedService? (slight performance cost)');
chooser = new Chooser<String>(['Yes', 'No']);
var typed = (await chooser.choose()) == 'Yes';
2016-09-14 04:33:28 +00:00
2017-02-23 02:48:08 +00:00
var generator =
GENERATORS.firstWhere((g) => g.name == type, orElse: () => null);
if (generator == null) {
2016-09-15 01:28:12 +00:00
_pen.blue();
2017-02-23 02:48:08 +00:00
_pen('${Icon.STAR} \'$type\' services are not yet implemented. :(');
2016-09-15 01:28:12 +00:00
_pen();
} else {
2017-02-23 02:48:08 +00:00
var rc = new ReCase(name);
name = rc.pascalCase;
var lower = rc.snakeCase;
var servicesDir = new Directory('lib/src/services');
var serviceFile =
new File.fromUri(servicesDir.uri.resolve('$lower.dart'));
var testDir = new Directory('test/services');
var testFile =
new File.fromUri(testDir.uri.resolve('${lower}_test.dart'));
if (!await servicesDir.exists())
await servicesDir.create(recursive: true);
if (!await testDir.exists()) await testDir.create(recursive: true);
await serviceFile
.writeAsString(_generateService(generator, name, lower, typed));
await testFile.writeAsString(_generateTests(lower, type));
var runConfig = new File('./.idea/runConfigurations/${name}_Tests.xml');
if (!await runConfig.exists()) {
await runConfig.create(recursive: true);
await runConfig.writeAsString(_generateRunConfiguration(name, lower));
}
if (generator.createsModel == true) {
await _generateModel(name, lower);
}
if (generator.createsValidator == true) {
await _generateValidator(lower, rc.constantCase);
}
if (generator.exportedInServiceLibrary == true) {
var serviceLibrary = new File('lib/src/models/models.dart');
await serviceLibrary.writeAsString("\nexport '$lower.dart';",
mode: FileMode.APPEND);
}
if (generator.shouldRunBuild == true) {
await preBuild(Directory.current);
}
_pen.green();
_pen('${Icon.CHECKMARK} Successfully generated service $name.');
_pen();
2016-09-15 01:28:12 +00:00
}
2017-02-23 02:48:08 +00:00
}
2016-09-15 01:28:12 +00:00
2017-02-23 02:48:08 +00:00
String _generateService(
ServiceGenerator generator, String name, String lower, bool typed) {
var lib = new LibraryBuilder();
2016-09-15 05:19:06 +00:00
2017-02-23 02:48:08 +00:00
/*
import 'package:angel_framework/angel_framework.dart';
import '../models/$lower.dart';
export '../models/$lower.dart';
*/
lib.addMember(
new ImportBuilder('package:angel_framework/angel_framework.dart'));
generator.applyToLibrary(lib, name, lower);
2016-11-24 00:42:29 +00:00
2017-02-23 02:48:08 +00:00
if (generator.createsModel == true) {
lib
..addMember(new ImportBuilder('../models/$lower.dart'))
..addMember(new ExportBuilder('../models/$lower.dart'));
2016-11-24 00:42:29 +00:00
}
2016-09-15 01:28:12 +00:00
2017-02-23 02:48:08 +00:00
// configureServer() {}
var configureServer = new MethodBuilder('configureServer',
returnType: new TypeBuilder('AngelConfigurer'));
generator.applyToConfigureServer(configureServer, name, lower);
2016-11-24 00:35:40 +00:00
2017-02-23 02:48:08 +00:00
// return (Angel app) async {}
var closure = new MethodBuilder.closure(modifier: MethodModifier.asAsync)
..addPositional(parameter('app', [new TypeBuilder('Angel')]));
generator.beforeService(closure, name, lower);
2016-09-15 01:28:12 +00:00
2017-02-23 02:48:08 +00:00
// app.use('/api/todos', new MapService());
var service = generator.createInstance(closure, name, lower);
2017-02-19 12:54:29 +00:00
2017-02-23 02:48:08 +00:00
if (typed == true) {
service =
new TypeBuilder('TypedService', genericTypes: [new TypeBuilder(name)])
.newInstance([service]);
}
2017-02-19 12:54:29 +00:00
2017-02-23 02:48:08 +00:00
closure.addStatement(reference('app')
.invoke('use', [literal('/api/${pluralize(lower)}'), service]));
if (generator.injectsSingleton == true) {
closure.addStatement(varField('service',
value: reference('app')
.invoke('service', [literal('/api/${pluralize(lower)}')]).castAs(
new TypeBuilder('HookedService'))));
closure.addStatement(reference('app')
.property('container')
.invoke('singleton', [reference('service').property('inner')]));
}
2017-02-19 12:54:29 +00:00
2017-02-23 02:48:08 +00:00
configureServer.addStatement(closure.asReturn());
2017-02-19 12:54:29 +00:00
2017-02-23 02:48:08 +00:00
lib.addMember(configureServer);
2016-09-14 04:33:28 +00:00
2017-02-23 02:48:08 +00:00
return prettyToSource(lib.buildAst());
2016-09-15 01:28:12 +00:00
}
2017-02-23 02:48:08 +00:00
_generateModel(String name, String lower) async {
2016-12-21 21:27:54 +00:00
var file = new File('lib/src/models/$lower.dart');
2016-12-21 17:34:15 +00:00
if (!await file.exists()) await file.createSync(recursive: true);
await file.writeAsString('''
2017-02-19 12:54:29 +00:00
import 'package:angel_framework/common.dart';
class $name extends Model {
2016-12-31 16:39:00 +00:00
String name;
String desc;
2016-12-21 17:34:15 +00:00
2017-02-23 02:48:08 +00:00
$name({String id, this.name, this.desc}) {
this.id = id;
2016-11-24 00:35:40 +00:00
}
2017-02-19 12:54:29 +00:00
}
'''
.trim());
}
2017-02-23 02:48:08 +00:00
_generateValidator(String lower, String constantCase) async {
var file = new File('lib/src/validators/$lower.dart');
2017-02-19 12:54:29 +00:00
if (!await file.exists()) await file.createSync(recursive: true);
await file.writeAsString('''
2016-12-31 16:39:00 +00:00
import 'package:angel_validate/angel_validate.dart';
2016-09-14 04:33:28 +00:00
2017-02-23 02:48:08 +00:00
final Validator CREATE_$constantCase =
new Validator({'name*': isString, 'desc*': isString});
2016-11-24 00:35:40 +00:00
'''
2017-02-23 02:48:08 +00:00
.trim());
2016-11-24 00:35:40 +00:00
}
2017-02-23 02:48:08 +00:00
_generateRunConfiguration(String name, String lower) {
2016-11-24 00:35:40 +00:00
return '''
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="$name Tests" type="DartTestRunConfigurationType" factoryName="Dart Test" singleton="true">
<option name="filePath" value="\$PROJECT_DIR\$/test/services/${lower}_test.dart" />
<method />
</configuration>
</component>
'''
.trim();
2016-09-14 04:33:28 +00:00
}
2016-09-15 05:19:06 +00:00
2017-02-23 02:48:08 +00:00
_generateTests(String lower, String type) {
2016-09-15 05:19:06 +00:00
return '''
import 'dart:io';
2016-12-10 18:52:14 +00:00
import 'package:angel/angel.dart';
2016-09-15 05:19:06 +00:00
import 'package:angel_framework/angel_framework.dart';
2016-12-10 18:52:14 +00:00
import 'package:angel_test/angel_test.dart';
2016-09-15 05:19:06 +00:00
import 'package:test/test.dart';
2016-12-10 18:52:14 +00:00
main() async {
Angel app;
TestClient client;
2016-09-15 05:19:06 +00:00
2016-12-10 18:52:14 +00:00
setUp(() async {
app = await createServer();
2016-12-31 16:39:00 +00:00
client = await connectTo(app);
2016-12-10 18:52:14 +00:00
});
2016-09-15 05:19:06 +00:00
2016-12-10 18:52:14 +00:00
tearDown(() async {
await client.close();
app = null;
});
2016-09-15 05:19:06 +00:00
2016-12-10 18:52:14 +00:00
test('index via REST', () async {
2017-02-23 02:48:08 +00:00
var response = await client.get('/api/${pluralize(lower)}');
2016-12-10 18:52:14 +00:00
expect(response, hasStatus(HttpStatus.OK));
});
2016-09-15 05:19:06 +00:00
2017-02-23 02:48:08 +00:00
test('Index ${pluralize(lower)}', () async {
var ${pluralize(lower)} = await client.service('api/${pluralize(lower)}').index();
print(${pluralize(lower)});
2016-12-10 18:52:14 +00:00
});
}
2016-09-15 05:19:06 +00:00
2016-12-21 17:34:15 +00:00
'''
.trim();
2016-09-15 05:19:06 +00:00
}
2016-11-24 00:35:40 +00:00
}