Compare commits

...

18 commits

Author SHA1 Message Date
thomashii
e8c109bce6 Updated dependencies 2023-06-23 21:02:40 +08:00
thomashii
c161ad984b Updated to v8 2023-06-19 23:35:09 +08:00
Thomas Hii
71e10b57d2
Merge pull request #4 from dukefirehawk/v6/angel3-graphql
V6/angel3 graphql
2022-04-26 09:16:41 +08:00
thomashii
b3b5d01aec Updated log message 2022-04-26 08:22:40 +08:00
thomashii
563f7f8dde Updated to SDK 2.16.0 2022-04-26 08:11:53 +08:00
thomashii
8facd65c14 Updated packages 2022-03-18 09:20:40 +08:00
thomashii
d8c3736955 Updated graphql template 2021-09-25 18:39:19 +08:00
thomashii
8c63811c50 Updated packages 2021-08-19 08:25:45 +08:00
thomashii
5c4eded653 Updated graphql 2021-07-17 13:05:34 +08:00
thomashii
16565c26cd Updated angel3-graphql 2021-06-14 09:37:53 +08:00
thomashii
9d9a94965e Migrated to NNBD 2021-06-14 09:28:20 +08:00
thomashii
77b61d30ed Graphql template for SDK 2.12.x 2021-03-07 20:59:21 +08:00
Tobe O
35b4706078 Merge branch 'master' into graphql 2019-10-09 14:27:01 -04:00
Tobe O
9f59ab1336 Merge branch 'master' into graphql 2019-10-09 14:22:05 -04:00
Tobe O
45f1a2f6f6 Merge branch 'master' into graphql 2019-05-01 19:33:15 -04:00
Tobe O
708502e0dc Merge branch 'master' into graphql 2019-05-01 19:30:25 -04:00
Tobe O
0148812c60 Add Graphiql redirect, css, etc. 2019-04-29 13:20:47 -04:00
Tobe O
9cfb56f123 Complete todo api 2019-04-29 13:12:23 -04:00
30 changed files with 424 additions and 274 deletions

3
.github/FUNDING.yml vendored
View file

@ -1,3 +0,0 @@
# These are supported funding model platforms
github: [thosakwe]

25
.gitignore vendored
View file

@ -37,25 +37,7 @@ pubspec.lock
# 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
@ -78,11 +60,8 @@ crashlytics-build.properties
fabric.properties
### VSCode template
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.vscode/
.metals/
logs/
*.pem

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>

7
CHANGELOG.md Normal file
View file

@ -0,0 +1,7 @@
# Change Log
## 1.0.0
* Changed to use `angel3` packages
* Updated to support NNBD
* Updated linter to `package:lints`

View file

