From b0033c4f4057b10f2206c2bf33a67cb19d8f9005 Mon Sep 17 00:00:00 2001 From: Alexandre Roux Date: Sun, 28 Jul 2024 18:45:18 +0200 Subject: [PATCH] [sqflite] fix multi factory path issue --- app_sqflite/lib/sqflite.dart | 2 +- app_sqflite/lib/src/sqflite.dart | 2 +- app_sqflite/lib/src/sqflite_io.dart | 101 +++++++++++++++++++++------ app_sqflite/lib/src/sqflite_web.dart | 5 ++ 4 files changed, 87 insertions(+), 23 deletions(-) diff --git a/app_sqflite/lib/sqflite.dart b/app_sqflite/lib/sqflite.dart index 4e3da6b..5750da7 100644 --- a/app_sqflite/lib/sqflite.dart +++ b/app_sqflite/lib/sqflite.dart @@ -9,7 +9,7 @@ DatabaseFactory get databaseFactory => src.databaseFactory; /// Get the database factory for a given package (setting in home path) /// -/// [packageName] or [rootPath] only used on linux and windows for now +/// [packageName] or [rootPath] only used on desktop (linux, windows and mac) for now /// /// autoInit is sqflite_ffi on windows DatabaseFactory getDatabaseFactory( diff --git a/app_sqflite/lib/src/sqflite.dart b/app_sqflite/lib/src/sqflite.dart index 2b6937f..ae10424 100644 --- a/app_sqflite/lib/src/sqflite.dart +++ b/app_sqflite/lib/src/sqflite.dart @@ -1,3 +1,3 @@ export 'sqflite_stub.dart' - if (dart.library.html) 'sqflite_web.dart' + if (dart.library.js_interop) 'sqflite_web.dart' if (dart.library.io) 'sqflite_io.dart'; diff --git a/app_sqflite/lib/src/sqflite_io.dart b/app_sqflite/lib/src/sqflite_io.dart index 948cfaa..927621c 100644 --- a/app_sqflite/lib/src/sqflite_io.dart +++ b/app_sqflite/lib/src/sqflite_io.dart @@ -1,36 +1,95 @@ import 'dart:io'; +import 'dart:typed_data'; import 'package:path/path.dart'; import 'package:process_run/process_run.dart'; -import 'package:sqflite_common_ffi/sqflite_ffi.dart'; - -String buildDatabasesPath(String packageName) { - var dataPath = join(userAppDataPath, packageName, 'databases'); - try { - var dir = Directory(dataPath); - if (!dir.existsSync()) { - dir.createSync(recursive: true); - } - } catch (_) {} - return dataPath; -} +import 'package:sqflite_common/sqflite.dart' as sqflite; +import 'package:sqflite_common_ffi/sqflite_ffi.dart' as ffi; -DatabaseFactory get _defaultDatabaseFactory => databaseFactoryFfi; +sqflite.DatabaseFactory get _defaultDatabaseFactory => +// ignore: invalid_use_of_visible_for_testing_member + sqflite.databaseFactoryOrNull ?? ffi.databaseFactoryFfi; /// All but Linux/Windows -DatabaseFactory get databaseFactory => _defaultDatabaseFactory; +sqflite.DatabaseFactory get databaseFactory => _defaultDatabaseFactory; /// Use sqflite on any platform -DatabaseFactory getDatabaseFactory( +sqflite.DatabaseFactory getDatabaseFactory( {String? packageName, String? rootPath, bool autoInit = true}) { - var databaseFactory = databaseFactoryFfi; if (autoInit) { sqfliteWindowsFfiInit(); } - // Should not return a future...or ignore - databaseFactory - .setDatabasesPath(rootPath ?? buildDatabasesPath(packageName ?? '.')); - return databaseFactory; + if ((Platform.isMacOS || Platform.isLinux || Platform.isWindows) && + (packageName != null || rootPath != null)) { + return _DatabaseFactory( + packageName: packageName, + rootPath: rootPath, + delegate: databaseFactory); + } else { + return databaseFactory; + } } -void sqfliteWindowsFfiInit() => sqfliteFfiInit(); +void sqfliteWindowsFfiInit() => ffi.sqfliteFfiInit(); + +class _DatabaseFactory implements sqflite.DatabaseFactory { + final String? packageName; + final String? rootPath; + final sqflite.DatabaseFactory delegate; + late final String databasesPath; + _DatabaseFactory( + {required this.packageName, + required this.rootPath, + required this.delegate}) { + databasesPath = packageName != null + ? join(userAppDataPath, packageName, 'databases') + : rootPath!; + } + + String _fixPath(String path) { + if (!isAbsolute(path)) { + path = join(databasesPath, path); + } + return path; + } + + String _fixAndCreatePath(String path) { + path = _fixPath(path); + try { + var dir = Directory(dirname(path)); + if (!dir.existsSync()) { + dir.createSync(recursive: true); + } + } catch (_) {} + return path; + } + + @override + Future databaseExists(String path) => + delegate.databaseExists(_fixPath(path)); + + @override + Future deleteDatabase(String path) => + delegate.deleteDatabase(_fixPath(path)); + + @override + Future getDatabasesPath() async => databasesPath; + + @override + Future openDatabase(String path, + {sqflite.OpenDatabaseOptions? options}) => + delegate.openDatabase(_fixAndCreatePath(path), options: options); + + @override + Future readDatabaseBytes(String path) => + delegate.readDatabaseBytes(_fixPath(path)); + + @override + Future setDatabasesPath(String path) async { + databasesPath = path; + } + + @override + Future writeDatabaseBytes(String path, Uint8List bytes) => + delegate.writeDatabaseBytes(_fixAndCreatePath(path), bytes); +} diff --git a/app_sqflite/lib/src/sqflite_web.dart b/app_sqflite/lib/src/sqflite_web.dart index 497fc0d..808e74b 100644 --- a/app_sqflite/lib/src/sqflite_web.dart +++ b/app_sqflite/lib/src/sqflite_web.dart @@ -10,6 +10,11 @@ DatabaseFactory getDatabaseFactory( /// Only needed/implemented on windows void sqfliteWindowsFfiInit() => _stub('sqfliteWindowsFfiInit'); +/// no op on the web +String getDatabasePath(String databasePath, + {String? packageName, String? rootPath}) => + databasePath; + T _stub(String message) { throw UnimplementedError(message); }