From d77f49a21bb6f926945236253540c42f0dbb1412 Mon Sep 17 00:00:00 2001 From: Elias Projahn Date: Sat, 25 Apr 2020 13:21:38 +0200 Subject: [PATCH] Add basic http server --- server/.gitignore | 31 ++++++++++++++++++++ server/bin/main.dart | 19 +++++++++++++ server/config.src.yaml | 3 ++ server/config.yaml | 3 ++ server/lib/musicus_server.dart | 2 ++ server/lib/src/compositions.dart | 14 +++++++++ server/lib/src/configuration.dart | 13 +++++++++ server/lib/src/ensembles.dart | 36 +++++++++++++++++++++++ server/lib/src/instruments.dart | 36 +++++++++++++++++++++++ server/lib/src/performances.dart | 14 +++++++++ server/lib/src/persons.dart | 36 +++++++++++++++++++++++ server/lib/src/recordings.dart | 26 +++++++++++++++++ server/lib/src/server.dart | 44 +++++++++++++++++++++++++++++ server/lib/src/work_parts.dart | 14 +++++++++ server/lib/src/work_recordings.dart | 14 +++++++++ server/lib/src/works.dart | 26 +++++++++++++++++ server/pubspec.yaml | 9 ++++++ 17 files changed, 340 insertions(+) create mode 100644 server/.gitignore create mode 100644 server/bin/main.dart create mode 100644 server/config.src.yaml create mode 100644 server/config.yaml create mode 100644 server/lib/musicus_server.dart create mode 100644 server/lib/src/compositions.dart create mode 100644 server/lib/src/configuration.dart create mode 100644 server/lib/src/ensembles.dart create mode 100644 server/lib/src/instruments.dart create mode 100644 server/lib/src/performances.dart create mode 100644 server/lib/src/persons.dart create mode 100644 server/lib/src/recordings.dart create mode 100644 server/lib/src/server.dart create mode 100644 server/lib/src/work_parts.dart create mode 100644 server/lib/src/work_recordings.dart create mode 100644 server/lib/src/works.dart create mode 100644 server/pubspec.yaml diff --git a/server/.gitignore b/server/.gitignore new file mode 100644 index 0000000..a242fcb --- /dev/null +++ b/server/.gitignore @@ -0,0 +1,31 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# VS Code related +.vscode/ + +# Flutter/Dart/Pub related +**/*.g.dart +**/doc/api/ +.dart_tool/ +pubspec.lock +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ diff --git a/server/bin/main.dart b/server/bin/main.dart new file mode 100644 index 0000000..3fe0109 --- /dev/null +++ b/server/bin/main.dart @@ -0,0 +1,19 @@ +import 'package:aqueduct/aqueduct.dart'; +import 'package:musicus_server/musicus_server.dart'; + +Future main() async { + final configFilePath = 'config.yaml'; + final config = MusicusServerConfiguration(configFilePath); + + final server = Application() + ..options.configurationFilePath = configFilePath + ..options.address = config.host + ..options.port = config.port; + + await server.start( + consoleLogging: true, + ); + + print('Database: ${config.dbPath ?? 'memory'}'); + print('Listening on ${config.host}:${config.port}'); +} diff --git a/server/config.src.yaml b/server/config.src.yaml new file mode 100644 index 0000000..ed01e99 --- /dev/null +++ b/server/config.src.yaml @@ -0,0 +1,3 @@ +# A dbPath of null means that we want an in-memory database. +host: localhost +port: 1833 \ No newline at end of file diff --git a/server/config.yaml b/server/config.yaml new file mode 100644 index 0000000..203c392 --- /dev/null +++ b/server/config.yaml @@ -0,0 +1,3 @@ +host: localhost +port: 1833 +dbPath: db.sqlite \ No newline at end of file diff --git a/server/lib/musicus_server.dart b/server/lib/musicus_server.dart new file mode 100644 index 0000000..148da78 --- /dev/null +++ b/server/lib/musicus_server.dart @@ -0,0 +1,2 @@ +export 'src/configuration.dart'; +export 'src/server.dart'; \ No newline at end of file diff --git a/server/lib/src/compositions.dart b/server/lib/src/compositions.dart new file mode 100644 index 0000000..92c3ab8 --- /dev/null +++ b/server/lib/src/compositions.dart @@ -0,0 +1,14 @@ +import 'package:aqueduct/aqueduct.dart'; +import 'package:musicus_database/musicus_database.dart'; + +class CompositionsController extends ResourceController { + final Database db; + + CompositionsController(this.db); + + @Operation.get('id') + Future getWorks(@Bind.path('id') int id) async { + final works = db.worksByComposer(id).get(); + return Response.ok(works); + } +} diff --git a/server/lib/src/configuration.dart b/server/lib/src/configuration.dart new file mode 100644 index 0000000..3d3af7c --- /dev/null +++ b/server/lib/src/configuration.dart @@ -0,0 +1,13 @@ +import 'dart:io'; + +import 'package:aqueduct/aqueduct.dart'; + +class MusicusServerConfiguration extends Configuration { + MusicusServerConfiguration(String fileName) : super.fromFile(File(fileName)); + + String host; + int port; + + @optionalConfiguration + String dbPath; +} \ No newline at end of file diff --git a/server/lib/src/ensembles.dart b/server/lib/src/ensembles.dart new file mode 100644 index 0000000..1d747fc --- /dev/null +++ b/server/lib/src/ensembles.dart @@ -0,0 +1,36 @@ +import 'package:aqueduct/aqueduct.dart'; +import 'package:musicus_database/musicus_database.dart'; + +class EnsemblesController extends ResourceController { + final Database db; + + EnsemblesController(this.db); + + @Operation.get() + Future getEnsembles() async { + final ensembles = await db.allEnsembles().get(); + return Response.ok(ensembles); + } + + @Operation.get('id') + Future getEnsemble(@Bind.path('id') int id) async { + final ensemble = await db.ensembleById(id).getSingle(); + if (ensemble != null) { + return Response.ok(ensemble); + } else { + return Response.notFound(); + } + } + + @Operation.put('id') + Future putEnsemble( + @Bind.path('id') int id, @Bind.body() Map json) async { + final ensemble = Ensemble.fromJson(json).copyWith( + id: id, + ); + + await db.updateEnsemble(ensemble); + + return Response.ok(null); + } +} diff --git a/server/lib/src/instruments.dart b/server/lib/src/instruments.dart new file mode 100644 index 0000000..8bc1777 --- /dev/null +++ b/server/lib/src/instruments.dart @@ -0,0 +1,36 @@ +import 'package:aqueduct/aqueduct.dart'; +import 'package:musicus_database/musicus_database.dart'; + +class InstrumentsController extends ResourceController { + final Database db; + + InstrumentsController(this.db); + + @Operation.get() + Future getInstruments() async { + final instruments = await db.allInstruments().get(); + return Response.ok(instruments); + } + + @Operation.get('id') + Future getInstrument(@Bind.path('id') int id) async { + final instrument = await db.instrumentById(id).getSingle(); + if (instrument != null) { + return Response.ok(instrument); + } else { + return Response.notFound(); + } + } + + @Operation.put('id') + Future putInstrument( + @Bind.path('id') int id, @Bind.body() Map json) async { + final instrument = Instrument.fromJson(json).copyWith( + id: id, + ); + + await db.updateInstrument(instrument); + + return Response.ok(null); + } +} diff --git a/server/lib/src/performances.dart b/server/lib/src/performances.dart new file mode 100644 index 0000000..79382a0 --- /dev/null +++ b/server/lib/src/performances.dart @@ -0,0 +1,14 @@ +import 'package:aqueduct/aqueduct.dart'; +import 'package:musicus_database/musicus_database.dart'; + +class PerformancesController extends ResourceController { + final Database db; + + PerformancesController(this.db); + + @Operation.get('id') + Future getPerformances(@Bind.path('id') int id) async { + final performances = await db.performancesByRecording(id).get(); + return Response.ok(performances); + } +} diff --git a/server/lib/src/persons.dart b/server/lib/src/persons.dart new file mode 100644 index 0000000..86ca865 --- /dev/null +++ b/server/lib/src/persons.dart @@ -0,0 +1,36 @@ +import 'package:aqueduct/aqueduct.dart'; +import 'package:musicus_database/musicus_database.dart'; + +class PersonsController extends ResourceController { + final Database db; + + PersonsController(this.db); + + @Operation.get() + Future getPersons() async { + final persons = await db.allPersons().get(); + return Response.ok(persons); + } + + @Operation.get('id') + Future getPerson(@Bind.path('id') int id) async { + final person = await db.personById(id).getSingle(); + if (person != null) { + return Response.ok(person); + } else { + return Response.notFound(); + } + } + + @Operation.put('id') + Future putPerson( + @Bind.path('id') int id, @Bind.body() Map json) async { + final person = Person.fromJson(json).copyWith( + id: id, + ); + + await db.updatePerson(person); + + return Response.ok(null); + } +} diff --git a/server/lib/src/recordings.dart b/server/lib/src/recordings.dart new file mode 100644 index 0000000..5fe35ea --- /dev/null +++ b/server/lib/src/recordings.dart @@ -0,0 +1,26 @@ +import 'package:aqueduct/aqueduct.dart'; +import 'package:musicus_database/musicus_database.dart'; + +class RecordingsController extends ResourceController { + final Database db; + + RecordingsController(this.db); + + @Operation.get('id') + Future getRecording(@Bind.path('id') int id) async { + final recording = await db.recordingById(id).getSingle(); + if (recording != null) { + return Response.ok(recording); + } else { + return Response.notFound(); + } + } + + @Operation.put('id') + Future putRecording( + @Bind.path('id') int id, @Bind.body() Map json) async { + final data = RecordingData.fromJson(json); + await db.updateRecording(data); + return Response.ok(null); + } +} diff --git a/server/lib/src/server.dart b/server/lib/src/server.dart new file mode 100644 index 0000000..a31821c --- /dev/null +++ b/server/lib/src/server.dart @@ -0,0 +1,44 @@ +import 'dart:io'; + +import 'package:aqueduct/aqueduct.dart'; +import 'package:moor_ffi/moor_ffi.dart'; +import 'package:musicus_database/musicus_database.dart'; +import 'package:musicus_server/src/work_recordings.dart'; + +import 'compositions.dart'; +import 'configuration.dart'; +import 'ensembles.dart'; +import 'instruments.dart'; +import 'performances.dart'; +import 'persons.dart'; +import 'recordings.dart'; +import 'work_parts.dart'; +import 'works.dart'; + +class MusicusServer extends ApplicationChannel { + Database db; + + @override + Future prepare() async { + final config = MusicusServerConfiguration(options.configurationFilePath); + + if (config.dbPath != null) { + db = Database(VmDatabase(File(config.dbPath))); + } else { + db = Database(VmDatabase.memory()); + } + } + + @override + Controller get entryPoint => Router() + ..route('/persons/[:id]').link(() => PersonsController(db)) + ..route('/persons/:id/works').link(() => CompositionsController(db)) + ..route('/instruments/[:id]').link(() => InstrumentsController(db)) + ..route('/works/:id').link(() => WorksController(db)) + ..route('/works/:id/parts').link(() => WorkPartsController(db)) + ..route('/works/:id/recordings').link(() => WorkRecordingsController(db)) + ..route('/ensembles/[:id]').link(() => EnsemblesController(db)) + ..route('/recordings/:id').link(() => RecordingsController(db)) + ..route('/recordings/:id/performances') + .link(() => PerformancesController(db)); +} diff --git a/server/lib/src/work_parts.dart b/server/lib/src/work_parts.dart new file mode 100644 index 0000000..92a7d1d --- /dev/null +++ b/server/lib/src/work_parts.dart @@ -0,0 +1,14 @@ +import 'package:aqueduct/aqueduct.dart'; +import 'package:musicus_database/musicus_database.dart'; + +class WorkPartsController extends ResourceController { + final Database db; + + WorkPartsController(this.db); + + @Operation.get('id') + Future getParts(@Bind.path('id') int id) async { + final parts = await db.workParts(id).get(); + return Response.ok(parts); + } +} diff --git a/server/lib/src/work_recordings.dart b/server/lib/src/work_recordings.dart new file mode 100644 index 0000000..0eb2e1f --- /dev/null +++ b/server/lib/src/work_recordings.dart @@ -0,0 +1,14 @@ +import 'package:aqueduct/aqueduct.dart'; +import 'package:musicus_database/musicus_database.dart'; + +class WorkRecordingsController extends ResourceController { + final Database db; + + WorkRecordingsController(this.db); + + @Operation.get('id') + Future getRecordings(@Bind.path('id') int id) async { + final recordings = await db.recordingsByWork(id).get(); + return Response.ok(recordings); + } +} diff --git a/server/lib/src/works.dart b/server/lib/src/works.dart new file mode 100644 index 0000000..eca1a0e --- /dev/null +++ b/server/lib/src/works.dart @@ -0,0 +1,26 @@ +import 'package:aqueduct/aqueduct.dart'; +import 'package:musicus_database/musicus_database.dart'; + +class WorksController extends ResourceController { + final Database db; + + WorksController(this.db); + + @Operation.get('id') + Future getWork(@Bind.path('id') int id) async { + final work = await db.workById(id).getSingle(); + if (work != null) { + return Response.ok(work); + } else { + return Response.notFound(); + } + } + + @Operation.put('id') + Future putWork( + @Bind.path('id') int id, @Bind.body() Map json) async { + final data = WorkData.fromJson(json); + await db.updateWork(data); + return Response.ok(null); + } +} diff --git a/server/pubspec.yaml b/server/pubspec.yaml new file mode 100644 index 0000000..2356dcb --- /dev/null +++ b/server/pubspec.yaml @@ -0,0 +1,9 @@ +name: musicus_server +description: A server hosting a Musicus database. +version: 0.0.1 + +dependencies: + aqueduct: + moor_ffi: + musicus_database: + path: ../database