veilid/veilid-flutter/lib/veilid_js.dart

340 lines
9.8 KiB
Dart
Raw Normal View History

2022-02-06 21:18:42 -05:00
import 'veilid.dart';
2022-03-17 10:31:10 -04:00
import 'dart:html' as html;
import 'dart:js' as js;
import 'dart:js_util' as js_util;
2022-02-06 21:18:42 -05:00
import 'dart:async';
2022-03-15 23:02:24 -04:00
import 'dart:convert';
2022-09-30 22:37:55 -04:00
import 'dart:typed_data';
2022-02-06 21:18:42 -05:00
2023-01-04 17:02:45 -05:00
import 'base64url_no_pad.dart';
2022-02-06 21:18:42 -05:00
//////////////////////////////////////////////////////////
Veilid getVeilid() => VeilidJS();
2022-03-17 10:31:10 -04:00
Object wasm = js_util.getProperty(html.window, "veilid_wasm");
2022-03-15 23:02:24 -04:00
2022-03-17 10:31:10 -04:00
Future<T> _wrapApiPromise<T>(Object p) {
return js_util.promiseToFuture(p).then((value) => value as T).catchError(
(error) => Future<T>.error(
VeilidAPIException.fromJson(jsonDecode(error as String))));
2022-03-15 23:02:24 -04:00
}
2022-12-02 22:52:03 -05:00
class _Ctx {
final int id;
final VeilidJS js;
_Ctx(this.id, this.js);
}
2022-11-26 14:16:02 -05:00
// JS implementation of VeilidRoutingContext
class VeilidRoutingContextJS implements VeilidRoutingContext {
2022-12-02 22:52:03 -05:00
final _Ctx _ctx;
static final Finalizer<_Ctx> _finalizer = Finalizer((ctx) => {
js_util.callMethod(wasm, "release_routing_context", [ctx.id])
});
VeilidRoutingContextJS._(this._ctx) {
_finalizer.attach(this, _ctx, detach: this);
}
2022-11-26 14:16:02 -05:00
@override
2022-12-02 22:52:03 -05:00
VeilidRoutingContextJS withPrivacy() {
int newId =
js_util.callMethod(wasm, "routing_context_with_privacy", [_ctx.id]);
return VeilidRoutingContextJS._(_Ctx(newId, _ctx.js));
2022-11-26 14:16:02 -05:00
}
@override
2022-12-02 22:52:03 -05:00
VeilidRoutingContextJS withCustomPrivacy(Stability stability) {
final newId = js_util.callMethod(
wasm, "routing_context_with_custom_privacy", [_ctx.id, stability.json]);
return VeilidRoutingContextJS._(_Ctx(newId, _ctx.js));
2022-11-26 14:16:02 -05:00
}
@override
2022-12-02 22:52:03 -05:00
VeilidRoutingContextJS withSequencing(Sequencing sequencing) {
final newId = js_util.callMethod(
wasm, "routing_context_with_sequencing", [_ctx.id, sequencing.json]);
return VeilidRoutingContextJS._(_Ctx(newId, _ctx.js));
2022-11-26 14:16:02 -05:00
}
@override
Future<Uint8List> appCall(String target, Uint8List request) async {
2023-01-04 17:02:45 -05:00
var encodedRequest = base64UrlNoPadEncode(request);
2022-11-26 14:16:02 -05:00
2023-01-04 17:02:45 -05:00
return base64UrlNoPadDecode(await _wrapApiPromise(js_util.callMethod(
2023-03-01 15:50:30 -05:00
wasm, "routing_context_app_call", [_ctx.id, target, encodedRequest])));
2022-11-26 14:16:02 -05:00
}
@override
2022-12-28 22:53:58 -05:00
Future<void> appMessage(String target, Uint8List message) {
2023-01-04 17:02:45 -05:00
var encodedMessage = base64UrlNoPadEncode(message);
2022-11-26 14:16:02 -05:00
2023-03-01 15:50:30 -05:00
return _wrapApiPromise(js_util.callMethod(wasm,
"routing_context_app_message", [_ctx.id, target, encodedMessage]));
2022-11-26 14:16:02 -05:00
}
}
2022-12-28 22:53:58 -05:00
class _TDBT {
final int id;
VeilidTableDBJS tdbjs;
VeilidJS js;
_TDBT(this.id, this.tdbjs, this.js);
}
// JS implementation of VeilidTableDBTransaction
class VeilidTableDBTransactionJS extends VeilidTableDBTransaction {
final _TDBT _tdbt;
static final Finalizer<_TDBT> _finalizer = Finalizer((tdbt) => {
js_util.callMethod(wasm, "release_table_db_transaction", [tdbt.id])
});
VeilidTableDBTransactionJS._(this._tdbt) {
_finalizer.attach(this, _tdbt, detach: this);
}
@override
Future<void> commit() {
2023-01-04 14:51:13 -05:00
return _wrapApiPromise(
js_util.callMethod(wasm, "table_db_transaction_commit", [_tdbt.id]));
2022-12-28 22:53:58 -05:00
}
@override
Future<void> rollback() {
2023-01-04 14:51:13 -05:00
return _wrapApiPromise(
js_util.callMethod(wasm, "table_db_transaction_rollback", [_tdbt.id]));
2022-12-28 22:53:58 -05:00
}
@override
Future<void> store(int col, Uint8List key, Uint8List value) {
2023-01-04 17:02:45 -05:00
final encodedKey = base64UrlNoPadEncode(key);
final encodedValue = base64UrlNoPadEncode(value);
2022-12-28 22:53:58 -05:00
2023-01-04 17:02:45 -05:00
return _wrapApiPromise(js_util.callMethod(
wasm,
"table_db_transaction_store",
[_tdbt.id, col, encodedKey, encodedValue]));
2022-12-28 22:53:58 -05:00
}
@override
Future<bool> delete(int col, Uint8List key) {
2023-01-04 17:02:45 -05:00
final encodedKey = base64UrlNoPadEncode(key);
2022-12-28 22:53:58 -05:00
return _wrapApiPromise(js_util.callMethod(
2023-01-04 17:02:45 -05:00
wasm, "table_db_transaction_delete", [_tdbt.id, col, encodedKey]));
2022-12-28 22:53:58 -05:00
}
}
class _TDB {
final int id;
VeilidJS js;
_TDB(this.id, this.js);
}
// JS implementation of VeilidTableDB
class VeilidTableDBJS extends VeilidTableDB {
final _TDB _tdb;
static final Finalizer<_TDB> _finalizer = Finalizer((tdb) => {
js_util.callMethod(wasm, "release_table_db", [tdb.id])
});
VeilidTableDBJS._(this._tdb) {
_finalizer.attach(this, _tdb, detach: this);
}
@override
int getColumnCount() {
return js_util.callMethod(wasm, "table_db_get_column_count", [_tdb.id]);
}
@override
List<Uint8List> getKeys(int col) {
String? s = js_util.callMethod(wasm, "table_db_get_keys", [_tdb.id, col]);
if (s == null) {
throw VeilidAPIExceptionInternal("No db for id");
}
List<dynamic> jarr = jsonDecode(s);
2023-01-04 17:02:45 -05:00
return jarr.map((e) => base64UrlNoPadDecode(e)).toList();
2022-12-28 22:53:58 -05:00
}
@override
VeilidTableDBTransaction transact() {
final id = js_util.callMethod(wasm, "table_db_transact", [_tdb.id]);
return VeilidTableDBTransactionJS._(_TDBT(id, this, _tdb.js));
}
@override
Future<void> store(int col, Uint8List key, Uint8List value) {
2023-01-04 17:02:45 -05:00
final encodedKey = base64UrlNoPadEncode(key);
final encodedValue = base64UrlNoPadEncode(value);
2022-12-28 22:53:58 -05:00
return _wrapApiPromise(js_util.callMethod(
2023-01-04 17:02:45 -05:00
wasm, "table_db_store", [_tdb.id, col, encodedKey, encodedValue]));
2022-12-28 22:53:58 -05:00
}
@override
Future<Uint8List?> load(int col, Uint8List key) async {
2023-01-04 17:02:45 -05:00
final encodedKey = base64UrlNoPadEncode(key);
2022-12-28 22:53:58 -05:00
2023-01-04 14:51:13 -05:00
String? out = await _wrapApiPromise(
2023-01-04 17:02:45 -05:00
js_util.callMethod(wasm, "table_db_load", [_tdb.id, col, encodedKey]));
2022-12-28 22:53:58 -05:00
if (out == null) {
return null;
}
2023-01-04 17:02:45 -05:00
return base64UrlNoPadDecode(out);
2022-12-28 22:53:58 -05:00
}
@override
Future<bool> delete(int col, Uint8List key) {
2023-01-04 17:02:45 -05:00
final encodedKey = base64UrlNoPadEncode(key);
2022-12-28 22:53:58 -05:00
2023-01-04 17:02:45 -05:00
return _wrapApiPromise(js_util
.callMethod(wasm, "table_db_delete", [_tdb.id, col, encodedKey]));
2022-12-28 22:53:58 -05:00
}
}
2022-11-26 14:16:02 -05:00
// JS implementation of high level Veilid API
2022-02-13 21:09:43 -05:00
class VeilidJS implements Veilid {
2022-06-15 21:51:38 -04:00
@override
2022-07-01 16:20:43 -04:00
void initializeVeilidCore(Map<String, dynamic> platformConfigJson) {
2022-06-15 21:51:38 -04:00
var platformConfigJsonString =
jsonEncode(platformConfigJson, toEncodable: veilidApiToEncodable);
2022-07-01 16:20:43 -04:00
js_util
.callMethod(wasm, "initialize_veilid_core", [platformConfigJsonString]);
2022-06-15 21:51:38 -04:00
}
2022-07-01 12:13:52 -04:00
@override
void changeLogLevel(String layer, VeilidConfigLogLevel logLevel) {
var logLevelJsonString =
jsonEncode(logLevel.json, toEncodable: veilidApiToEncodable);
js_util.callMethod(wasm, "change_log_level", [layer, logLevelJsonString]);
}
2022-03-03 20:45:39 -05:00
@override
2022-09-09 16:27:13 -04:00
Future<Stream<VeilidUpdate>> startupVeilidCore(VeilidConfig config) async {
2022-03-15 23:02:24 -04:00
var streamController = StreamController<VeilidUpdate>();
2022-03-17 10:31:10 -04:00
updateCallback(String update) {
var updateJson = jsonDecode(update);
if (updateJson["kind"] == "Shutdown") {
streamController.close();
} else {
var update = VeilidUpdate.fromJson(updateJson);
streamController.add(update);
}
}
await _wrapApiPromise(js_util.callMethod(wasm, "startup_veilid_core", [
js.allowInterop(updateCallback),
jsonEncode(config.json, toEncodable: veilidApiToEncodable)
]));
2022-09-09 16:27:13 -04:00
return streamController.stream;
2022-02-06 21:18:42 -05:00
}
2022-03-03 20:45:39 -05:00
@override
2022-03-15 23:02:24 -04:00
Future<VeilidState> getVeilidState() async {
2022-03-17 10:31:10 -04:00
return VeilidState.fromJson(jsonDecode(await _wrapApiPromise(
js_util.callMethod(wasm, "get_veilid_state", []))));
2022-02-06 21:18:42 -05:00
}
2022-09-06 18:59:41 -04:00
@override
2022-12-28 22:53:58 -05:00
Future<void> attach() {
2022-09-06 18:59:41 -04:00
return _wrapApiPromise(js_util.callMethod(wasm, "attach", []));
}
@override
2022-12-28 22:53:58 -05:00
Future<void> detach() {
2022-09-06 18:59:41 -04:00
return _wrapApiPromise(js_util.callMethod(wasm, "detach", []));
}
2022-03-03 20:45:39 -05:00
@override
2022-03-17 10:31:10 -04:00
Future<void> shutdownVeilidCore() {
return _wrapApiPromise(
js_util.callMethod(wasm, "shutdown_veilid_core", []));
2022-02-06 21:18:42 -05:00
}
2022-03-03 20:45:39 -05:00
@override
2022-11-26 14:16:02 -05:00
Future<VeilidRoutingContext> routingContext() async {
2023-01-04 14:20:41 -05:00
int id =
await _wrapApiPromise(js_util.callMethod(wasm, "routing_context", []));
2022-12-02 22:52:03 -05:00
return VeilidRoutingContextJS._(_Ctx(id, this));
2022-11-26 14:16:02 -05:00
}
@override
2023-03-01 15:50:30 -05:00
Future<RouteBlob> newPrivateRoute() async {
2022-12-02 22:52:03 -05:00
Map<String, dynamic> blobJson = jsonDecode(await _wrapApiPromise(
js_util.callMethod(wasm, "new_private_route", [])));
2023-03-01 15:50:30 -05:00
return RouteBlob.fromJson(blobJson);
2022-11-26 14:16:02 -05:00
}
@override
2023-03-01 15:50:30 -05:00
Future<RouteBlob> newCustomPrivateRoute(
2022-11-26 14:16:02 -05:00
Stability stability, Sequencing sequencing) async {
2022-12-02 22:52:03 -05:00
var stabilityString =
jsonEncode(stability, toEncodable: veilidApiToEncodable);
var sequencingString =
jsonEncode(sequencing, toEncodable: veilidApiToEncodable);
2022-11-26 14:16:02 -05:00
2022-12-02 22:52:03 -05:00
Map<String, dynamic> blobJson = jsonDecode(await _wrapApiPromise(js_util
.callMethod(
wasm, "new_private_route", [stabilityString, sequencingString])));
2023-03-01 15:50:30 -05:00
return RouteBlob.fromJson(blobJson);
2022-11-26 14:16:02 -05:00
}
@override
2022-12-28 22:53:58 -05:00
Future<String> importRemotePrivateRoute(Uint8List blob) {
2023-01-04 17:02:45 -05:00
var encodedBlob = base64UrlNoPadEncode(blob);
2022-11-26 14:16:02 -05:00
return _wrapApiPromise(
js_util.callMethod(wasm, "import_remote_private_route", [encodedBlob]));
}
@override
2022-12-28 22:53:58 -05:00
Future<void> releasePrivateRoute(String key) {
2022-11-26 14:16:02 -05:00
return _wrapApiPromise(
js_util.callMethod(wasm, "release_private_route", [key]));
2022-03-03 20:45:39 -05:00
}
2022-09-30 22:37:55 -04:00
@override
Future<void> appCallReply(String id, Uint8List message) {
2023-01-04 17:02:45 -05:00
var encodedMessage = base64UrlNoPadEncode(message);
2022-09-30 22:37:55 -04:00
return _wrapApiPromise(
js_util.callMethod(wasm, "app_call_reply", [id, encodedMessage]));
}
2022-12-02 22:52:03 -05:00
2022-12-28 22:53:58 -05:00
@override
Future<VeilidTableDB> openTableDB(String name, int columnCount) async {
int id = await _wrapApiPromise(
js_util.callMethod(wasm, "open_table_db", [name, columnCount]));
return VeilidTableDBJS._(_TDB(id, this));
}
@override
Future<bool> deleteTableDB(String name) {
return _wrapApiPromise(js_util.callMethod(wasm, "delete_table_db", [name]));
}
2022-11-26 14:16:02 -05:00
@override
2022-12-10 19:11:58 -05:00
Future<String> debug(String command) async {
2023-01-04 14:20:41 -05:00
return await _wrapApiPromise(js_util.callMethod(wasm, "debug", [command]));
2022-11-26 14:16:02 -05:00
}
2022-09-30 22:37:55 -04:00
2022-03-03 20:45:39 -05:00
@override
2022-03-17 10:31:10 -04:00
String veilidVersionString() {
return js_util.callMethod(wasm, "veilid_version_string", []);
2022-02-06 21:18:42 -05:00
}
2022-03-03 20:45:39 -05:00
@override
2022-03-17 10:31:10 -04:00
VeilidVersion veilidVersion() {
2022-12-02 22:52:03 -05:00
Map<String, dynamic> jsonVersion =
2022-03-17 10:31:10 -04:00
jsonDecode(js_util.callMethod(wasm, "veilid_version", []));
2022-03-15 23:02:24 -04:00
return VeilidVersion(
jsonVersion["major"], jsonVersion["minor"], jsonVersion["patch"]);
2022-02-06 21:18:42 -05:00
}
}