feat: create app and api projects.
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
# Created by .ignore support plugin (hsz.mobi)
|
||||
### Dart template
|
||||
# See https://www.dartlang.org/guides/libraries/private-files
|
||||
|
||||
# Files and directories created by pub
|
||||
.dart_tool/
|
||||
.packages
|
||||
build/
|
||||
# If you're building an application, you may want to check-in your pubspec.lock
|
||||
pubspec.lock
|
||||
|
||||
# Directory created by dartdoc
|
||||
# If you don't generate documentation locally you can remove this line.
|
||||
doc/api/
|
||||
|
||||
# Avoid committing generated Javascript files:
|
||||
*.dart.js
|
||||
*.info.json # Produced by the --dump-info flag.
|
||||
*.js # When generated by dart2js. Don't specify *.js if your
|
||||
# project includes source files written in JavaScript.
|
||||
*.js_
|
||||
*.js.deps
|
||||
*.js.map
|
||||
|
||||
.flutter-plugins
|
||||
.flutter-plugins-dependencies
|
||||
|
||||
config.yaml
|
||||
@@ -0,0 +1,37 @@
|
||||
# dde_gesture_manager
|
||||
|
||||
## Running the Application Locally
|
||||
|
||||
Run `conduit serve` from this directory to run the application. For running within an IDE, run `bin/main.dart`. By default, a configuration file named `config.yaml` will be used.
|
||||
|
||||
You must have a `config.yaml` file that has correct database connection info, which should point to a local database. To configure a database to match your application's schema, run the following commands:
|
||||
|
||||
```
|
||||
# if this is a project, run db generate first
|
||||
conduit db generate
|
||||
conduit db upgrade --connect postgres://user:password@localhost:5432/app_name
|
||||
```
|
||||
|
||||
To generate a SwaggerUI client, run `conduit document client`.
|
||||
|
||||
## Running Application Tests
|
||||
|
||||
Tests are run with a local PostgreSQL database named `conduit_test_db`. If this database does not exist, create it from your SQL prompt:
|
||||
|
||||
CREATE DATABASE conduit_test_db;
|
||||
CREATE USER conduit_test_user WITH createdb;
|
||||
ALTER USER conduit_test_user WITH password 'conduit!';
|
||||
GRANT all ON DATABASE conduit_test_db TO conduit_test_user;
|
||||
|
||||
|
||||
To run all tests for this application, run the following in this directory:
|
||||
|
||||
```
|
||||
pub run test
|
||||
```
|
||||
|
||||
The default configuration file used when testing is `config.src.yaml`. This file should be checked into version control. It also the template for configuration files used in deployment.
|
||||
|
||||
## Deploying an Application
|
||||
|
||||
See the documentation for [Deployment](https://conduit.io/docs/deploy/).
|
||||
@@ -0,0 +1,98 @@
|
||||
analyzer:
|
||||
strong-mode:
|
||||
implicit-casts: false
|
||||
|
||||
linter:
|
||||
rules:
|
||||
- always_declare_return_types
|
||||
- always_put_control_body_on_new_line
|
||||
- always_put_required_named_parameters_first
|
||||
- always_require_non_null_named_parameters
|
||||
- annotate_overrides
|
||||
- avoid_bool_literals_in_conditional_expressions
|
||||
- avoid_double_and_int_checks
|
||||
- avoid_empty_else
|
||||
- avoid_field_initializers_in_const_classes
|
||||
- avoid_init_to_null
|
||||
- avoid_null_checks_in_equality_operators
|
||||
- avoid_positional_boolean_parameters
|
||||
- avoid_relative_lib_imports
|
||||
- avoid_renaming_method_parameters
|
||||
- avoid_return_types_on_setters
|
||||
- avoid_returning_null
|
||||
- avoid_single_cascade_in_expression_statements
|
||||
- avoid_slow_async_io
|
||||
- avoid_types_as_parameter_names
|
||||
- avoid_unused_constructor_parameters
|
||||
- await_only_futures
|
||||
- camel_case_types
|
||||
- cancel_subscriptions
|
||||
- close_sinks
|
||||
- comment_references
|
||||
- constant_identifier_names
|
||||
- control_flow_in_finally
|
||||
- directives_ordering
|
||||
- empty_catches
|
||||
- empty_constructor_bodies
|
||||
- empty_statements
|
||||
- hash_and_equals
|
||||
- implementation_imports
|
||||
- invariant_booleans
|
||||
- iterable_contains_unrelated_type
|
||||
- join_return_with_assignment
|
||||
- library_names
|
||||
- library_prefixes
|
||||
- list_remove_unrelated_type
|
||||
- literal_only_boolean_expressions
|
||||
- no_duplicate_case_values
|
||||
- non_constant_identifier_names
|
||||
- null_closures
|
||||
- package_api_docs
|
||||
- package_names
|
||||
- package_prefixed_library_names
|
||||
- parameter_assignments
|
||||
- prefer_adjacent_string_concatenation
|
||||
- prefer_asserts_in_initializer_lists
|
||||
- prefer_collection_literals
|
||||
- prefer_conditional_assignment
|
||||
- prefer_const_constructors
|
||||
- prefer_const_constructors_in_immutables
|
||||
- prefer_const_declarations
|
||||
- prefer_const_literals_to_create_immutables
|
||||
- prefer_constructors_over_static_methods
|
||||
- prefer_contains
|
||||
- prefer_equal_for_default_values
|
||||
- prefer_final_fields
|
||||
- prefer_final_locals
|
||||
- prefer_foreach
|
||||
- prefer_generic_function_type_aliases
|
||||
- prefer_interpolation_to_compose_strings
|
||||
- prefer_is_empty
|
||||
- prefer_is_not_empty
|
||||
- prefer_iterable_whereType
|
||||
- prefer_typing_uninitialized_variables
|
||||
- recursive_getters
|
||||
- slash_for_doc_comments
|
||||
- sort_constructors_first
|
||||
- sort_unnamed_constructors_first
|
||||
- test_types_in_equals
|
||||
- throw_in_finally
|
||||
- type_annotate_public_apis
|
||||
- type_init_formals
|
||||
- unawaited_futures
|
||||
- unnecessary_const
|
||||
- unnecessary_getters_setters
|
||||
- unnecessary_lambdas
|
||||
- unnecessary_new
|
||||
- unnecessary_null_aware_assignments
|
||||
- unnecessary_null_in_if_null_operators
|
||||
- unnecessary_overrides
|
||||
- unnecessary_parenthesis
|
||||
- unnecessary_statements
|
||||
- unnecessary_this
|
||||
- unrelated_type_equality_checks
|
||||
- use_rethrow_when_possible
|
||||
- use_string_buffers
|
||||
- use_to_and_as_if_applicable
|
||||
- valid_regexps
|
||||
- void_checks
|
||||
@@ -0,0 +1,13 @@
|
||||
import 'package:dde_gesture_manager/dde_gesture_manager.dart';
|
||||
|
||||
Future main() async {
|
||||
final app = Application<DdeGestureManagerChannel>()
|
||||
..options.configurationFilePath = "config.yaml"
|
||||
..options.port = 8888;
|
||||
|
||||
await app.startOnCurrentIsolate();
|
||||
|
||||
print("Application started on port: ${app.options.port}.");
|
||||
print("Click to open in browser: http://localhost:${app.options.port}");
|
||||
print("Use Ctrl-C (SIGINT) to stop running the application.");
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
database:
|
||||
username: conduit_test_user
|
||||
password: conduit!
|
||||
host: localhost
|
||||
port: 15432 # change this value
|
||||
databaseName: conduit_test_db
|
||||
@@ -0,0 +1,77 @@
|
||||
import 'package:dde_gesture_manager/model/model.dart';
|
||||
import 'package:dde_gesture_manager/dde_gesture_manager.dart';
|
||||
|
||||
/// This type initializes an application.
|
||||
///
|
||||
/// Override methods in this class to set up routes and initialize services like
|
||||
/// database connections. See http://conduit.io/docs/http/channel/.
|
||||
class DdeGestureManagerChannel extends ApplicationChannel {
|
||||
late ManagedContext context;
|
||||
|
||||
/// Initialize services in this method.
|
||||
///
|
||||
/// Implement this method to initialize services, read values from [options]
|
||||
/// and any other initialization required before constructing [entryPoint].
|
||||
///
|
||||
/// This method is invoked prior to [entryPoint] being accessed.
|
||||
@override
|
||||
Future prepare() async {
|
||||
logger.onRecord.listen(
|
||||
(rec) => print("$rec ${rec.error ?? ""} ${rec.stackTrace ?? ""}"));
|
||||
|
||||
final config =
|
||||
DdeGestureManagerConfiguration(options!.configurationFilePath!);
|
||||
context = contextWithConnectionInfo(config.database!);
|
||||
}
|
||||
|
||||
/// Construct the request channel.
|
||||
///
|
||||
/// Return an instance of some [Controller] that will be the initial receiver
|
||||
/// of all [Request]s.
|
||||
///
|
||||
/// This method is invoked after [prepare].
|
||||
@override
|
||||
Controller get entryPoint {
|
||||
final router = Router();
|
||||
|
||||
router
|
||||
.route("/model/[:id]")
|
||||
.link(() => ManagedObjectController<Model>(context));
|
||||
|
||||
router
|
||||
.route("/")
|
||||
.linkFunction((Request request) async => Response.ok('ok'));
|
||||
|
||||
return router;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper methods
|
||||
*/
|
||||
|
||||
ManagedContext contextWithConnectionInfo(
|
||||
DatabaseConfiguration connectionInfo) {
|
||||
final dataModel = ManagedDataModel.fromCurrentMirrorSystem();
|
||||
final psc = PostgreSQLPersistentStore(
|
||||
connectionInfo.username,
|
||||
connectionInfo.password,
|
||||
connectionInfo.host,
|
||||
connectionInfo.port,
|
||||
connectionInfo.databaseName);
|
||||
|
||||
return ManagedContext(dataModel, psc);
|
||||
}
|
||||
}
|
||||
|
||||
/// An instance of this class reads values from a configuration
|
||||
/// file specific to this application.
|
||||
///
|
||||
/// Configuration files must have key-value for the properties in this class.
|
||||
/// For more documentation on configuration files, see https://conduit.io/docs/configure/ and
|
||||
/// https://pub.dartlang.org/packages/safe_config.
|
||||
class DdeGestureManagerConfiguration extends Configuration {
|
||||
DdeGestureManagerConfiguration(String fileName)
|
||||
: super.fromFile(File(fileName));
|
||||
|
||||
DatabaseConfiguration? database;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/// dde_gesture_manager
|
||||
///
|
||||
/// A conduit web server.
|
||||
library dde_gesture_manager;
|
||||
|
||||
export 'dart:async';
|
||||
export 'dart:io';
|
||||
|
||||
export 'package:conduit/conduit.dart';
|
||||
|
||||
export 'channel.dart';
|
||||
@@ -0,0 +1,18 @@
|
||||
import 'package:dde_gesture_manager/dde_gesture_manager.dart';
|
||||
|
||||
class Model extends ManagedObject<_Model> implements _Model {
|
||||
@override
|
||||
void willInsert() {
|
||||
createdAt = DateTime.now().toUtc();
|
||||
}
|
||||
}
|
||||
|
||||
class _Model {
|
||||
@primaryKey
|
||||
int? id;
|
||||
|
||||
@Column(indexed: true)
|
||||
String? name;
|
||||
|
||||
DateTime? createdAt;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
name: dde_gesture_manager
|
||||
description: An conduit application with a database connection and data model.
|
||||
version: 0.0.1
|
||||
|
||||
environment:
|
||||
sdk: ">=2.12.0 <3.0.0"
|
||||
|
||||
dependencies:
|
||||
conduit: ^3.0.0
|
||||
|
||||
dev_dependencies:
|
||||
test: ^1.16.5
|
||||
conduit_test: ^3.0.0
|
||||
@@ -0,0 +1,38 @@
|
||||
import 'package:dde_gesture_manager/dde_gesture_manager.dart';
|
||||
import 'package:conduit_test/conduit_test.dart';
|
||||
|
||||
export 'package:dde_gesture_manager/dde_gesture_manager.dart';
|
||||
export 'package:conduit_test/conduit_test.dart';
|
||||
export 'package:test/test.dart';
|
||||
export 'package:conduit/conduit.dart';
|
||||
|
||||
/// A testing harness for dde_gesture_manager.
|
||||
///
|
||||
/// A harness for testing an conduit application. Example test file:
|
||||
///
|
||||
/// void main() {
|
||||
/// Harness harness = Harness()..install();
|
||||
///
|
||||
/// test("GET /path returns 200", () async {
|
||||
/// final response = await harness.agent.get("/path");
|
||||
/// expectResponse(response, 200);
|
||||
/// });
|
||||
/// }
|
||||
///
|
||||
class Harness extends TestHarness<DdeGestureManagerChannel> with TestHarnessORMMixin {
|
||||
@override
|
||||
ManagedContext? get context => channel?.context;
|
||||
|
||||
@override
|
||||
Future onSetUp() async {
|
||||
await resetData();
|
||||
}
|
||||
|
||||
@override
|
||||
Future onTearDown() async {}
|
||||
|
||||
@override
|
||||
Future seed() async {
|
||||
// restore any static data. called by resetData.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import 'harness/app.dart';
|
||||
|
||||
Future main() async {
|
||||
final harness = Harness()..install();
|
||||
|
||||
tearDown(() async {
|
||||
await harness.resetData();
|
||||
});
|
||||
|
||||
test("POST /model", () async {
|
||||
final response = await harness.agent!.post("/model", body: {"name": "Bob"});
|
||||
expect(
|
||||
response,
|
||||
hasResponse(200,
|
||||
body: {"id": isNotNull, "name": "Bob", "createdAt": isTimestamp}));
|
||||
});
|
||||
|
||||
test("GET /model/:id returns previously created object", () async {
|
||||
var response = await harness.agent!.post("/model", body: {"name": "Bob"});
|
||||
|
||||
final createdObject = response?.body.as();
|
||||
response =
|
||||
await harness.agent!.request("/model/${createdObject["id"]}").get();
|
||||
expect(
|
||||
response,
|
||||
hasResponse(200, body: {
|
||||
"id": createdObject["id"],
|
||||
"name": createdObject["name"],
|
||||
"createdAt": createdObject["createdAt"]
|
||||
}));
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Login</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Login</h1>
|
||||
<form action="{{path}}" method="POST">
|
||||
<input type="hidden" name="state" value="{{state}}">
|
||||
<input type="hidden" name="client_id" value="{{client_id}}">
|
||||
<input type="hidden" name="response_type" value="code">
|
||||
<div class="form-group">
|
||||
<label for="username">User Name</label>
|
||||
<input type="text" class="form-control" name="username" placeholder="Please enter your user name">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" class="form-control" name="password" placeholder="Please enter your password">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-success">Login</button>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user