Migrated to NNBD

This commit is contained in:
thomashii 2021-06-12 12:10:34 +08:00
parent dcd001fc65
commit a71e02d7bd
24 changed files with 165 additions and 163 deletions

View file

@ -1,5 +1,7 @@
# 3.0.0 # 3.0.0-beta.1
* Migrated to work with Dart SDK 2.12.x Non NNBD * Migrated to work with Dart SDK 2.12.x Non NNBD
* Replaced `mustache4dart2` with `mustache_template`
* Replaced `inflection2` with `inflection3`
# 2.1.7+1 # 2.1.7+1
* Fix a bug where new directories were not being created in * Fix a bug where new directories were not being created in

View file

@ -2,7 +2,14 @@
![Screenshot of Terminal](screenshots/screenshot.png) ![Screenshot of Terminal](screenshots/screenshot.png)
Command-line tools for the Angel framework. [![version](https://img.shields.io/badge/pub-v3.0.-brightgreen)](https://pub.dartlang.org/angel3-cli)
[![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety)
[![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion)
[![License](https://img.shields.io/github/license/dukefirehawk/angel)](https://github.com/dukefirehawk/angel3-cli/blob/master/LICENSE)
Command-line tools for the Angel3 framework.
Includes functionality such as: Includes functionality such as:
* Project scaffolding * Project scaffolding
* Generating service models, plugins, tests and more * Generating service models, plugins, tests and more
@ -16,8 +23,7 @@ $ pub global activate angel3_cli
``` ```
* Install development version * Install development version
`dart pub global activate --source path ./packages/cli` `dart pub global activate --source git https://github.com/dukefirehawk/angel3-cli`
`dart pub global activate --source git https://github.com/dukefirehawk/angel/packages/cli`
And then, for information on each command: And then, for information on each command:

View file

@ -28,7 +28,7 @@ server {
root ${p.absolute(webPath)}; # Set to your static files directory root ${p.absolute(webPath)}; # Set to your static files directory
location / { location / {
try_files \$uri @proxy; # Try to serve static files; fallback to proxied Angel server try_files \$uri @proxy; # Try to serve static files; fallback to proxied Angel3 server
} }
location @proxy { location @proxy {
@ -39,10 +39,10 @@ server {
''' '''
.trim(); .trim();
if (!argResults.wasParsed('out')) { if (!argResults!.wasParsed('out')) {
print(nginxText); print(nginxText);
} else { } else {
var file = File(argResults['out'] as String); var file = File(argResults!['out'] as String);
await file.create(recursive: true); await file.create(recursive: true);
await file.writeAsString(nginxText); await file.writeAsString(nginxText);
print(green.wrap( print(green.wrap(

View file

@ -30,7 +30,7 @@ class SystemdCommand extends Command {
Future run() async { Future run() async {
var projectPath = p.absolute(p.current); var projectPath = p.absolute(p.current);
var pubspec = await loadPubspec(); var pubspec = await loadPubspec();
var user = argResults['user']; var user = argResults!['user'];
var systemdText = ''' var systemdText = '''
[Unit] [Unit]
Description=`${pubspec.name}` server Description=`${pubspec.name}` server
@ -47,14 +47,14 @@ WantedBy=multi-user.target
''' '''
.trim(); .trim();
if (!argResults.wasParsed('out') && !argResults.wasParsed('install')) { if (!argResults!.wasParsed('out') && !argResults!.wasParsed('install')) {
print(systemdText); print(systemdText);
} else if (argResults.wasParsed('install')) { } else if (argResults!.wasParsed('install')) {
var systemdPath = argResults.wasParsed('out') var systemdPath = argResults!.wasParsed('out')
? argResults['out'] as String ? (argResults!['out'] as String?)!
: p.join('etc', 'systemd', 'system'); : p.join('etc', 'systemd', 'system');
var serviceFilename = p.join(systemdPath, var serviceFilename = p.join(systemdPath,
p.setExtension(argResults['install'] as String, '.service')); p.setExtension(argResults!['install'] as String, '.service'));
var file = File(serviceFilename); var file = File(serviceFilename);
await file.create(recursive: true); await file.create(recursive: true);
await file.writeAsString(systemdText); await file.writeAsString(systemdText);
@ -76,7 +76,7 @@ WantedBy=multi-user.target
print(red.wrap('$ballot Failed to install service system-wide.')); print(red.wrap('$ballot Failed to install service system-wide.'));
} }
} else { } else {
var file = File(argResults['out'] as String); var file = File(argResults!['out'] as String);
await file.create(recursive: true); await file.create(recursive: true);
await file.writeAsString(systemdText); await file.writeAsString(systemdText);
print(green.wrap( print(green.wrap(

View file

@ -10,7 +10,7 @@ class DoctorCommand extends Command {
@override @override
String get description => String get description =>
'Ensures that the current system is capable of running Angel.'; 'Ensures that the current system is capable of running Angel3.';
@override @override
Future run() async { Future run() async {

View file

@ -19,7 +19,7 @@ class InitCommand extends Command {
@override @override
String get description => String get description =>
'Initializes a new Angel project in the current directory.'; 'Initializes a new Angel3 project in the current directory.';
InitCommand() { InitCommand() {
argParser argParser
@ -35,8 +35,8 @@ class InitCommand extends Command {
@override @override
void run() async { void run() async {
var projectDir = var projectDir =
Directory(argResults.rest.isEmpty ? '.' : argResults.rest[0]); Directory(argResults!.rest.isEmpty ? '.' : argResults!.rest[0]);
print('Creating new Angel project in ${projectDir.absolute.path}...'); print('Creating new Angel3 project in ${projectDir.absolute.path}...');
await _cloneRepo(projectDir); await _cloneRepo(projectDir);
// await preBuild(projectDir); // await preBuild(projectDir);
var secret = rs.randomAlphaNumeric(32); var secret = rs.randomAlphaNumeric(32);
@ -49,8 +49,8 @@ class InitCommand extends Command {
await _key.changeSecret( await _key.changeSecret(
File.fromUri(projectDir.uri.resolve('config/production.yaml')), secret); File.fromUri(projectDir.uri.resolve('config/production.yaml')), secret);
var name = argResults.wasParsed('project-name') var name = argResults!.wasParsed('project-name')
? argResults['project-name'] as String ? (argResults!['project-name'] as String?)!
: p.basenameWithoutExtension( : p.basenameWithoutExtension(
projectDir.absolute.uri.normalizePath().toFilePath()); projectDir.absolute.uri.normalizePath().toFilePath());
@ -59,26 +59,26 @@ class InitCommand extends Command {
await renamePubspec(projectDir, 'angel', name); await renamePubspec(projectDir, 'angel', name);
await renameDartFiles(projectDir, 'angel', name); await renameDartFiles(projectDir, 'angel', name);
if (argResults['pub-get'] != false && argResults['offline'] == false) { if (argResults!['pub-get'] != false && argResults!['offline'] == false) {
print('Now running pub get...'); print('Now running pub get...');
await _pubGet(projectDir); await _pubGet(projectDir);
} }
print(green.wrap('$checkmark Successfully initialized Angel project.')); print(green.wrap('$checkmark Successfully initialized Angel3 project.'));
stdout stdout
..writeln() ..writeln()
..writeln( ..writeln(
'Congratulations! You are ready to start developing with Angel!') 'Congratulations! You are ready to start developing with Angel3!')
..write('To start the server (with ') ..write('To start the server (with ')
..write(cyan.wrap('hot-reloading')) ..write(cyan.wrap('hot-reloading'))
..write('), run ') ..write('), run ')
..write(magenta.wrap('`dart --observe bin/dev.dart`')) ..write(magenta.wrap('`dart --observe bin/dev.dart`'))
..writeln(' in your terminal.') ..writeln(' in your terminal.')
..writeln() ..writeln()
..writeln('Find more documentation about Angel:') ..writeln('Find more documentation about Angel3:')
..writeln(' * https://angel-dart.github.io') ..writeln(' * https://angel3-docs.dukefirehaw.com')
..writeln(' * https://github.com/angel-dart/angel/wiki') ..writeln(' * https://github.com/dukefirehawk/angel/wiki')
..writeln( ..writeln(
' * https://www.youtube.com/playlist?list=PLl3P3tmiT-frEV50VdH_cIrA2YqIyHkkY') ' * https://www.youtube.com/playlist?list=PLl3P3tmiT-frEV50VdH_cIrA2YqIyHkkY')
..writeln(' * https://medium.com/the-angel-framework') ..writeln(' * https://medium.com/the-angel-framework')
@ -124,7 +124,7 @@ class InitCommand extends Command {
} }
Future _cloneRepo(Directory projectDir) async { Future _cloneRepo(Directory projectDir) async {
Directory boilerplateDir; late Directory boilerplateDir;
try { try {
if (await projectDir.exists()) { if (await projectDir.exists()) {
@ -144,11 +144,11 @@ class InitCommand extends Command {
// var boilerplate = basicBoilerplate; // var boilerplate = basicBoilerplate;
print('Choose a project type before continuing:'); print('Choose a project type before continuing:');
var boilerplate = prompts.choose( var boilerplate = prompts.choose(
'Choose a project type before continuing', boilerplates); 'Choose a project type before continuing', boilerplates)!;
// Ultimately, we want a clone of every boilerplate locally on the system. // Ultimately, we want a clone of every boilerplate locally on the system.
var boilerplateRootDir = Directory(p.join(angelDir.path, 'boilerplates')); var boilerplateRootDir = Directory(p.join(angelDir.path, 'boilerplates'));
var boilerplateBasename = p.basenameWithoutExtension(boilerplate.url); var boilerplateBasename = p.basenameWithoutExtension(boilerplate.url!);
if (boilerplate.ref != null) boilerplateBasename += '.${boilerplate.ref}'; if (boilerplate.ref != null) boilerplateBasename += '.${boilerplate.ref}';
boilerplateDir = boilerplateDir =
Directory(p.join(boilerplateRootDir.path, boilerplateBasename)); Directory(p.join(boilerplateRootDir.path, boilerplateBasename));
@ -158,7 +158,7 @@ class InitCommand extends Command {
// If there is no clone existing, clone it. // If there is no clone existing, clone it.
if (!await boilerplateDir.exists()) { if (!await boilerplateDir.exists()) {
if (argResults['offline'] as bool) { if (argResults!['offline'] as bool) {
throw Exception( throw Exception(
'--offline was selected, but the "${boilerplate.name}" boilerplate has not yet been downloaded.'); '--offline was selected, but the "${boilerplate.name}" boilerplate has not yet been downloaded.');
} }
@ -176,7 +176,7 @@ class InitCommand extends Command {
'clone', 'clone',
'--depth', '--depth',
'1', '1',
boilerplate.url, boilerplate.url!,
boilerplateDir.absolute.path boilerplateDir.absolute.path
], ],
mode: ProcessStartMode.inheritStdio, mode: ProcessStartMode.inheritStdio,
@ -193,8 +193,8 @@ class InitCommand extends Command {
'1', '1',
'--single-branch', '--single-branch',
'-b', '-b',
boilerplate.ref, boilerplate.ref!,
boilerplate.url, boilerplate.url!,
boilerplateDir.absolute.path boilerplateDir.absolute.path
], ],
mode: ProcessStartMode.inheritStdio, mode: ProcessStartMode.inheritStdio,
@ -207,7 +207,7 @@ class InitCommand extends Command {
} }
// Otherwise, pull from git. // Otherwise, pull from git.
else if (!(argResults['offline'] as bool)) { else if (!(argResults!['offline'] as bool)) {
print(darkGray.wrap('\$ git pull origin $branch')); print(darkGray.wrap('\$ git pull origin $branch'));
var git = await Process.start('git', ['pull', 'origin', '$branch'], var git = await Process.start('git', ['pull', 'origin', '$branch'],
mode: ProcessStartMode.inheritStdio, mode: ProcessStartMode.inheritStdio,
@ -234,7 +234,7 @@ class InitCommand extends Command {
await boilerplateDir.delete(recursive: true).catchError((_) => null); await boilerplateDir.delete(recursive: true).catchError((_) => null);
if (e is! String) { if (e is! String) {
print(red.wrap('$ballot Could not initialize Angel project.')); print(red.wrap('$ballot Could not initialize Angel3 project.'));
} }
rethrow; rethrow;
} }
@ -267,35 +267,27 @@ Future preBuild(Directory projectDir) async {
if (buildCode != 0) throw Exception('Failed to pre-build resources.'); if (buildCode != 0) throw Exception('Failed to pre-build resources.');
} }
const RepoArchiveLocation = 'https://github.com/angel-dart';
const RepoLocation = 'https://github.com/dukefirehawk'; const RepoLocation = 'https://github.com/dukefirehawk';
const BoilerplateInfo graphQLBoilerplate = BoilerplateInfo( const BoilerplateInfo graphQLBoilerplate = BoilerplateInfo(
'GraphQL', 'GraphQL',
'A starting point for GraphQL API servers.', 'A starting point for GraphQL API servers.',
'$RepoLocation/boilerplates.git', '$RepoLocation/boilerplates.git',
ref: 'graphql-sdk-2.12.x', ref: 'angel3-graphql',
); );
const BoilerplateInfo ormBoilerplate = BoilerplateInfo( const BoilerplateInfo ormBoilerplate = BoilerplateInfo(
'ORM', 'ORM',
"A starting point for applications that use Angel's ORM.", "A starting point for applications that use Angel3's ORM.",
'$RepoLocation/boilerplates.git', '$RepoLocation/boilerplates.git',
ref: 'orm-sdk-2.12.x', ref: 'angel3-orm',
); );
const BoilerplateInfo basicBoilerplate = BoilerplateInfo( const BoilerplateInfo basicBoilerplate = BoilerplateInfo(
'Basic', 'Basic',
'Minimal starting point for Angel 2.x - A simple server with only a few additional packages.', 'Minimal starting point for Angel3 - A simple server with only a few additional packages.',
'$RepoLocation/boilerplates.git', '$RepoLocation/boilerplates.git',
ref: 'basic-sdk-2.12.x'); ref: 'angel3-basic');
const BoilerplateInfo legacyBoilerplate = BoilerplateInfo(
'Legacy',
'Minimal starting point for applications running Angel 1.1.x.',
'$RepoArchiveLocation/angel.git',
ref: '1.1.x',
);
const BoilerplateInfo sharedBoilerplate = BoilerplateInfo( const BoilerplateInfo sharedBoilerplate = BoilerplateInfo(
'Shared', 'Shared',
@ -311,7 +303,6 @@ const BoilerplateInfo sharedOrmBoilerplate = BoilerplateInfo(
const List<BoilerplateInfo> boilerplates = [ const List<BoilerplateInfo> boilerplates = [
basicBoilerplate, basicBoilerplate,
//legacyBoilerplate,
ormBoilerplate, ormBoilerplate,
graphQLBoilerplate, graphQLBoilerplate,
//sharedBoilerplate, //sharedBoilerplate,
@ -319,7 +310,7 @@ const List<BoilerplateInfo> boilerplates = [
]; ];
class BoilerplateInfo { class BoilerplateInfo {
final String name, description, url, ref; final String? name, description, url, ref;
final bool needsPrebuild; final bool needsPrebuild;
const BoilerplateInfo(this.name, this.description, this.url, const BoilerplateInfo(this.name, this.description, this.url,

View file

@ -3,7 +3,8 @@ import 'dart:io';
import 'package:args/command_runner.dart'; import 'package:args/command_runner.dart';
import 'package:glob/glob.dart'; import 'package:glob/glob.dart';
import 'package:io/ansi.dart'; import 'package:io/ansi.dart';
import 'package:mustache4dart2/mustache4dart2.dart' as mustache; //import 'package:mustache4dart2/mustache4dart2.dart' as mustache;
import 'package:mustache_template/mustache_template.dart' as mustache;
import 'package:path/path.dart' as p; import 'package:path/path.dart' as p;
import 'package:prompts/prompts.dart' as prompts; import 'package:prompts/prompts.dart' as prompts;
import 'package:pubspec_parse/pubspec_parse.dart'; import 'package:pubspec_parse/pubspec_parse.dart';
@ -53,34 +54,34 @@ class InstallCommand extends Command {
'See here: https://github.com/angel-dart/install.git\n\n' 'See here: https://github.com/angel-dart/install.git\n\n'
'To stop seeing this, downgrade to `package:angel_cli@<=2.0.0`.')); 'To stop seeing this, downgrade to `package:angel_cli@<=2.0.0`.'));
if (argResults['wipe'] as bool) { if (argResults!['wipe'] as bool) {
if (await installRepo.exists()) await installRepo.delete(recursive: true); if (await installRepo.exists()) await installRepo.delete(recursive: true);
} else if (argResults['list'] as bool) { } else if (argResults!['list'] as bool) {
var addons = await list(); var addons = await list();
print('${addons.length} add-on(s) installed:'); print('${addons.length} add-on(s) installed:');
for (var addon in addons) { for (var addon in addons) {
print(' * ${addon.name}@${addon.version}: ${addon.description}'); print(' * ${addon.name}@${addon.version}: ${addon.description}');
} }
} else if (argResults['update'] as bool) { } else if (argResults!['update'] as bool) {
await update(); await update();
} else if (argResults.rest.isNotEmpty) { } else if (argResults!.rest.isNotEmpty) {
if (!await installRepo.exists()) { if (!await installRepo.exists()) {
throw 'No local add-on database exists. Run `angel install --update` first.'; throw 'No local add-on database exists. Run `angel3 install --update` first.';
} }
var pubspec = await loadPubspec(); var pubspec = await loadPubspec();
for (var packageName in argResults.rest) { for (var packageName in argResults!.rest) {
var packageDir = var packageDir =
Directory.fromUri(installRepo.uri.resolve(packageName)); Directory.fromUri(installRepo.uri.resolve(packageName));
if (!await packageDir.exists()) { if (!await packageDir.exists()) {
throw 'No add-on named "$packageName" is installed. You might need to run `angel install --update`.'; throw 'No add-on named "$packageName" is installed. You might need to run `angel3 install --update`.';
} }
print('Installing $packageName...'); print('Installing $packageName...');
Map values = { var values = {
'project_name': pubspec.name, 'project_name': pubspec.name,
'pubspec': pubspec, 'pubspec': pubspec,
}; };
@ -129,11 +130,11 @@ class InstallCommand extends Command {
var desc = val[key]['description'] ?? key; var desc = val[key]['description'] ?? key;
if (val[key]['type'] == 'prompt') { if (val[key]['type'] == 'prompt') {
values[key] = prompts.get(desc.toString(), values[key as String] = prompts.get(desc.toString(),
defaultsTo: val[key]['default']?.toString()); defaultsTo: val[key]['default']?.toString());
} else if (val[key]['type'] == 'choice') { } else if (val[key]['type'] == 'choice') {
values[key] = prompts.choose( values[key as String] = prompts.choose(desc.toString(),
desc.toString(), val[key]['choices'] as Iterable); (val[key]['choices'] as Iterable) as Iterable<Object>)!;
} }
} }
} }
@ -171,8 +172,10 @@ class InstallCommand extends Command {
print( print(
'Rendering Mustache template from ${entity.absolute.path} to ${targetFile.absolute.path}...'); 'Rendering Mustache template from ${entity.absolute.path} to ${targetFile.absolute.path}...');
var contents = await entity.readAsString(); var contents = await entity.readAsString();
var renderer = mustache.compile(contents); //var renderer = mustache.compile(contents);
var generated = renderer(values); //var generated = renderer(values);
var template = mustache.Template(contents);
var generated = template.renderString(values);
await targetFile.writeAsString(generated.toString()); await targetFile.writeAsString(generated.toString());
} else { } else {
print( print(
@ -201,7 +204,7 @@ class InstallCommand extends Command {
Future<List<Pubspec>> list() async { Future<List<Pubspec>> list() async {
if (!await installRepo.exists()) { if (!await installRepo.exists()) {
throw 'No local add-on database exists. Run `angel install --update` first.'; throw 'No local add-on database exists. Run `angel3 install --update` first.';
} else { } else {
var repos = <Pubspec>[]; var repos = <Pubspec>[];

View file

@ -7,7 +7,7 @@ class KeyCommand extends Command {
String get name => 'key'; String get name => 'key';
@override @override
String get description => 'Generates a new `angel_auth` key.'; String get description => 'Generates a new `angel3_auth` key.';
@override @override
Future run() async { Future run() async {

View file

@ -31,8 +31,8 @@ class ControllerCommand extends Command {
@override @override
Future run() async { Future run() async {
String name; String? name;
if (argResults.wasParsed('name')) name = argResults['name'] as String; if (argResults!.wasParsed('name')) name = argResults!['name'] as String?;
if (name?.isNotEmpty != true) { if (name?.isNotEmpty != true) {
name = prompts.get('Name of controller class'); name = prompts.get('Name of controller class');
@ -44,9 +44,9 @@ class ControllerCommand extends Command {
//${pubspec.name}.src.models.${rc.snakeCase} //${pubspec.name}.src.models.${rc.snakeCase}
var rc = ReCase(name); var rc = ReCase(name!);
var controllerLib = Library((controllerLib) { var controllerLib = Library((controllerLib) {
if (argResults['websocket'] as bool) { if (argResults!['websocket'] as bool) {
deps.add(const MakerDependency('angel_websocket', '^2.0.0')); deps.add(const MakerDependency('angel_websocket', '^2.0.0'));
controllerLib.directives controllerLib.directives
.add(Directive.import('package:angel_websocket/server.dart')); .add(Directive.import('package:angel_websocket/server.dart'));
@ -58,11 +58,11 @@ class ControllerCommand extends Command {
controllerLib.body.add(Class((clazz) { controllerLib.body.add(Class((clazz) {
clazz clazz
..name = '${rc.pascalCase}Controller' ..name = '${rc.pascalCase}Controller'
..extend = refer(argResults['websocket'] as bool ..extend = refer(argResults!['websocket'] as bool
? 'WebSocketController' ? 'WebSocketController'
: 'Controller'); : 'Controller');
if (argResults['websocket'] as bool) { if (argResults!['websocket'] as bool) {
// XController(AngelWebSocket ws) : super(ws); // XController(AngelWebSocket ws) : super(ws);
clazz.constructors.add(Constructor((b) { clazz.constructors.add(Constructor((b) {
b b
@ -106,7 +106,7 @@ class ControllerCommand extends Command {
}); });
var outputDir = Directory.fromUri( var outputDir = Directory.fromUri(
Directory.current.uri.resolve(argResults['output-dir'] as String)); Directory.current.uri.resolve(argResults!['output-dir'] as String));
var controllerFile = var controllerFile =
File.fromUri(outputDir.uri.resolve('${rc.snakeCase}.dart')); File.fromUri(outputDir.uri.resolve('${rc.snakeCase}.dart'));
if (!await controllerFile.exists()) { if (!await controllerFile.exists()) {

View file

@ -12,13 +12,13 @@ class MakerDependency implements Comparable<MakerDependency> {
int compareTo(MakerDependency other) => name.compareTo(other.name); int compareTo(MakerDependency other) => name.compareTo(other.name);
} }
Future depend(Iterable<MakerDependency> deps) async { Future depend(Iterable<MakerDependency?> deps) async {
var pubspec = await loadPubspec(); var pubspec = await loadPubspec();
var missing = <MakerDependency>[]; var missing = <MakerDependency?>[];
for (var dep in deps) { for (var dep in deps) {
var isPresent = false; var isPresent = false;
if (dep.dev) { if (dep!.dev) {
isPresent = pubspec.devDependencies.containsKey(dep.name); isPresent = pubspec.devDependencies.containsKey(dep.name);
} else { } else {
isPresent = pubspec.dependencies.containsKey(dep.name); isPresent = pubspec.dependencies.containsKey(dep.name);
@ -41,8 +41,8 @@ Future depend(Iterable<MakerDependency> deps) async {
} }
} }
var missingDeps = missing.where((d) => !d.dev).toList()..sort(); var missingDeps = missing.where((d) => !d!.dev).toList()..sort();
var missingDevDeps = missing.where((d) => d.dev).toList()..sort(); var missingDevDeps = missing.where((d) => d!.dev).toList()..sort();
var totalCount = missingDeps.length + missingDevDeps.length; var totalCount = missingDeps.length + missingDevDeps.length;
if (totalCount > 0) { if (totalCount > 0) {
@ -52,11 +52,11 @@ Future depend(Iterable<MakerDependency> deps) async {
print(yellow.wrap( print(yellow.wrap(
'Update your `pubspec.yaml` to add the following dependencies:\n')); 'Update your `pubspec.yaml` to add the following dependencies:\n'));
void printMissing(String type, Iterable<MakerDependency> deps) { void printMissing(String type, Iterable<MakerDependency?> deps) {
if (deps.isNotEmpty) { if (deps.isNotEmpty) {
print(yellow.wrap(' $type:')); print(yellow.wrap(' $type:'));
for (var dep in deps) { for (var dep in deps) {
print(yellow.wrap(' ${dep.name}: ${dep.version}')); print(yellow.wrap(' ${dep!.name}: ${dep.version}'));
} }
} }
} }

View file

@ -28,15 +28,15 @@ class MigrationCommand extends Command {
@override @override
FutureOr run() async { FutureOr run() async {
String name; String? name;
if (argResults.wasParsed('name')) name = argResults['name'] as String; if (argResults!.wasParsed('name')) name = argResults!['name'] as String?;
if (name?.isNotEmpty != true) { if (name?.isNotEmpty != true) {
name = prompts.get('Name of model class'); name = prompts.get('Name of model class');
} }
var deps = [const MakerDependency('angel_migration', '^2.0.0')]; var deps = [const MakerDependency('angel_migration', '^2.0.0')];
var rc = new ReCase(name); var rc = new ReCase(name!);
var migrationLib = new Library((migrationLib) { var migrationLib = new Library((migrationLib) {
migrationLib migrationLib
@ -116,7 +116,7 @@ class MigrationCommand extends Command {
// Save migration file // Save migration file
var migrationDir = new Directory.fromUri( var migrationDir = new Directory.fromUri(
Directory.current.uri.resolve(argResults['output-dir'] as String)); Directory.current.uri.resolve(argResults!['output-dir'] as String));
var migrationFile = var migrationFile =
new File.fromUri(migrationDir.uri.resolve('${rc.snakeCase}.dart')); new File.fromUri(migrationDir.uri.resolve('${rc.snakeCase}.dart'));
if (!await migrationFile.exists()) if (!await migrationFile.exists())

View file

@ -33,8 +33,8 @@ class ModelCommand extends Command {
@override @override
Future run() async { Future run() async {
String name; String? name;
if (argResults.wasParsed('name')) name = argResults['name'] as String; if (argResults!.wasParsed('name')) name = argResults!['name'] as String?;
if (name?.isNotEmpty != true) { if (name?.isNotEmpty != true) {
name = prompts.get('Name of model class'); name = prompts.get('Name of model class');
@ -44,17 +44,17 @@ class ModelCommand extends Command {
const MakerDependency('angel_model', '^1.0.0'), const MakerDependency('angel_model', '^1.0.0'),
]; ];
var rc = ReCase(name); var rc = ReCase(name!);
var modelLib = Library((modelLib) { var modelLib = Library((modelLib) {
if (argResults['orm'] as bool && argResults['migration'] as bool) { if (argResults!['orm'] as bool && argResults!['migration'] as bool) {
modelLib.directives.addAll([ modelLib.directives.addAll([
Directive.import('package:angel_migration/angel_migration.dart'), Directive.import('package:angel_migration/angel_migration.dart'),
]); ]);
} }
var needsSerialize = var needsSerialize =
argResults['serializable'] as bool || argResults['orm'] as bool; argResults!['serializable'] as bool || argResults!['orm'] as bool;
// argResults['migration'] as bool; // argResults['migration'] as bool;
if (needsSerialize) { if (needsSerialize) {
@ -71,7 +71,7 @@ class ModelCommand extends Command {
// deps.add(const MakerDependency('angel_model', '^1.0.0')); // deps.add(const MakerDependency('angel_model', '^1.0.0'));
// } // }
if (argResults['orm'] as bool) { if (argResults!['orm'] as bool) {
modelLib.directives.addAll([ modelLib.directives.addAll([
Directive.import('package:angel_orm/angel_orm.dart'), Directive.import('package:angel_orm/angel_orm.dart'),
]); ]);
@ -93,8 +93,8 @@ class ModelCommand extends Command {
modelClazz.annotations.add(refer('serializable')); modelClazz.annotations.add(refer('serializable'));
} }
if (argResults['orm'] as bool) { if (argResults!['orm'] as bool) {
if (argResults['migration'] as bool) { if (argResults!['migration'] as bool) {
modelClazz.annotations.add(refer('orm')); modelClazz.annotations.add(refer('orm'));
} else { } else {
modelClazz.annotations.add( modelClazz.annotations.add(
@ -106,7 +106,7 @@ class ModelCommand extends Command {
// Save model file // Save model file
var outputDir = Directory.fromUri( var outputDir = Directory.fromUri(
Directory.current.uri.resolve(argResults['output-dir'] as String)); Directory.current.uri.resolve(argResults!['output-dir'] as String));
var modelFile = File.fromUri(outputDir.uri.resolve('${rc.snakeCase}.dart')); var modelFile = File.fromUri(outputDir.uri.resolve('${rc.snakeCase}.dart'));
if (!await modelFile.exists()) await modelFile.create(recursive: true); if (!await modelFile.exists()) await modelFile.create(recursive: true);

View file

@ -27,8 +27,8 @@ class PluginCommand extends Command {
@override @override
Future run() async { Future run() async {
var pubspec = await loadPubspec(); var pubspec = await loadPubspec();
String name; String? name;
if (argResults.wasParsed('name')) name = argResults['name'] as String; if (argResults!.wasParsed('name')) name = argResults!['name'] as String?;
if (name?.isNotEmpty != true) { if (name?.isNotEmpty != true) {
name = prompts.get('Name of plug-in class'); name = prompts.get('Name of plug-in class');
@ -38,9 +38,9 @@ class PluginCommand extends Command {
const MakerDependency('angel_framework', '^2.0.0') const MakerDependency('angel_framework', '^2.0.0')
]; ];
var rc = ReCase(name); var rc = ReCase(name!);
final pluginDir = Directory.fromUri( final pluginDir = Directory.fromUri(
Directory.current.uri.resolve(argResults['output-dir'] as String)); Directory.current.uri.resolve(argResults!['output-dir'] as String));
final pluginFile = final pluginFile =
File.fromUri(pluginDir.uri.resolve('${rc.snakeCase}.dart')); File.fromUri(pluginDir.uri.resolve('${rc.snakeCase}.dart'));
if (!await pluginFile.exists()) await pluginFile.create(recursive: true); if (!await pluginFile.exists()) await pluginFile.create(recursive: true);

View file

@ -33,8 +33,8 @@ class ServiceCommand extends Command {
@override @override
run() async { run() async {
var pubspec = await loadPubspec(); var pubspec = await loadPubspec();
String name; String? name;
if (argResults.wasParsed('name')) name = argResults['name'] as String; if (argResults!.wasParsed('name')) name = argResults!['name'] as String?;
if (name?.isNotEmpty != true) { if (name?.isNotEmpty != true) {
name = prompts.get('Name of service'); name = prompts.get('Name of service');
@ -45,10 +45,10 @@ class ServiceCommand extends Command {
]; ];
// '${pubspec.name}.src.services.${rc.snakeCase}' // '${pubspec.name}.src.services.${rc.snakeCase}'
var rc = ReCase(name); var rc = ReCase(name!);
var serviceLib = Library((serviceLib) { var serviceLib = Library((serviceLib) {
var generator = prompts.choose( var generator = prompts.choose(
'Choose which type of service to create', serviceGenerators); 'Choose which type of service to create', serviceGenerators)!;
// if (generator == null) { // if (generator == null) {
// _pen.red(); // _pen.red();
@ -71,7 +71,7 @@ class ServiceCommand extends Command {
generator.applyToLibrary(serviceLib, name, rc.snakeCase); generator.applyToLibrary(serviceLib, name, rc.snakeCase);
} }
if (argResults['typed'] as bool) { if (argResults!['typed'] as bool) {
serviceLib.directives serviceLib.directives
.add(Directive.import('../models/${rc.snakeCase}.dart')); .add(Directive.import('../models/${rc.snakeCase}.dart'));
} }
@ -100,7 +100,7 @@ class ServiceCommand extends Command {
var service = generator.createInstance( var service = generator.createInstance(
serviceLib, closure, name, rc.snakeCase); serviceLib, closure, name, rc.snakeCase);
if (argResults['typed'] as bool) { if (argResults!['typed'] as bool) {
var tb = TypeReference((b) => b var tb = TypeReference((b) => b
..symbol = 'TypedService' ..symbol = 'TypedService'
..types.add(refer(rc.pascalCase))); ..types.add(refer(rc.pascalCase)));
@ -120,7 +120,7 @@ class ServiceCommand extends Command {
}); });
final outputDir = Directory.fromUri( final outputDir = Directory.fromUri(
Directory.current.uri.resolve(argResults['output-dir'] as String)); Directory.current.uri.resolve(argResults!['output-dir'] as String));
final serviceFile = final serviceFile =
File.fromUri(outputDir.uri.resolve("${rc.snakeCase}.dart")); File.fromUri(outputDir.uri.resolve("${rc.snakeCase}.dart"));
if (!await serviceFile.exists()) await serviceFile.create(recursive: true); if (!await serviceFile.exists()) await serviceFile.create(recursive: true);

View file

@ -30,8 +30,8 @@ class TestCommand extends Command {
@override @override
Future run() async { Future run() async {
var pubspec = await loadPubspec(); var pubspec = await loadPubspec();
String name; String? name;
if (argResults.wasParsed('name')) name = argResults['name'] as String; if (argResults!.wasParsed('name')) name = argResults!['name'] as String?;
if (name?.isNotEmpty != true) { if (name?.isNotEmpty != true) {
name = prompter.get('Name of test'); name = prompter.get('Name of test');
@ -43,9 +43,9 @@ class TestCommand extends Command {
const MakerDependency('test', '^1.0.0', dev: true), const MakerDependency('test', '^1.0.0', dev: true),
]; ];
var rc = ReCase(name); var rc = ReCase(name!);
final testDir = Directory.fromUri( final testDir = Directory.fromUri(
Directory.current.uri.resolve(argResults['output-dir'] as String)); Directory.current.uri.resolve(argResults!['output-dir'] as String));
final testFile = final testFile =
File.fromUri(testDir.uri.resolve('${rc.snakeCase}_test.dart')); File.fromUri(testDir.uri.resolve('${rc.snakeCase}_test.dart'));
if (!await testFile.exists()) await testFile.create(recursive: true); if (!await testFile.exists()) await testFile.create(recursive: true);
@ -57,7 +57,7 @@ class TestCommand extends Command {
print(green.wrap( print(green.wrap(
'$checkmark Successfully generated test file "${testFile.absolute.path}".')); '$checkmark Successfully generated test file "${testFile.absolute.path}".'));
if (argResults['run-configuration'] as bool) { if (argResults!['run-configuration'] as bool) {
final runConfig = File.fromUri(Directory.current.uri final runConfig = File.fromUri(Directory.current.uri
.resolve('.idea/runConfigurations/${name}_Tests.xml')); .resolve('.idea/runConfigurations/${name}_Tests.xml'));
@ -69,7 +69,7 @@ class TestCommand extends Command {
} }
} }
String _generateRunConfiguration(String name, ReCase rc) { String _generateRunConfiguration(String? name, ReCase rc) {
return ''' return '''
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="$name Tests" type="DartTestRunConfigurationType" factoryName="Dart Test" singleton="true"> <configuration default="false" name="$name Tests" type="DartTestRunConfigurationType" factoryName="Dart Test" singleton="true">

View file

@ -23,8 +23,8 @@ class RenameCommand extends Command {
Future run() async { Future run() async {
String newName; String newName;
if (argResults.rest.isNotEmpty) { if (argResults!.rest.isNotEmpty) {
newName = argResults.rest.first; newName = argResults!.rest.first;
} else { } else {
newName = prompts.get('Rename project to'); newName = prompts.get('Rename project to');
} }
@ -126,9 +126,9 @@ Future renameDartFiles(Directory dir, String oldName, String newName) async {
visitor.replace.forEach((range, replacement) { visitor.replace.forEach((range, replacement) {
if (range.first is int) { if (range.first is int) {
contents = contents.replaceRange( contents = contents.replaceRange(
range.first as int, range.last as int, replacement); range.first as int, range.last as int?, replacement!);
} else if (range.first is String) { } else if (range.first is String) {
contents = contents.replaceAll(range.first as String, replacement); contents = contents.replaceAll(range.first as String, replacement!);
} }
}); });
@ -141,16 +141,16 @@ Future renameDartFiles(Directory dir, String oldName, String newName) async {
class RenamingVisitor extends RecursiveAstVisitor { class RenamingVisitor extends RecursiveAstVisitor {
final String oldName, newName; final String oldName, newName;
final Map<List, String> replace = {}; final Map<List, String?> replace = {};
RenamingVisitor(this.oldName, this.newName) { RenamingVisitor(this.oldName, this.newName) {
replace[['{{$oldName}}']] = newName; replace[['{{$oldName}}']] = newName;
} }
String updateUri(String uri) { String? updateUri(String? uri) {
if (uri == 'package:$oldName/$oldName.dart') { if (uri == 'package:$oldName/$oldName.dart') {
return 'package:$newName/$newName.dart'; return 'package:$newName/$newName.dart';
} else if (uri.startsWith('package:$oldName/')) { } else if (uri!.startsWith('package:$oldName/')) {
return 'package:$newName/' + uri.replaceFirst('package:$oldName/', ''); return 'package:$newName/' + uri.replaceFirst('package:$oldName/', '');
} else { } else {
return uri; return uri;
@ -182,7 +182,7 @@ class RenamingVisitor extends RecursiveAstVisitor {
@override @override
void visitPartOfDirective(PartOfDirective ctx) { void visitPartOfDirective(PartOfDirective ctx) {
if (ctx.libraryName != null) { if (ctx.libraryName != null) {
var name = ctx.libraryName.name; var name = ctx.libraryName!.name;
if (name.startsWith(oldName)) { if (name.startsWith(oldName)) {
replace[[ctx.offset, ctx.end]] = replace[[ctx.offset, ctx.end]] =

View file

@ -11,7 +11,7 @@ class CustomServiceGenerator extends ServiceGenerator {
const CustomServiceGenerator() : super('Custom'); const CustomServiceGenerator() : super('Custom');
@override @override
void applyToLibrary(LibraryBuilder library, String name, String lower) { void applyToLibrary(LibraryBuilder library, String? name, String lower) {
library.body.add(Class((clazz) { library.body.add(Class((clazz) {
clazz clazz
..name = '${name}Service' ..name = '${name}Service'
@ -21,7 +21,7 @@ class CustomServiceGenerator extends ServiceGenerator {
@override @override
Expression createInstance(LibraryBuilder library, MethodBuilder methodBuilder, Expression createInstance(LibraryBuilder library, MethodBuilder methodBuilder,
String name, String lower) { String? name, String lower) {
return refer('${name}Service').newInstance([]); return refer('${name}Service').newInstance([]);
} }
} }

View file

@ -8,7 +8,7 @@ class FileServiceGenerator extends ServiceGenerator {
@override @override
List<MakerDependency> get dependencies => List<MakerDependency> get dependencies =>
const [MakerDependency('angel_file_service', '^2.0.0')]; const [MakerDependency('angel3_file_service', '^4.0.0')];
@override @override
bool get goesFirst => true; bool get goesFirst => true;
@ -18,26 +18,25 @@ class FileServiceGenerator extends ServiceGenerator {
LibraryBuilder library, LibraryBuilder library,
MethodBuilder configureServer, MethodBuilder configureServer,
BlockBuilder block, BlockBuilder block,
String name, String? name,
String lower) { String lower) {
configureServer.requiredParameters.add(new Parameter((b) => b configureServer.requiredParameters.add(Parameter((b) => b
..name = 'dbDirectory' ..name = 'dbDirectory'
..type = refer('Directory'))); ..type = refer('Directory')));
} }
@override @override
void applyToLibrary(LibraryBuilder library, String name, String lower) { void applyToLibrary(LibraryBuilder library, String? name, String lower) {
library.directives.addAll([ library.directives.addAll([
new Directive.import( Directive.import('package:angel3_file_service/angel3_file_service.dart'),
'package:angel_file_service/angel_file_service.dart'),
]); ]);
} }
@override @override
Expression createInstance(LibraryBuilder library, MethodBuilder methodBuilder, Expression createInstance(LibraryBuilder library, MethodBuilder methodBuilder,
String name, String lower) { String? name, String lower) {
library.directives.addAll([ library.directives.addAll([
new Directive.import('package:file/file.dart'), Directive.import('package:file/file.dart'),
]); ]);
return refer('JsonFileService').newInstance([ return refer('JsonFileService').newInstance([
refer('dbDirectory') refer('dbDirectory')

View file

@ -25,20 +25,20 @@ class ServiceGenerator {
bool get goesFirst => false; bool get goesFirst => false;
void applyToLibrary(LibraryBuilder library, String name, String lower) {} void applyToLibrary(LibraryBuilder library, String? name, String lower) {}
void beforeService(LibraryBuilder library, BlockBuilder builder, String name, void beforeService(LibraryBuilder library, BlockBuilder builder, String? name,
String lower) {} String lower) {}
void applyToConfigureServer( void applyToConfigureServer(
LibraryBuilder library, LibraryBuilder library,
MethodBuilder configureServer, MethodBuilder configureServer,
BlockBuilder block, BlockBuilder block,
String name, String? name,
String lower) {} String lower) {}
Expression createInstance(LibraryBuilder library, MethodBuilder methodBuilder, Expression createInstance(LibraryBuilder library, MethodBuilder methodBuilder,
String name, String lower) => String? name, String lower) =>
literal(null); literal(null);
@override @override

View file

@ -9,7 +9,7 @@ class MapServiceGenerator extends ServiceGenerator {
@override @override
Expression createInstance(LibraryBuilder library, MethodBuilder methodBuilder, Expression createInstance(LibraryBuilder library, MethodBuilder methodBuilder,
String name, String lower) { String? name, String lower) {
return refer('MapService').newInstance([]); return refer('MapService').newInstance([]);
} }
} }

View file

@ -8,7 +8,7 @@ class MongoServiceGenerator extends ServiceGenerator {
@override @override
List<MakerDependency> get dependencies => List<MakerDependency> get dependencies =>
const [MakerDependency('angel_mongo', '^2.0.0')]; const [MakerDependency('angel3_mongo', '^4.0.0')];
@override @override
bool get createsModel => false; bool get createsModel => false;
@ -18,7 +18,7 @@ class MongoServiceGenerator extends ServiceGenerator {
LibraryBuilder library, LibraryBuilder library,
MethodBuilder configureServer, MethodBuilder configureServer,
BlockBuilder block, BlockBuilder block,
String name, String? name,
String lower) { String lower) {
configureServer.requiredParameters.add(Parameter((b) => b configureServer.requiredParameters.add(Parameter((b) => b
..name = 'db' ..name = 'db'
@ -26,16 +26,16 @@ class MongoServiceGenerator extends ServiceGenerator {
} }
@override @override
void applyToLibrary(LibraryBuilder library, String name, String lower) { void applyToLibrary(LibraryBuilder library, String? name, String lower) {
library.directives.addAll([ library.directives.addAll([
Directive.import('package:angel_mongo/angel_mongo.dart'), Directive.import('package:angel3_mongo/angel3_mongo.dart'),
Directive.import('package:mongo_dart/mongo_dart.dart'), Directive.import('package:mongo_dart/mongo_dart.dart'),
]); ]);
} }
@override @override
Expression createInstance(LibraryBuilder library, MethodBuilder methodBuilder, Expression createInstance(LibraryBuilder library, MethodBuilder methodBuilder,
String name, String lower) { String? name, String lower) {
return refer('MongoService').newInstance([ return refer('MongoService').newInstance([
refer('db').property('collection').call([literal(pluralize(lower))]) refer('db').property('collection').call([literal(pluralize(lower))])
]); ]);

View file

@ -8,7 +8,7 @@ class RethinkServiceGenerator extends ServiceGenerator {
@override @override
List<MakerDependency> get dependencies => List<MakerDependency> get dependencies =>
const [MakerDependency('angel_rethink', '^2.0.0')]; const [MakerDependency('angel3_rethink', '^4.0.0')];
@override @override
bool get createsModel => false; bool get createsModel => false;
@ -18,7 +18,7 @@ class RethinkServiceGenerator extends ServiceGenerator {
LibraryBuilder library, LibraryBuilder library,
MethodBuilder configureServer, MethodBuilder configureServer,
BlockBuilder block, BlockBuilder block,
String name, String? name,
String lower) { String lower) {
configureServer.requiredParameters.addAll([ configureServer.requiredParameters.addAll([
Parameter((b) => b Parameter((b) => b
@ -31,16 +31,16 @@ class RethinkServiceGenerator extends ServiceGenerator {
} }
@override @override
void applyToLibrary(LibraryBuilder library, String name, String lower) { void applyToLibrary(LibraryBuilder library, String? name, String lower) {
library.directives.addAll([ library.directives.addAll([
'package:angel_rethink/angel_rethink.dart', 'package:angel3_rethink/angel3_rethink.dart',
'package:rethinkdb_dart/rethinkdb_dart.dart' 'package:rethinkdb_dart/rethinkdb_dart.dart'
].map((str) => Directive.import(str))); ].map((str) => Directive.import(str)));
} }
@override @override
Expression createInstance(LibraryBuilder library, MethodBuilder methodBuilder, Expression createInstance(LibraryBuilder library, MethodBuilder methodBuilder,
String name, String lower) { String? name, String lower) {
return refer('RethinkService').newInstance([ return refer('RethinkService').newInstance([
refer('connection'), refer('connection'),
refer('r').property('table').call([literal(pluralize(lower))]) refer('r').property('table').call([literal(pluralize(lower))])

View file

@ -9,14 +9,14 @@ final String checkmark = ansiOutputEnabled ? '\u2714' : '[Success]';
final String ballot = ansiOutputEnabled ? '\u2717' : '[Failure]'; final String ballot = ansiOutputEnabled ? '\u2717' : '[Failure]';
String get homeDirPath => String? get homeDirPath =>
Platform.environment['HOME'] ?? Platform.environment['USERPROFILE']; Platform.environment['HOME'] ?? Platform.environment['USERPROFILE'];
Directory get homeDir => Directory(homeDirPath); Directory get homeDir => Directory(homeDirPath!);
Directory get angelDir => Directory(p.join(homeDir.path, '.angel')); Directory get angelDir => Directory(p.join(homeDir.path, '.angel'));
Future<Pubspec> loadPubspec([Directory directory]) { Future<Pubspec> loadPubspec([Directory? directory]) {
directory ??= Directory.current; directory ??= Directory.current;
var file = File.fromUri(directory.uri.resolve('pubspec.yaml')); var file = File.fromUri(directory.uri.resolve('pubspec.yaml'));
return file return file

View file

@ -1,27 +1,28 @@
name: angel3_cli name: angel3_cli
version: 3.0.0 version: 3.0.0-beta.1
description: Command-line tools for the Angel framework, including scaffolding. description: Command-line tools for the Angel framework, including scaffolding.
homepage: https://github.com/dukefirehawk/angel3_cli homepage: https://github.com/dukefirehawk/angel3_cli
environment: environment:
sdk: ">=2.10.0 <3.0.0" sdk: '>=2.12.0 <3.0.0'
dependencies: dependencies:
analyzer: ^1.1.0 analyzer: ^1.7.0
args: ^2.0.0 args: ^2.1.1
code_builder: ^3.0.0 code_builder: ^4.0.0
dart_style: ^1.0.0 dart_style: ^2.0.1
glob: ^2.0.0 glob: ^2.0.1
http: ^0.13.0 http: ^0.13.3
io: ^0.3.5 io: ^1.0.0
inflection3: ^0.5.0 inflection3: ^0.5.3+2
mustache4dart2: ^0.1.0 #mustache4dart2: ^0.1.0
path: ^1.0.0 mustache_template: ^2.0.0
prompts: ^1.3.1 path: ^1.8.0
prompts: ^2.0.0
pubspec_parse: ^1.0.0 pubspec_parse: ^1.0.0
quiver: ^3.0.0 quiver: ^3.0.1
recase: ^3.0.1 recase: ^4.0.0
shutdown: ^0.4.0 shutdown: ^0.4.3
watcher: ^1.0.0 watcher: ^1.0.0
yaml: ^3.0.0 yaml: ^3.1.0
dev_dependencies: dev_dependencies:
pedantic: ^1.11.0 pedantic: ^1.11.0
executables: executables: