Compare commits

..

No commits in common. "master" and "sdk-2.10.x" have entirely different histories.

54 changed files with 642 additions and 969 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

29
.gitignore vendored
View file

@ -3,17 +3,38 @@
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff:
.idea/workspace.xml
.idea/tasks.xml
.idea/dictionaries
.idea/vcs.xml
.idea/jsLibraryMappings.xml
# Sensitive or high-churn files:
.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: ## File-based project format:
*.iws *.iws
.DS_Store
## Plugin-specific files: ## Plugin-specific files:
# IntelliJ # IntelliJ
/out/ /out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin # JIRA plugin
atlassian-ide-plugin.xml atlassian-ide-plugin.xml
@ -56,8 +77,4 @@ pubspec.lock
/sample_project/ /sample_project/
sample_project/ sample_project/
sample-project sample-project
.dart_tool .dart_tool
.metals
#.vscode
#!.vscode/settings.json

19
.idea/angel_cli.iml Normal file
View file

@ -0,0 +1,19 @@
<?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$/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/.pub" />
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/build" />
<excludeFolder url="file://$MODULE_DIR$/sample_project/.pub" />
<excludeFolder url="file://$MODULE_DIR$/sample_project/build" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</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>

8
.idea/modules.xml Normal file
View 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/angel_cli.iml" filepath="$PROJECT_DIR$/.idea/angel_cli.iml" />
</modules>
</component>
</project>

View file

@ -0,0 +1,8 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Controller" type="DartCommandLineRunConfigurationType" factoryName="Dart Command Line Application" singleton="true">
<option name="arguments" value="controller" />
<option name="filePath" value="$PROJECT_DIR$/bin/angel.dart" />
<option name="workingDirectory" value="$PROJECT_DIR$/sample_project" />
<method />
</configuration>
</component>

View file

@ -0,0 +1,7 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Doctor" type="DartCommandLineRunConfigurationType" factoryName="Dart Command Line Application" singleton="true">
<option name="arguments" value="doctor" />
<option name="filePath" value="$PROJECT_DIR$/bin/angel.dart" />
<method />
</configuration>
</component>

View file

@ -0,0 +1,8 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Init" type="DartCommandLineRunConfigurationType" factoryName="Dart Command Line Application" singleton="true">
<option name="arguments" value="init sample_project" />
<option name="filePath" value="$PROJECT_DIR$/bin/angel.dart" />
<option name="workingDirectory" value="$PROJECT_DIR$" />
<method />
</configuration>
</component>

View file

@ -0,0 +1,7 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Show Help" type="DartCommandLineRunConfigurationType" factoryName="Dart Command Line Application" singleton="true">
<option name="arguments" value="--help" />
<option name="filePath" value="$PROJECT_DIR$/bin/angel.dart" />
<method />
</configuration>
</component>

View file

@ -0,0 +1,8 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Update" type="DartCommandLineRunConfigurationType" factoryName="Dart Command Line Application" singleton="true">
<option name="arguments" value="update" />
<option name="filePath" value="$PROJECT_DIR$/bin/angel.dart" />
<option name="workingDirectory" value="$PROJECT_DIR$" />
<method />
</configuration>
</component>

View file

@ -0,0 +1,7 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Version" type="DartCommandLineRunConfigurationType" factoryName="Dart Command Line Application" singleton="true">
<option name="arguments" value="version" />
<option name="filePath" value="$PROJECT_DIR$/bin/angel.dart" />
<method />
</configuration>
</component>

View file

@ -1,3 +0,0 @@
# Pub Ignore
.vscode

1
.travis.yml Normal file
View file

@ -0,0 +1 @@
language: dart

View file

@ -1,6 +0,0 @@
{
"files.watcherExclude": {
"**/target": true
},
"cmake.configureOnOpen": false
}

View file

@ -1,12 +0,0 @@
Primary Authors
===============
* __[Thomas Hii](dukefirehawk.apps@gmail.com)__
Thomas is the current maintainer of the code base. He has refactored and migrated the
code base to support NNBD.
* __[Tobe O](thosakwe@gmail.com)__
Tobe has written much of the original code prior to NNBD migration. He has moved on and
is no longer involved with the project.

View file

@ -1,88 +1,8 @@
# Change Log # 2.1.7+1
## 8.2.0
* Updated to `analyzer` 6.3.x
* Updated repository link
* Updated `lints` to 3.0.0
## 8.1.1
* Updated README
* Updated to logo
## 8.1.0
* Updated README
* Updated to logo
* Updated to `analyzer` 6.2.x
* Updated to support Dart SDK 3.1.x
## 8.0.0
* Required Dart SDK > 3.0.x
* Updated to `analyzer` 5.0.x
## 7.0.0
* Skipped release
## 6.0.0
* Updated Dart SDK to 2.16.x
## 5.0.0
* Skipped release
## 4.0.0
* Changed `pub` to `dart pub`
* Changed `pub build` to `dart build`
* Updated Dart SDK to 2.14.0
## 3.2.0
* Upgraded from `pedantic` to `lints` linter
## 3.1.1
* Fixed NNBD issues
## 3.1.0
* Upgraded to support `analyzer` 2.0.0
## 3.0.1
* Updated help to use `angel3`
* Updated to use `angel3` packages
* Updated screenshot
## 3.0.0
* Fixed NNBD issues
* Updated to use `angel3` packages
* Fixed incorrect import for new project
* Updated screenshot
## 3.0.0-beta.2
* Updated README
## 3.0.0-beta.1
* Migrated to work with Dart SDK 2.12.x Non NNBD
* Replaced `mustache4dart2` with `mustache_template`
* Replaced `inflection2` with `inflection3`
## 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
`init`. `init`.
## 2.1.7 # 2.1.7
* Fix a bug where `ArgResults.arguments` was used in `init` instead of the * Fix a bug where `ArgResults.arguments` was used in `init` instead of the
intended `ArgResults.rest`. intended `ArgResults.rest`.
* Stop including `package:angel_model` imports in `make model`. * Stop including `package:angel_model` imports in `make model`.
@ -90,45 +10,36 @@ intended `ArgResults.rest`.
* Fix `make model` to generate ORM + migration by default. * Fix `make model` to generate ORM + migration by default.
* Fix `MakerDependency` logic to print missing dependencies. * Fix `MakerDependency` logic to print missing dependencies.
## 2.1.6 # 2.1.6
* Fix a bug where models always defaulted to ORM. * Fix a bug where models always defaulted to ORM.
* Add GraphQL boilerplate. * Add GraphQL boilerplate.
* Automatically restore terminal colors on shutdown. * Automatically restore terminal colors on shutdown.
## 2.1.5+1 # 2.1.5+1
* Update to `inflection2`. * Update to `inflection2`.
## 2.1.5 # 2.1.5
* Add `shared` boilerplates. * Add `shared` boilerplates.
* Remove uncecessary `angel_model` imports. * Remove uncecessary `angel_model` imports.
## 2.1.4+1 # 2.1.4+1
* Patch `part of 'path'` renames. * Patch `part of 'path'` renames.
## 2.1.4 # 2.1.4
* The `migration` argument to `model` just emits an annotation now. * The `migration` argument to `model` just emits an annotation now.
* Add the ORM boilerplate. * Add the ORM boilerplate.
## 2.1.3 # 2.1.3
* Fix generation of ORM models. * Fix generation of ORM models.
* A `--project-name` to `init` command. * A `--project-name` to `init` command.
## 2.1.2 # 2.1.2
* No migrations-by-default. * No migrations-by-default.
## 2.1.1 # 2.1.1
* Edit the way `rename` runs, leaving no corner unturned. * Edit the way `rename` runs, leaving no corner unturned.
## 2.1.0 # 2.1.0
* Deprecate `angel install`. * Deprecate `angel install`.
* Rename projects using `snake_case`. * Rename projects using `snake_case`.
* `init` now fetches from `master`. * `init` now fetches from `master`.
@ -137,43 +48,34 @@ intended `ArgResults.rest`.
* Replace `{{oldName}}` in the `rename` command. * Replace `{{oldName}}` in the `rename` command.
* `pub get` now runs with `inheritStdio`. * `pub get` now runs with `inheritStdio`.
## 2.0.1 # 2.0.1
* `deploy systemd` now has an `--install` option, where you can immediately * `deploy systemd` now has an `--install` option, where you can immediately
spawn the service. spawn the service.
## 2.0.0 # 2.0.0
* `init` can now produce either 1.x or 2.x projects. * `init` can now produce either 1.x or 2.x projects.
* Fixed deps for compatibility with Dart2 stable. * Fixed deps for compatibility with Dart2 stable.
## 1.3.4 # 1.3.4
* Fix another typo. * Fix another typo.
## 1.3.3 # 1.3.3
* Fix a small typo in the model generator. * Fix a small typo in the model generator.
## 1.3.2 # 1.3.2
* Restore `part` directives in generated models. * Restore `part` directives in generated models.
## 1.3.1 # 1.3.1
* Add `deploy nginx` and `deploy systemd`. * Add `deploy nginx` and `deploy systemd`.
## 1.3.0 # 1.3.0
* Focus on Dart2 from here on out. * Focus on Dart2 from here on out.
* Update `code_builder`. * Update `code_builder`.
* More changes... * More changes...
## 1.1.5 # 1.1.5
Deprecated several commands, in favor of the `make` Deprecated several commands, in favor of the `make`
command: command:
* `controller` * `controller`
* `plugin` * `plugin`
* `service` * `service`

42
LICENSE
View file

