From e23e3ae424a66853d398ed7bb1cd8fd647213edc Mon Sep 17 00:00:00 2001 From: Simon Binder Date: Thu, 20 Jun 2019 21:04:22 +0200 Subject: [PATCH] First experiment on the web using AlaSLQ --- moor/example_web/.gitignore | 11 ++++ moor/example_web/README.md | 1 + moor/example_web/pubspec.yaml | 16 ++++++ moor/example_web/web/favicon.ico | Bin 0 -> 3559 bytes moor/example_web/web/index.html | 22 +++++++ moor/example_web/web/main.dart | 9 +++ moor/example_web/web/styles.css | 14 +++++ moor/lib/moor_web.dart | 17 ++++++ moor/lib/src/web/alasql.dart | 95 +++++++++++++++++++++++++++++++ 9 files changed, 185 insertions(+) create mode 100644 moor/example_web/.gitignore create mode 100644 moor/example_web/README.md create mode 100644 moor/example_web/pubspec.yaml create mode 100644 moor/example_web/web/favicon.ico create mode 100644 moor/example_web/web/index.html create mode 100644 moor/example_web/web/main.dart create mode 100644 moor/example_web/web/styles.css create mode 100644 moor/lib/moor_web.dart create mode 100644 moor/lib/src/web/alasql.dart diff --git a/moor/example_web/.gitignore b/moor/example_web/.gitignore new file mode 100644 index 00000000..50602ac6 --- /dev/null +++ b/moor/example_web/.gitignore @@ -0,0 +1,11 @@ +# Files and directories created by pub +.dart_tool/ +.packages +# Remove the following pattern if you wish to check in your lock file +pubspec.lock + +# Conventional directory for build outputs +build/ + +# Directory created by dartdoc +doc/api/ diff --git a/moor/example_web/README.md b/moor/example_web/README.md new file mode 100644 index 00000000..126dd771 --- /dev/null +++ b/moor/example_web/README.md @@ -0,0 +1 @@ +Experimental example for using moor on the web. \ No newline at end of file diff --git a/moor/example_web/pubspec.yaml b/moor/example_web/pubspec.yaml new file mode 100644 index 00000000..42278ffe --- /dev/null +++ b/moor/example_web/pubspec.yaml @@ -0,0 +1,16 @@ +name: example_web +description: Experimental usage of moor on the web + +environment: + sdk: '>=2.2.0 <3.0.0' + +dependencies: + moor: ^1.4.0 + +dependency_overrides: + moor: + path: ../ + +dev_dependencies: + build_runner: ^1.1.2 + build_web_compilers: ^1.0.0 diff --git a/moor/example_web/web/favicon.ico b/moor/example_web/web/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..7ba349b3e628d2423d4a2ed217422a4722f73739 GIT binary patch literal 3559 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 + + + + + + + + example_web + + + + + + + + + +
+ + + diff --git a/moor/example_web/web/main.dart b/moor/example_web/web/main.dart new file mode 100644 index 00000000..b65da869 --- /dev/null +++ b/moor/example_web/web/main.dart @@ -0,0 +1,9 @@ +import 'package:moor/moor_web.dart'; + +void main() async { + final executor = AlaSqlDatabase('database'); + final result = await executor.doWhenOpened((e) { + return e.runSelect('SELECT 1', const []); + }); + print(result); +} diff --git a/moor/example_web/web/styles.css b/moor/example_web/web/styles.css new file mode 100644 index 00000000..cc035c95 --- /dev/null +++ b/moor/example_web/web/styles.css @@ -0,0 +1,14 @@ +@import url(https://fonts.googleapis.com/css?family=Roboto); + +html, body { + width: 100%; + height: 100%; + margin: 0; + padding: 0; + font-family: 'Roboto', sans-serif; +} + +#output { + padding: 20px; + text-align: center; +} diff --git a/moor/lib/moor_web.dart b/moor/lib/moor_web.dart new file mode 100644 index 00000000..5b52bdd2 --- /dev/null +++ b/moor/lib/moor_web.dart @@ -0,0 +1,17 @@ +/// A version of moor that runs on the web by using [AlaSQL.js](https://alasql.org/) +/// You manually need to include that library into your website by using +/// ```html +/// +/// ``` +@experimental +library moor_web; + +import 'dart:async'; +import 'dart:html'; +import 'dart:js'; +import 'package:meta/meta.dart'; +import 'moor.dart'; + +export 'moor.dart'; + +part 'src/web/alasql.dart'; diff --git a/moor/lib/src/web/alasql.dart b/moor/lib/src/web/alasql.dart new file mode 100644 index 00000000..4260c351 --- /dev/null +++ b/moor/lib/src/web/alasql.dart @@ -0,0 +1,95 @@ +part of 'package:moor/moor_web.dart'; + +JsObject _alasql = context['alasql'] as JsObject; + +class AlaSqlDatabase extends QueryExecutor { + JsObject _database; + final bool logStatements; + final String name; + + Completer _opening; + + AlaSqlDatabase(this.name, {this.logStatements = false}) { + if (_alasql == null) { + throw UnsupportedError('Could not access the alasql javascript library. ' + 'The moor documentation contains instructions on how to setup moor ' + 'the web, which might help you fix this.'); + } + + _database = JsObject(_alasql['Database'] as JsFunction); + } + + @override + TransactionExecutor beginTransaction() { + throw StateError('Transactions are not currently supported with AlaSQL'); + } + + @override + Future ensureOpen() async { + if (_opening == null) { + _opening = Completer(); + await _openInternal(); + _opening.complete(); + } else { + await _opening.future; + } + + return true; + } + + Future _openInternal() async { + // todo handle possible injection vulnerability of $name + await _run('CREATE INDEXEDDB DATABASE IF NOT EXISTS `$name`;', const []); + await _run('ATTACH INDEXEDDB DATABASE `$name`;', const []); + await _run('USE `$name`;', const []); + } + + @override + Future runBatched(List statements) { + throw StateError( + 'Batched statements are not currently supported with AlaSQL'); + } + + Future _run(String query, List variables) { + JsObject promise; + if (variables.isEmpty) { + promise = _database.callMethod('promise', [query]) as JsObject; + } else { + promise = _database + .callMethod('promise', [query, JsArray.from(variables)]) as JsObject; + } + + return promiseToFuture(promise); + } + + @override + Future runCustom(String statement) { + _run(statement, const []); + return Future.value(); + } + + @override + Future runDelete(String statement, List args) { + return Future.value(_run(statement, args) as int); + } + + @override + Future runInsert(String statement, List args) { + // todo (needs api change). We need to know the table and column name + // to get the last insert id in AlaSQL. See https://github.com/agershun/alasql/wiki/AUTOINCREMENT + _run(statement, args); + + return Future.value(42); + } + + @override + Future>> runSelect(String statement, List args) { + // TODO: implement runSelect + return null; + } + + @override + Future runUpdate(String statement, List args) { + return Future.value(_run(statement, args) as int); + } +}