This commit is contained in:
Tobe O 2018-12-31 11:29:40 -05:00
parent 27879f8b19
commit 5775c2ff1a
38 changed files with 166 additions and 726 deletions

2
.gitignore vendored
View file

@ -75,4 +75,6 @@ pubspec.lock
/sample_project/lib/src/services/
/sample_project/test/services/
/sample_project/
sample_project/
sample-project
.dart_tool

View file

@ -3,6 +3,9 @@
* Rename projects using `snake_case`.
* `init` now fetches from `master`.
* Remove the `1.x` option.
* Add `make migration` command.
* Replace `{{oldName}}` in the `rename` command.
* `pub get` now runs with `inheritStdio`.
# 2.0.1
* `deploy systemd` now has an `--install` option, where you can immediately

View file

@ -196,9 +196,8 @@ class InitCommand extends Command {
var pubPath = resolvePub();
print('Running pub at "$pubPath"...');
var pub = await Process.start(pubPath, ["get"],
workingDirectory: projectDir.absolute.path);
stdout.addStream(pub.stdout);
stderr.addStream(pub.stderr);
workingDirectory: projectDir.absolute.path,
mode: ProcessStartMode.inheritStdio);
var code = await pub.exitCode;
print("Pub process exited with code $code");
}

View file

@ -1,5 +1,6 @@
import 'package:args/command_runner.dart';
import 'make/controller.dart';
import 'make/migration.dart';
import 'make/model.dart';
import 'make/plugin.dart';
import 'make/service.dart';
@ -15,6 +16,7 @@ class MakeCommand extends Command {
MakeCommand() {
addSubcommand(new ControllerCommand());
addSubcommand(new MigrationCommand());
addSubcommand(new ModelCommand());
addSubcommand(new PluginCommand());
addSubcommand(new TestCommand());

View file

@ -0,0 +1,133 @@
import 'dart:async';
import 'dart:io';
import 'package:args/command_runner.dart';
import 'package:code_builder/code_builder.dart';
import 'package:dart_style/dart_style.dart';
import 'package:inflection/inflection.dart';
import 'package:io/ansi.dart';
import 'package:prompts/prompts.dart' as prompts;
import 'package:recase/recase.dart';
import '../../util.dart';
import 'maker.dart';
class MigrationCommand extends Command {
@override
String get name => 'migration';
@override
String get description => 'Generates a migration class.';
MigrationCommand() {
argParser
..addOption('name',
abbr: 'n', help: 'Specifies a name for the model class.')
..addOption('output-dir',
help: 'Specifies a directory to create the migration class in.',
defaultsTo: 'tool/migrations');
}
@override
FutureOr run() async {
String name;
if (argResults.wasParsed('name')) name = argResults['name'] as String;
if (name?.isNotEmpty != true) {
name = prompts.get('Name of model class');
}
var deps = [const MakerDependency('angel_migration', '^1.0.0-alpha')];
var rc = new ReCase(name);
var migrationLib = new Library((migrationLib) {
migrationLib
..directives.add(new Directive.import(
'package:angel_migration.dart/angel_migration.dart'))
..body.add(new Class((migrationClazz) {
migrationClazz
..name = '${rc.pascalCase}Migration'
..extend = refer('Migration');
var tableName = pluralize(rc.snakeCase);
// up()
migrationClazz.methods.add(new Method((up) {
up
..name = 'up'
..returns = refer('void')
..annotations.add(refer('override'))
..requiredParameters.add(new Parameter((b) => b
..name = 'schema'
..type = refer('Schema')))
..body = new Block((block) {
// (table) { ... }
var callback = new Method((callback) {
callback
..requiredParameters
.add(new Parameter((b) => b..name = 'table'))
..body = new Block((block) {
var table = refer('table');
block.addExpression(
(table.property('serial').call([literal('id')]))
.property('primaryKey')
.call([]),
);
block.addExpression(
table.property('date').call([
literal('created_at'),
]),
);
block.addExpression(
table.property('date').call([
literal('updated_at'),
]),
);
});
});
block.addExpression(refer('schema').property('create').call([
literal(tableName),
callback.closure,
]));
});
}));
// down()
migrationClazz.methods.add(new Method((down) {
down
..name = 'down'
..returns = refer('void')
..annotations.add(refer('override'))
..requiredParameters.add(new Parameter((b) => b
..name = 'schema'
..type = refer('Schema')))
..body = new Block((block) {
block.addExpression(
refer('schema').property('drop').call([
literal(tableName),
]),
);
});
}));
}));
});
// Save migration file
var migrationDir = new Directory.fromUri(
Directory.current.uri.resolve(argResults['output-dir'] as String));
var migrationFile =
new File.fromUri(migrationDir.uri.resolve('${rc.snakeCase}.dart'));
if (!await migrationFile.exists())
await migrationFile.create(recursive: true);
await migrationFile.writeAsString(new DartFormatter()
.format(migrationLib.accept(new DartEmitter()).toString()));
print(green.wrap(
'$checkmark Created migration file "${migrationFile.absolute.path}".'));
await depend(deps);
}
}

View file

@ -2,7 +2,6 @@ import 'dart:io';
import 'package:args/command_runner.dart';
import 'package:code_builder/code_builder.dart';
import 'package:dart_style/dart_style.dart';
import 'package:inflection/inflection.dart';
import 'package:io/ansi.dart';
import 'package:prompts/prompts.dart' as prompts;
import 'package:recase/recase.dart';
@ -21,7 +20,7 @@ class ModelCommand extends Command {
..addFlag('migration',
abbr: 'm',
help: 'Generate an angel_orm migration file.',
negatable: false)
defaultsTo: true)
..addFlag('orm', help: 'Generate angel_orm code.', negatable: false)
..addFlag('serializable',
help: 'Generate angel_serialize annotations.', defaultsTo: true)
@ -37,7 +36,6 @@ class ModelCommand extends Command {
@override
run() async {
var pubspec = await loadPubspec();
String name;
if (argResults.wasParsed('name')) name = argResults['name'] as String;
@ -52,6 +50,12 @@ class ModelCommand extends Command {
var rc = new ReCase(name);
var modelLib = new Library((modelLib) {
if (argResults['migration'] as bool) {
modelLib.directives.addAll([
new Directive.import('package:angel_migration/angel_migration.dart'),
]);
}
modelLib.directives
.add(new Directive.import('package:angel_model/angel_model.dart'));
@ -67,14 +71,14 @@ class ModelCommand extends Command {
}
if (argResults['orm'] as bool) {
modelLib.directives
.add(new Directive.import('package:angel_orm/angel_orm.dart'));
modelLib.directives.addAll([
new Directive.import('package:angel_orm/angel_orm.dart'),
]);
deps.add(const MakerDependency('angel_orm', '^1.0.0-alpha'));
}
modelLib.body.addAll([
new Code("part '${rc.snakeCase}.g.dart';"),
new Code("part '${rc.snakeCase}.serializer.g.dart';"),
]);
modelLib.body.add(new Class((modelClazz) {
@ -89,7 +93,12 @@ class ModelCommand extends Command {
}
if (argResults['orm'] as bool) {
modelClazz.annotations.add(refer('orm'));
if (argResults['migration'] as bool) {
modelClazz.annotations.add(refer('orm'));
} else {
modelClazz.annotations.add(refer('Orm')
.newInstance([], {'generateMigration': literalFalse}));
}
}
}));
});
@ -108,97 +117,14 @@ class ModelCommand extends Command {
.wrap('$checkmark Created model file "${modelFile.absolute.path}".'));
if (argResults['migration'] as bool) {
deps.add(const MakerDependency('angel_migration', '^1.0.0-alpha'));
var migrationLib = new Library((migrationLib) {
migrationLib
..directives.add(new Directive.import(
'package:angel_migration.dart/angel_migration.dart'))
..body.add(new Class((migrationClazz) {
migrationClazz
..name = '${rc.pascalCase}Migration'
..extend = refer('Migration');
var tableName = pluralize(rc.snakeCase);
// up()
migrationClazz.methods.add(new Method((up) {
up
..name = 'up'
..returns = refer('void')
..annotations.add(refer('override'))
..requiredParameters.add(new Parameter((b) => b
..name = 'schema'
..type = refer('Schema')))
..body = new Block((block) {
// (table) { ... }
var callback = new Method((callback) {
callback
..requiredParameters
.add(new Parameter((b) => b..name = 'table'))
..body = new Block((block) {
var table = refer('table');
block.addExpression(
(table.property('serial').call([literal('id')]))
.property('primaryKey')
.call([]),
);
block.addExpression(
table.property('date').call([
literal('created_at'),
]),
);
block.addExpression(
table.property('date').call([
literal('updated_at'),
]),
);
});
});
block.addExpression(refer('schema').property('create').call([
literal(tableName),
callback.closure,
]));
});
}));
// down()
migrationClazz.methods.add(new Method((down) {
down
..name = 'down'
..returns = refer('void')
..annotations.add(refer('override'))
..requiredParameters.add(new Parameter((b) => b
..name = 'schema'
..type = refer('Schema')))
..body = new Block((block) {
block.addExpression(
refer('schema').property('drop').call([
literal(tableName),
]),
);
});
}));
}));
});
// Save migration file
var migrationDir = new Directory.fromUri(
Directory.current.uri.resolve(argResults['migration-dir'] as String));
var migrationFile =
new File.fromUri(migrationDir.uri.resolve('${rc.snakeCase}.dart'));
if (!await migrationFile.exists())
await migrationFile.create(recursive: true);
await migrationFile.writeAsString(new DartFormatter()
.format(migrationLib.accept(new DartEmitter()).toString()));
print(green.wrap(
'$checkmark Created migration file "${migrationFile.absolute.path}".'));
await runner.run([
'make',
'migration',
'-n',
name,
'--output-dir',
argResults['migration-dir'] as String,
]);
}
if (deps.isNotEmpty) await depend(deps);

View file

@ -1,10 +0,0 @@
.dart_tool
.idea
.pub
.vscode
logs/
test/
build/
.analysis-options
.packages
*.g.dart

View file

@ -1,90 +0,0 @@
# Created by .ignore support plugin (hsz.mobi)
### Dart template
# See https://www.dartlang.org/tools/private-files.html
# source_gen
.dart_tool
# Files and directories created by pub
.buildlog
.packages
.project
.pub/
.scripts-bin/
build/
**/packages/
# Files created by dart2js
# (Most Dart developers will use pub build to compile Dart, use/modify these
# rules if you intend to use dart2js directly
# Convention is to use extension '.dart.js' for Dart compiled to Javascript to
# differentiate from explicit Javascript files)
*.dart.js
*.part.js
*.js.deps
*.js.map
*.info.json
# Directory created by dartdoc
doc/api/
# Don't commit pubspec lock file
# (Library packages only! Remove pattern if developing an application package)
pubspec.lock
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff:
.idea/workspace.xml
.idea/tasks.xml
.idea/dictionaries
.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:
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
### VSCode template
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
logs/
*.pem
.DS_Store
server_log.txt

View file

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.pub" />
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/build" />
<excludeFolder url="file://$MODULE_DIR$/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>

View file

@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
<component name="ProjectInspectionProfilesVisibleTreeState">
<entry key="Project Default">
<profile-state>
<expanded-state>
<State>
<id />
</State>
<State>
<id>General</id>
</State>
<State>
<id>XPath</id>
</State>
</expanded-state>
<selected-state>
<State>
<id>AngularJS</id>
</State>
</selected-state>
</profile-state>
</entry>
</component>
</project>

View file

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/angel.iml" filepath="$PROJECT_DIR$/.idea/angel.iml" />
</modules>
</component>
</project>

View file

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

View file

@ -1,11 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="prod.dart" type="DartCommandLineRunConfigurationType" factoryName="Dart Command Line Application" singleton="true" nameIsGenerated="true">
<option name="checkedMode" value="false" />
<option name="envs">
<entry key="ANGEL_ENV" value="production" />
</option>
<option name="filePath" value="$PROJECT_DIR$/bin/prod.dart" />
<option name="workingDirectory" value="$PROJECT_DIR$" />
<method />
</configuration>
</component>

View file

@ -1,19 +0,0 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Development Server",
"type": "dart",
"request": "launch",
"program": "${workspaceRoot}/bin/dev.dart",
"checkedMode": true
},
{
"name": "Production Server",
"type": "dart",
"request": "launch",
"program": "${workspaceRoot}/bin/prod.dart",
"checkedMode": true
}
]
}

View file

@ -1,27 +0,0 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "0.1.0",
"command": "pub",
"isShellCommand": true,
"echoCommand": true,
"showOutput": "always",
"tasks": [
{
"taskName": "pub:build",
"suppressTaskName": true,
"args": [
"build"
]
},
{
"taskName": "pub:serve",
"showOutput": "silent",
"suppressTaskName": true,
"isBackground": true,
"args": [
"serve"
]
}
]
}

View file

@ -1,14 +0,0 @@
FROM google/dart:2.0
COPY ./ ./
# Install dependencies, pre-build
RUN pub get
# Optionally build generaed sources.
# RUN pub run build_runner build
# Set environment, start server
ENV ANGEL_ENV=production
EXPOSE 3000
CMD dart bin/prod.dart

View file

@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2016 angel-dart
Permission is hereby granted, free of charge, to any person obtaining a copy
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:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,67 +0,0 @@
[![The Angel Framework](https://angel-dart.github.io/assets/images/logo.png)](https://angel-dart.github.io)
[![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg)](https://gitter.im/angel_dart/discussion)
[![Pub](https://img.shields.io/pub/v/angel_framework.svg)](https://pub.dartlang.org/packages/angel_framework)
[![Build status](https://travis-ci.org/angel-dart/framework.svg?branch=master)](https://travis-ci.org/angel-dart/framework)
![License](https://img.shields.io/github/license/angel-dart/framework.svg)
**A batteries-included, full-stack Web server framework for Dart.**
-----
[Wiki (in-depth documentation)](https://github.com/angel-dart/angel/wiki)
[API Documentation](http://www.dartdocs.org/documentation/angel_common/latest)
[Roadmap](https://github.com/angel-dart/roadmap/blob/master/ROADMAP.md)
[File an Issue](https://github.com/angel-dart/roadmap/issues)
[Awesome Angel :fire:](https://github.com/angel-dart/awesome-angel)
Like what you see? Please lend us a star! :star:
## Newest Tutorials
* [Dependency Injection Patterns with Angel 2](https://thosakwe.com/dependency-injection-patterns-in-angel-2/)
* [Angel 2.0.0 is Almost Here - What it Means for You](https://thosakwe.com/new-features-coming-to-angel-in-version-2-0-0/)
* [GraphQL is coming to Angel (and Dart)](https://thosakwe.com/graphql-is-coming-to-angel-and-dart/)
## Installation & Setup
*Having errors with a fresh Angel installation? See [here](https://angel-dart.gitbook.io/angel/the-basics/installation) for help.*
Once you have [Dart](https://www.dartlang.org/) installed, bootstrapping a project is as simple as running a few shell commands:
Install the [Angel CLI](https://github.com/angel-dart/cli):
```bash
pub global activate angel_cli
```
Bootstrap a project:
```bash
angel init hello
```
You can even have your server run and be *hot-reloaded* on file changes:
```bash
dart --observe bin/dev.dart
```
Next, check out the [detailed documentation](https://angel-dart.gitbook.io/angel) to learn to flesh out your project.
## Features
With features like the following, Angel is the all-in-one framework you should choose to build your next project:
* [Advanced, Modular Routing](https://github.com/angel-dart/route)
* [Middleware](https://angel-dart.gitbook.io/angel/the-basics/middleware)
* [Dependency Injection](https://angel-dart.gitbook.io/angel/the-basics/dependency-injection)
* [Strongly-typed ORM](https://github.com/angel-dart/orm)
* And [much more](https://github.com/angel-dart)...
## Basic Example
Examples and complete projects can be found here:
https://github.com/angel-dart/examples-v2

View file

@ -1,4 +0,0 @@
include: package:pedantic/analysis_options.yaml
analyzer:
strong-mode:
implicit-casts: false

View file

@ -1,26 +0,0 @@
import 'dart:io';
import 'package:sample_project/src/pretty_logging.dart';
import 'package:sample_project/sample_project.dart';
import 'package:angel_container/mirrors.dart';
import 'package:angel_framework/angel_framework.dart';
import 'package:angel_hot/angel_hot.dart';
import 'package:logging/logging.dart';
main() async {
// Watch the config/ and web/ directories for changes, and hot-reload the server.
var hot = new HotReloader(() async {
var app = new Angel(reflector: MirrorsReflector());
await app.configure(configureServer);
hierarchicalLoggingEnabled = true;
app.logger = new Logger('angel');
var sub = app.logger.onRecord.listen(prettyLog);
app.shutdownHooks.add((_) => sub.cancel());
return app;
}, [
new Directory('config'),
new Directory('lib'),
]);
var server = await hot.startServer('127.0.0.1', 3000);
print('Listening at http://${server.address.address}:${server.port}');
}

View file

@ -1,4 +0,0 @@
import 'package:sample_project/sample_project.dart';
import 'package:angel_production/angel_production.dart';
main(List<String> args) => Runner('angel', configureServer).run(args);

View file

@ -1,5 +0,0 @@
# Default server configuration.
host: 127.0.0.1
mongo_db: mongodb://localhost:27017/angel
port: 3000
jwt_secret: "IIeewWFKTdCJIT5zLh09J2gFKmfpgh0J"

View file

@ -1,2 +0,0 @@
# Development-only server configuration.
debug: true

View file

@ -1,3 +0,0 @@
# Production-only server configuration
debug: false
jwt_secret: "DJ3JnBDBS6UcnbAGwPQb3m7YWxja7KLZ"

View file

@ -1,20 +0,0 @@
library sample_project;
import 'dart:async';
import 'package:angel_framework/angel_framework.dart';
import 'package:file/local.dart';
import 'src/config/config.dart' as configuration;
import 'src/routes/routes.dart' as routes;
import 'src/services/services.dart' as services;
/// Configures the server instance.
Future configureServer(Angel app) async {
// Grab a handle to the file system, so that we can do things like
// serve static files.
var fs = const LocalFileSystem();
// Set up our application, using the plug-ins defined with this project.
await app.configure(configuration.configureServer(fs));
await app.configure(services.configureServer);
await app.configure(routes.configureServer(fs));
}

View file

@ -1,32 +0,0 @@
library sample_project.src.config;
import 'package:angel_configuration/angel_configuration.dart';
import 'package:angel_framework/angel_framework.dart';
import 'package:angel_jael/angel_jael.dart';
import 'package:file/file.dart';
import 'plugins/plugins.dart' as plugins;
/// This is a perfect place to include configuration and load plug-ins.
AngelConfigurer configureServer(FileSystem fileSystem) {
return (Angel app) async {
// Load configuration from the `config/` directory.
//
// See: https://github.com/angel-dart/configuration
await app.configure(configuration(fileSystem));
// Configure our application to render Jael templates from the `views/` directory.
//
// See: https://github.com/angel-dart/jael
await app.configure(jael(fileSystem.directory('views')));
// Apply another plug-ins, i.e. ones that *you* have written.
//
// Typically, the plugins in `lib/src/config/plugins/plugins.dart` are plug-ins
// that add functionality specific to your application.
//
// If you write a plug-in that you plan to use again, or are
// using one created by the community, include it in
// `lib/src/config/config.dart`.
await plugins.configureServer(app);
};
}

View file

@ -1,8 +0,0 @@
library sample_project.src.config.plugins;
import 'dart:async';
import 'package:angel_framework/angel_framework.dart';
Future configureServer(Angel app) async {
// Include any plugins you have made here.
}

View file

@ -1,8 +0,0 @@
library sample_project.src.routes.controllers;
import 'dart:async';
import 'package:angel_framework/angel_framework.dart';
Future configureServer(Angel app) async {
/// Controllers will not function unless wired to the application!
}

View file

@ -1,61 +0,0 @@
library sample_project.src.routes;
import 'package:angel_framework/angel_framework.dart';
import 'package:angel_static/angel_static.dart';
import 'package:file/file.dart';
import 'controllers/controllers.dart' as controllers;
/// Put your app routes here!
///
/// See the wiki for information about routing, requests, and responses:
/// * https://github.com/angel-dart/angel/wiki/Basic-Routing
/// * https://github.com/angel-dart/angel/wiki/Requests-&-Responses
AngelConfigurer configureServer(FileSystem fileSystem) {
return (Angel app) async {
// Typically, you want to mount controllers first, after any global middleware.
await app.configure(controllers.configureServer);
// Render `views/hello.jl` when a user visits the application root.
app.get('/', (req, res) => res.render('hello'));
// Mount static server at web in development.
// The `CachingVirtualDirectory` variant of `VirtualDirectory` also sends `Cache-Control` headers.
//
// In production, however, prefer serving static files through NGINX or a
// similar reverse proxy.
//
// Read the following two sources for documentation:
// * https://medium.com/the-angel-framework/serving-static-files-with-the-angel-framework-2ddc7a2b84ae
// * https://github.com/angel-dart/static
if (!app.isProduction) {
var vDir = VirtualDirectory(
app,
fileSystem,
source: fileSystem.directory('web'),
);
app.fallback(vDir.handleRequest);
}
// Throw a 404 if no route matched the request.
app.fallback((req, res) => throw AngelHttpException.notFound());
// Set our application up to handle different errors.
//
// Read the following for documentation:
// * https://github.com/angel-dart/angel/wiki/Error-Handling
var oldErrorHandler = app.errorHandler;
app.errorHandler = (e, req, res) async {
if (!req.accepts('text/html'))
return await oldErrorHandler(e, req, res);
else {
if (e.statusCode == 404) {
return await res
.render('error', {'message': 'No file exists at ${req.uri}.'});
}
return await res.render('error', {'message': e.message});
}
};
};
}

View file

@ -1,14 +0,0 @@
library sample_project.services;
import 'dart:async';
import 'package:angel_framework/angel_framework.dart';
/// Configure our application to use *services*.
/// Services must be wired to the app via `app.use`.
///
/// They provide many benefits, such as instant REST API generation,
/// and respond to both REST and WebSockets.
///
/// Read more here:
/// https://github.com/angel-dart/angel/wiki/Service-Basics
Future configureServer(Angel app) async {}

View file

@ -1,20 +0,0 @@
name: sample_project
description: An app that's going to be amazing pretty soon.
publish_to: none # Ensure we don't accidentally publish our private code! ;)
environment:
sdk: '>=2.0.0-dev <3.0.0'
homepage: https://github.com/angel-dart/angel
dependencies:
angel_auth: ^2.0.0-alpha # Supports stateless authentication via JWT
angel_configuration: ^2.0.0 # Loads application configuration, along with support for .env files.
angel_framework: ^2.0.0-alpha # The core server library.
angel_jael: ^2.0.0 # Server-side templating engine
angel_production: ^1.0.0-alpha
angel_static: ^2.0.0-alpha # Static file server
angel_validate: ^2.0.0-alpha # Allows for validation of input data
dev_dependencies:
angel_hot: ^2.0.0 # Hot-reloading support. :)
angel_test: ^2.0.0-alpha # Utilities for testing Angel servers.
io: ^0.3.2
pedantic: ^1.0.0
test: ^1.0.0

View file

@ -1,43 +0,0 @@
import 'package:sample_project/sample_project.dart';
import 'package:angel_framework/angel_framework.dart';
import 'package:angel_test/angel_test.dart';
import 'package:test/test.dart';
// Angel also includes facilities to make testing easier.
//
// `package:angel_test` ships a client that can test
// both plain HTTP and WebSockets.
//
// Tests do not require your server to actually be mounted on a port,
// so they will run faster than they would in other frameworks, where you
// would have to first bind a socket, and then account for network latency.
//
// See the documentation here:
// https://github.com/angel-dart/test
//
// If you are unfamiliar with Dart's advanced testing library, you can read up
// here:
// https://github.com/dart-lang/test
main() async {
TestClient client;
setUp(() async {
var app = Angel();
await app.configure(configureServer);
client = await connectTo(app);
});
tearDown(() async {
await client.close();
});
test('index returns 200', () async {
// Request a resource at the given path.
var response = await client.get('/');
// Expect a 200 response.
expect(response, hasStatus(200));
});
}

View file

@ -1,5 +0,0 @@
<extend src="layout.jael">
<block name="content">
<div class="title">{{ message }}</div>
</block>
</extend>

View file

@ -1,5 +0,0 @@
<extend src="layout.jael">
<block name="content">
<div class="title">Angel</div>
</block>
</extend>

View file

@ -1,17 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>{{ title ?? 'Angel' }}</title>
<link href="https://fonts.googleapis.com/css?family=Lato:100" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="/css/site.css">
<link rel="icon" href="/images/favicon.png">
</head>
<body>
<div class="container">
<div class="content">
<block name="content"></block>
</div>
</div>
</body>
</html>

View file

@ -1,27 +0,0 @@
html, body {
height: 100%;
}
body {
margin: 0;
padding: 0;
width: 100%;
display: table;
font-weight: 100;
font-family: 'Lato', sans-serif;
}
.container {
text-align: center;
display: table-cell;
vertical-align: middle;
}
.content {
text-align: center;
display: inline-block;
}
.title {
font-size: 96px;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -1,2 +0,0 @@
User-agent: *
Disallow: /admin