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