This commit is contained in:
thosakwe 2017-08-07 21:45:37 -04:00
parent c351f0ed14
commit 7d2696f1f6
24 changed files with 760 additions and 31 deletions

View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

14
CHANGELOG.md Normal file
View file

@ -0,0 +1,14 @@
# 1.1.5
Deprecated several commands, in favor of the `make`
command:
* `controller`
* `plugin`
* `service`
* `test`
The `rename` command will now replace *all* occurrences
of the old project names with the new one in `config/`
YAML files, and also operates on the glob `config/**/*.yaml`.
Changed the call to run `angel start` to run `dart bin/server.dart` instead, after an
`init` command.

View file

@ -22,6 +22,7 @@ main(List<String> args) async {
..addCommand(new StartCommand()) ..addCommand(new StartCommand())
..addCommand(new RenameCommand()) ..addCommand(new RenameCommand())
..addCommand(new UpdateCommand()) ..addCommand(new UpdateCommand())
..addCommand(new MakeCommand())
..addCommand(new VersionCommand()); ..addCommand(new VersionCommand());
return await runner.run(args).then((_) {}).catchError((exc) { return await runner.run(args).then((_) {}).catchError((exc) {

View file

@ -4,6 +4,7 @@ export 'controller.dart';
export "doctor.dart"; export "doctor.dart";
export "key.dart"; export "key.dart";
export "init.dart"; export "init.dart";
export "make.dart";
export "plugin.dart"; export "plugin.dart";
export "rename.dart"; export "rename.dart";
export "service.dart"; export "service.dart";

View file

@ -4,6 +4,7 @@ import 'package:code_builder/code_builder.dart';
import "package:console/console.dart"; import "package:console/console.dart";
import 'package:pubspec/pubspec.dart'; import 'package:pubspec/pubspec.dart';
import 'package:recase/recase.dart'; import 'package:recase/recase.dart';
import 'deprecated.dart';
class ControllerCommand extends Command { class ControllerCommand extends Command {
final TextPen _pen = new TextPen(); final TextPen _pen = new TextPen();
@ -17,6 +18,8 @@ class ControllerCommand extends Command {
@override @override
run() async { run() async {
warnDeprecated(this.name, _pen);
final name = await readInput("Name of Controller: "), final name = await readInput("Name of Controller: "),
recase = new ReCase(name), recase = new ReCase(name),
lower = recase.snakeCase; lower = recase.snakeCase;

View file

@ -0,0 +1,10 @@
import 'package:console/console.dart';
void warnDeprecated(String command, [TextPen pen]) {
pen ??= new TextPen();
pen
..yellow()
..call('The `$command` command is deprecated, and will be removed by v1.2.0.')
..call()
..reset();
}

View file

@ -60,7 +60,7 @@ class InitCommand extends Command {
..text('\nCongratulations! You are ready to start developing with Angel!') ..text('\nCongratulations! You are ready to start developing with Angel!')
..text('\nTo start the server (with file watching), run ') ..text('\nTo start the server (with file watching), run ')
..magenta() ..magenta()
..text('`angel start`') ..text('`dart bin/server.dart`')
..normal() ..normal()
..text(' in your terminal.') ..text(' in your terminal.')
..text('\n\nFind more documentation about Angel:') ..text('\n\nFind more documentation about Angel:')
@ -192,7 +192,8 @@ const BoilerplateInfo ormBoilerplate = const BoilerplateInfo(
const List<BoilerplateInfo> allBoilerplates = const [ const List<BoilerplateInfo> allBoilerplates = const [
fullApplicationBoilerplate, fullApplicationBoilerplate,
lightBoilerplate lightBoilerplate,
ormBoilerplate
]; ];
class BoilerplateInfo { class BoilerplateInfo {

View file

@ -0,0 +1,22 @@
import 'package:args/command_runner.dart';
import 'make/controller.dart';
import 'make/model.dart';
import 'make/plugin.dart';
import 'make/service.dart';
import 'make/test.dart';
class MakeCommand extends Command {
@override
String get name => 'make';
@override
String get description => 'Generates common code for your project, such as projects and controllers.';
MakeCommand() {
addSubcommand(new ControllerCommand());
addSubcommand(new ModelCommand());
addSubcommand(new PluginCommand());
addSubcommand(new TestCommand());
addSubcommand(new ServiceCommand());
}
}

View file

@ -0,0 +1,105 @@
import 'dart:io';
import 'package:args/command_runner.dart';
import 'package:code_builder/dart/core.dart';
import 'package:code_builder/code_builder.dart';
import 'package:console/console.dart';
import 'package:pubspec/pubspec.dart';
import 'package:recase/recase.dart';
import 'maker.dart';
class ControllerCommand extends Command {
final TextPen _pen = new TextPen();
@override
String get name => 'controller';
@override
String get description => 'Generates a controller class.';
ControllerCommand() {
argParser
..addFlag('websocket',
abbr: 'w',
help:
'Generates a WebSocketController, instead of an HTTP controller.',
negatable: false)
..addOption('name',
abbr: 'n', help: 'Specifies a name for the model class.')
..addOption('output-dir',
help: 'Specifies a directory to create the controller class in.',
defaultsTo: 'lib/src/controllers');
}
@override
run() async {
var pubspec = await PubSpec.load(Directory.current);
String name;
if (argResults.wasParsed('name')) name = argResults['name'];
if (name?.isNotEmpty != true) {
var p = new Prompter('Name of Controller class: ');
name = await p.prompt(checker: (s) => s.isNotEmpty);
}
List<MakerDependency> deps = [
const MakerDependency('angel_framework', '^1.0.0')
];
var rc = new ReCase(name);
var controllerLib =
new LibraryBuilder('${pubspec.name}.src.controllers.${rc.snakeCase}');
if (argResults['websocket']) {
deps.add(const MakerDependency('angel_websocket', '^1.0.0'));
controllerLib.addDirective(
new ImportBuilder('package:angel_websocket/server.dart'));
} else
controllerLib.addDirective(
new ImportBuilder('package:angel_framework/angel_framework.dart'));
TypeBuilder parentType = new TypeBuilder(
argResults['websocket'] ? 'WebSocketController' : 'Controller');
ClassBuilder clazz =
new ClassBuilder('${rc.pascalCase}Controller', asExtends: parentType);
controllerLib.addMember(clazz);
if (argResults['websocket']) {
var meth = new MethodBuilder('hello', returnType: lib$core.$void);
meth.addAnnotation(new TypeBuilder('ExposeWs')
.constInstance([literal('get_${rc.snakeCase}')]));
meth.addPositional(
parameter('socket', [new TypeBuilder('WebSocketContext')]));
meth.addStatement(reference('socket').invoke('send', [
literal('got_${rc.snakeCase}'),
map({'message': literal('Hello, world!')})
]));
clazz.addMethod(meth);
} else {
clazz.addAnnotation(new TypeBuilder('Expose')
.constInstance([literal('/${rc.snakeCase}')]));
var meth = new MethodBuilder('hello',
returnType: lib$core.String, returns: literal('Hello, world!'));
meth.addAnnotation(
new TypeBuilder('Expose').constInstance([literal('/')]));
clazz.addMethod(meth);
}
var outputDir = new Directory.fromUri(
Directory.current.uri.resolve(argResults['output-dir']));
var controllerFile =
new File.fromUri(outputDir.uri.resolve('${rc.snakeCase}.dart'));
if (!await controllerFile.exists())
await controllerFile.create(recursive: true);
await controllerFile
.writeAsString(prettyToSource(controllerLib.buildAst()));
_pen
..green()
..call(
'${Icon.CHECKMARK} Created controller file "${controllerFile.absolute.path}".')
..call()
..reset();
if (deps.isNotEmpty) await depend(deps);
}
}

View file

@ -0,0 +1,58 @@
import 'dart:async';
import 'dart:io';
import 'package:pubspec/pubspec.dart';
import 'package:pub_semver/pub_semver.dart';
import '../pub.dart';
class MakerDependency {
final String name, version;
final bool dev;
const MakerDependency(this.name, this.version, {this.dev: false});
}
Future depend(Iterable<MakerDependency> deps) async {
var pubspec = await PubSpec.load(Directory.current);
Map<String, DependencyReference> newDeps = {}, newDevDeps = {};
for (var dep in deps) {
var isPresent = false;
if (dep.dev)
isPresent = pubspec.devDependencies.containsKey(dep.name);
else
isPresent = pubspec.dependencies.containsKey(dep.name);
if (!isPresent) {
print('Installing ${dep.name}@${dep.version}...');
if (dep.dev)
newDevDeps[dep.name] =
new HostedReference(new VersionConstraint.parse(dep.version));
else
newDeps[dep.name] =
new HostedReference(new VersionConstraint.parse(dep.version));
}
if (newDeps.isNotEmpty || newDevDeps.isNotEmpty) {
var newPubspec = pubspec.copy(
dependencies:
new Map<String, DependencyReference>.from(pubspec.dependencies)
..addAll(newDeps),
devDependencies:
new Map<String, DependencyReference>.from(pubspec.devDependencies)
..addAll(newDevDeps));
await newPubspec.save(Directory.current);
var pubPath = resolvePub();
print('Now running `$pubPath get`...');
var pubGet = await Process.start(pubPath, ['get']);
pubGet.stdout.listen(stdout.add);
pubGet.stderr.listen(stderr.add);
var code = await pubGet.exitCode;
if (code != 0) throw 'pub get terminated with exit code $code';
}
}
}

View file

@ -0,0 +1,161 @@
import 'dart:io';
import 'package:args/command_runner.dart';
import 'package:code_builder/dart/core.dart';
import 'package:code_builder/code_builder.dart';
import 'package:console/console.dart';
import 'package:inflection/inflection.dart';
import 'package:pubspec/pubspec.dart';
import 'package:recase/recase.dart';
import 'maker.dart';
class ModelCommand extends Command {
final TextPen _pen = new TextPen();
@override
String get name => 'model';
@override
String get description => 'Generates a model class.';
ModelCommand() {
argParser
..addFlag('migration',
abbr: 'm',
help: 'Generate an angel_orm migration file.',
negatable: false)
..addFlag('orm', help: 'Generate angel_orm code.', negatable: false)
..addFlag('serializable',
help: 'Generate angel_serialize annotations.', defaultsTo: true)
..addOption('name',
abbr: 'n', help: 'Specifies a name for the model class.')
..addOption('output-dir',
help: 'Specifies a directory to create the model class in.',
defaultsTo: 'lib/src/models')
..addOption('migration-dir',
help: 'Specifies a directory to create the migration class in.',
defaultsTo: 'tool/migrations');
}
@override
run() async {
var pubspec = await PubSpec.load(Directory.current);
String name;
if (argResults.wasParsed('name')) name = argResults['name'];
if (name?.isNotEmpty != true) {
var p = new Prompter('Name of Model class: ');
name = await p.prompt(checker: (s) => s.isNotEmpty);
}
List<MakerDependency> deps = [
const MakerDependency('angel_framework', '^1.0.0'),
const MakerDependency('angel_model', '^1.0.0'),
];
var rc = new ReCase(name);
var modelLib =
new LibraryBuilder('${pubspec.name}.src.models.${rc.snakeCase}');
modelLib.addDirective(
new ImportBuilder('package:angel_model/angel_model.dart'));
var needsSerialize = argResults['serializable'] || argResults['orm'];
if (needsSerialize) {
modelLib.addDirective(
new ImportBuilder('package:angel_serialize/angel_serialize.dart'));
deps.add(const MakerDependency('angel_serialize', '^1.0.0-alpha'));
}
if (argResults['orm']) {
modelLib
.addDirective(new ImportBuilder('package:angel_orm/angel_orm.dart'));
deps.add(const MakerDependency('angel_orm', '^1.0.0-alpha'));
}
var modelClazz = new ClassBuilder(
needsSerialize ? '_${rc.pascalCase}' : rc.pascalCase,
asExtends: new TypeBuilder('Model'));
modelLib.addMember(modelClazz);
if (needsSerialize) {
modelLib.addDirective(new PartBuilder('${rc.snakeCase}.g.dart'));
modelClazz.addAnnotation(reference('serializable'));
}
if (argResults['orm']) {
modelClazz.addAnnotation(reference('orm'));
}
// Save model file
var outputDir = new Directory.fromUri(
Directory.current.uri.resolve(argResults['output-dir']));
var modelFile =
new File.fromUri(outputDir.uri.resolve('${rc.snakeCase}.dart'));
if (!await modelFile.exists()) await modelFile.create(recursive: true);
await modelFile.writeAsString(prettyToSource(modelLib.buildAst()));
_pen
..green()
..call(
'${Icon.CHECKMARK} Created model file "${modelFile.absolute.path}".')
..call()
..reset();
if (argResults['migration']) {
deps.add(
const MakerDependency('angel_migration', '^1.0.0-alpha', dev: true));
var migrationLib = new LibraryBuilder()
..addDirective(
new ImportBuilder('package:angel_migration/angel_migration.dart'));
var migrationClazz = new ClassBuilder('${rc.pascalCase}Migration',
asExtends: new TypeBuilder('Migration'));
migrationLib.addMember(migrationClazz);
var tableName = pluralize(rc.snakeCase);
// up()
var up = new MethodBuilder('up', returnType: lib$core.$void);
migrationClazz.addMethod(up);
up.addAnnotation(lib$core.override);
up.addPositional(parameter('schema', [new TypeBuilder('Schema')]));
// (table) { ... }
var callback = new MethodBuilder.closure();
callback.addPositional(parameter('table'));
var cascade = reference('table').cascade((table) => [
table.invoke('serial', [literal('id')]).invoke('primaryKey', []),
table.invoke('date', [literal('created_at')]),
table.invoke('date', [literal('updated_at')])
]);
callback.addStatement(cascade);
up.addStatement(reference('schema').invoke('create', [callback]));
// down()
var down = new MethodBuilder('down', returnType: lib$core.$void);
migrationClazz.addMethod(down);
down.addAnnotation(lib$core.override);
down.addPositional(parameter('schema', [new TypeBuilder('Schema')]));
down.addStatement(
reference('schema').invoke('drop', [literal(tableName)]));
// Save migration file
var migrationDir = new Directory.fromUri(
Directory.current.uri.resolve(argResults['migration-dir']));
var migrationFile =
new File.fromUri(migrationDir.uri.resolve('${rc.snakeCase}.dart'));
if (!await migrationFile.exists())
await migrationFile.create(recursive: true);
await migrationFile
.writeAsString(prettyToSource(migrationLib.buildAst()));
_pen
..green()
..call(
'${Icon.CHECKMARK} Created migration file "${migrationFile.absolute.path}".')
..call()
..reset();
}
if (deps.isNotEmpty) await depend(deps);
}
}

View file

@ -0,0 +1,74 @@
import 'dart:io';
import 'package:args/command_runner.dart';
import "package:console/console.dart";
import 'package:dart_style/dart_style.dart';
import 'package:pubspec/pubspec.dart';
import 'package:recase/recase.dart';
import 'maker.dart';
class PluginCommand extends Command {
final TextPen _pen = new TextPen();
@override
String get name => "plugin";
@override
String get description => "Creates a new plug-in within the given project.";
PluginCommand() {
argParser
..addOption('name',
abbr: 'n', help: 'Specifies a name for the plug-in class.')
..addOption('output-dir',
help: 'Specifies a directory to create the plug-in class in.',
defaultsTo: 'lib/src/config/plugins');
}
@override
run() async {
var pubspec = await PubSpec.load(Directory.current);
String name;
if (argResults.wasParsed('name')) name = argResults['name'];
if (name?.isNotEmpty != true) {
var p = new Prompter('Name of Controller class: ');
name = await p.prompt(checker: (s) => s.isNotEmpty);
}
List<MakerDependency> deps = [
const MakerDependency('angel_framework', '^1.0.0')
];
var rc = new ReCase(name);
final pluginDir = new Directory.fromUri(
Directory.current.uri.resolve(argResults['output-dir']));
final pluginFile =
new File.fromUri(pluginDir.uri.resolve("${rc.snakeCase}.dart"));
if (!await pluginFile.exists()) await pluginFile.create(recursive: true);
await pluginFile.writeAsString(
new DartFormatter().format(_generatePlugin(pubspec, rc)));
if (deps.isNotEmpty) await depend(deps);
_pen.green();
_pen(
'${Icon.CHECKMARK} Successfully generated plug-in file "${pluginFile.absolute.path}".');
_pen();
}
String _generatePlugin(PubSpec pubspec, ReCase rc) {
return '''
library ${pubspec.name}.src.config.plugins.${rc.snakeCase};
import 'dart:async';
import 'package:angel_framework/angel_framework.dart';
class ${rc.pascalCase}Plugin extends AngelPlugin {
@override
Future call(Angel app) async {
// Work some magic...
}
}
''';
}
}

View file

@ -0,0 +1,126 @@
import 'dart:io';
import 'package:args/command_runner.dart';
import 'package:code_builder/code_builder.dart';
import 'package:console/console.dart';
import 'package:inflection/inflection.dart';
import 'package:pubspec/pubspec.dart';
import 'package:recase/recase.dart';
import '../service_generators/service_generators.dart';
import 'maker.dart';
class ServiceCommand extends Command {
final TextPen _pen = new TextPen();
@override
String get name => 'service';
@override
String get description => 'Generates an Angel service.';
ServiceCommand() {
argParser
..addFlag('typed',
abbr: 't',
help: 'Wrap the generated service in a `TypedService` instance.',
negatable: false)
..addOption('name',
abbr: 'n', help: 'Specifies a name for the service file.')
..addOption('output-dir',
help: 'Specifies a directory to create the service file.',
defaultsTo: 'lib/src/services');
}
@override
run() async {
var pubspec = await PubSpec.load(Directory.current);
String name;
if (argResults.wasParsed('name')) name = argResults['name'];
if (name?.isNotEmpty != true) {
var p = new Prompter('Name of Service: ');
name = await p.prompt(checker: (s) => s.isNotEmpty);
}
List<MakerDependency> deps = [
const MakerDependency('angel_framework', '^1.0.0')
];
var rc = new ReCase(name);
var serviceLib =
new LibraryBuilder('${pubspec.name}.src.services.${rc.snakeCase}');
ServiceGenerator generator;
var chooser = new Chooser<String>(
serviceGenerators.map<String>((g) => g.name).toList(),
message: 'What type of service would you like to create? ');
var type = await chooser.choose();
generator =
serviceGenerators.firstWhere((g) => g.name == type, orElse: () => null);
if (generator == null) {
_pen.red();
_pen('${Icon.BALLOT_X} \'$type\' services are not yet implemented. :(');
_pen();
throw 'Unrecognized service type: "$type".';
}
for (var dep in generator.dependencies) {
if (!deps.any((d) => d.name == dep.name)) deps.add(dep);
}
if (generator.goesFirst) {
generator.applyToLibrary(serviceLib, name, rc.snakeCase);
serviceLib.addMember(
new ImportBuilder('package:angel_framework/angel_framework.dart'));
} else {
serviceLib.addMember(
new ImportBuilder('package:angel_framework/angel_framework.dart'));
generator.applyToLibrary(serviceLib, name, rc.snakeCase);
}
if (argResults['typed']) {
serviceLib
..addMember(new ImportBuilder('../models/${rc.snakeCase}.dart'));
}
// configureServer() {}
var configureServer = new MethodBuilder('configureServer',
returnType: new TypeBuilder('AngelConfigurer'));
generator.applyToConfigureServer(configureServer, name, rc.snakeCase);
// return (Angel app) async {}
var closure = new MethodBuilder.closure(modifier: MethodModifier.asAsync)
..addPositional(parameter('app', [new TypeBuilder('Angel')]));
generator.beforeService(closure, name, rc.snakeCase);
// app.use('/api/todos', new MapService());
var service = generator.createInstance(closure, name, rc.snakeCase);
if (argResults['typed']) {
service = new TypeBuilder('TypedService',
genericTypes: [new TypeBuilder(rc.pascalCase)])
.newInstance([service]);
}
closure.addStatement(reference('app')
.invoke('use', [literal('/api/${pluralize(rc.snakeCase)}'), service]));
configureServer.addStatement(closure.asReturn());
serviceLib.addMember(configureServer);
final outputDir = new Directory.fromUri(
Directory.current.uri.resolve(argResults['output-dir']));
final serviceFile =
new File.fromUri(outputDir.uri.resolve("${rc.snakeCase}.dart"));
if (!await serviceFile.exists()) await serviceFile.create(recursive: true);
await serviceFile.writeAsString(prettyToSource(serviceLib.buildAst()));
_pen.green();
_pen(
'${Icon.CHECKMARK} Successfully generated service file "${serviceFile.absolute.path}".');
_pen();
if (deps.isNotEmpty) await depend(deps);
}
}

View file

@ -0,0 +1,115 @@
import 'dart:io';
import 'package:args/command_runner.dart';
import "package:console/console.dart";
import 'package:dart_style/dart_style.dart';
import 'package:pubspec/pubspec.dart';
import 'package:recase/recase.dart';
import 'maker.dart';
class TestCommand extends Command {
final TextPen _pen = new TextPen();
@override
String get name => "test";
@override
String get description => "Creates a new test within the given project.";
TestCommand() {
argParser
..addFlag('run-configuration',
help: 'Generate a run configuration for JetBrains IDE\'s.',
defaultsTo: true)
..addOption('name',
abbr: 'n', help: 'Specifies a name for the plug-in class.')
..addOption('output-dir',
help: 'Specifies a directory to create the plug-in class in.',
defaultsTo: 'test');
}
@override
run() async {
var pubspec = await PubSpec.load(Directory.current);
String name;
if (argResults.wasParsed('name')) name = argResults['name'];
if (name?.isNotEmpty != true) {
var p = new Prompter('Name of Test: ');
name = await p.prompt(checker: (s) => s.isNotEmpty);
}
List<MakerDependency> deps = [
const MakerDependency('angel_framework', '^1.0.0'),
const MakerDependency('angel_test', '^1.0.0', dev: true),
const MakerDependency('test', '^0.12.0', dev: true),
];
var rc = new ReCase(name);
final testDir = new Directory.fromUri(
Directory.current.uri.resolve(argResults['output-dir']));
final testFile =
new File.fromUri(testDir.uri.resolve("${rc.snakeCase}_test.dart"));
if (!await testFile.exists()) await testFile.create(recursive: true);
await testFile
.writeAsString(new DartFormatter().format(_generateTest(pubspec, rc)));
if (deps.isNotEmpty) await depend(deps);
_pen.green();
_pen(
'${Icon.CHECKMARK} Successfully generated test file "${testFile.absolute.path}".');
_pen();
if (argResults['run-configuration']) {
final runConfig = new File.fromUri(Directory.current.uri
.resolve('.idea/runConfigurations/${name}_Tests.xml'));
if (!await runConfig.exists()) await runConfig.create(recursive: true);
await runConfig.writeAsString(_generateRunConfiguration(name, rc));
_pen.reset();
_pen.green();
_pen(
'${Icon.CHECKMARK} Successfully generated run configuration "$name Tests" at "${runConfig.absolute.path}".');
_pen();
}
}
_generateRunConfiguration(String name, ReCase rc) {
return '''
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="$name Tests" type="DartTestRunConfigurationType" factoryName="Dart Test" singleton="true">
<option name="filePath" value="\$PROJECT_DIR\$/test/${rc.snakeCase}_test.dart" />
<method />
</configuration>
</component>
'''
.trim();
}
String _generateTest(PubSpec pubspec, ReCase rc) {
return '''
import 'dart:io';
import 'package:${pubspec.name}/${pubspec.name}.dart';
import 'package:angel_framework/angel_framework.dart';
import 'package:angel_test/angel_test.dart';
import 'package:test/test.dart';
main() async {
TestClient client;
setUp(() async {
var app = await createServer();
client = await connectTo(app);
});
tearDown(() => client.close());
test('${rc.snakeCase}', () async {
final response = await client.get('/${rc.snakeCase}');
expect(response, hasStatus(HttpStatus.OK));
});
}
''';
}
}

View file

@ -4,6 +4,7 @@ import "package:console/console.dart";
import 'package:dart_style/dart_style.dart'; import 'package:dart_style/dart_style.dart';
import 'package:pubspec/pubspec.dart'; import 'package:pubspec/pubspec.dart';
import 'package:recase/recase.dart'; import 'package:recase/recase.dart';
import 'deprecated.dart';
class PluginCommand extends Command { class PluginCommand extends Command {
final TextPen _pen = new TextPen(); final TextPen _pen = new TextPen();
@ -16,6 +17,8 @@ class PluginCommand extends Command {
@override @override
run() async { run() async {
warnDeprecated(this.name, _pen);
var pubspec = await PubSpec.load(Directory.current); var pubspec = await PubSpec.load(Directory.current);
final name = await readInput("Name of Plugin: "), final name = await readInput("Name of Plugin: "),
lower = new ReCase(name).snakeCase; lower = new ReCase(name).snakeCase;

View file

@ -3,6 +3,7 @@ import 'package:analyzer/analyzer.dart';
import 'package:args/command_runner.dart'; import 'package:args/command_runner.dart';
import 'package:console/console.dart'; import 'package:console/console.dart';
import 'package:dart_style/dart_style.dart'; import 'package:dart_style/dart_style.dart';
import 'package:glob/glob.dart';
import 'package:pubspec/pubspec.dart'; import 'package:pubspec/pubspec.dart';
import 'pub.dart'; import 'pub.dart';
@ -63,14 +64,15 @@ renamePubspec(Directory dir, String oldName, String newName) async {
renameDartFiles(Directory dir, String oldName, String newName) async { renameDartFiles(Directory dir, String oldName, String newName) async {
// Try to replace MongoDB URL // Try to replace MongoDB URL
var defaultYaml = new File.fromUri(dir.uri.resolve('config/default.yaml')); var configGlob = new Glob('config/**/*.yaml');
if (await defaultYaml.exists()) { await for (var yamlFile in configGlob.list(root: dir.absolute.path)) {
print('Changing MongoDB URL in file "${defaultYaml.absolute.path}"...'); if (yamlFile is File) {
var contents = await defaultYaml.readAsString(); print('Replacing occurrences of "$oldName" with "$newName" in file "${yamlFile.absolute.path}"...');
contents = contents.replaceAll('mongodb://localhost:27017/$oldName', var contents = await yamlFile.readAsString();
'mongodb://localhost:27017/$newName'); contents = contents.replaceAll(oldName, newName);
await defaultYaml.writeAsString(contents); await yamlFile.writeAsString(contents);
}
} }
var entry = new File.fromUri(dir.uri.resolve('lib/$oldName.dart')); var entry = new File.fromUri(dir.uri.resolve('lib/$oldName.dart'));

View file

@ -7,16 +7,9 @@ import 'package:inflection/inflection.dart';
import 'package:pubspec/pubspec.dart'; import 'package:pubspec/pubspec.dart';
import 'package:recase/recase.dart'; import 'package:recase/recase.dart';
import 'service_generators/service_generators.dart'; import 'service_generators/service_generators.dart';
import 'deprecated.dart';
import 'init.dart' show preBuild; import 'init.dart' show preBuild;
const List<ServiceGenerator> GENERATORS = const [
const MapServiceGenerator(),
const FileServiceGenerator(),
const MongoServiceGenerator(),
const RethinkServiceGenerator(),
const CustomServiceGenerator()
];
class ServiceCommand extends Command { class ServiceCommand extends Command {
final TextPen _pen = new TextPen(); final TextPen _pen = new TextPen();
@ -28,10 +21,12 @@ class ServiceCommand extends Command {
@override @override
run() async { run() async {
warnDeprecated(this.name, _pen);
var pubspec = await PubSpec.load(Directory.current); var pubspec = await PubSpec.load(Directory.current);
var name = await readInput('Name of Service (not plural): '); var name = await readInput('Name of Service (not plural): ');
var chooser = new Chooser<String>( var chooser = new Chooser<String>(
GENERATORS.map<String>((g) => g.name).toList(), serviceGenerators.map<String>((g) => g.name).toList(),
message: 'What type of service would you like to create? '); message: 'What type of service would you like to create? ');
var type = await chooser.choose(); var type = await chooser.choose();
@ -40,7 +35,7 @@ class ServiceCommand extends Command {
var typed = (await chooser.choose()) == 'Yes'; var typed = (await chooser.choose()) == 'Yes';
var generator = var generator =
GENERATORS.firstWhere((g) => g.name == type, orElse: () => null); serviceGenerators.firstWhere((g) => g.name == type, orElse: () => null);
if (generator == null) { if (generator == null) {
_pen.blue(); _pen.blue();

View file

@ -1,12 +1,17 @@
import 'generator.dart'; import 'generator.dart';
import 'package:code_builder/code_builder.dart'; import 'package:code_builder/code_builder.dart';
import 'package:inflection/inflection.dart'; import 'package:inflection/inflection.dart';
import '../make/maker.dart';
class FileServiceGenerator extends ServiceGenerator { class FileServiceGenerator extends ServiceGenerator {
const FileServiceGenerator() : super('Persistent JSON File'); const FileServiceGenerator() : super('Persistent JSON File');
@override @override
bool get createsModel => false; List<MakerDependency> get dependencies =>
const [const MakerDependency('angel_file_service', '^1.0.0')];
@override
bool get goesFirst => true;
@override @override
void applyToLibrary(LibraryBuilder library, String name, String lower) { void applyToLibrary(LibraryBuilder library, String name, String lower) {

View file

@ -1,16 +1,30 @@
import 'package:code_builder/code_builder.dart'; import 'package:code_builder/code_builder.dart';
import '../make/maker.dart';
class ServiceGenerator { class ServiceGenerator {
final String name; final String name;
const ServiceGenerator(this.name); const ServiceGenerator(this.name);
List<MakerDependency> get dependencies => [];
@deprecated
bool get createsModel => true; bool get createsModel => true;
@deprecated
bool get createsValidator => true; bool get createsValidator => true;
@deprecated
bool get exportedInServiceLibrary => true; bool get exportedInServiceLibrary => true;
@deprecated
bool get injectsSingleton => false; bool get injectsSingleton => false;
@deprecated
bool get shouldRunBuild => false; bool get shouldRunBuild => false;
bool get goesFirst => false;
void applyToLibrary(LibraryBuilder library, String name, String lower) {} void applyToLibrary(LibraryBuilder library, String name, String lower) {}
void beforeService(MethodBuilder methodBuilder, String name, String lower) {} void beforeService(MethodBuilder methodBuilder, String name, String lower) {}

View file

@ -1,10 +1,15 @@
import 'generator.dart'; import 'generator.dart';
import 'package:code_builder/code_builder.dart'; import 'package:code_builder/code_builder.dart';
import 'package:inflection/inflection.dart'; import 'package:inflection/inflection.dart';
import '../make/maker.dart';
class MongoServiceGenerator extends ServiceGenerator { class MongoServiceGenerator extends ServiceGenerator {
const MongoServiceGenerator() : super('MongoDB'); const MongoServiceGenerator() : super('MongoDB');
@override
List<MakerDependency> get dependencies =>
const [const MakerDependency('angel_mongo', '^1.0.0')];
@override @override
bool get createsModel => false; bool get createsModel => false;

View file

@ -1,10 +1,15 @@
import 'generator.dart'; import 'generator.dart';
import 'package:code_builder/code_builder.dart'; import 'package:code_builder/code_builder.dart';
import 'package:inflection/inflection.dart'; import 'package:inflection/inflection.dart';
import '../make/maker.dart';
class RethinkServiceGenerator extends ServiceGenerator { class RethinkServiceGenerator extends ServiceGenerator {
const RethinkServiceGenerator() : super('RethinkDB'); const RethinkServiceGenerator() : super('RethinkDB');
@override
List<MakerDependency> get dependencies =>
const [const MakerDependency('angel_rethink', '^1.0.0')];
@override @override
bool get createsModel => false; bool get createsModel => false;

View file

@ -1,6 +1,15 @@
export 'custom.dart'; import 'custom.dart';
export 'file_service.dart'; import 'file_service.dart';
import 'generator.dart';
import 'map.dart';
import 'mongo.dart';
import 'rethink.dart';
export 'generator.dart'; export 'generator.dart';
export 'map.dart';
export 'mongo.dart'; const List<ServiceGenerator> serviceGenerators = const [
export 'rethink.dart'; const MapServiceGenerator(),
const FileServiceGenerator(),
const MongoServiceGenerator(),
const RethinkServiceGenerator(),
const CustomServiceGenerator()
];

View file

@ -3,6 +3,7 @@ import 'dart:io';
import 'package:args/command_runner.dart'; import 'package:args/command_runner.dart';
import 'package:watcher/watcher.dart'; import 'package:watcher/watcher.dart';
import 'package:yaml/yaml.dart'; import 'package:yaml/yaml.dart';
import 'deprecated.dart';
import 'pub.dart'; import 'pub.dart';
Process server; Process server;
@ -34,6 +35,8 @@ class StartCommand extends Command {
@override @override
run() async { run() async {
warnDeprecated(this.name);
stderr stderr
..writeln( ..writeln(
'WARNING: `angel start` is now deprecated, in favor of `package:angel_hot`.') 'WARNING: `angel start` is now deprecated, in favor of `package:angel_hot`.')

View file

@ -4,6 +4,7 @@ import "package:console/console.dart";
import 'package:dart_style/dart_style.dart'; import 'package:dart_style/dart_style.dart';
import 'package:pubspec/pubspec.dart'; import 'package:pubspec/pubspec.dart';
import 'package:recase/recase.dart'; import 'package:recase/recase.dart';
import 'deprecated.dart';
class TestCommand extends Command { class TestCommand extends Command {
final TextPen _pen = new TextPen(); final TextPen _pen = new TextPen();
@ -16,6 +17,8 @@ class TestCommand extends Command {
@override @override
run() async { run() async {
warnDeprecated(this.name, _pen);
final name = await readInput("Name of Test: "), final name = await readInput("Name of Test: "),
lower = new ReCase(name).snakeCase; lower = new ReCase(name).snakeCase;
final testDir = new Directory("test/services"); final testDir = new Directory("test/services");