@ -1,29 +1,21 @@
BSD 3-Clause License MIT License
Copyright (c) 2021, dukefirehawk.com Copyright (c) [year] [fullname]
All rights reserved.
Redistribution and use in source and binary forms, with or without Permission is hereby granted, free of charge, to any person obtaining a copy
modification, are permitted provided that the following conditions are met: of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
1. Redistributions of source code must retain the above copyright notice, this The above copyright notice and this permission notice shall be included in all
list of conditions and the following disclaimer. copies or substantial portions of the Software.
2. Redistributions in binary form must reproduce the above copyright notice, THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
this list of conditions and the following disclaimer in the documentation IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
and/or other materials provided with the distribution. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
3. Neither the name of the copyright holder nor the names of its LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
contributors may be used to endorse or promote products derived from OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
this software without specific prior written permission. SOFTWARE.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -1,31 +1,26 @@
# Angel3 CLI # angel_cli
[![Angel3 Logo](angel3_logo.png)](https://github.com/dart-backend/angel3-cli) ![Screenshot of Terminal](screenshots/screenshot.png)
![Pub Version (including pre-releases)](https://img.shields.io/pub/v/angel3_cli?include_prereleases)
[![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/dart-backend/angel3-cli)](https://github.com/dart-backend/angel3-cli/blob/master/LICENSE)
The command line interface for buidling dart backend in [Angel3 framework](https://pub.dev/packages/angel3_framework) that provides the following functionalities:
Command-line tools for the Angel framework.
Includes functionality such as:
* Project scaffolding * Project scaffolding
* Generating service models, plugins, tests and more * Generating service models, plugins, tests and more
* Renaming projects * Renaming projects
* Much more... * Much more...
## Installation * To install:
```bash ```bash
dart pub global activate angel3_cli $ pub global activate angel_cli
``` ```
## Help * Install development version
`dart pub global activate --source path ./packages/cli`
`dart pub global activate --source git https://github.com/dukefirehawk/angel/packages/cli`
For information on the available options: And then, for information on each command:
```bash ```bash
angel3 help $ angel help
``` ```
[![Screenshot of Terminal](screenshots/angel3-screenshot.png)](https://github.com/dart-backend/angel3-cli)

7
TODO.md Normal file
View file

@ -0,0 +1,7 @@
# Todo
* `service`
* Add tests
* `migration`
* `deploy`
* Call these from Grinder script :)

View file

@ -1 +1,3 @@
include: package:lints/recommended.yaml analyzer:
strong-mode:
implicit-casts: false

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

View file

@ -1,135 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="128"
height="128"
viewBox="0 0 128 128"
version="1.1"
id="svg1"
inkscape:version="1.3 (0e150ed, 2023-07-21)"
sodipodi:docname="logo128.svg"
inkscape:export-filename="logo_icon_128.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="px"
showgrid="true"
inkscape:zoom="1.5862247"
inkscape:cx="58.629776"
inkscape:cy="90.466375"
inkscape:window-width="1312"
inkscape:window-height="738"
inkscape:window-x="128"
inkscape:window-y="111"
inkscape:window-maximized="0"
inkscape:current-layer="layer1">
<inkscape:grid
id="grid1"
units="px"
originx="0"
originy="0"
spacingx="1"
spacingy="1"
empcolor="#0099e5"
empopacity="0.30196078"
color="#0099e5"
opacity="0.14901961"
empspacing="5"
dotted="false"
gridanglex="30"
gridanglez="30"
visible="true" />
</sodipodi:namedview>
<defs
id="defs1">
<linearGradient
id="linearGradient15"
inkscape:collect="always">
<stop
style="stop-color:#d81c1c;stop-opacity:1;"
offset="0"
id="stop15" />
<stop
style="stop-color:#d81c1c;stop-opacity:0;"
offset="1"
id="stop16" />
</linearGradient>
<linearGradient
id="swatch13"
inkscape:swatch="solid">
<stop
style="stop-color:#d81c1c;stop-opacity:1;"
offset="0"
id="stop14" />
</linearGradient>
<linearGradient
id="swatch7"
inkscape:swatch="solid">
<stop
style="stop-color:#d81c1c;stop-opacity:1;"
offset="0"
id="stop7" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#swatch13"
id="linearGradient14"
x1="76.307388"
y1="264.40897"
x2="425.84061"
y2="264.40897"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient15"
id="linearGradient16"
x1="185.07693"
y1="354.51111"
x2="296.18161"
y2="354.51111"
gradientUnits="userSpaceOnUse" />
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:137.557px;font-family:'Comic Sans MS';-inkscape-font-specification:'Comic Sans MS, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;opacity:1;fill:#d81c1c;fill-opacity:1;stroke-width:0.716443"
x="13.382875"
y="114.63321"
id="text1"
transform="scale(1.0161156,0.98414)"><tspan
sodipodi:role="line"
id="tspan1"
x="13.382875"
y="114.63321"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:137.557px;font-family:'Comic Sans MS';-inkscape-font-specification:'Comic Sans MS, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#d81c1c;fill-opacity:1;stroke-width:0.716443">A</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:54.9757px;font-family:'Comic Sans MS';-inkscape-font-specification:'Comic Sans MS, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;opacity:1;fill:#d81c1c;fill-opacity:1;stroke:#ffffff;stroke-width:0.725;stroke-dasharray:none;stroke-opacity:1"
x="44.028919"
y="108.3848"
id="text2"
transform="scale(1.1577238,0.86376387)"><tspan
sodipodi:role="line"
id="tspan2"
x="44.028919"
y="108.3848"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:54.9757px;font-family:'Comic Sans MS';-inkscape-font-specification:'Comic Sans MS, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#d81c1c;fill-opacity:1;stroke:#ffffff;stroke-width:0.725;stroke-dasharray:none;stroke-opacity:1">3</tspan></text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

55
bin/angel.dart Normal file
View file

@ -0,0 +1,55 @@
#!/usr/bin/env dart
library angel_cli.tool;
import "dart:io";
import "package:args/command_runner.dart";
import 'package:angel_cli/angel_cli.dart';
import 'package:io/ansi.dart';
final String DOCTOR = "doctor";
main(List<String> args) async {
var runner = new CommandRunner(
"angel",
asciiArt.trim() +
'\n\n' +
"Command-line tools for the Angel framework." +
'\n\n' +
'https://angel-dart.github.io');
runner.argParser
.addFlag('verbose', help: 'Print verbose output.', negatable: false);
runner
..addCommand(new DeployCommand())
..addCommand(new DoctorCommand())
..addCommand(new KeyCommand())
..addCommand(new InitCommand())
..addCommand(new InstallCommand())
..addCommand(new RenameCommand())
..addCommand(new MakeCommand());
return await runner.run(args).catchError((exc, st) {
if (exc is String) {
stdout.writeln(exc);
} else {
stderr.writeln("Oops, something went wrong: $exc");
if (args.contains('--verbose')) {
stderr.writeln(st);
}
}
exitCode = 1;
}).whenComplete(() {
stdout.write(resetAll.wrap(''));
});
}
const String asciiArt = '''
____________ ________________________
___ |__ | / /_ ____/__ ____/__ /
__ /| |_ |/ /_ / __ __ __/ __ /
_ ___ | /| / / /_/ / _ /___ _ /___
/_/ |_/_/ |_/ \____/ /_____/ /_____/
''';

View file

@ -1,76 +0,0 @@
#!/usr/bin/env dart
library angel3_cli.tool;
import 'dart:io';
import 'package:args/command_runner.dart';
import 'package:angel3_cli/angel3_cli.dart';
import 'package:io/ansi.dart';
void main(List<String> args) async {
var runner = CommandRunner('angel3',
'$asciiArt\n\nCommand-line tools for the Angel3 framework.\n\nhttps://angel3-framework.web.app');
runner.argParser
.addFlag('verbose', help: 'Print verbose output.', negatable: false);
runner
..addCommand(DeployCommand())
..addCommand(DoctorCommand())
..addCommand(KeyCommand())
..addCommand(InitCommand())
// ..addCommand(InstallCommand())
..addCommand(RenameCommand())
..addCommand(MakeCommand());
await runner.run(args).catchError((exc, st) {
if (exc is String) {
stdout.writeln(exc);
} else {
stderr.writeln('Oops, something went wrong: $exc');
if (args.contains('--verbose')) {
stderr.writeln(st);
}
}
exitCode = 1;
}).whenComplete(() {
stdout.write(resetAll.wrap(''));
});
}
const String asciiArt2 = '''
___ _ ________________ _____
/ | / | / / ____/ ____/ / |__ /
/ /| | / |/ / / __/ __/ / / /_ <
/ ___ |/ /| / /_/ / /___/ /______/ /
/_/ |_/_/ |_/\\____/_____/_____/____/
''';
const String asciiArt = '''
_ _ _ ____ _____ _ _____
/ \\ | \\ | |/ ___| ____| | |___ /
/ _ \\ | \\| | | _| _| | | |_ \\
/ ___ \\| |\\ | |_| | |___| |___ ___) |
/_/ \\_\\_| \\_|\\____|_____|_____|____/
''';
const String asciiArt3 = '''
\\ \\ | ___| ____| | ___ /
_ \\ \\ | | __| | _ \\
___ \\ |\\ | | | | | ) |
_/ _\\ _| \\_| \\____| _____| _____| ____/
''';
const String asciiArtOld = '''
____________ ________________________
___ |__ | / /_ ____/__ ____/__ /
__ /| |_ |/ /_ / __ __ __/ __ /
_ ___ | /| / / /_/ / _ /___ _ /___
/_/ |_/_/ |_/ \\____/ /_____/ /_____/
''';

View file

@ -1,3 +1,3 @@
library angel3_cli; library angel_cli;
export 'src/commands/commands.dart'; export 'src/commands/commands.dart';

View file

@ -1,9 +1,9 @@
library angel3_cli.commands; library angel_cli.commands;
export 'deploy.dart'; export "deploy.dart";
export 'doctor.dart'; export "doctor.dart";
export 'key.dart'; export "key.dart";
export 'init.dart'; export "init.dart";
export 'install.dart'; export "install.dart";
export 'make.dart'; export "make.dart";
export 'rename.dart'; export "rename.dart";

View file

@ -20,7 +20,7 @@ class NginxCommand extends Command {
} }
@override @override
Future run() async { run() async {
var webPath = p.join(p.current, 'web'); var webPath = p.join(p.current, 'web');
var nginxText = ''' var nginxText = '''
server { server {
@ -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 Angel3 server try_files \$uri @proxy; # Try to serve static files; fallback to proxied Angel 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 = new 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

@ -27,10 +27,10 @@ class SystemdCommand extends Command {
} }
@override @override
Future run() async { 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,16 +47,15 @@ WantedBy=multi-user.target
''' '''
.trim(); .trim();
if (argResults?.wasParsed('out') != true && if (!argResults.wasParsed('out') && !argResults.wasParsed('install')) {
argResults?.wasParsed('install') != true) {
print(systemdText); print(systemdText);
} else if (argResults?.wasParsed('install') == true) { } else if (argResults.wasParsed('install')) {
var systemdPath = argResults?.wasParsed('out') == true 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 = new File(serviceFilename);
await file.create(recursive: true); await file.create(recursive: true);
await file.writeAsString(systemdText); await file.writeAsString(systemdText);
print(green.wrap( print(green.wrap(
@ -77,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 = new 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

@ -1,35 +1,34 @@
import 'dart:convert'; import "dart:convert";
import 'dart:io'; import "dart:io";
import 'package:args/command_runner.dart'; import "package:args/command_runner.dart";
import 'package:io/ansi.dart'; import 'package:io/ansi.dart';
import '../util.dart'; import '../util.dart';
class DoctorCommand extends Command { class DoctorCommand extends Command {
@override @override
String get name => 'doctor'; String get name => "doctor";
@override @override
String get description => String get description =>
'Ensures that the current system is capable of running Angel3.'; "Ensures that the current system is capable of running Angel.";
@override @override
Future run() async { run() async {
print('Checking your system for dependencies...'); print("Checking your system for dependencies...");
await _checkForGit(); await _checkForGit();
} }
Future _checkForGit() async { _checkForGit() async {
try { try {
var git = await Process.start('git', ['--version']); var git = await Process.start("git", ["--version"]);
if (await git.exitCode == 0) { if (await git.exitCode == 0) {
var version = await git.stdout.transform(utf8.decoder).join(); var version = await git.stdout.transform(utf8.decoder).join();
print(green.wrap( print(green.wrap(
"$checkmark Git executable found: v${version.replaceAll('git version', '').trim()}")); "$checkmark Git executable found: v${version.replaceAll('git version', '').trim()}"));
} else { } else
throw Exception('Git executable exit code not 0'); throw Exception("Git executable exit code not 0");
}
} catch (exc) { } catch (exc) {
print(red.wrap('$ballot Git executable not found')); print(red.wrap("$ballot Git executable not found"));
} }
} }
} }

View file

@ -1,6 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'dart:io'; import "dart:io";
import 'package:args/command_runner.dart'; import "package:args/command_runner.dart";
import 'package:io/ansi.dart'; import 'package:io/ansi.dart';
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;
@ -8,17 +8,18 @@ import 'package:recase/recase.dart';
import '../random_string.dart' as rs; import '../random_string.dart' as rs;
import '../util.dart'; import '../util.dart';
import 'key.dart'; import 'key.dart';
import 'pub.dart';
import 'rename.dart'; import 'rename.dart';
class InitCommand extends Command { class InitCommand extends Command {
final KeyCommand _key = KeyCommand(); final KeyCommand _key = KeyCommand();
@override @override
String get name => 'init'; String get name => "init";
@override @override
String get description => String get description =>
'Initializes a new Angel3 project in the current directory.'; "Initializes a new Angel project in the current directory.";
InitCommand() { InitCommand() {
argParser argParser
@ -32,15 +33,10 @@ class InitCommand extends Command {
} }
@override @override
void run() async { run() async {
if (argResults == null) { Directory projectDir =
print('Invalid arguements'); Directory(argResults.rest.isEmpty ? "." : argResults.rest[0]);
return; print("Creating new Angel project in ${projectDir.absolute.path}...");
}
var projectDir =
Directory(argResults!.rest.isEmpty ? '.' : argResults!.rest[0]);
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);
@ -53,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());
@ -62,57 +58,50 @@ class InitCommand extends Command {
print('Renaming project from "angel" to "$name"...'); print('Renaming project from "angel" to "$name"...');
await renamePubspec(projectDir, 'angel', name); await renamePubspec(projectDir, 'angel', name);
await renameDartFiles(projectDir, 'angel', name); await renameDartFiles(projectDir, 'angel', name);
// Renaming executable files
if (argResults!['pub-get'] != false && argResults!['offline'] == false) { if (argResults['pub-get'] != false && argResults['offline'] == false) {
print('Now running dart pub get...'); print('Now running pub get...');
await _pubGet(projectDir); await _pubGet(projectDir);
} }
print(green.wrap('$checkmark Successfully initialized Angel3 project.')); print(green.wrap("$checkmark Successfully initialized Angel project."));
stdout stdout
..writeln() ..writeln()
..writeln( ..writeln(
'Congratulations! You are ready to start developing with Angel3!') 'Congratulations! You are ready to start developing with Angel!')
..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 Angel3:') ..writeln('Find more documentation about Angel:')
..writeln(' * https://angel3-framework.web.app') ..writeln(' * https://angel-dart.github.io')
..writeln(' * https://angel3-docs.dukefirehawk.com') ..writeln(' * https://github.com/angel-dart/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')
// ..writeln(' * https://dart.academy/tag/angel') ..writeln(' * https://dart.academy/tag/angel')
..writeln() ..writeln()
..writeln('Happy coding!'); ..writeln('Happy coding!');
} }
Future _deleteRecursive(FileSystemEntity entity, [bool self = true]) async { _deleteRecursive(FileSystemEntity entity, [bool self = true]) async {
if (entity is Directory) { if (entity is Directory) {
await for (var entity in entity.list(recursive: true)) { await for (var entity in entity.list(recursive: true)) {
try { try {
await _deleteRecursive(entity); await _deleteRecursive(entity);
} catch (e) { } catch (e) {}
print(e);
}
} }
try { try {
if (self != false) await entity.delete(recursive: true); if (self != false) await entity.delete(recursive: true);
} catch (e) { } catch (e) {}
print(e);
}
} else if (entity is File) { } else if (entity is File) {
try { try {
await entity.delete(recursive: true); await entity.delete(recursive: true);
} catch (e) { } catch (e) {}
print(e);
}
} else if (entity is Link) { } else if (entity is Link) {
var path = await entity.resolveSymbolicLinks(); var path = await entity.resolveSymbolicLinks();
var stat = await FileStat.stat(path); var stat = await FileStat.stat(path);
@ -128,49 +117,42 @@ class InitCommand extends Command {
} }
} }
Future _cloneRepo(Directory projectDir) async { _cloneRepo(Directory projectDir) async {
Directory boilerplateDir = Directory("./empty"); Directory boilerplateDir;
try { try {
if (await projectDir.exists()) { if (await projectDir.exists()) {
var shouldDelete = prompts.getBool( var shouldDelete = prompts.getBool(
"Directory '${projectDir.absolute.path}' already exists. Overwrite it?"); "Directory '${projectDir.absolute.path}' already exists. Overwrite it?");
if (!shouldDelete) { if (!shouldDelete)
throw 'Chose not to overwrite existing directory.'; throw "Chose not to overwrite existing directory.";
} else if (projectDir.absolute.uri.normalizePath().toFilePath() != else if (projectDir.absolute.uri.normalizePath().toFilePath() !=
Directory.current.absolute.uri.normalizePath().toFilePath()) { Directory.current.absolute.uri.normalizePath().toFilePath())
await projectDir.delete(recursive: true); await projectDir.delete(recursive: true);
} else { else {
await _deleteRecursive(projectDir, false); await _deleteRecursive(projectDir, false);
} }
} }
// 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);
basicBoilerplate;
// 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 != '') { if (boilerplate.ref != null) boilerplateBasename += '.${boilerplate.ref}';
boilerplateBasename += '.${boilerplate.ref}';
}
boilerplateDir = boilerplateDir =
Directory(p.join(boilerplateRootDir.path, boilerplateBasename)); Directory(p.join(boilerplateRootDir.path, boilerplateBasename));
await boilerplateRootDir.create(recursive: true); await boilerplateRootDir.create(recursive: true);
var branch = boilerplate.ref; var branch = boilerplate.ref ?? 'master';
if (branch == '') {
branch = 'master';
}
// 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.');
} }
@ -179,15 +161,15 @@ class InitCommand extends Command {
'Cloning "${boilerplate.name}" boilerplate from "${boilerplate.url}"...'); 'Cloning "${boilerplate.name}" boilerplate from "${boilerplate.url}"...');
Process git; Process git;
if (boilerplate.ref == '') { if (boilerplate.ref == null) {
print(darkGray.wrap( print(darkGray.wrap(
'\$ git clone --depth 1 ${boilerplate.url} ${boilerplateDir.absolute.path}')); '\$ git clone --depth 1 ${boilerplate.url} ${boilerplateDir.absolute.path}'));
git = await Process.start( git = await Process.start(
'git', "git",
[ [
'clone', "clone",
'--depth', "--depth",
'1', "1",
boilerplate.url, boilerplate.url,
boilerplateDir.absolute.path boilerplateDir.absolute.path
], ],
@ -198,13 +180,13 @@ class InitCommand extends Command {
print(darkGray.wrap( print(darkGray.wrap(
'\$ git clone --depth 1 --single-branch -b ${boilerplate.ref} ${boilerplate.url} ${boilerplateDir.absolute.path}')); '\$ git clone --depth 1 --single-branch -b ${boilerplate.ref} ${boilerplate.url} ${boilerplateDir.absolute.path}'));
git = await Process.start( git = await Process.start(
'git', "git",
[ [
'clone', "clone",
'--depth', "--depth",
'1', "1",
'--single-branch', "--single-branch",
'-b', "-b",
boilerplate.ref, boilerplate.ref,
boilerplate.url, boilerplate.url,
boilerplateDir.absolute.path boilerplateDir.absolute.path
@ -214,19 +196,19 @@ class InitCommand extends Command {
} }
if (await git.exitCode != 0) { if (await git.exitCode != 0) {
throw Exception('Could not clone repo.'); throw Exception("Could not clone repo.");
} }
} }
// 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,
workingDirectory: boilerplateDir.absolute.path); workingDirectory: boilerplateDir.absolute.path);
if (await git.exitCode != 0) { if (await git.exitCode != 0) {
print(yellow.wrap( print(yellow.wrap(
'Update of $branch failed. Attempting to continue with existing contents.')); "Update of $branch failed. Attempting to continue with existing contents."));
} }
} else { } else {
print(darkGray.wrap( print(darkGray.wrap(
@ -240,39 +222,37 @@ class InitCommand extends Command {
await preBuild(projectDir).catchError((_) => null); await preBuild(projectDir).catchError((_) => null);
} }
var gitDir = Directory.fromUri(projectDir.uri.resolve('.git')); var gitDir = Directory.fromUri(projectDir.uri.resolve(".git"));
if (await gitDir.exists()) await gitDir.delete(recursive: true); if (await gitDir.exists()) await gitDir.delete(recursive: true);
} catch (e) { } catch (e) {
await boilerplateDir.delete(recursive: true); await boilerplateDir.delete(recursive: true).catchError((_) => null);
//await boilerplateDir.delete(recursive: true).catchError((e) {
// print('Got error: ${e.error}');
//});
if (e is! String) { if (e is! String) {
print(red.wrap('$ballot Could not initialize Angel3 project.')); print(red.wrap("$ballot Could not initialize Angel project."));
} }
rethrow; rethrow;
} }
} }
Future _pubGet(Directory projectDir) async { _pubGet(Directory projectDir) async {
var dartPath = "dart"; var pubPath = resolvePub();
print(darkGray.wrap('Running "$dartPath"...')); print(darkGray.wrap('Running pub at "$pubPath"...'));
print(darkGray.wrap('\$ $dartPath pub get')); print(darkGray.wrap('\$ $pubPath get'));
var dart = await Process.start(dartPath, ['pub', 'get'], var pub = await Process.start(pubPath, ["get"],
workingDirectory: projectDir.absolute.path, workingDirectory: projectDir.absolute.path,
mode: ProcessStartMode.inheritStdio); mode: ProcessStartMode.inheritStdio);
var code = await dart.exitCode; var code = await pub.exitCode;
print('Dart process exited with code $code'); print("Pub process exited with code $code");
} }
} }
Future preBuild(Directory projectDir) async { Future preBuild(Directory projectDir) async {
// Run build // Run build
// print('Running `dart run build_runner build`...'); // print('Running `pub run build_runner build`...');
print(darkGray.wrap('\$ dart run build_runner build')); print(darkGray.wrap('\$ pub run build_runner build'));
var build = await Process.start("dart", ['run', 'build_runner', 'build'], var build = await Process.start(
resolvePub(), ['run', 'build_runner', 'build'],
workingDirectory: projectDir.absolute.path, workingDirectory: projectDir.absolute.path,
mode: ProcessStartMode.inheritStdio); mode: ProcessStartMode.inheritStdio);
@ -281,63 +261,63 @@ 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 repoLocation = 'https://github.com/dart-backend'; const RepoArchiveLocation = "https://github.com/angel-dart";
const RepoLocation = "https://github.com/dukefirehawk";
const BoilerplateInfo graphQLBoilerplate = BoilerplateInfo( const BoilerplateInfo graphQLBoilerplate = const BoilerplateInfo(
'GraphQL', 'GraphQL',
'A starter application with GraphQL support.', "A starting point for GraphQL API servers.",
'$repoLocation/boilerplates.git', '${RepoLocation}/boilerplates.git',
ref: 'v7/angel3-graphql', ref: 'graphql-sdk-2.12.x',
); );
const BoilerplateInfo ormBoilerplate = BoilerplateInfo( const BoilerplateInfo ormBoilerplate = const BoilerplateInfo(
'ORM for PostgreSQL', 'ORM',
'A starter application with ORM support for PostgreSQL.', "A starting point for applications that use Angel's ORM.",
'$repoLocation/boilerplates.git', '${RepoLocation}/boilerplates.git',
ref: 'v7/angel3-orm', ref: 'orm-sdk-2.12.x',
); );
const BoilerplateInfo ormMySqlBoilerplate = BoilerplateInfo( const BoilerplateInfo basicBoilerplate = const BoilerplateInfo(
'ORM for MySQL/MariaDB',
'A starter application with ORM support for MySQL/MariaDB.',
'$repoLocation/boilerplates.git',
ref: 'v7/angel3-orm-mysql',
);
const BoilerplateInfo basicBoilerplate = BoilerplateInfo(
'Basic', 'Basic',
'A basic starter application with minimal packages.', 'Minimal starting point for Angel 2.x - A simple server with only a few additional packages.',
'$repoLocation/boilerplates.git', '${RepoLocation}/boilerplates.git',
ref: 'v7/angel3-basic'); ref: 'basic-sdk-2.12.x');
const BoilerplateInfo sharedBoilerplate = BoilerplateInfo( const BoilerplateInfo legacyBoilerplate = const BoilerplateInfo(
'Legacy',
'Minimal starting point for applications running Angel 1.1.x.',
'${RepoArchiveLocation}/angel.git',
ref: '1.1.x',
);
const BoilerplateInfo sharedBoilerplate = const BoilerplateInfo(
'Shared', 'Shared',
'Holds common models and files shared across multiple Dart projects.', 'Holds common models and files shared across multiple Dart projects.',
'$repoLocation/boilerplate_shared.git'); '${RepoLocation}/boilerplate_shared.git');
const BoilerplateInfo sharedOrmBoilerplate = BoilerplateInfo( const BoilerplateInfo sharedOrmBoilerplate = const BoilerplateInfo(
'Shared (ORM)', 'Shared (ORM)',
'Holds common models and files shared across multiple Dart projects.', 'Holds common models and files shared across multiple Dart projects.',
'$repoLocation/boilerplate_shared.git', '${RepoLocation}/boilerplate_shared.git',
ref: 'orm', ref: 'orm',
); );
const List<BoilerplateInfo> boilerplates = [ const List<BoilerplateInfo> boilerplates = const [
basicBoilerplate, basicBoilerplate,
//legacyBoilerplate,
ormBoilerplate, ormBoilerplate,
ormMySqlBoilerplate,
graphQLBoilerplate, graphQLBoilerplate,
//sharedBoilerplate, //sharedBoilerplate,
//sharedOrmBoilerplate, //sharedOrmBoilerplate,
]; ];
class BoilerplateInfo { class BoilerplateInfo {
final String name, description, url; final String name, description, url, ref;
final String ref;
final bool needsPrebuild; final bool needsPrebuild;
const BoilerplateInfo(this.name, this.description, this.url, const BoilerplateInfo(this.name, this.description, this.url,
{this.ref = '', this.needsPrebuild = false}); {this.ref, this.needsPrebuild: false});
@override @override
String toString() => '$name ($description)'; String toString() => '$name ($description)';

View file

@ -3,8 +3,7 @@ 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';
@ -12,7 +11,6 @@ import 'package:yaml/yaml.dart' as yaml;
import '../util.dart'; import '../util.dart';
import 'make/maker.dart'; import 'make/maker.dart';
@Deprecated("No longer needed")
class InstallCommand extends Command { class InstallCommand extends Command {
static const String repo = 'https://github.com/angel-dart/install.git'; static const String repo = 'https://github.com/angel-dart/install.git';
static final Directory installRepo = static final Directory installRepo =
@ -48,66 +46,62 @@ class InstallCommand extends Command {
} }
@override @override
Future run() async { run() async {
print(yellow.wrap( print(yellow.wrap(
'WARNING: The `install` command is no longer considered necessary, and has been deprecated.\n' 'WARNING: The `install` command is no longer considered necessary, and has been deprecated.\n'
'Expect it to be removed in an upcoming release.\n\n' 'Expect it to be removed in an upcoming release.\n\n'
'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 `angel3 install --update` first.'; throw 'No local add-on database exists. Run `angel install --update` first.';
}
var pubspec = await loadPubspec(); var pubspec = await loadPubspec();
for (var packageName in argResults?.rest ?? <String>[]) { 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 `angel3 install --update`.'; throw 'No add-on named "$packageName" is installed. You might need to run `angel install --update`.';
}
print('Installing $packageName...'); print('Installing $packageName...');
var values = { Map values = {
'project_name': pubspec.name, 'project_name': pubspec.name,
'pubspec': pubspec, 'pubspec': pubspec,
}; };
var globs = <Glob>[]; List<Glob> globs = [];
var projectPubspec = await loadPubspec(packageDir); var projectPubspec = await loadPubspec(packageDir);
var deps = projectPubspec.dependencies.keys var deps = projectPubspec.dependencies.keys
.map((k) { .map((k) {
var dep = projectPubspec.dependencies[k]; var dep = projectPubspec.dependencies[k];
if (dep is HostedDependency) { if (dep is HostedDependency)
return MakerDependency(k, dep.version.toString()); return MakerDependency(k, dep.version.toString());
}
return null; return null;
}) })
.whereType<MakerDependency>() .where((d) => d != null)
.toList(); .toList();
deps.addAll(projectPubspec.devDependencies.keys.map((k) { deps.addAll(projectPubspec.devDependencies.keys.map((k) {
var dep = projectPubspec.devDependencies[k]; var dep = projectPubspec.devDependencies[k];
if (dep is HostedDependency) { if (dep is HostedDependency)
return MakerDependency(k, dep.version.toString(), dev: true); return MakerDependency(k, dep.version.toString(), dev: true);
}
return null; return null;
}).whereType<MakerDependency>()); }).where((d) => d != null));
await depend(deps); await depend(deps);
@ -131,11 +125,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 as String] = prompts.get(desc.toString(), values[key] = 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 as String] = prompts.choose(desc.toString(), values[key] = prompts.choose(
(val[key]['choices'] as Iterable) as Iterable<Object>)!; desc.toString(), val[key]['choices'] as Iterable);
} }
} }
} }
@ -157,7 +151,7 @@ class InstallCommand extends Command {
var name = p.basename(entity.path); var name = p.basename(entity.path);
var target = dst.uri.resolve(name); var target = dst.uri.resolve(name);
var targetFile = File.fromUri(target); var targetFile = File.fromUri(target);
var allClear = !await targetFile.exists(); bool allClear = !await targetFile.exists();
if (!allClear) { if (!allClear) {
print('The file ${entity.absolute.path} already exists.'); print('The file ${entity.absolute.path} already exists.');
@ -173,10 +167,8 @@ 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(
@ -205,9 +197,9 @@ 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 `angel3 install --update` first.'; throw 'No local add-on database exists. Run `angel install --update` first.';
} else { } else {
var repos = <Pubspec>[]; List<Pubspec> repos = [];
await for (var entity in installRepo.list()) { await for (var entity in installRepo.list()) {
if (entity is Directory) { if (entity is Directory) {
@ -244,9 +236,7 @@ class InstallCommand extends Command {
); );
} }
git git..stdout.listen(stdout.add)..stderr.listen(stderr.add);
..stdout.listen(stdout.add)
..stderr.listen(stderr.add);
var code = await git.exitCode; var code = await git.exitCode;

View file

@ -7,10 +7,10 @@ class KeyCommand extends Command {
String get name => 'key'; String get name => 'key';
@override @override
String get description => 'Generates a new `angel3_auth` key.'; String get description => 'Generates a new `angel_auth` key.';
@override @override
Future run() async { run() async {
var secret = rs.randomAlphaNumeric(32); var secret = rs.randomAlphaNumeric(32);
print('Generated new development JWT secret: $secret'); print('Generated new development JWT secret: $secret');
await changeSecret(File('config/default.yaml'), secret); await changeSecret(File('config/default.yaml'), secret);
@ -20,11 +20,11 @@ class KeyCommand extends Command {
await changeSecret(File('config/production.yaml'), secret); await changeSecret(File('config/production.yaml'), secret);
} }
Future changeSecret(File file, String secret) async { changeSecret(File file, String secret) async {
if (await file.exists()) { if (await file.exists()) {
var contents = await file.readAsString(); var contents = await file.readAsString();
contents = contents.replaceAll(RegExp(r'jwt_secret:[^\n]+\n?'), ''); contents = contents.replaceAll(RegExp(r'jwt_secret:[^\n]+\n?'), '');
await file.writeAsString('${contents.trim()}\njwt_secret: "$secret"'); await file.writeAsString(contents.trim() + '\njwt_secret: "$secret"');
} }
} }
} }

View file

@ -30,60 +30,59 @@ class ControllerCommand extends Command {
} }
@override @override
Future run() async { run() async {
String? name; var pubspec = await loadPubspec();
if (argResults?.wasParsed('name') == true) { String 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');
} }
var deps = <MakerDependency>[ List<MakerDependency> deps = [
const MakerDependency('angel3_framework', '^7.0.0') const MakerDependency('angel_framework', '^2.0.0')
]; ];
//${pubspec.name}.src.models.${rc.snakeCase} //${pubspec.name}.src.models.${rc.snakeCase}
var rc = ReCase(name!); var rc = new ReCase(name);
var controllerLib = Library((controllerLib) { var controllerLib = new Library((controllerLib) {
if (argResults?['websocket'] as bool) { if (argResults['websocket'] as bool) {
deps.add(const MakerDependency('angel3_websocket', '^7.0.0')); deps.add(const MakerDependency('angel_websocket', '^2.0.0'));
controllerLib.directives controllerLib.directives
.add(Directive.import('package:angel3_websocket/server.dart')); .add(new Directive.import('package:angel_websocket/server.dart'));
} else { } else {
controllerLib.directives.add( controllerLib.directives.add(new Directive.import(
Directive.import('package:angel3_framework/angel3_framework.dart')); 'package:angel_framework/angel_framework.dart'));
} }
controllerLib.body.add(Class((clazz) { controllerLib.body.add(new 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(new Constructor((b) {
b b
..requiredParameters.add(Parameter((b) => b ..requiredParameters.add(new Parameter((b) => b
..name = 'ws' ..name = 'ws'
..type = refer('AngelWebSocket'))) ..type = refer('AngelWebSocket')))
..initializers.add(Code('super(ws)')); ..initializers.add(new Code('super(ws)'));
})); }));
clazz.methods.add(Method((meth) { clazz.methods.add(new Method((meth) {
meth meth
..name = 'hello' ..name = 'hello'
..returns = refer('void') ..returns = refer('void')
..annotations ..annotations
.add(refer('ExposeWs').call([literal('get_${rc.snakeCase}')])) .add(refer('ExposeWs').call([literal('get_${rc.snakeCase}')]))
..requiredParameters.add(Parameter((b) => b ..requiredParameters.add(new Parameter((b) => b
..name = 'socket' ..name = 'socket'
..type = refer('WebSocketContext'))) ..type = refer('WebSocketContext')))
..body = Block((block) { ..body = new Block((block) {
block.addExpression(refer('socket').property('send').call([ block.addExpression(refer('socket').property('send').call([
literal('got_${rc.snakeCase}'), literal('got_${rc.snakeCase}'),
literalMap({'message': literal('Hello, world!')}), literalMap({'message': literal('Hello, world!')}),
@ -94,7 +93,7 @@ class ControllerCommand extends Command {
clazz clazz
..annotations ..annotations
.add(refer('Expose').call([literal('/${rc.snakeCase}')])) .add(refer('Expose').call([literal('/${rc.snakeCase}')]))
..methods.add(Method((meth) { ..methods.add(new Method((meth) {
meth meth
..name = 'hello' ..name = 'hello'
..returns = refer('String') ..returns = refer('String')
@ -107,15 +106,14 @@ class ControllerCommand extends Command {
})); }));
}); });
var outputDir = Directory.fromUri( var outputDir = new 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')); new File.fromUri(outputDir.uri.resolve('${rc.snakeCase}.dart'));
if (!await controllerFile.exists()) { if (!await controllerFile.exists())
await controllerFile.create(recursive: true); await controllerFile.create(recursive: true);
} await controllerFile.writeAsString(new DartFormatter()
await controllerFile.writeAsString( .format(controllerLib.accept(new DartEmitter()).toString()));
DartFormatter().format(controllerLib.accept(DartEmitter()).toString()));
print(green.wrap( print(green.wrap(
'$checkmark Created controller file "${controllerFile.absolute.path}"')); '$checkmark Created controller file "${controllerFile.absolute.path}"'));

View file

@ -6,7 +6,7 @@ class MakerDependency implements Comparable<MakerDependency> {
final String name, version; final String name, version;
final bool dev; final bool dev;
const MakerDependency(this.name, this.version, {this.dev = false}); const MakerDependency(this.name, this.version, {this.dev: false});
@override @override
int compareTo(MakerDependency other) => name.compareTo(other.name); int compareTo(MakerDependency other) => name.compareTo(other.name);
@ -18,11 +18,10 @@ Future depend(Iterable<MakerDependency> deps) async {
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);
}
if (!isPresent) { if (!isPresent) {
missing.add(dep); missing.add(dep);
@ -52,11 +51,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

@ -3,7 +3,7 @@ import 'dart:io';
import 'package:args/command_runner.dart'; import 'package:args/command_runner.dart';
import 'package:code_builder/code_builder.dart'; import 'package:code_builder/code_builder.dart';
import 'package:dart_style/dart_style.dart'; import 'package:dart_style/dart_style.dart';
import 'package:inflection3/inflection3.dart'; import 'package:inflection2/inflection2.dart';
import 'package:io/ansi.dart'; import 'package:io/ansi.dart';
import 'package:prompts/prompts.dart' as prompts; import 'package:prompts/prompts.dart' as prompts;
import 'package:recase/recase.dart'; import 'package:recase/recase.dart';
@ -28,23 +28,21 @@ class MigrationCommand extends Command {
@override @override
FutureOr run() async { FutureOr run() async {
String? name; String name;
if (argResults?.wasParsed('name') == true) { if (argResults.wasParsed('name')) name = argResults['name'] as String;
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('angel3_migration', '^7.0.0')]; var deps = [const MakerDependency('angel_migration', '^2.0.0')];
var rc = ReCase(name!); var rc = new ReCase(name);
var migrationLib = Library((migrationLib) { var migrationLib = new Library((migrationLib) {
migrationLib migrationLib
..directives.add(Directive.import( ..directives.add(new Directive.import(
'package:angel3_migration.dart/angel3_migration.dart')) 'package:angel_migration.dart/angel_migration.dart'))
..body.add(Class((migrationClazz) { ..body.add(new Class((migrationClazz) {
migrationClazz migrationClazz
..name = '${rc.pascalCase}Migration' ..name = '${rc.pascalCase}Migration'
..extend = refer('Migration'); ..extend = refer('Migration');
@ -52,21 +50,21 @@ class MigrationCommand extends Command {
var tableName = pluralize(rc.snakeCase); var tableName = pluralize(rc.snakeCase);
// up() // up()
migrationClazz.methods.add(Method((up) { migrationClazz.methods.add(new Method((up) {
up up
..name = 'up' ..name = 'up'
..returns = refer('void') ..returns = refer('void')
..annotations.add(refer('override')) ..annotations.add(refer('override'))
..requiredParameters.add(Parameter((b) => b ..requiredParameters.add(new Parameter((b) => b
..name = 'schema' ..name = 'schema'
..type = refer('Schema'))) ..type = refer('Schema')))
..body = Block((block) { ..body = new Block((block) {
// (table) { ... } // (table) { ... }
var callback = Method((callback) { var callback = new Method((callback) {
callback callback
..requiredParameters ..requiredParameters
.add(Parameter((b) => b..name = 'table')) .add(new Parameter((b) => b..name = 'table'))
..body = Block((block) { ..body = new Block((block) {
var table = refer('table'); var table = refer('table');
block.addExpression( block.addExpression(
@ -97,15 +95,15 @@ class MigrationCommand extends Command {
})); }));
// down() // down()
migrationClazz.methods.add(Method((down) { migrationClazz.methods.add(new Method((down) {
down down
..name = 'down' ..name = 'down'
..returns = refer('void') ..returns = refer('void')
..annotations.add(refer('override')) ..annotations.add(refer('override'))
..requiredParameters.add(Parameter((b) => b ..requiredParameters.add(new Parameter((b) => b
..name = 'schema' ..name = 'schema'
..type = refer('Schema'))) ..type = refer('Schema')))
..body = Block((block) { ..body = new Block((block) {
block.addExpression( block.addExpression(
refer('schema').property('drop').call([ refer('schema').property('drop').call([
literal(tableName), literal(tableName),
@ -117,16 +115,15 @@ class MigrationCommand extends Command {
}); });
// Save migration file // Save migration file
var migrationDir = 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 =
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())
await migrationFile.create(recursive: true); await migrationFile.create(recursive: true);
}
await migrationFile.writeAsString( await migrationFile.writeAsString(new DartFormatter()
DartFormatter().format(migrationLib.accept(DartEmitter()).toString())); .format(migrationLib.accept(new DartEmitter()).toString()));
print(green.wrap( print(green.wrap(
'$checkmark Created migration file "${migrationFile.absolute.path}".')); '$checkmark Created migration file "${migrationFile.absolute.path}".'));

View file

@ -32,39 +32,37 @@ class ModelCommand extends Command {
} }
@override @override
Future run() async { run() async {
String? name; String name;
if (argResults?.wasParsed('name') == true) { if (argResults.wasParsed('name')) name = argResults['name'] as String;
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 = <MakerDependency>[ List<MakerDependency> deps = [
const MakerDependency('angel3_model', '^3.0.0'), const MakerDependency('angel_model', '^1.0.0'),
]; ];
var rc = ReCase(name!); var rc = new ReCase(name);
var modelLib = Library((modelLib) { var modelLib = new 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:angel3_migration/angel3_migration.dart'), new 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) {
modelLib.directives.add( modelLib.directives.add(new Directive.import(
Directive.import('package:angel3_serialize/angel3_serialize.dart')); 'package:angel_serialize/angel_serialize.dart'));
deps.add(const MakerDependency('angel3_serialize', '^7.0.0')); deps.add(const MakerDependency('angel_serialize', '^2.0.0'));
deps.add(const MakerDependency('angel3_serialize_generator', '^7.0.0')); deps.add(const MakerDependency('angel_serialize_generator', '^2.0.0'));
deps.add(const MakerDependency('build_runner', '^2.2.0')); deps.add(const MakerDependency('build_runner', '^1.0.0'));
} }
// else { // else {
@ -73,18 +71,18 @@ 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:angel3_orm/angel3_orm.dart'), new Directive.import('package:angel_orm/angel_orm.dart'),
]); ]);
deps.add(const MakerDependency('angel3_orm', '^7.0.0')); deps.add(const MakerDependency('angel_orm', '^2.0.0'));
} }
modelLib.body.addAll([ modelLib.body.addAll([
Code("part '${rc.snakeCase}.g.dart';"), new Code("part '${rc.snakeCase}.g.dart';"),
]); ]);
modelLib.body.add(Class((modelClazz) { modelLib.body.add(new Class((modelClazz) {
modelClazz modelClazz
..abstract = true ..abstract = true
..name = needsSerialize ? '_${rc.pascalCase}' : rc.pascalCase ..name = needsSerialize ? '_${rc.pascalCase}' : rc.pascalCase
@ -95,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(
@ -107,13 +105,14 @@ class ModelCommand extends Command {
}); });
// Save model file // Save model file
var outputDir = Directory.fromUri( var outputDir = new 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 =
new 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);
await modelFile.writeAsString( await modelFile.writeAsString(new DartFormatter()
DartFormatter().format(modelLib.accept(DartEmitter()).toString())); .format(modelLib.accept(new DartEmitter()).toString()));
print(green print(green
.wrap('$checkmark Created model file "${modelFile.absolute.path}".')); .wrap('$checkmark Created model file "${modelFile.absolute.path}".'));

View file

@ -10,10 +10,10 @@ import 'maker.dart';
class PluginCommand extends Command { class PluginCommand extends Command {
@override @override
String get name => 'plugin'; String get name => "plugin";
@override @override
String get description => 'Creates a new plug-in within the given project.'; String get description => "Creates a new plug-in within the given project.";
PluginCommand() { PluginCommand() {
argParser argParser
@ -25,29 +25,27 @@ class PluginCommand extends Command {
} }
@override @override
Future run() async { run() async {
var pubspec = await loadPubspec(); var pubspec = await loadPubspec();
String? name; String name;
if (argResults?.wasParsed('name') == true) { if (argResults.wasParsed('name')) name = argResults['name'] as String;
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');
} }
var deps = <MakerDependency>[ List<MakerDependency> deps = [
const MakerDependency('angel3_framework', '^7.0.0') const MakerDependency('angel_framework', '^2.0.0')
]; ];
var rc = ReCase(name!); var rc = new ReCase(name);
final pluginDir = Directory.fromUri( final pluginDir = new 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')); new 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);
await pluginFile await pluginFile.writeAsString(
.writeAsString(DartFormatter().format(_generatePlugin(pubspec, rc))); new DartFormatter().format(_generatePlugin(pubspec, rc)));
if (deps.isNotEmpty) await depend(deps); if (deps.isNotEmpty) await depend(deps);
@ -59,7 +57,7 @@ class PluginCommand extends Command {
return ''' return '''
library ${pubspec.name}.src.config.plugins.${rc.snakeCase}; library ${pubspec.name}.src.config.plugins.${rc.snakeCase};
import 'package:angel3_framework/angel3_framework.dart'; import 'package:angel_framework/angel_framework.dart';
AngelConfigurer ${rc.camelCase}() { AngelConfigurer ${rc.camelCase}() {
return (Angel app) async { return (Angel app) async {

View file

@ -2,9 +2,10 @@ import 'dart:io';
import 'package:args/command_runner.dart'; import 'package:args/command_runner.dart';
import 'package:code_builder/code_builder.dart'; import 'package:code_builder/code_builder.dart';
import 'package:dart_style/dart_style.dart'; import 'package:dart_style/dart_style.dart';
import 'package:inflection3/inflection3.dart'; import 'package:inflection2/inflection2.dart';
import 'package:io/ansi.dart'; import 'package:io/ansi.dart';
import 'package:prompts/prompts.dart' as prompts; import 'package:prompts/prompts.dart' as prompts;
import 'package:pubspec_parse/pubspec_parse.dart';
import 'package:recase/recase.dart'; import 'package:recase/recase.dart';
import '../service_generators/service_generators.dart'; import '../service_generators/service_generators.dart';
import '../../util.dart'; import '../../util.dart';
@ -31,26 +32,24 @@ class ServiceCommand extends Command {
} }
@override @override
void run() async { run() async {
await loadPubspec(); var pubspec = await loadPubspec();
String? name; String name;
if (argResults?.wasParsed('name') == true) { if (argResults.wasParsed('name')) name = argResults['name'] as String;
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');
} }
var deps = <MakerDependency>[ List<MakerDependency> deps = [
const MakerDependency('angel3_framework', '^7.0.0') const MakerDependency('angel_framework', '^2.0.0')
]; ];
// '${pubspec.name}.src.services.${rc.snakeCase}' // '${pubspec.name}.src.services.${rc.snakeCase}'
var rc = ReCase(name!); var rc = new ReCase(name);
var serviceLib = Library((serviceLib) { var serviceLib = new 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();
@ -63,61 +62,56 @@ class ServiceCommand extends Command {
if (!deps.any((d) => d.name == dep.name)) deps.add(dep); if (!deps.any((d) => d.name == dep.name)) deps.add(dep);
} }
if (name != null && generator.goesFirst) { if (generator.goesFirst) {
generator.applyToLibrary(serviceLib, name, rc.snakeCase); generator.applyToLibrary(serviceLib, name, rc.snakeCase);
serviceLib.directives.add( serviceLib.directives.add(new Directive.import(
Directive.import('package:angel3_framework/angel3_framework.dart')); 'package:angel_framework/angel_framework.dart'));
} else if (name != null) { } else {
serviceLib.directives.add( serviceLib.directives.add(new Directive.import(
Directive.import('package:angel3_framework/angel3_framework.dart')); 'package:angel_framework/angel_framework.dart'));
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(new Directive.import('../models/${rc.snakeCase}.dart'));
} }
// configureServer() {} // configureServer() {}
serviceLib.body.add(Method((configureServer) { serviceLib.body.add(new Method((configureServer) {
configureServer configureServer
..name = 'configureServer' ..name = 'configureServer'
..returns = refer('AngelConfigurer'); ..returns = refer('AngelConfigurer');
configureServer.body = Block((block) { configureServer.body = new Block((block) {
if (name != null) { generator.applyToConfigureServer(
generator.applyToConfigureServer( serviceLib, configureServer, block, name, rc.snakeCase);
serviceLib, configureServer, block, name, rc.snakeCase);
}
// return (Angel app) async {} // return (Angel app) async {}
var closure = Method((closure) { var closure = new Method((closure) {
closure closure
..modifier = MethodModifier.async ..modifier = MethodModifier.async
..requiredParameters.add(Parameter((b) => b ..requiredParameters.add(new Parameter((b) => b
..name = 'app' ..name = 'app'
..type = refer('Angel'))); ..type = refer('Angel')));
closure.body = new Block((block) {
generator.beforeService(serviceLib, block, name, rc.snakeCase);
closure.body = Block((block) { // app.use('/api/todos', new MapService());
if (name != null) { var service = generator.createInstance(
generator.beforeService(serviceLib, block, name, rc.snakeCase); serviceLib, closure, name, rc.snakeCase);
// app.use('/api/todos', new MapService()); if (argResults['typed'] as bool) {
var service = generator.createInstance( var tb = new TypeReference((b) => b
serviceLib, closure, name, rc.snakeCase); ..symbol = 'TypedService'
..types.add(refer(rc.pascalCase)));
if (argResults!['typed'] as bool) { service = tb.newInstance([service]);
var tb = TypeReference((b) => b
..symbol = 'TypedService'
..types.add(refer(rc.pascalCase)));
service = tb.newInstance([service]);
}
block.addExpression(refer('app').property('use').call([
literal('/api/${pluralize(rc.snakeCase)}'),
service,
]));
} }
block.addExpression(refer('app').property('use').call([
literal('/api/${pluralize(rc.snakeCase)}'),
service,
]));
}); });
}); });
@ -126,13 +120,13 @@ class ServiceCommand extends Command {
})); }));
}); });
final outputDir = Directory.fromUri( final outputDir = new 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')); new 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);
await serviceFile.writeAsString( await serviceFile.writeAsString(new DartFormatter()
DartFormatter().format(serviceLib.accept(DartEmitter()).toString())); .format(serviceLib.accept(new DartEmitter()).toString()));
print(green.wrap( print(green.wrap(
'$checkmark Successfully generated service file "${serviceFile.absolute.path}".')); '$checkmark Successfully generated service file "${serviceFile.absolute.path}".'));

View file

@ -10,10 +10,10 @@ import 'maker.dart';
class TestCommand extends Command { class TestCommand extends Command {
@override @override
String get name => 'test'; String get name => "test";
@override @override
String get description => 'Creates a new test within the given project.'; String get description => "Creates a new test within the given project.";
TestCommand() { TestCommand() {
argParser argParser
@ -28,39 +28,37 @@ class TestCommand extends Command {
} }
@override @override
Future run() async { run() async {
var pubspec = await loadPubspec(); var pubspec = await loadPubspec();
String? name; String name;
if (argResults?.wasParsed('name') == true) { if (argResults.wasParsed('name')) name = argResults['name'] as String;
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');
} }
var deps = <MakerDependency>[ List<MakerDependency> deps = [
const MakerDependency('angel3_framework', '^7.0.0'), const MakerDependency('angel_framework', '^2.0.0'),
const MakerDependency('angel3_test', '^7.0.0', dev: true), const MakerDependency('angel_test', '^2.0.0', dev: true),
const MakerDependency('test', '^1.21.0', dev: true), const MakerDependency('test', '^1.0.0', dev: true),
]; ];
var rc = ReCase(name!); var rc = new ReCase(name);
final testDir = Directory.fromUri( final testDir = new 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')); new 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);
await testFile await testFile
.writeAsString(DartFormatter().format(_generateTest(pubspec, rc))); .writeAsString(new DartFormatter().format(_generateTest(pubspec, rc)));
if (deps.isNotEmpty) await depend(deps); if (deps.isNotEmpty) await depend(deps);
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 = new File.fromUri(Directory.current.uri
.resolve('.idea/runConfigurations/${name}_Tests.xml')); .resolve('.idea/runConfigurations/${name}_Tests.xml'));
if (!await runConfig.exists()) await runConfig.create(recursive: true); if (!await runConfig.exists()) await runConfig.create(recursive: true);
@ -87,15 +85,15 @@ class TestCommand extends Command {
return ''' return '''
import 'dart:io'; import 'dart:io';
import 'package:${pubspec.name}/${pubspec.name}.dart' as ${pubspec.name}; import 'package:${pubspec.name}/${pubspec.name}.dart' as ${pubspec.name};
import 'package:angel3_framework/angel3_framework.dart'; import 'package:angel_framework/angel_framework.dart';
import 'package:angel3_test/angel3_test.dart'; import 'package:angel_test/angel_test.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
main() async { main() async {
TestClient client; TestClient client;
setUp(() async { setUp(() async {
var app = Angel(); var app = new Angel();
await app.configure(${pubspec.name}.configureServer); await app.configure(${pubspec.name}.configureServer);
client = await connectTo(app); client = await connectTo(app);
}); });

View file

@ -2,13 +2,11 @@ import 'dart:io';
final RegExp _leadingSlashes = RegExp(r'^/+'); final RegExp _leadingSlashes = RegExp(r'^/+');
@Deprecated("Replaced by dart pub")
String resolvePub() { String resolvePub() {
var exec = File(Platform.resolvedExecutable); var exec = File(Platform.resolvedExecutable);
var pubPath = exec.parent.uri.resolve('pub').path; var pubPath = exec.parent.uri.resolve('pub').path;
if (Platform.isWindows) { if (Platform.isWindows)
pubPath = '${pubPath.replaceAll(_leadingSlashes, '')}.bat'; pubPath = pubPath.replaceAll(_leadingSlashes, '') + '.bat';
}
pubPath = Uri.decodeFull(pubPath); pubPath = Uri.decodeFull(pubPath);
return pubPath; return pubPath;
} }

View file

@ -8,6 +8,8 @@ import 'package:glob/list_local_fs.dart';
import 'package:io/ansi.dart'; import 'package:io/ansi.dart';
import 'package:prompts/prompts.dart' as prompts; import 'package:prompts/prompts.dart' as prompts;
import 'package:recase/recase.dart'; import 'package:recase/recase.dart';
import '../util.dart';
import 'pub.dart';
class RenameCommand extends Command { class RenameCommand extends Command {
@override @override
@ -20,16 +22,16 @@ class RenameCommand extends Command {
String get invocation => '$name <new name>'; String get invocation => '$name <new name>';
@override @override
Future run() async { run() async {
String? newName; String newName;
if (argResults?.rest.isNotEmpty == true) { 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');
} }
newName = ReCase(newName!).snakeCase; newName = ReCase(newName).snakeCase;
var choice = prompts.getBool('Rename the project to `$newName`?'); var choice = prompts.getBool('Rename the project to `$newName`?');
@ -61,7 +63,7 @@ class RenameCommand extends Command {
} }
} }
Future renamePubspec(Directory dir, String oldName, String newName) async { renamePubspec(Directory dir, String oldName, String newName) async {
// var pubspec = await loadPubspec(dir); // var pubspec = await loadPubspec(dir);
print(cyan.wrap('Renaming your project to `$newName.`')); print(cyan.wrap('Renaming your project to `$newName.`'));
@ -84,13 +86,13 @@ Future renamePubspec(Directory dir, String oldName, String newName) async {
// await newPubspec.save(dir); // await newPubspec.save(dir);
} }
Future renameDartFiles(Directory dir, String oldName, String newName) async { renameDartFiles(Directory dir, String oldName, String newName) async {
if (!await dir.exists()) return; if (!await dir.exists()) return;
// Try to replace MongoDB URL // Try to replace MongoDB URL
// Replace name in config directory var configGlob = Glob('config/**/*.yaml');
try { try {
var configGlob = Glob('config/**/*.yaml');
await for (var yamlFile in configGlob.list(root: dir.absolute.path)) { await for (var yamlFile in configGlob.list(root: dir.absolute.path)) {
if (yamlFile is File) { if (yamlFile is File) {
print( print(
@ -111,58 +113,12 @@ Future renameDartFiles(Directory dir, String oldName, String newName) async {
print('Renaming library file `${entry.absolute.path}`...'); print('Renaming library file `${entry.absolute.path}`...');
} }
// Replace package:oldName/oldName.dart with package:newName/newName.dart
// Replace package:oldName/ with package:newName/
String updateImport(String content, String oldName, String newName) {
if (!content.startsWith('import')) {
return content;
}
if (content.contains('package:$oldName/$oldName.dart')) {
return content.replaceFirst(
'package:$oldName/$oldName.dart', 'package:$newName/$newName.dart');
}
if (content.contains('package:$oldName/')) {
return content.replaceFirst('package:$oldName/', 'package:$newName/');
}
return content;
}
// Replace mustache {{oldName}} with newName
String updateMustacheBinding(String content, String oldName, String newName) {
if (content.contains('{{$oldName}}')) {
return content.replaceAll('{{$oldName}}', newName);
}
return content;
}
var fmt = DartFormatter();
await for (FileSystemEntity file in dir.list(recursive: true)) {
if (file is File && file.path.endsWith('.dart')) {
var lineList = await file.readAsLines();
if (oldName.isNotEmpty && newName.isNotEmpty) {
var contents = lineList.fold<String>('', (prev, cur) {
var updatedCur = updateImport(cur, oldName, newName);
updatedCur = updateMustacheBinding(updatedCur, oldName, newName);
return '$prev\n$updatedCur';
});
await file.writeAsString(fmt.format(contents));
print('Updated file `${file.absolute.path}`.');
}
}
}
/* Deprecated, Not working
var fmt = DartFormatter(); var fmt = DartFormatter();
await for (FileSystemEntity file in dir.list(recursive: true)) { await for (FileSystemEntity file in dir.list(recursive: true)) {
if (file is File && file.path.endsWith('.dart')) { if (file is File && file.path.endsWith('.dart')) {
var contents = await file.readAsString(); var contents = await file.readAsString();
// TODO: Issue to be fixed: parseCompilationUnit uses Hubbub library which uses discontinued Google front_end library
// front_end package. Temporarily commeted out // front_end package. Temporarily commeted out
//var ast = parseCompilationUnit(contents); //var ast = parseCompilationUnit(contents);
var visitor = RenamingVisitor(oldName, newName); var visitor = RenamingVisitor(oldName, newName);
@ -172,7 +128,7 @@ 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);
} }
@ -183,7 +139,6 @@ Future renameDartFiles(Directory dir, String oldName, String newName) async {
} }
} }
} }
*/
} }
class RenamingVisitor extends RecursiveAstVisitor { class RenamingVisitor extends RecursiveAstVisitor {
@ -198,49 +153,41 @@ class RenamingVisitor extends RecursiveAstVisitor {
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;
}
} }
@override @override
void visitExportDirective(ExportDirective node) { visitExportDirective(ExportDirective ctx) {
var uri = node.uri.stringValue; var uri = ctx.uri.stringValue, updated = updateUri(uri);
if (uri != null) { if (uri != updated) replace[[uri]] = updated;
var updated = updateUri(uri);
if (uri != updated) replace[[uri]] = updated;
}
} }
@override @override
void visitImportDirective(ImportDirective node) { visitImportDirective(ImportDirective ctx) {
var uri = node.uri.stringValue; var uri = ctx.uri.stringValue, updated = updateUri(uri);
if (uri != updated) replace[[uri]] = updated;
if (uri != null) {
var updated = updateUri(uri);
if (uri != updated) replace[[uri]] = updated;
}
} }
@override @override
void visitLibraryDirective(LibraryDirective node) { visitLibraryDirective(LibraryDirective ctx) {
var name = node.name2?.name ?? ''; var name = ctx.name.name;
if (name.startsWith(oldName)) { if (name.startsWith(oldName)) {
replace[[node.offset, node.end]] = replace[[ctx.offset, ctx.end]] =
'library ${name.replaceFirst(oldName, newName)};'; 'library ' + name.replaceFirst(oldName, newName) + ';';
} }
} }
@override @override
void visitPartOfDirective(PartOfDirective node) { visitPartOfDirective(PartOfDirective ctx) {
if (node.libraryName != null) { if (ctx.libraryName != null) {
var name = node.libraryName!.name; var name = ctx.libraryName.name;
if (name.startsWith(oldName)) { if (name.startsWith(oldName)) {
replace[[node.offset, node.end]] = replace[[ctx.offset, ctx.end]] =
'part of ${name.replaceFirst(oldName, newName)};'; 'part of ' + name.replaceFirst(oldName, newName) + ';';
} }
} }
} }

View file

@ -2,8 +2,10 @@ import 'package:code_builder/code_builder.dart';
import 'generator.dart'; import 'generator.dart';
class CustomServiceGenerator extends ServiceGenerator { class CustomServiceGenerator extends ServiceGenerator {
@override
bool get createsModel => false; bool get createsModel => false;
@override
bool get createsValidator => false; bool get createsValidator => false;
const CustomServiceGenerator() : super('Custom'); const CustomServiceGenerator() : super('Custom');

View file

@ -1,6 +1,6 @@
import 'generator.dart'; import 'generator.dart';
import 'package:code_builder/code_builder.dart'; import 'package:code_builder/code_builder.dart';
import 'package:inflection3/inflection3.dart'; import 'package:inflection2/inflection2.dart';
import '../make/maker.dart'; import '../make/maker.dart';
class FileServiceGenerator extends ServiceGenerator { class FileServiceGenerator extends ServiceGenerator {
@ -8,7 +8,7 @@ class FileServiceGenerator extends ServiceGenerator {
@override @override
List<MakerDependency> get dependencies => List<MakerDependency> get dependencies =>
const [MakerDependency('angel3_file_service', '^7.0.0')]; const [const MakerDependency('angel_file_service', '^2.0.0')];
@override @override
bool get goesFirst => true; bool get goesFirst => true;
@ -18,9 +18,9 @@ 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(Parameter((b) => b configureServer.requiredParameters.add(new Parameter((b) => b
..name = 'dbDirectory' ..name = 'dbDirectory'
..type = refer('Directory'))); ..type = refer('Directory')));
} }
@ -28,7 +28,8 @@ class FileServiceGenerator 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:angel3_file_service/angel3_file_service.dart'), new Directive.import(
'package:angel_file_service/angel_file_service.dart'),
]); ]);
} }
@ -36,12 +37,12 @@ class FileServiceGenerator extends ServiceGenerator {
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([
Directive.import('package:file/file.dart'), new Directive.import('package:file/file.dart'),
]); ]);
return refer('JsonFileService').newInstance([ return refer('JsonFileService').newInstance([
refer('dbDirectory') refer('dbDirectory')
.property('childFile') .property('childFile')
.call([literal('${pluralize(lower)}_db.json')]) .call([literal(pluralize(lower) + '_db.json')])
]); ]);
} }
} }

View file

@ -8,6 +8,21 @@ class ServiceGenerator {
List<MakerDependency> get dependencies => []; List<MakerDependency> get dependencies => [];
@deprecated
bool get createsModel => true;
@deprecated
bool get createsValidator => true;
@deprecated
bool get exportedInServiceLibrary => true;
@deprecated
bool get injectsSingleton => false;
@deprecated
bool get shouldRunBuild => false;
bool get goesFirst => false; bool get goesFirst => false;
void applyToLibrary(LibraryBuilder library, String name, String lower) {} void applyToLibrary(LibraryBuilder library, String name, String lower) {}

View file

@ -4,6 +4,7 @@ import 'package:code_builder/code_builder.dart';
class MapServiceGenerator extends ServiceGenerator { class MapServiceGenerator extends ServiceGenerator {
const MapServiceGenerator() : super('In-Memory'); const MapServiceGenerator() : super('In-Memory');
@override
bool get createsModel => false; bool get createsModel => false;
@override @override

View file

@ -1,6 +1,6 @@
import 'generator.dart'; import 'generator.dart';
import 'package:code_builder/code_builder.dart'; import 'package:code_builder/code_builder.dart';
import 'package:inflection3/inflection3.dart'; import 'package:inflection2/inflection2.dart';
import '../make/maker.dart'; import '../make/maker.dart';
class MongoServiceGenerator extends ServiceGenerator { class MongoServiceGenerator extends ServiceGenerator {
@ -8,8 +8,9 @@ class MongoServiceGenerator extends ServiceGenerator {
@override @override
List<MakerDependency> get dependencies => List<MakerDependency> get dependencies =>
const [MakerDependency('angel3_mongo', '^4.0.0')]; const [const MakerDependency('angel_mongo', '^2.0.0')];
@override
bool get createsModel => false; bool get createsModel => false;
@override @override
@ -17,9 +18,9 @@ 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(new Parameter((b) => b
..name = 'db' ..name = 'db'
..type = refer('Db'))); ..type = refer('Db')));
} }
@ -27,8 +28,8 @@ 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:angel3_mongo/angel3_mongo.dart'), new Directive.import('package:angel_mongo/angel_mongo.dart'),
Directive.import('package:mongo_dart/mongo_dart.dart'), new Directive.import('package:mongo_dart/mongo_dart.dart'),
]); ]);
} }

View file

@ -1,6 +1,6 @@
import 'generator.dart'; import 'generator.dart';
import 'package:code_builder/code_builder.dart'; import 'package:code_builder/code_builder.dart';
import 'package:inflection3/inflection3.dart'; import 'package:inflection2/inflection2.dart';
import '../make/maker.dart'; import '../make/maker.dart';
class RethinkServiceGenerator extends ServiceGenerator { class RethinkServiceGenerator extends ServiceGenerator {
@ -8,8 +8,9 @@ class RethinkServiceGenerator extends ServiceGenerator {
@override @override
List<MakerDependency> get dependencies => List<MakerDependency> get dependencies =>
const [MakerDependency('angel3_rethink', '^4.0.0')]; const [const MakerDependency('angel_rethink', '^2.0.0')];
@override
bool get createsModel => false; bool get createsModel => false;
@override @override
@ -17,13 +18,13 @@ 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 new Parameter((b) => b
..name = 'connection' ..name = 'connection'
..type = refer('Connection')), ..type = refer('Connection')),
Parameter((b) => b new Parameter((b) => b
..name = 'r' ..name = 'r'
..type = refer('Rethinkdb')), ..type = refer('Rethinkdb')),
]); ]);
@ -32,9 +33,9 @@ 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:angel3_rethink/angel3_rethink.dart', 'package:angel_rethink/angel_rethink.dart',
'package:rethinkdb_dart/rethinkdb_dart.dart' 'package:rethinkdb_dart/rethinkdb_dart.dart'
].map((str) => Directive.import(str))); ].map((str) => new Directive.import(str)));
} }
@override @override

View file

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

View file

@ -7,7 +7,7 @@ final Random _rnd = Random.secure();
String randomAlphaNumeric(int length) { String randomAlphaNumeric(int length) {
var b = StringBuffer(); var b = StringBuffer();
for (var i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
b.writeCharCode(_valid.codeUnitAt(_rnd.nextInt(_valid.length))); b.writeCharCode(_valid.codeUnitAt(_rnd.nextInt(_valid.length)));
} }

View file

@ -10,18 +10,18 @@ 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 => new 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 = new File.fromUri(directory.uri.resolve('pubspec.yaml'));
return file return file
.readAsString() .readAsString()
.then((yaml) => Pubspec.parse(yaml, sourceUrl: file.uri)); .then((yaml) => new Pubspec.parse(yaml, sourceUrl: file.uri));
} }
// From: https://gist.github.com/tobischw/98dcd2563eec9a2a87bda8299055358a // From: https://gist.github.com/tobischw/98dcd2563eec9a2a87bda8299055358a

View file

@ -1,29 +1,27 @@
name: angel3_cli #author: Tobe O <thosakwe@gmail.com>
version: 8.2.0 description: Command-line tools for the Angel framework, including scaffolding.
description: The command line interface for building dart backend in Angel3 framework. homepage: https://github.com/dukefirehawk/angel/packages/angel_cli
homepage: https://angel3-framework.web.app/ name: angel_cli
repository: https://github.com/dart-backend/angel3-cli version: 3.0.0
environment: environment:
sdk: '>=3.0.0 <4.0.0' sdk: ">=2.10.0 <3.0.0"
dependencies: dependencies:
analyzer: ^6.3.0 analyzer: ^1.1.0
args: ^2.4.0 args: ^2.0.0
code_builder: ^4.5.0 code_builder: ^3.0.0
dart_style: ^2.3.0 dart_style: ^1.0.0
glob: ^2.1.0 glob: ^2.0.0
http: ^1.0.0 http: ^0.13.0
io: ^1.0.0 io: ^0.3.5
inflection3: ^0.5.3+2 inflection2: ^0.4.2
mustache_template: ^2.0.0 mustache4dart2: ^0.1.0
path: ^1.9.0 path: ^1.0.0
prompts: ^2.0.0 prompts: ^1.3.1
pubspec_parse: ^1.2.0 pubspec_parse: ^1.0.0
quiver: ^3.2.0 quiver: ^3.0.0
recase: ^4.1.0 recase: ^3.0.1
shutdown: ^0.4.3 shutdown: ^0.4.0
watcher: ^1.1.0 watcher: ^1.0.0
yaml: ^3.1.0 yaml: ^3.0.0
dev_dependencies:
lints: ^3.0.0
executables: executables:
angel3: angel3 angel: angel

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

BIN
screenshots/screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

View file

@ -1,53 +0,0 @@
import 'dart:io';
import 'package:dart_style/dart_style.dart';
void main() async {
String updateImport(String content, String oldName, String newName) {
if (!content.startsWith('import')) {
return content;
}
if (content.contains('package:$oldName/$oldName.dart')) {
return content.replaceFirst(
'package:$oldName/$oldName.dart', 'package:$newName/$newName.dart');
}
if (content.contains('package:$oldName/')) {
return content.replaceFirst('package:$oldName/', 'package:$newName/');
}
return content;
}
String updateMustacheBinding(String content, String oldName, String newName) {
if (content.contains('{{$oldName}}')) {
return content.replaceAll('{{$oldName}}', newName);
}
return content;
}
var fmt = DartFormatter();
var dir = Directory('graph');
await for (FileSystemEntity file in dir.list(recursive: true)) {
if (file is File && file.path.endsWith('.dart')) {
var lineList = await file.readAsLines();
var oldName = 'angel';
var newName = 'graph';
var replace = {oldName: newName};
if (replace.isNotEmpty) {
var contents = lineList.fold<String>('', (prev, cur) {
var updatedCur = updateImport(cur, oldName, newName);
updatedCur = updateMustacheBinding(updatedCur, oldName, newName);
return '$prev\n$updatedCur';
});
await file.writeAsString(fmt.format(contents));
print('Updated file `${file.absolute.path}`.');
}
}
}
}