mirror of https://github.com/AMT-Cheif/drift.git
176 lines
5.2 KiB
Dart
176 lines
5.2 KiB
Dart
import 'dart:convert';
|
|
import 'dart:html';
|
|
import 'dart:js_util';
|
|
|
|
import 'package:async/async.dart';
|
|
import 'package:drift/drift.dart';
|
|
import 'package:drift/wasm.dart';
|
|
import 'package:http/http.dart' as http;
|
|
import 'package:web_wasm/initialization_mode.dart';
|
|
import 'package:web_wasm/src/database.dart';
|
|
import 'package:sqlite3/wasm.dart';
|
|
|
|
const dbName = 'drift_test';
|
|
final sqlite3WasmUri = Uri.parse('/sqlite3.wasm');
|
|
final driftWorkerUri = Uri.parse('/worker.dart.js');
|
|
|
|
TestDatabase? openedDatabase;
|
|
StreamQueue<void>? tableUpdates;
|
|
|
|
InitializationMode initializationMode = InitializationMode.none;
|
|
|
|
void main() {
|
|
_addCallbackForWebDriver('detectImplementations', _detectImplementations);
|
|
_addCallbackForWebDriver('open', _open);
|
|
_addCallbackForWebDriver('insert', _insert);
|
|
_addCallbackForWebDriver('get_rows', _getRows);
|
|
_addCallbackForWebDriver('wait_for_update', _waitForUpdate);
|
|
_addCallbackForWebDriver('enable_initialization', (arg) async {
|
|
initializationMode = InitializationMode.values.byName(arg!);
|
|
return true;
|
|
});
|
|
_addCallbackForWebDriver('delete_database', (arg) async {
|
|
final result = await WasmDatabase.probe(
|
|
sqlite3Uri: sqlite3WasmUri,
|
|
driftWorkerUri: driftWorkerUri,
|
|
);
|
|
|
|
final decoded = json.decode(arg!);
|
|
|
|
await result.deleteDatabase(
|
|
(WebStorageApi.byName[decoded[0] as String]!, decoded[1] as String),
|
|
);
|
|
});
|
|
|
|
document.getElementById('selfcheck')?.onClick.listen((event) async {
|
|
print('starting');
|
|
final database = await WasmDatabase.open(
|
|
databaseName: dbName,
|
|
sqlite3Uri: sqlite3WasmUri,
|
|
driftWorkerUri: driftWorkerUri,
|
|
initializeDatabase: _initializeDatabase,
|
|
);
|
|
|
|
print('selected storage: ${database.chosenImplementation}');
|
|
print('missing features: ${database.missingFeatures}');
|
|
});
|
|
}
|
|
|
|
void _addCallbackForWebDriver(String name, Future Function(String?) impl) {
|
|
setProperty(globalThis, name,
|
|
allowInterop((String? arg, Function callback) async {
|
|
Object? result;
|
|
|
|
try {
|
|
result = await impl(arg);
|
|
} catch (e, s) {
|
|
final console = getProperty(globalThis, 'console');
|
|
callMethod(console, 'error', [e, s]);
|
|
}
|
|
|
|
callMethod(callback, 'call', [null, result]);
|
|
}));
|
|
}
|
|
|
|
Future<Uint8List?> _initializeDatabase() async {
|
|
switch (initializationMode) {
|
|
case InitializationMode.loadAsset:
|
|
final response = await http.get(Uri.parse('/initial.db'));
|
|
return response.bodyBytes;
|
|
|
|
case InitializationMode.migrateCustomWasmDatabase:
|
|
|
|
// Let's first open a custom WasmDatabase, the way it would have been
|
|
// done before WasmDatabase.open.
|
|
final sqlite3 = await WasmSqlite3.loadFromUrl(Uri.parse('/sqlite3.wasm'));
|
|
final fs = await IndexedDbFileSystem.open(dbName: dbName);
|
|
sqlite3.registerVirtualFileSystem(fs, makeDefault: true);
|
|
|
|
final wasmDb = WasmDatabase(sqlite3: sqlite3, path: '/app.db');
|
|
final db = TestDatabase(wasmDb);
|
|
await db
|
|
.into(db.testTable)
|
|
.insert(TestTableCompanion.insert(content: 'from old database'));
|
|
await db.close();
|
|
|
|
final (file: file, outFlags: _) = fs.xOpen(Sqlite3Filename('/app.db'), 0);
|
|
final blob = Uint8List(file.xFileSize());
|
|
file.xRead(blob, 0);
|
|
file.xClose();
|
|
fs.xDelete('/app.db', 0);
|
|
await fs.close();
|
|
|
|
return blob;
|
|
case InitializationMode.none:
|
|
return null;
|
|
}
|
|
}
|
|
|
|
Future<String> _detectImplementations(String? _) async {
|
|
final result = await WasmDatabase.probe(
|
|
sqlite3Uri: sqlite3WasmUri,
|
|
driftWorkerUri: driftWorkerUri,
|
|
databaseName: dbName,
|
|
);
|
|
|
|
return json.encode({
|
|
'impls': result.availableStorages.map((r) => r.name).toList(),
|
|
'missing': result.missingFeatures.map((r) => r.name).toList(),
|
|
'existing': result.existingDatabases.map((r) => [r.$1.name, r.$2]).toList(),
|
|
});
|
|
}
|
|
|
|
Future<void> _open(String? implementationName) async {
|
|
DatabaseConnection connection;
|
|
|
|
if (implementationName != null) {
|
|
final probeResult = await WasmDatabase.probe(
|
|
sqlite3Uri: sqlite3WasmUri,
|
|
driftWorkerUri: driftWorkerUri,
|
|
databaseName: dbName,
|
|
);
|
|
|
|
connection = await probeResult.open(
|
|
WasmStorageImplementation.values.byName(implementationName),
|
|
dbName,
|
|
initializeDatabase: _initializeDatabase,
|
|
);
|
|
} else {
|
|
final result = await WasmDatabase.open(
|
|
databaseName: dbName,
|
|
sqlite3Uri: sqlite3WasmUri,
|
|
driftWorkerUri: driftWorkerUri,
|
|
initializeDatabase: _initializeDatabase,
|
|
);
|
|
|
|
connection = result.resolvedExecutor;
|
|
}
|
|
|
|
final db = openedDatabase = TestDatabase(connection);
|
|
|
|
// Make sure it works!
|
|
await db.customSelect('SELECT 1').get();
|
|
|
|
tableUpdates = StreamQueue(db.testTable.all().watch());
|
|
await tableUpdates!.next;
|
|
}
|
|
|
|
Future<void> _waitForUpdate(String? _) async {
|
|
await tableUpdates!.next;
|
|
}
|
|
|
|
Future<void> _insert(String? _) async {
|
|
final db = openedDatabase!;
|
|
await db
|
|
.into(db.testTable)
|
|
.insert(TestTableCompanion.insert(content: DateTime.now().toString()));
|
|
}
|
|
|
|
Future<int> _getRows(String? _) async {
|
|
final db = openedDatabase!;
|
|
final count = countAll();
|
|
|
|
final query = db.selectOnly(db.testTable)..addColumns([count]);
|
|
return await query.map((row) => row.read(count)!).getSingle();
|
|
}
|