@ -1,14 +1,23 @@
FROM google/dart:latest
FROM dart:latest
COPY ./ ./
# Copy all the source code
COPY ./config /app/config
COPY ./lib /app/lib
COPY ./bin /app/bin
COPY ./views /app/views
COPY ./web /app/web
COPY ./*.yaml /app/
# Install dependencies, pre-build
RUN pub get
WORKDIR /app
RUN dart pub upgrade
# Optionally build generaed sources.
# Optionally build generated sources.
# RUN pub run build_runner build
# Set environment, start server
# Set environment, start server in JIT mode
ENV ANGEL_ENV=production
EXPOSE 3000
CMD dart bin/prod.dart
CMD dart ./bin/prod.dart -p 3000 -a 0.0.0.0
# Use -j flag to set higher number of isolates
#CMD dart ./bin/prod.dart -p 3000 -a 0.0.0.0 -j 50

42
LICENSE
View file

@ -1,21 +1,29 @@
The MIT License (MIT)
BSD 3-Clause License
Copyright (c) 2016 angel-dart
Copyright (c) 2021, dukefirehawk.com
All rights reserved.
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:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
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.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
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,60 +1,35 @@
[![The Angel Framework](https://angel-dart.github.io/assets/images/logo.png)](https://angel-dart.dev)
# Graphql Starter Application for Angel3 framework
[![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 polished, production-ready backend framework in Dart.**
*Note: This repo is an application boilerplate ,and not the underlying framework library.*
-----
## About
Angel is a full-stack Web framework in Dart. It aims to
streamline development by providing many common features
out-of-the-box in a consistent manner.
With features like the following, Angel is the all-in-one framework you should choose to build your next project:
* [GraphQL Support](https://github.com/angel-dart/graphql)
* [PostgreSQL ORM](https://github.com/angel-dart/orm)
* [Dependency Injection](https://docs.angel-dart.dev/guides/dependency-injection)
* And [much more](https://github.com/angel-dart)...
This is a graphql starter application for [Angel3 framework](https://angel3-framework.web.app) which is a full-stack Web framework in Dart.
## Installation & Setup
Once you have [Dart](https://www.dartlang.org/) installed, bootstrapping a project is as simple as running a few shell commands:
1. Download and install [Dart](https://dart.dev/get-dart).
Install the [Angel CLI](https://github.com/angel-dart/cli):
### Development
```bash
pub global activate angel_cli
```
1. Run the following command to start Angel3 server in dev mode to *hot-reloaded* on file changes:
Bootstrap a project:
```bash
dart --observe bin/dev.dart
```
```bash
angel init hello
```
2. Modify the code and watch the changes applied to the application
You can even have your server run and be *hot-reloaded* on file changes:
### Production
```bash
dart --observe bin/dev.dart
```
1. Run the following command:
Next, check out the [detailed documentation](https://docs.angel-dart.dev/v/2.x) to learn to flesh out your project.
```bash
dart bin/prod.dart
```
## Examples and Documentation
Visit the [documentation](https://docs.angel-dart.dev/v/2.x)
for dozens of guides and resources, including video tutorials,
to get up and running as quickly as possible with Angel.
2. Run as docker. Edit and run the provided `Dockerfile` to build the image.
Examples and complete projects can be found
[here](https://github.com/angel-dart/examples-v2).
## Resources
Visit the [Developer Guide](https://angel3-docs.dukefirehawk.com/guides) for dozens of guides and resources, including video tutorials, to get up and running as quickly as possible with Angel3.
You can also view the [API Documentation](http://www.dartdocs.org/documentation/angel_framework/latest).
There is also an [Awesome Angel :fire:](https://github.com/angel-dart/awesome-angel) list.
Examples and complete projects can be found [here](https://angel3-framework.web.app/#/examples).
You can also view the [API Documentation](https://pub.dev/documentation/angel3_framework/latest/).

View file

@ -1,8 +1 @@
include: package:pedantic/analysis_options.yaml
analyzer:
strong-mode:
implicit-casts: false
linter:
rules:
- unnecessary_const
- unnecessary_new
include: package:lints/recommended.yaml

View file

@ -1,17 +1,17 @@
import 'dart:io';
import 'package:angel/src/pretty_logging.dart';
import 'package:belatuk_pretty_logging/belatuk_pretty_logging.dart';
import 'package:angel/angel.dart';
import 'package:angel_container/mirrors.dart';
import 'package:angel_framework/angel_framework.dart';
import 'package:angel_hot/angel_hot.dart';
import 'package:angel3_container/mirrors.dart';
import 'package:angel3_framework/angel3_framework.dart';
import 'package:angel3_hot/angel3_hot.dart';
import 'package:logging/logging.dart';
main() async {
void main() async {
// Watch the config/ and web/ directories for changes, and hot-reload the server.
hierarchicalLoggingEnabled = true;
var hot = HotReloader(() async {
var logger = Logger.detached('{{angel}}')
var logger = Logger.detached('Angel3')
..level = Level.ALL
..onRecord.listen(prettyLog);
var app = Angel(logger: logger, reflector: MirrorsReflector());
@ -24,5 +24,5 @@ main() async {
var server = await hot.startServer('127.0.0.1', 3000);
print(
'{{angel}} server listening at http://${server.address.address}:${server.port}');
'[Angel3] server listening at http://${server.address.address}:${server.port}');
}

View file

@ -1,6 +1,6 @@
import 'package:angel/angel.dart';
import 'package:angel_container/mirrors.dart';
import 'package:angel_production/angel_production.dart';
import 'package:angel3_container/mirrors.dart';
import 'package:angel3_production/angel3_production.dart';
// NOTE: By default, the Runner class does not use the `MirrorsReflector`, or any
// reflector, by default.
@ -17,7 +17,7 @@ import 'package:angel_production/angel_production.dart';
// so use it if possible.
//
// However, the following alternatives exist:
// * Generation via `package:angel_container_generator`
// * Generation via `package:angel3_container_generator`
// * Creating an instance of `StaticReflector`
// * Manually implementing the `Reflector` interface (cumbersome; not recommended)
//
@ -25,6 +25,5 @@ import 'package:angel_production/angel_production.dart';
// so in the meantime, visit the Angel chat for further questions:
//
// https://gitter.im/angel_dart/discussion
main(List<String> args) =>
Runner('{{angel}}', configureServer, reflector: MirrorsReflector())
.run(args);
void main(List<String> args) =>
Runner('Angel3', configureServer, reflector: MirrorsReflector()).run(args);

View file

@ -1,8 +1,6 @@
/// Your very own web application!
library angel;
import 'dart:async';
import 'package:angel_framework/angel_framework.dart';
import 'package:angel3_framework/angel3_framework.dart';
import 'package:file/local.dart';
import 'src/config/config.dart' as configuration;
import 'src/routes/routes.dart' as routes;

View file

@ -1,9 +1,6 @@
/// Configuration for this Angel instance.
library angel.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:angel3_configuration/angel3_configuration.dart';
import 'package:angel3_framework/angel3_framework.dart';
import 'package:angel3_jael/angel3_jael.dart';
import 'package:file/file.dart';
import 'plugins/plugins.dart' as plugins;

View file

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

11
lib/src/models/todo.dart Normal file
View file

@ -0,0 +1,11 @@
import 'package:angel3_serialize/angel3_serialize.dart';
import 'package:graphql_schema2/graphql_schema2.dart';
part 'todo.g.dart';
@graphQLClass
@serializable
abstract class _Todo extends Model {
String? get text;
bool? get isComplete;
}

155
lib/src/models/todo.g.dart Normal file
View file

@ -0,0 +1,155 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'todo.dart';
// **************************************************************************
// JsonModelGenerator
// **************************************************************************
@generatedSerializable
class Todo extends _Todo {
Todo({this.id, this.text, this.isComplete, this.createdAt, this.updatedAt});
@override
final String? id;
@override
final String? text;
@override
final bool? isComplete;
@override
final DateTime? createdAt;
@override
final DateTime? updatedAt;
Todo copyWith(
{String? id,
String? text,
bool? isComplete,
DateTime? createdAt,
DateTime? updatedAt}) {
return Todo(
id: id ?? this.id,
text: text ?? this.text,
isComplete: isComplete ?? this.isComplete,
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt);
}
@override
bool operator ==(other) {
return other is _Todo &&
other.id == id &&
other.text == text &&
other.isComplete == isComplete &&
other.createdAt == createdAt &&
other.updatedAt == updatedAt;
}
@override
int get hashCode {
return hashObjects([id, text, isComplete, createdAt, updatedAt]);
}
@override
String toString() {
return 'Todo(id=$id, text=$text, isComplete=$isComplete, createdAt=$createdAt, updatedAt=$updatedAt)';
}
Map<String, dynamic> toJson() {
return TodoSerializer.toMap(this);
}
}
// **************************************************************************
// SerializerGenerator
// **************************************************************************
const TodoSerializer todoSerializer = TodoSerializer();
class TodoEncoder extends Converter<Todo, Map> {
const TodoEncoder();
@override
Map convert(Todo model) => TodoSerializer.toMap(model);
}
class TodoDecoder extends Converter<Map, Todo> {
const TodoDecoder();
@override
Todo convert(Map map) => TodoSerializer.fromMap(map);
}
class TodoSerializer extends Codec<Todo, Map> {
const TodoSerializer();
@override
TodoEncoder get encoder => const TodoEncoder();
@override
TodoDecoder get decoder => const TodoDecoder();
static Todo fromMap(Map map) {
return Todo(
id: map['id'] as String?,
text: map['text'] as String?,
isComplete: map['is_complete'] as bool?,
createdAt: map['created_at'] != null
? (map['created_at'] is DateTime
? (map['created_at'] as DateTime?)
: DateTime.parse(map['created_at'].toString()))
: null,
updatedAt: map['updated_at'] != null
? (map['updated_at'] is DateTime
? (map['updated_at'] as DateTime?)
: DateTime.parse(map['updated_at'].toString()))
: null);
}
static Map<String, dynamic> toMap(_Todo model) {
return {
'id': model.id,
'text': model.text,
'is_complete': model.isComplete,
'created_at': model.createdAt?.toIso8601String(),
'updated_at': model.updatedAt?.toIso8601String()
};
}
}
abstract class TodoFields {
static const List<String> allFields = <String>[
id,
text,
isComplete,
createdAt,
updatedAt
];
static const String id = 'id';
static const String text = 'text';
static const String isComplete = 'is_complete';
static const String createdAt = 'created_at';
static const String updatedAt = 'updated_at';
}
// **************************************************************************
// _GraphQLGenerator
// **************************************************************************
/// Auto-generated from [Todo].
final GraphQLObjectType todoGraphQLType =
objectType('Todo', isInterface: false, interfaces: [], fields: [
field('id', graphQLString),
field('text', graphQLString),
field('is_complete', graphQLBoolean),
field('created_at', graphQLDate),
field('updated_at', graphQLDate),
field('idAsInt', graphQLInt)
]);

View file

@ -1,38 +0,0 @@
import 'package:angel_http_exception/angel_http_exception.dart';
import 'package:logging/logging.dart';
import 'package:io/ansi.dart';
/// Prints the contents of a [LogRecord] with pretty colors.
void prettyLog(LogRecord record) {
var code = chooseLogColor(record.level);
if (record.error == null) print(code.wrap(record.toString()));
if (record.error != null) {
var err = record.error;
if (err is AngelHttpException && err.statusCode != 500) return;
print(code.wrap(record.toString() + '\n'));
print(code.wrap(err.toString()));
if (record.stackTrace != null) {
print(code.wrap(record.stackTrace.toString()));
}
}
}
/// Chooses a color based on the logger [level].
AnsiCode chooseLogColor(Level level) {
if (level == Level.SHOUT)
return backgroundRed;
else if (level == Level.SEVERE)
return red;
else if (level == Level.WARNING)
return yellow;
else if (level == Level.INFO)
return cyan;
else if (level == Level.CONFIG ||
level == Level.FINE ||
level == Level.FINER ||
level == Level.FINEST) return lightGray;
return resetAll;
}

View file

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

View file

@ -0,0 +1,20 @@
import 'package:angel3_framework/angel3_framework.dart';
import 'package:angel3_graphql/angel3_graphql.dart';
import 'package:graphql_server2/graphql_server2.dart';
import 'schema.dart';
/// Configures the [app] to server GraphQL.
void configureServer(Angel app) {
// Create a [GraphQL] service instance, using our schema.
var schema = createSchema(app);
var graphQL = GraphQL(schema);
// Mount a handler that responds to GraphQL queries.
app.all('/graphql', graphQLHttp(graphQL));
// In development, serve the GraphiQL IDE/editor.
// More info: https://github.com/graphql/graphiql
if (!app.environment.isProduction) {
app.get('/graphiql', graphiQL());
}
}

View file

@ -0,0 +1,22 @@
import 'package:angel3_framework/angel3_framework.dart';
import 'package:graphql_schema2/graphql_schema2.dart';
import 'todo.dart';
/// Creates a GraphQL schema that manages an in-memory store of
/// Todo items.
GraphQLSchema createSchema(Angel app) {
var queryType = objectType(
'TodoQuery',
fields: todoQueryFields(app),
);
var mutationType = objectType(
'TodoMutation',
fields: todoMutationFields(app),
);
return graphQLSchema(
queryType: queryType,
mutationType: mutationType,
);
}

View file

@ -0,0 +1,73 @@
import 'package:angel/src/models/todo.dart';
import 'package:angel3_framework/angel3_framework.dart';
import 'package:angel3_graphql/angel3_graphql.dart';
import 'package:graphql_schema2/graphql_schema2.dart';
/// Find or create an in-memory Todo store.
MapService? _getTodoService(Angel app) {
const key = 'todoService';
// If there is already an existing singleton, return it.
if (app.container.hasNamed(key)) {
return app.container.findByName<MapService>(key);
}
// Create an in-memory service. We will use this
// as the backend to store Todo objects, serialized to Maps.
var mapService = MapService();
// Register this service as a named singleton in the app container,
// so that we do not inadvertently create another instance.
app.container.registerNamedSingleton(key, mapService);
return mapService;
}
/// Returns fields to be inserted into the query type.
Iterable<GraphQLObjectField> todoQueryFields(Angel app) {
var todoService = _getTodoService(app)!;
// Here, we use special resolvers to read data from our store.
return [
field(
'todos',
listOf(todoGraphQLType),
resolve: resolveViaServiceIndex(todoService),
),
field(
'todo',
todoGraphQLType,
resolve: resolveViaServiceRead(todoService),
inputs: [
GraphQLFieldInput('id', graphQLString.nonNullable()),
],
),
];
}
/// Returns fields to be inserted into the query type.
Iterable<GraphQLObjectField> todoMutationFields(Angel app) {
var todoService = _getTodoService(app)!;
var todoInputType = todoGraphQLType.toInputObject('TodoInput');
// This time, we use resolvers to modify the data in the store.
return [
field(
'createTodo',
todoGraphQLType,
resolve: resolveViaServiceCreate(todoService),
inputs: [
GraphQLFieldInput('data', todoInputType.nonNullable()),
],
),
field(
'modifyTodo',
todoGraphQLType,
resolve: resolveViaServiceModify(todoService),
inputs: [
GraphQLFieldInput('id', graphQLString.nonNullable()),
GraphQLFieldInput('data', todoInputType.nonNullable()),
],
),
];
}

View file

@ -1,21 +1,22 @@
/// This app's route configuration.
library angel.src.routes;
import 'package:angel_framework/angel_framework.dart';
import 'package:angel_static/angel_static.dart';
import 'package:angel3_framework/angel3_framework.dart';
import 'package:angel3_static/angel3_static.dart';
import 'package:file/file.dart';
import 'controllers/controllers.dart' as controllers;
import 'graphql/graphql.dart' as graphql;
/// 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
/// * https://angel3-docs.dukefirehawk.com/guides/basic-routing
/// * https://angel3-docs.dukefirehawk.com/guides/requests-and-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);
// Mount our GraphQL routes as well.
await app.configure(graphql.configureServer);
// Render `views/hello.jl` when a user visits the application root.
app.get('/', (req, res) => res.render('hello'));
@ -27,7 +28,7 @@ AngelConfigurer configureServer(FileSystem fileSystem) {
//
// 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
// * https://pub.dev/packages/angel3_static
if (!app.environment.isProduction) {
var vDir = VirtualDirectory(
app,
@ -43,7 +44,7 @@ AngelConfigurer configureServer(FileSystem fileSystem) {
// Set our application up to handle different errors.
//
// Read the following for documentation:
// * https://github.com/angel-dart/angel/wiki/Error-Handling
// * https://angel3-docs.dukefirehawk.com/guides/error-handling
var oldErrorHandler = app.errorHandler;
app.errorHandler = (e, req, res) async {

View file

@ -1,8 +1,5 @@
/// Declare services here!
library angel.services;
import 'dart:async';
import 'package:angel_framework/angel_framework.dart';
import 'package:angel3_framework/angel3_framework.dart';
/// Configure our application to use *services*.
/// Services must be wired to the app via `app.use`.

View file

@ -1,20 +1,30 @@
name: angel
description: An app that's going to be amazing pretty soon.
publish_to: none # Ensure we don't accidentally publish our private code! ;)
description: A graphql starter application for Angel3 framework
publish_to: none
environment:
sdk: '>=2.0.0-dev <3.0.0'
homepage: https://github.com/angel-dart/angel
sdk: '>=3.0.0 <4.0.0'
dependencies:
angel_auth: ^2.0.0 # Supports stateless authentication via JWT
angel_configuration: ^2.0.0 # Loads application configuration, along with support for .env files.
angel_framework: ^2.0.0 # The core server library.
angel_jael: ^2.0.0 # Server-side templating engine
angel_production: ^1.0.0 # Production application runner.
angel_static: ^2.0.0 # Static file server
angel_validate: ^2.0.0 # Allows for validation of input data
angel3_auth: ^8.0.0
angel3_configuration: ^8.0.0
angel3_framework: ^8.0.0
angel3_graphql: ^8.0.0
angel3_jael: ^8.0.0
angel3_production: ^8.0.0
angel3_container: ^8.0.0
angel3_static: ^8.0.0
angel3_validate: ^8.0.0
angel3_serialize: ^8.0.0
graphql_server2: ^6.0.0
graphql_schema2: ^6.0.0
file: ^7.0.0
logging: ^1.2.0
dev_dependencies:
angel_hot: ^2.0.0 # Hot-reloading support. :)
angel_test: ^2.0.0 # Utilities for testing Angel servers.
io: ^0.3.2 # For pretty printing.
pedantic: ^1.0.0 # Enforces Dart style conventions.
test: ^1.0.0 # For unit testing.
angel3_hot: ^8.0.0
angel3_serialize_generator: ^8.0.0
angel3_test: ^8.0.0
graphql_generator2: ^6.0.0
belatuk_pretty_logging: ^6.0.0
build_runner: ^2.0.4
io: ^1.0.0
test: ^1.21.0
lints: ^2.1.1

View file

@ -1,6 +1,6 @@
import 'package:angel/angel.dart';
import 'package:angel_framework/angel_framework.dart';
import 'package:angel_test/angel_test.dart';
import 'package:angel3_framework/angel3_framework.dart';
import 'package:angel3_test/angel3_test.dart';
import 'package:test/test.dart';
// Angel also includes facilities to make testing easier.
@ -19,8 +19,8 @@ import 'package:test/test.dart';
// here:
// https://github.com/dart-lang/test
main() async {
TestClient client;
void main() async {
late TestClient client;
setUp(() async {
var app = Angel();
@ -35,7 +35,7 @@ main() async {
test('index returns 200', () async {
// Request a resource at the given path.
var response = await client.get('/');
var response = await client.get(Uri.parse('/'));
// Expect a 200 response.
expect(response, hasStatus(200));

View file

@ -1,5 +1,8 @@
<extend src="layout.jael">
<block name="content">
<div class="title">Angel</div>
<p>
<a href="/graphiql">Click here</a> to access GraphiQL.
</p>
</block>
</extend>

View file

@ -11,6 +11,16 @@ body {
font-family: 'Lato', sans-serif;
}
a {
color: rgb(8, 114, 175) !important;
font-weight: 900;
text-decoration: none;
}
p {
font-size: 1.3em;
}
.container {
text-align: center;
display: table-cell;