|
| 1 | +/// Exposes interfaces implemented by database implementations on the web. |
| 2 | +/// |
| 3 | +/// These expose methods allowing database instances to be shared across web |
| 4 | +/// workers. |
| 5 | +library sqlite_async.web; |
| 6 | + |
| 7 | +import 'package:sqlite3_web/sqlite3_web.dart'; |
| 8 | +import 'package:web/web.dart'; |
| 9 | +import 'sqlite_async.dart'; |
| 10 | +import 'src/web/database.dart'; |
| 11 | + |
| 12 | +/// An endpoint that can be used, by any running JavaScript context in the same |
| 13 | +/// website, to connect to an existing [WebSqliteConnection]. |
| 14 | +/// |
| 15 | +/// These endpoints are created by calling [WebSqliteConnection.exposeEndpoint] |
| 16 | +/// and consist of a [MessagePort] and two [String]s internally identifying the |
| 17 | +/// connection. Both objects can be transferred over send ports towards another |
| 18 | +/// worker or context. That context can then use |
| 19 | +/// [WebSqliteConnection.connectToEndpoint] to connect to the port already |
| 20 | +/// opened. |
| 21 | +typedef WebDatabaseEndpoint = ({ |
| 22 | + MessagePort connectPort, |
| 23 | + String connectName, |
| 24 | + String? lockName, |
| 25 | +}); |
| 26 | + |
| 27 | +/// A [SqliteConnection] interface implemented by opened connections when |
| 28 | +/// running on the web. |
| 29 | +/// |
| 30 | +/// This adds the [exposeEndpoint], which uses `dart:js_interop` types not |
| 31 | +/// supported on native Dart platforms. The method can be used to access an |
| 32 | +/// opened database across different JavaScript contexts |
| 33 | +/// (e.g. document windows and workers). |
| 34 | +abstract class WebSqliteConnection implements SqliteConnection { |
| 35 | + /// Returns a future that completes when this connection is closed. |
| 36 | + /// |
| 37 | + /// This usually only happens when calling [close], but on the web |
| 38 | + /// specifically, it can also happen when a remote context closes a database |
| 39 | + /// accessed via [connectToEndpoint]. |
| 40 | + Future<void> get closedFuture; |
| 41 | + |
| 42 | + /// Returns a [WebDatabaseEndpoint] - a structure that consists only of types |
| 43 | + /// that can be transferred across a [MessagePort] in JavaScript. |
| 44 | + /// |
| 45 | + /// After transferring this endpoint to another JavaScript context (e.g. a |
| 46 | + /// worker), the worker can call [connectToEndpoint] to obtain a connection to |
| 47 | + /// the same sqlite database. |
| 48 | + Future<WebDatabaseEndpoint> exposeEndpoint(); |
| 49 | + |
| 50 | + /// Connect to an endpoint obtained through [exposeEndpoint]. |
| 51 | + /// |
| 52 | + /// The endpoint is transferrable in JavaScript, allowing multiple JavaScript |
| 53 | + /// contexts to exchange opened database connections. |
| 54 | + static Future<WebSqliteConnection> connectToEndpoint( |
| 55 | + WebDatabaseEndpoint endpoint) async { |
| 56 | + final rawSqlite = await WebSqlite.connectToPort( |
| 57 | + (endpoint.connectPort, endpoint.connectName)); |
| 58 | + |
| 59 | + final database = WebDatabase( |
| 60 | + rawSqlite, |
| 61 | + switch (endpoint.lockName) { |
| 62 | + var lock? => Mutex(identifier: lock), |
| 63 | + null => null, |
| 64 | + }, |
| 65 | + ); |
| 66 | + return database; |
| 67 | + } |
| 68 | +} |
0 commit comments