mirror of https://github.com/AMT-Cheif/drift.git
Use `package:js` to wrap sql.js library
This commit is contained in:
parent
fc0d30583a
commit
6e79a5b58c
|
@ -1,3 +1,7 @@
|
|||
## 1.6.0-dev
|
||||
|
||||
- Internally use `package:js` to wrap sql.js.
|
||||
|
||||
## 1.5.0
|
||||
|
||||
- Add `DataClassName.extending` to control the superclass of generated row
|
||||
|
|
|
@ -1,7 +1,17 @@
|
|||
@JS()
|
||||
import 'dart:async';
|
||||
import 'dart:js';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:js/js.dart';
|
||||
import 'package:js/js_util.dart';
|
||||
|
||||
@JS('initSqlJs')
|
||||
external Object /*Promise<_SqlJs>*/ _initSqlJs();
|
||||
|
||||
@JS('undefined')
|
||||
external Null get _undefined;
|
||||
|
||||
// We write our own mapping code to js instead of depending on package:js
|
||||
// This way, projects using drift can run on flutter as long as they don't
|
||||
// import this file.
|
||||
|
@ -21,24 +31,53 @@ Future<SqlJsModule> initSqlJs() {
|
|||
'The drift documentation contains instructions on how to setup drift '
|
||||
'the web, which might help you fix this.'));
|
||||
} else {
|
||||
(context.callMethod('initSqlJs') as JsObject)
|
||||
.callMethod('then', [allowInterop(_handleModuleResolved)]);
|
||||
completer
|
||||
.complete(promiseToFuture<_SqlJs>(_initSqlJs()).then(SqlJsModule._));
|
||||
}
|
||||
|
||||
return _moduleCompleter!.future;
|
||||
}
|
||||
|
||||
// We're extracting this into its own method so that we don't have to call
|
||||
// [allowInterop] on this method or a lambda.
|
||||
// todo figure out why dart2js generates invalid js when wrapping this in
|
||||
// allowInterop
|
||||
void _handleModuleResolved(dynamic module) {
|
||||
_moduleCompleter!.complete(SqlJsModule._(module as JsObject));
|
||||
@JS()
|
||||
@anonymous
|
||||
class _SqlJs {
|
||||
// ignore: non_constant_identifier_names
|
||||
external Object get Database;
|
||||
}
|
||||
|
||||
@JS()
|
||||
@anonymous
|
||||
class _SqlJsDatabase {
|
||||
external int getRowsModified();
|
||||
|
||||
external void run(String sql, List<Object?>? args);
|
||||
external List<_QueryExecResult> exec(String sql, List<Object?>? params);
|
||||
external _SqlJsStatement prepare(String sql);
|
||||
|
||||
external Uint8List export();
|
||||
external void close();
|
||||
}
|
||||
|
||||
@JS()
|
||||
@anonymous
|
||||
class _QueryExecResult {
|
||||
external List<String> get columns;
|
||||
external List<List<Object?>> get values;
|
||||
}
|
||||
|
||||
@JS()
|
||||
@anonymous
|
||||
class _SqlJsStatement {
|
||||
external void bind(List<Object?> values);
|
||||
external bool step();
|
||||
external List<Object?> get();
|
||||
external List<String> getColumnNames();
|
||||
external void free();
|
||||
}
|
||||
|
||||
/// `sql.js` module from the underlying library
|
||||
class SqlJsModule {
|
||||
final JsObject _obj;
|
||||
final _SqlJs _obj;
|
||||
SqlJsModule._(this._obj);
|
||||
|
||||
/// Constructs a new [SqlJsDatabase], optionally from the [data] blob.
|
||||
|
@ -53,20 +92,18 @@ class SqlJsModule {
|
|||
return SqlJsDatabase._(dbObj);
|
||||
}
|
||||
|
||||
JsObject _createInternally(Uint8List? data) {
|
||||
final constructor = _obj['Database'] as JsFunction;
|
||||
|
||||
_SqlJsDatabase _createInternally(Uint8List? data) {
|
||||
if (data != null) {
|
||||
return JsObject(constructor, [data]);
|
||||
return callConstructor<_SqlJsDatabase>(_obj.Database, [data]);
|
||||
} else {
|
||||
return JsObject(constructor);
|
||||
return callConstructor<_SqlJsDatabase>(_obj.Database, const []);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Dart wrapper around a sql database provided by the sql.js library.
|
||||
class SqlJsDatabase {
|
||||
final JsObject _obj;
|
||||
final _SqlJsDatabase _obj;
|
||||
SqlJsDatabase._(this._obj);
|
||||
|
||||
/// Returns the `user_version` pragma from sqlite.
|
||||
|
@ -81,13 +118,12 @@ class SqlJsDatabase {
|
|||
|
||||
/// Calls `prepare` on the underlying js api
|
||||
PreparedStatement prepare(String sql) {
|
||||
final obj = _obj.callMethod('prepare', [sql]) as JsObject;
|
||||
return PreparedStatement._(obj);
|
||||
return PreparedStatement._(_obj.prepare(sql));
|
||||
}
|
||||
|
||||
/// Calls `run(sql)` on the underlying js api
|
||||
void run(String sql) {
|
||||
_obj.callMethod('run', [sql]);
|
||||
_obj.run(sql, _undefined);
|
||||
}
|
||||
|
||||
/// Calls `run(sql, args)` on the underlying js api
|
||||
|
@ -96,18 +132,15 @@ class SqlJsDatabase {
|
|||
// Call run without providing arguments. sql.js will then use sqlite3_exec
|
||||
// internally, which supports running multiple statements at once. This
|
||||
// matches the behavior from a `NativeDatabase`.
|
||||
_obj.callMethod('run', [sql]);
|
||||
_obj.run(sql, _undefined);
|
||||
} else {
|
||||
final ar = JsArray.from(args);
|
||||
_obj.callMethod('run', [sql, ar]);
|
||||
_obj.run(sql, args);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the amount of rows affected by the most recent INSERT, UPDATE or
|
||||
/// DELETE statement.
|
||||
int lastModifiedRows() {
|
||||
return _obj.callMethod('getRowsModified') as int;
|
||||
}
|
||||
int lastModifiedRows() => _obj.getRowsModified();
|
||||
|
||||
/// The row id of the last inserted row. This counter is reset when calling
|
||||
/// [export].
|
||||
|
@ -117,52 +150,39 @@ class SqlJsDatabase {
|
|||
}
|
||||
|
||||
dynamic _selectSingleRowAndColumn(String sql) {
|
||||
final results = _obj.callMethod('exec', [sql]) as JsArray;
|
||||
final row = results.first as JsObject;
|
||||
final data = (row['values'] as JsArray).first as JsArray;
|
||||
return data.first;
|
||||
final results = _obj.exec(sql, _undefined);
|
||||
final result = results.first;
|
||||
final row = result.values.first;
|
||||
|
||||
return row.first;
|
||||
}
|
||||
|
||||
/// Runs `export` on the underlying js api
|
||||
Uint8List export() {
|
||||
return _obj.callMethod('export') as Uint8List;
|
||||
}
|
||||
Uint8List export() => _obj.export();
|
||||
|
||||
/// Runs `close` on the underlying js api
|
||||
void close() {
|
||||
_obj.callMethod('close');
|
||||
}
|
||||
void close() => _obj.close();
|
||||
}
|
||||
|
||||
/// Dart api wrapping an underlying prepared statement object from the sql.js
|
||||
/// library.
|
||||
class PreparedStatement {
|
||||
final JsObject _obj;
|
||||
final _SqlJsStatement _obj;
|
||||
PreparedStatement._(this._obj);
|
||||
|
||||
/// Executes this statement with the bound [args].
|
||||
void executeWith(List<dynamic> args) {
|
||||
_obj.callMethod('bind', [JsArray.from(args)]);
|
||||
}
|
||||
void executeWith(List<dynamic> args) => _obj.bind(args);
|
||||
|
||||
/// Performs `step` on the underlying js api
|
||||
bool step() {
|
||||
return _obj.callMethod('step') as bool;
|
||||
}
|
||||
bool step() => _obj.step();
|
||||
|
||||
/// Reads the current from the underlying js api
|
||||
List<dynamic> currentRow() {
|
||||
return _obj.callMethod('get') as JsArray;
|
||||
}
|
||||
List<dynamic> currentRow() => _obj.get();
|
||||
|
||||
/// The columns returned by this statement. This will only be available after
|
||||
/// [step] has been called once.
|
||||
List<String> columnNames() {
|
||||
return (_obj.callMethod('getColumnNames') as JsArray).cast<String>();
|
||||
}
|
||||
List<String> columnNames() => _obj.getColumnNames();
|
||||
|
||||
/// Calls `free` on the underlying js api
|
||||
void free() {
|
||||
_obj.callMethod('free');
|
||||
}
|
||||
void free() => _obj.free();
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ dependencies:
|
|||
async: ^2.5.0
|
||||
convert: ^3.0.0
|
||||
collection: ^1.15.0
|
||||
js: ^0.6.4
|
||||
meta: ^1.3.0
|
||||
stream_channel: ^2.1.0
|
||||
sqlite3: ^1.5.1
|
||||
|
|
|
@ -3,7 +3,7 @@ This example demonstrates how a shared web worker can be used with drift.
|
|||
To view this example, run
|
||||
|
||||
```
|
||||
dart run build_runner serve --release
|
||||
dart run build_runner serve
|
||||
```
|
||||
|
||||
Then, open `localhost:8080` in different tabs and note how changes propagate across tabs
|
||||
|
|
|
@ -1,4 +1,17 @@
|
|||
targets:
|
||||
# We use dartdevc by default, but the worker should always be compiled with dart2js
|
||||
worker:
|
||||
auto_apply_builders: false
|
||||
dependencies: [":$default"]
|
||||
builders:
|
||||
build_web_compilers|entrypoint:
|
||||
enabled: true
|
||||
generate_for:
|
||||
- web/worker.dart
|
||||
options:
|
||||
compiler: dart2js
|
||||
|
||||
|
||||
$default:
|
||||
builders:
|
||||
drift_dev:
|
||||
|
@ -9,3 +22,8 @@ targets:
|
|||
generate_values_in_copy_with: true
|
||||
named_parameters: true
|
||||
new_sql_code_generation: true
|
||||
build_web_compilers|entrypoint:
|
||||
generate_for:
|
||||
# This one is compiled in the other target
|
||||
exclude:
|
||||
- "web/worker.dart"
|
||||
|
|
Loading…
Reference in New Issue