diff --git a/.gitignore b/dio_cache_interceptor/.gitignore similarity index 100% rename from .gitignore rename to dio_cache_interceptor/.gitignore diff --git a/CHANGELOG.md b/dio_cache_interceptor/CHANGELOG.md similarity index 97% rename from CHANGELOG.md rename to dio_cache_interceptor/CHANGELOG.md index f47f636..81f7fd5 100644 --- a/CHANGELOG.md +++ b/dio_cache_interceptor/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.0.0 +- core: Moved DB & Hive cache stores to their respective packages. +- fix: import of file_cache_store. + ## 2.3.1 - fix: Cache-Control parsing. Dio does not expand multi valued headers. diff --git a/LICENSE b/dio_cache_interceptor/LICENSE similarity index 100% rename from LICENSE rename to dio_cache_interceptor/LICENSE diff --git a/README.md b/dio_cache_interceptor/README.md similarity index 90% rename from README.md rename to dio_cache_interceptor/README.md index 444edea..7eabac4 100644 --- a/README.md +++ b/dio_cache_interceptor/README.md @@ -16,16 +16,11 @@ Dio HTTP cache interceptor with multiple stores respecting HTTP directives (or n ## Stores - __BackupCacheStore__: Combined store with primary and secondary. -- __DbCacheStore__: Cache with database (Moor). +- __DbCacheStore__: Cache with database (Moor) [Get it](https://pub.dev/packages/dio_cache_interceptor_db_store). - __FileCacheStore__: Cache with file system (no web support obviously). -- __HiveCacheStore__: Cache using Hive package (available on all platforms). +- __HiveCacheStore__: Cache using Hive package (available on all platforms) [Get it](https://pub.dev/packages/dio_cache_interceptor_hive_store). - __MemCacheStore__: Volatile cache with LRU strategy. -### DbCacheStore: -- __Android - iOS support__: Add sqlite3_flutter_libs as dependency in your app (version 0.4.0+1 or later). -- __Desktop support__: Follow Moor install [documentation](https://moor.simonbinder.eu/docs/platforms/). -- __Web support__: You must include 'sql.js' library. Follow Moor install [documentation](https://moor.simonbinder.eu/web/) for further info. - ## Usage ```dart diff --git a/analysis_options.yaml b/dio_cache_interceptor/analysis_options.yaml similarity index 95% rename from analysis_options.yaml rename to dio_cache_interceptor/analysis_options.yaml index 4ae0e01..29d9c07 100644 --- a/analysis_options.yaml +++ b/dio_cache_interceptor/analysis_options.yaml @@ -1,5 +1,5 @@ -include: package:pedantic/analysis_options.yaml - -analyzer: - exclude: +include: package:pedantic/analysis_options.yaml + +analyzer: + exclude: - "example/**" \ No newline at end of file diff --git a/example/.gitignore b/dio_cache_interceptor/example/.gitignore similarity index 100% rename from example/.gitignore rename to dio_cache_interceptor/example/.gitignore diff --git a/example/.metadata b/dio_cache_interceptor/example/.metadata similarity index 100% rename from example/.metadata rename to dio_cache_interceptor/example/.metadata diff --git a/example/README.md b/dio_cache_interceptor/example/README.md similarity index 100% rename from example/README.md rename to dio_cache_interceptor/example/README.md diff --git a/example/android/.gitignore b/dio_cache_interceptor/example/android/.gitignore similarity index 100% rename from example/android/.gitignore rename to dio_cache_interceptor/example/android/.gitignore diff --git a/example/android/app/build.gradle b/dio_cache_interceptor/example/android/app/build.gradle similarity index 100% rename from example/android/app/build.gradle rename to dio_cache_interceptor/example/android/app/build.gradle diff --git a/example/android/app/src/debug/AndroidManifest.xml b/dio_cache_interceptor/example/android/app/src/debug/AndroidManifest.xml similarity index 100% rename from example/android/app/src/debug/AndroidManifest.xml rename to dio_cache_interceptor/example/android/app/src/debug/AndroidManifest.xml diff --git a/example/android/app/src/main/AndroidManifest.xml b/dio_cache_interceptor/example/android/app/src/main/AndroidManifest.xml similarity index 100% rename from example/android/app/src/main/AndroidManifest.xml rename to dio_cache_interceptor/example/android/app/src/main/AndroidManifest.xml diff --git a/example/android/app/src/main/java/com/llfbandit/dio_cache_interceptor_example/MainActivity.java b/dio_cache_interceptor/example/android/app/src/main/java/com/llfbandit/dio_cache_interceptor_example/MainActivity.java similarity index 100% rename from example/android/app/src/main/java/com/llfbandit/dio_cache_interceptor_example/MainActivity.java rename to dio_cache_interceptor/example/android/app/src/main/java/com/llfbandit/dio_cache_interceptor_example/MainActivity.java diff --git a/example/android/app/src/main/res/drawable/launch_background.xml b/dio_cache_interceptor/example/android/app/src/main/res/drawable/launch_background.xml similarity index 100% rename from example/android/app/src/main/res/drawable/launch_background.xml rename to dio_cache_interceptor/example/android/app/src/main/res/drawable/launch_background.xml diff --git a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/dio_cache_interceptor/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png similarity index 100% rename from example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png rename to dio_cache_interceptor/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png diff --git a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/dio_cache_interceptor/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png similarity index 100% rename from example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png rename to dio_cache_interceptor/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png diff --git a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/dio_cache_interceptor/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png similarity index 100% rename from example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png rename to dio_cache_interceptor/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png diff --git a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/dio_cache_interceptor/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png similarity index 100% rename from example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png rename to dio_cache_interceptor/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png diff --git a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/dio_cache_interceptor/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png similarity index 100% rename from example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png rename to dio_cache_interceptor/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png diff --git a/example/android/app/src/main/res/values/styles.xml b/dio_cache_interceptor/example/android/app/src/main/res/values/styles.xml similarity index 100% rename from example/android/app/src/main/res/values/styles.xml rename to dio_cache_interceptor/example/android/app/src/main/res/values/styles.xml diff --git a/example/android/app/src/profile/AndroidManifest.xml b/dio_cache_interceptor/example/android/app/src/profile/AndroidManifest.xml similarity index 100% rename from example/android/app/src/profile/AndroidManifest.xml rename to dio_cache_interceptor/example/android/app/src/profile/AndroidManifest.xml diff --git a/example/android/build.gradle b/dio_cache_interceptor/example/android/build.gradle similarity index 100% rename from example/android/build.gradle rename to dio_cache_interceptor/example/android/build.gradle diff --git a/example/android/gradle.properties b/dio_cache_interceptor/example/android/gradle.properties similarity index 100% rename from example/android/gradle.properties rename to dio_cache_interceptor/example/android/gradle.properties diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/dio_cache_interceptor/example/android/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from example/android/gradle/wrapper/gradle-wrapper.properties rename to dio_cache_interceptor/example/android/gradle/wrapper/gradle-wrapper.properties diff --git a/example/android/settings.gradle b/dio_cache_interceptor/example/android/settings.gradle similarity index 100% rename from example/android/settings.gradle rename to dio_cache_interceptor/example/android/settings.gradle diff --git a/example/ios/.gitignore b/dio_cache_interceptor/example/ios/.gitignore similarity index 100% rename from example/ios/.gitignore rename to dio_cache_interceptor/example/ios/.gitignore diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/dio_cache_interceptor/example/ios/Flutter/AppFrameworkInfo.plist similarity index 100% rename from example/ios/Flutter/AppFrameworkInfo.plist rename to dio_cache_interceptor/example/ios/Flutter/AppFrameworkInfo.plist diff --git a/example/ios/Flutter/Debug.xcconfig b/dio_cache_interceptor/example/ios/Flutter/Debug.xcconfig similarity index 100% rename from example/ios/Flutter/Debug.xcconfig rename to dio_cache_interceptor/example/ios/Flutter/Debug.xcconfig diff --git a/example/ios/Flutter/Release.xcconfig b/dio_cache_interceptor/example/ios/Flutter/Release.xcconfig similarity index 100% rename from example/ios/Flutter/Release.xcconfig rename to dio_cache_interceptor/example/ios/Flutter/Release.xcconfig diff --git a/example/ios/Podfile b/dio_cache_interceptor/example/ios/Podfile similarity index 100% rename from example/ios/Podfile rename to dio_cache_interceptor/example/ios/Podfile diff --git a/example/ios/Podfile.lock b/dio_cache_interceptor/example/ios/Podfile.lock similarity index 100% rename from example/ios/Podfile.lock rename to dio_cache_interceptor/example/ios/Podfile.lock diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/dio_cache_interceptor/example/ios/Runner.xcodeproj/project.pbxproj similarity index 100% rename from example/ios/Runner.xcodeproj/project.pbxproj rename to dio_cache_interceptor/example/ios/Runner.xcodeproj/project.pbxproj diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/dio_cache_interceptor/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to dio_cache_interceptor/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/dio_cache_interceptor/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to dio_cache_interceptor/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/dio_cache_interceptor/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings similarity index 100% rename from example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings rename to dio_cache_interceptor/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/dio_cache_interceptor/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme similarity index 100% rename from example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme rename to dio_cache_interceptor/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme diff --git a/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/dio_cache_interceptor/example/ios/Runner.xcworkspace/contents.xcworkspacedata similarity index 100% rename from example/ios/Runner.xcworkspace/contents.xcworkspacedata rename to dio_cache_interceptor/example/ios/Runner.xcworkspace/contents.xcworkspacedata diff --git a/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/dio_cache_interceptor/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to dio_cache_interceptor/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/dio_cache_interceptor/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings similarity index 100% rename from example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings rename to dio_cache_interceptor/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings diff --git a/example/ios/Runner/AppDelegate.swift b/dio_cache_interceptor/example/ios/Runner/AppDelegate.swift similarity index 100% rename from example/ios/Runner/AppDelegate.swift rename to dio_cache_interceptor/example/ios/Runner/AppDelegate.swift diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json rename to dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png rename to dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png rename to dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png rename to dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png rename to dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png rename to dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png rename to dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png rename to dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png rename to dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png rename to dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png rename to dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png rename to dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png rename to dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png rename to dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png rename to dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png rename to dio_cache_interceptor/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/dio_cache_interceptor/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json similarity index 100% rename from example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json rename to dio_cache_interceptor/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/dio_cache_interceptor/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png rename to dio_cache_interceptor/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/dio_cache_interceptor/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png rename to dio_cache_interceptor/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/dio_cache_interceptor/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png similarity index 100% rename from example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png rename to dio_cache_interceptor/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/dio_cache_interceptor/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md similarity index 100% rename from example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md rename to dio_cache_interceptor/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md diff --git a/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/dio_cache_interceptor/example/ios/Runner/Base.lproj/LaunchScreen.storyboard similarity index 100% rename from example/ios/Runner/Base.lproj/LaunchScreen.storyboard rename to dio_cache_interceptor/example/ios/Runner/Base.lproj/LaunchScreen.storyboard diff --git a/example/ios/Runner/Base.lproj/Main.storyboard b/dio_cache_interceptor/example/ios/Runner/Base.lproj/Main.storyboard similarity index 100% rename from example/ios/Runner/Base.lproj/Main.storyboard rename to dio_cache_interceptor/example/ios/Runner/Base.lproj/Main.storyboard diff --git a/example/ios/Runner/Info.plist b/dio_cache_interceptor/example/ios/Runner/Info.plist similarity index 100% rename from example/ios/Runner/Info.plist rename to dio_cache_interceptor/example/ios/Runner/Info.plist diff --git a/example/ios/Runner/Runner-Bridging-Header.h b/dio_cache_interceptor/example/ios/Runner/Runner-Bridging-Header.h similarity index 100% rename from example/ios/Runner/Runner-Bridging-Header.h rename to dio_cache_interceptor/example/ios/Runner/Runner-Bridging-Header.h diff --git a/example/lib/main.dart b/dio_cache_interceptor/example/lib/main.dart similarity index 96% rename from example/lib/main.dart rename to dio_cache_interceptor/example/lib/main.dart index 9f8af02..e592138 100644 --- a/example/lib/main.dart +++ b/dio_cache_interceptor/example/lib/main.dart @@ -25,8 +25,12 @@ class _MyAppState extends State { @override void initState() { pp.getApplicationDocumentsDirectory().then((dir) { - cacheStore = DbCacheStore(databasePath: dir.path, logStatements: true); - // cacheStore = FileCacheStore(dir.path); + cacheStore = FileCacheStore(dir.path); + + // or + + // cacheStore = DbCacheStore(databasePath: dir.path, logStatements: true); + // cacheStore = HiveCacheStore(dir.path); cacheOptions = CacheOptions( store: cacheStore, diff --git a/example/pubspec.yaml b/dio_cache_interceptor/example/pubspec.yaml similarity index 94% rename from example/pubspec.yaml rename to dio_cache_interceptor/example/pubspec.yaml index f5c56c8..27f25bb 100644 --- a/example/pubspec.yaml +++ b/dio_cache_interceptor/example/pubspec.yaml @@ -17,7 +17,7 @@ dependencies: path: ../ path_provider: ^2.0.0 - sqlite3_flutter_libs: ^0.4.1 + sqlite3_flutter_libs: ^0.5.0 # The following section is specific to Flutter. flutter: diff --git a/lib/dio_cache_interceptor.dart b/dio_cache_interceptor/lib/dio_cache_interceptor.dart similarity index 67% rename from lib/dio_cache_interceptor.dart rename to dio_cache_interceptor/lib/dio_cache_interceptor.dart index 388fd24..12a486c 100644 --- a/lib/dio_cache_interceptor.dart +++ b/dio_cache_interceptor/lib/dio_cache_interceptor.dart @@ -1,7 +1,5 @@ library dio_cache_interceptor; -export 'io_unsupported.dart' - if (dart.library.io) 'src/store/file_cache_store.dart'; export 'src/dio_cache_interceptor.dart'; export 'src/model/cache_control.dart'; export 'src/model/cache_options.dart'; @@ -9,6 +7,5 @@ export 'src/model/cache_priority.dart'; export 'src/model/cache_response.dart'; export 'src/store/backup_cache_store.dart'; export 'src/store/cache_store.dart'; -export 'src/store/db_cache_store.dart'; -export 'src/store/hive_cache_store.dart'; +export 'src/store/file_cache_store/file_cache_store.dart'; export 'src/store/mem_cache_store.dart'; diff --git a/lib/src/dio_cache_interceptor.dart b/dio_cache_interceptor/lib/src/dio_cache_interceptor.dart similarity index 100% rename from lib/src/dio_cache_interceptor.dart rename to dio_cache_interceptor/lib/src/dio_cache_interceptor.dart diff --git a/lib/src/model/cache_cipher.dart b/dio_cache_interceptor/lib/src/model/cache_cipher.dart similarity index 96% rename from lib/src/model/cache_cipher.dart rename to dio_cache_interceptor/lib/src/model/cache_cipher.dart index e45f54a..47f692f 100644 --- a/lib/src/model/cache_cipher.dart +++ b/dio_cache_interceptor/lib/src/model/cache_cipher.dart @@ -1,15 +1,15 @@ -/// Encrypt content/headers method. -typedef Encrypt = Future> Function(List bytes); - -/// Decrypt content/headers method. -typedef Decrypt = Future> Function(List bytes); - -class CacheCipher { - /// Optional method to decrypt cache content - final Decrypt decrypt; - - /// Optional method to encrypt cache content - final Encrypt encrypt; - - const CacheCipher({required this.decrypt, required this.encrypt}); -} +/// Encrypt content/headers method. +typedef Encrypt = Future> Function(List bytes); + +/// Decrypt content/headers method. +typedef Decrypt = Future> Function(List bytes); + +class CacheCipher { + /// Optional method to decrypt cache content + final Decrypt decrypt; + + /// Optional method to encrypt cache content + final Encrypt encrypt; + + const CacheCipher({required this.decrypt, required this.encrypt}); +} diff --git a/lib/src/model/cache_control.dart b/dio_cache_interceptor/lib/src/model/cache_control.dart similarity index 96% rename from lib/src/model/cache_control.dart rename to dio_cache_interceptor/lib/src/model/cache_control.dart index 33ffbc0..c28e98f 100644 --- a/lib/src/model/cache_control.dart +++ b/dio_cache_interceptor/lib/src/model/cache_control.dart @@ -1,80 +1,80 @@ -/// Cache-Control header subset representation -class CacheControl { - /// How long the response can be used from the time it was requested (in seconds). - /// https://tools.ietf.org/html/rfc7234#section-5.2.2.8 - final int? maxAge; - - /// 'public' / 'private'. - /// https://tools.ietf.org/html/rfc7234#section-5.2.2.5 - final String? privacy; - - /// Must first submit a validation request to an origin server. - /// https://tools.ietf.org/html/rfc7234#section-5.2.2.2 - final bool? noCache; - - /// Disallow cache, overriding any other directives (Etag, Last-Modified) - /// https://tools.ietf.org/html/rfc7234#section-5.2.2.3 - final bool? noStore; - - /// Other attributes not parsed - final List other; - - CacheControl({ - this.maxAge, - this.privacy, - this.noCache = false, - this.noStore = false, - this.other = const [], - }); - - static CacheControl? fromHeader(List? headerValues) { - if (headerValues == null) return null; - - int? maxAge; - String? privacy; - bool? noCache; - bool? noStore; - final other = []; - - for (var value in headerValues) { - // Expand values since dio does not do it ! - for (var expandedValue in value.split(',')) { - expandedValue = expandedValue.trim(); - if (expandedValue == 'no-cache') { - noCache = true; - } else if (expandedValue == 'no-store') { - noStore = true; - } else if (expandedValue == 'public' || expandedValue == 'private') { - privacy = expandedValue; - } else if (expandedValue.startsWith('max-age')) { - maxAge = int.tryParse( - expandedValue.substring(expandedValue.indexOf('=') + 1), - ); - } else { - other.add(expandedValue); - } - } - } - - return CacheControl( - maxAge: maxAge, - privacy: privacy, - noCache: noCache, - noStore: noStore, - other: other, - ); - } - - /// Serialize cache-control values - String toHeader() { - final values = [ - maxAge != null ? 'max-age=$maxAge' : '', - privacy ?? '', - (noCache ?? false) ? 'no-cache' : '', - (noStore ?? false) ? 'no-store' : '', - ...other - ]; - - return values.join(', '); - } -} +/// Cache-Control header subset representation +class CacheControl { + /// How long the response can be used from the time it was requested (in seconds). + /// https://tools.ietf.org/html/rfc7234#section-5.2.2.8 + final int? maxAge; + + /// 'public' / 'private'. + /// https://tools.ietf.org/html/rfc7234#section-5.2.2.5 + final String? privacy; + + /// Must first submit a validation request to an origin server. + /// https://tools.ietf.org/html/rfc7234#section-5.2.2.2 + final bool? noCache; + + /// Disallow cache, overriding any other directives (Etag, Last-Modified) + /// https://tools.ietf.org/html/rfc7234#section-5.2.2.3 + final bool? noStore; + + /// Other attributes not parsed + final List other; + + CacheControl({ + this.maxAge, + this.privacy, + this.noCache = false, + this.noStore = false, + this.other = const [], + }); + + static CacheControl? fromHeader(List? headerValues) { + if (headerValues == null) return null; + + int? maxAge; + String? privacy; + bool? noCache; + bool? noStore; + final other = []; + + for (var value in headerValues) { + // Expand values since dio does not do it ! + for (var expandedValue in value.split(',')) { + expandedValue = expandedValue.trim(); + if (expandedValue == 'no-cache') { + noCache = true; + } else if (expandedValue == 'no-store') { + noStore = true; + } else if (expandedValue == 'public' || expandedValue == 'private') { + privacy = expandedValue; + } else if (expandedValue.startsWith('max-age')) { + maxAge = int.tryParse( + expandedValue.substring(expandedValue.indexOf('=') + 1), + ); + } else { + other.add(expandedValue); + } + } + } + + return CacheControl( + maxAge: maxAge, + privacy: privacy, + noCache: noCache, + noStore: noStore, + other: other, + ); + } + + /// Serialize cache-control values + String toHeader() { + final values = [ + maxAge != null ? 'max-age=$maxAge' : '', + privacy ?? '', + (noCache ?? false) ? 'no-cache' : '', + (noStore ?? false) ? 'no-store' : '', + ...other + ]; + + return values.join(', '); + } +} diff --git a/lib/src/model/cache_options.dart b/dio_cache_interceptor/lib/src/model/cache_options.dart similarity index 100% rename from lib/src/model/cache_options.dart rename to dio_cache_interceptor/lib/src/model/cache_options.dart diff --git a/lib/src/model/cache_priority.dart b/dio_cache_interceptor/lib/src/model/cache_priority.dart similarity index 100% rename from lib/src/model/cache_priority.dart rename to dio_cache_interceptor/lib/src/model/cache_priority.dart diff --git a/lib/src/model/cache_response.dart b/dio_cache_interceptor/lib/src/model/cache_response.dart similarity index 100% rename from lib/src/model/cache_response.dart rename to dio_cache_interceptor/lib/src/model/cache_response.dart diff --git a/lib/src/store/backup_cache_store.dart b/dio_cache_interceptor/lib/src/store/backup_cache_store.dart similarity index 96% rename from lib/src/store/backup_cache_store.dart rename to dio_cache_interceptor/lib/src/store/backup_cache_store.dart index c8e2a42..e0888bc 100644 --- a/lib/src/store/backup_cache_store.dart +++ b/dio_cache_interceptor/lib/src/store/backup_cache_store.dart @@ -1,69 +1,69 @@ -import '../model/cache_priority.dart'; -import '../model/cache_response.dart'; -import 'cache_store.dart'; - -/// A store saving responses in a dedicated [primary] -/// store and [secondary] store. -/// -/// Cached responses are read from [primary] first, and then -/// from [secondary]. -/// -/// Mostly useful when you want MemCacheStore before another. -/// -class BackupCacheStore implements CacheStore { - /// Primary cache store - final CacheStore primary; - - /// Secondary cache store - final CacheStore secondary; - - BackupCacheStore({required this.primary, required this.secondary}) { - clean(staleOnly: true); - } - - @override - Future clean({ - CachePriority priorityOrBelow = CachePriority.high, - bool staleOnly = false, - }) async { - await primary.clean( - priorityOrBelow: priorityOrBelow, - staleOnly: staleOnly, - ); - return secondary.clean( - priorityOrBelow: priorityOrBelow, - staleOnly: staleOnly, - ); - } - - @override - Future delete(String key, {bool staleOnly = false}) async { - await primary.delete(key, staleOnly: staleOnly); - return secondary.delete(key, staleOnly: staleOnly); - } - - @override - Future exists(String key) async { - return await primary.exists(key) || await secondary.exists(key); - } - - @override - Future get(String key) async { - final resp = await primary.get(key); - if (resp != null) return resp; - - return secondary.get(key); - } - - @override - Future set(CacheResponse response) async { - await primary.set(response); - return secondary.set(response); - } - - @override - Future close() async { - await primary.close(); - return secondary.close(); - } -} +import '../model/cache_priority.dart'; +import '../model/cache_response.dart'; +import 'cache_store.dart'; + +/// A store saving responses in a dedicated [primary] +/// store and [secondary] store. +/// +/// Cached responses are read from [primary] first, and then +/// from [secondary]. +/// +/// Mostly useful when you want MemCacheStore before another. +/// +class BackupCacheStore implements CacheStore { + /// Primary cache store + final CacheStore primary; + + /// Secondary cache store + final CacheStore secondary; + + BackupCacheStore({required this.primary, required this.secondary}) { + clean(staleOnly: true); + } + + @override + Future clean({ + CachePriority priorityOrBelow = CachePriority.high, + bool staleOnly = false, + }) async { + await primary.clean( + priorityOrBelow: priorityOrBelow, + staleOnly: staleOnly, + ); + return secondary.clean( + priorityOrBelow: priorityOrBelow, + staleOnly: staleOnly, + ); + } + + @override + Future delete(String key, {bool staleOnly = false}) async { + await primary.delete(key, staleOnly: staleOnly); + return secondary.delete(key, staleOnly: staleOnly); + } + + @override + Future exists(String key) async { + return await primary.exists(key) || await secondary.exists(key); + } + + @override + Future get(String key) async { + final resp = await primary.get(key); + if (resp != null) return resp; + + return secondary.get(key); + } + + @override + Future set(CacheResponse response) async { + await primary.set(response); + return secondary.set(response); + } + + @override + Future close() async { + await primary.close(); + return secondary.close(); + } +} diff --git a/lib/src/store/cache_store.dart b/dio_cache_interceptor/lib/src/store/cache_store.dart similarity index 100% rename from lib/src/store/cache_store.dart rename to dio_cache_interceptor/lib/src/store/cache_store.dart diff --git a/dio_cache_interceptor/lib/src/store/file_cache_store/file_cache_store.dart b/dio_cache_interceptor/lib/src/store/file_cache_store/file_cache_store.dart new file mode 100644 index 0000000..55c8201 --- /dev/null +++ b/dio_cache_interceptor/lib/src/store/file_cache_store/file_cache_store.dart @@ -0,0 +1,2 @@ +export 'file_cache_store_none.dart' + if (dart.library.io) 'file_cache_store_io.dart'; diff --git a/lib/src/store/file_cache_store.dart b/dio_cache_interceptor/lib/src/store/file_cache_store/file_cache_store_io.dart similarity index 98% rename from lib/src/store/file_cache_store.dart rename to dio_cache_interceptor/lib/src/store/file_cache_store/file_cache_store_io.dart index f599470..3ea145e 100644 --- a/lib/src/store/file_cache_store.dart +++ b/dio_cache_interceptor/lib/src/store/file_cache_store/file_cache_store_io.dart @@ -5,9 +5,9 @@ import 'dart:typed_data'; import 'package:dio_cache_interceptor/src/model/cache_control.dart'; import 'package:path/path.dart' as path; -import '../model/cache_priority.dart'; -import '../model/cache_response.dart'; -import 'cache_store.dart'; +import '../../model/cache_priority.dart'; +import '../../model/cache_response.dart'; +import '../cache_store.dart'; /// A store saving responses in a dedicated file from a given root [directory]. /// diff --git a/lib/io_unsupported.dart b/dio_cache_interceptor/lib/src/store/file_cache_store/file_cache_store_none.dart similarity index 100% rename from lib/io_unsupported.dart rename to dio_cache_interceptor/lib/src/store/file_cache_store/file_cache_store_none.dart diff --git a/lib/src/store/mem_cache_store.dart b/dio_cache_interceptor/lib/src/store/mem_cache_store.dart similarity index 95% rename from lib/src/store/mem_cache_store.dart rename to dio_cache_interceptor/lib/src/store/mem_cache_store.dart index e337904..b75155b 100644 --- a/lib/src/store/mem_cache_store.dart +++ b/dio_cache_interceptor/lib/src/store/mem_cache_store.dart @@ -1,188 +1,188 @@ -import '../../dio_cache_interceptor.dart'; - -/// A store saving responses in a dedicated memory LRU map. -/// -class MemCacheStore implements CacheStore { - final _LruMap _cache; - - /// [maxSize]: Total allowed size in bytes (7MB by default) - /// [maxEntrySize]: Allowed size per entry in bytes (500KB by default). - /// - /// To prevent making this store useless, be sure to - /// respect the following lower-limit rule: maxEntrySize * 5 <= maxSize. - /// - MemCacheStore({ - int maxSize = 7340032, - int maxEntrySize = 512000, - }) : _cache = _LruMap(maxSize, maxEntrySize); - - @override - Future clean({ - CachePriority priorityOrBelow = CachePriority.high, - bool staleOnly = false, - }) { - final keys = []; - - _cache.entries.forEach((key, resp) { - var shouldRemove = resp.value.priority.index <= priorityOrBelow.index; - shouldRemove &= (staleOnly && resp.value.isStaled()) || !staleOnly; - - if (shouldRemove) { - keys.add(key); - } - }); - - keys.forEach((key) => _cache.remove(key)); - - return Future.value(); - } - - @override - Future delete(String key, {bool staleOnly = false}) { - final resp = _cache.entries[key]; - if (resp == null) return Future.value(); - - if (staleOnly && !resp.value.isStaled()) { - return Future.value(); - } - - _cache.remove(key); - - return Future.value(); - } - - @override - Future exists(String key) { - return Future.value(_cache.entries.containsKey(key)); - } - - @override - Future get(String key) async { - final resp = _cache[key]; - if (resp == null) return null; - - // Purge entry if staled - if (resp.isStaled()) { - await delete(key); - return null; - } - - return resp; - } - - @override - Future set(CacheResponse response) { - _cache.remove(response.key); - _cache[response.key] = response; - - return Future.value(); - } - - @override - Future close() { - return Future.value(); - } -} - -class _LruMap { - _Link? _head; - _Link? _tail; - - final entries = {}; - - int _currentSize = 0; - final int maxSize; - final int maxEntrySize; - - _LruMap(this.maxSize, this.maxEntrySize) { - assert(maxEntrySize != maxSize); - assert(maxEntrySize * 5 <= maxSize); - } - - CacheResponse? operator [](String key) { - final entry = entries[key]; - if (entry == null) return null; - - _moveToHead(entry); - return entry.value; - } - - void operator []=(String key, CacheResponse resp) { - final entrySize = _computeSize(resp); - // Entry too heavy, skip it - if (entrySize > maxEntrySize) return; - - final entry = _Link(key, resp, entrySize); - - entries[key] = entry; - _currentSize += entry.size; - _moveToHead(entry); - - while (_currentSize > maxSize) { - assert(_tail != null); - remove(_tail!.key); - } - } - - CacheResponse? remove(String key) { - final entry = entries[key]; - if (entry == null) return null; - - _currentSize -= entry.size; - entries.remove(key); - - if (entry == _tail) { - _tail = entry.next; - _tail?.previous = null; - } - if (entry == _head) { - _head = entry.previous; - _head?.next = null; - } - - return entry.value; - } - - void _moveToHead(_Link link) { - if (link == _head) return; - - if (link == _tail) { - _tail = link.next; - } - - if (link.previous != null) { - link.previous!.next = link.next; - } - if (link.next != null) { - link.next!.previous = link.previous; - } - - _head?.next = link; - link.previous = _head; - _head = link; - _tail ??= link; - link.next = null; - } - - int _computeSize(CacheResponse resp) { - var size = resp.content?.length ?? 0; - size += resp.headers?.length ?? 0; - - return size * 8; - } -} - -class _Link implements MapEntry { - _Link? next; - _Link? previous; - - final int size; - - @override - final String key; - - @override - final CacheResponse value; - - _Link(this.key, this.value, this.size); -} +import '../../dio_cache_interceptor.dart'; + +/// A store saving responses in a dedicated memory LRU map. +/// +class MemCacheStore implements CacheStore { + final _LruMap _cache; + + /// [maxSize]: Total allowed size in bytes (7MB by default) + /// [maxEntrySize]: Allowed size per entry in bytes (500KB by default). + /// + /// To prevent making this store useless, be sure to + /// respect the following lower-limit rule: maxEntrySize * 5 <= maxSize. + /// + MemCacheStore({ + int maxSize = 7340032, + int maxEntrySize = 512000, + }) : _cache = _LruMap(maxSize, maxEntrySize); + + @override + Future clean({ + CachePriority priorityOrBelow = CachePriority.high, + bool staleOnly = false, + }) { + final keys = []; + + _cache.entries.forEach((key, resp) { + var shouldRemove = resp.value.priority.index <= priorityOrBelow.index; + shouldRemove &= (staleOnly && resp.value.isStaled()) || !staleOnly; + + if (shouldRemove) { + keys.add(key); + } + }); + + keys.forEach((key) => _cache.remove(key)); + + return Future.value(); + } + + @override + Future delete(String key, {bool staleOnly = false}) { + final resp = _cache.entries[key]; + if (resp == null) return Future.value(); + + if (staleOnly && !resp.value.isStaled()) { + return Future.value(); + } + + _cache.remove(key); + + return Future.value(); + } + + @override + Future exists(String key) { + return Future.value(_cache.entries.containsKey(key)); + } + + @override + Future get(String key) async { + final resp = _cache[key]; + if (resp == null) return null; + + // Purge entry if staled + if (resp.isStaled()) { + await delete(key); + return null; + } + + return resp; + } + + @override + Future set(CacheResponse response) { + _cache.remove(response.key); + _cache[response.key] = response; + + return Future.value(); + } + + @override + Future close() { + return Future.value(); + } +} + +class _LruMap { + _Link? _head; + _Link? _tail; + + final entries = {}; + + int _currentSize = 0; + final int maxSize; + final int maxEntrySize; + + _LruMap(this.maxSize, this.maxEntrySize) { + assert(maxEntrySize != maxSize); + assert(maxEntrySize * 5 <= maxSize); + } + + CacheResponse? operator [](String key) { + final entry = entries[key]; + if (entry == null) return null; + + _moveToHead(entry); + return entry.value; + } + + void operator []=(String key, CacheResponse resp) { + final entrySize = _computeSize(resp); + // Entry too heavy, skip it + if (entrySize > maxEntrySize) return; + + final entry = _Link(key, resp, entrySize); + + entries[key] = entry; + _currentSize += entry.size; + _moveToHead(entry); + + while (_currentSize > maxSize) { + assert(_tail != null); + remove(_tail!.key); + } + } + + CacheResponse? remove(String key) { + final entry = entries[key]; + if (entry == null) return null; + + _currentSize -= entry.size; + entries.remove(key); + + if (entry == _tail) { + _tail = entry.next; + _tail?.previous = null; + } + if (entry == _head) { + _head = entry.previous; + _head?.next = null; + } + + return entry.value; + } + + void _moveToHead(_Link link) { + if (link == _head) return; + + if (link == _tail) { + _tail = link.next; + } + + if (link.previous != null) { + link.previous!.next = link.next; + } + if (link.next != null) { + link.next!.previous = link.previous; + } + + _head?.next = link; + link.previous = _head; + _head = link; + _tail ??= link; + link.next = null; + } + + int _computeSize(CacheResponse resp) { + var size = resp.content?.length ?? 0; + size += resp.headers?.length ?? 0; + + return size * 8; + } +} + +class _Link implements MapEntry { + _Link? next; + _Link? previous; + + final int size; + + @override + final String key; + + @override + final CacheResponse value; + + _Link(this.key, this.value, this.size); +} diff --git a/lib/src/util/contants.dart b/dio_cache_interceptor/lib/src/util/contants.dart similarity index 97% rename from lib/src/util/contants.dart rename to dio_cache_interceptor/lib/src/util/contants.dart index af4d01d..cd37040 100644 --- a/lib/src/util/contants.dart +++ b/dio_cache_interceptor/lib/src/util/contants.dart @@ -1,9 +1,9 @@ -const cacheControlHeader = 'cache-control'; -const dateHeader = 'date'; -const etagHeader = 'etag'; -const expiresHeader = 'expires'; -const contentLocationHeader = 'content-location'; -const varyHeader = 'vary'; -const ifModifiedSinceHeader = 'if-modified-since'; -const ifNoneMatchHeader = 'if-none-match'; -const lastModifiedHeader = 'last-modified'; +const cacheControlHeader = 'cache-control'; +const dateHeader = 'date'; +const etagHeader = 'etag'; +const expiresHeader = 'expires'; +const contentLocationHeader = 'content-location'; +const varyHeader = 'vary'; +const ifModifiedSinceHeader = 'if-modified-since'; +const ifNoneMatchHeader = 'if-none-match'; +const lastModifiedHeader = 'last-modified'; diff --git a/lib/src/util/content_serialization.dart b/dio_cache_interceptor/lib/src/util/content_serialization.dart similarity index 92% rename from lib/src/util/content_serialization.dart rename to dio_cache_interceptor/lib/src/util/content_serialization.dart index 17bf9be..d34b205 100644 --- a/lib/src/util/content_serialization.dart +++ b/dio_cache_interceptor/lib/src/util/content_serialization.dart @@ -2,7 +2,7 @@ import 'dart:convert'; import 'package:dio/dio.dart'; -Future> serializeContent(ResponseType type, dynamic? content) async { +Future> serializeContent(ResponseType type, dynamic content) async { switch (type) { case ResponseType.bytes: return content; diff --git a/lib/src/util/http_date.dart b/dio_cache_interceptor/lib/src/util/http_date.dart similarity index 96% rename from lib/src/util/http_date.dart rename to dio_cache_interceptor/lib/src/util/http_date.dart index 8ffa14f..3ed2a1e 100644 --- a/lib/src/util/http_date.dart +++ b/dio_cache_interceptor/lib/src/util/http_date.dart @@ -1,149 +1,149 @@ -class HttpDate { - /// Parse a date string in either of the formats - /// [RFC-1123](http://tools.ietf.org/html/rfc1123 "RFC-1123"), - /// [RFC-850](http://tools.ietf.org/html/rfc850 "RFC-850") or - /// ANSI C's asctime() format. These formats are listed here. - /// - /// Thu, 1 Jan 1970 00:00:00 GMT - /// Thursday, 1-Jan-1970 00:00:00 GMT - /// Thu Jan 1 00:00:00 1970 - /// - /// For more information see [RFC-2616 section - /// 3.1.1](http://tools.ietf.org/html/rfc2616#section-3.3.1 - /// "RFC-2616 section 3.1.1"). - /// - static DateTime parse(String date) { - final sp = 32; - const wkdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; - const weekdays = [ - 'Monday', - 'Tuesday', - 'Wednesday', - 'Thursday', - 'Friday', - 'Saturday', - 'Sunday' - ]; - const months = [ - 'Jan', - 'Feb', - 'Mar', - 'Apr', - 'May', - 'Jun', - 'Jul', - 'Aug', - 'Sep', - 'Oct', - 'Nov', - 'Dec' - ]; - - final formatRfc1123 = 0; - final formatRfc850 = 1; - final formatAsctime = 2; - - var index = 0; - String tmp; - - void expect(String s) { - if (date.length - index < s.length) { - throw Exception('Invalid HTTP date $date'); - } - final tmp = date.substring(index, index + s.length); - if (tmp != s) { - throw Exception('Invalid HTTP date $date'); - } - index += s.length; - } - - int expectWeekday() { - int weekday; - // The formatting of the weekday signals the format of the date string. - var pos = date.indexOf(',', index); - if (pos == -1) { - var pos = date.indexOf(' ', index); - if (pos == -1) throw Exception('Invalid HTTP date $date'); - tmp = date.substring(index, pos); - index = pos + 1; - weekday = wkdays.indexOf(tmp); - if (weekday != -1) { - return formatAsctime; - } - } else { - tmp = date.substring(index, pos); - index = pos + 1; - weekday = wkdays.indexOf(tmp); - if (weekday != -1) { - return formatRfc1123; - } - weekday = weekdays.indexOf(tmp); - if (weekday != -1) { - return formatRfc850; - } - } - throw Exception('Invalid HTTP date $date'); - } - - int expectMonth(String separator) { - var pos = date.indexOf(separator, index); - if (pos - index != 3) throw Exception('Invalid HTTP date $date'); - tmp = date.substring(index, pos); - index = pos + 1; - var month = months.indexOf(tmp); - if (month != -1) return month; - throw Exception('Invalid HTTP date $date'); - } - - int expectNum(String separator) { - int pos; - if (separator.isNotEmpty) { - pos = date.indexOf(separator, index); - } else { - pos = date.length; - } - var tmp = date.substring(index, pos); - index = pos + separator.length; - try { - var value = int.parse(tmp); - return value; - } on FormatException { - throw Exception('Invalid HTTP date $date'); - } - } - - void expectEnd() { - if (index != date.length) { - throw Exception('Invalid HTTP date $date'); - } - } - - var format = expectWeekday(); - int year; - int month; - int day; - int hours; - int minutes; - int seconds; - if (format == formatAsctime) { - month = expectMonth(' '); - if (date.codeUnitAt(index) == sp) index++; - day = expectNum(' '); - hours = expectNum(':'); - minutes = expectNum(':'); - seconds = expectNum(' '); - year = expectNum(''); - } else { - expect(' '); - day = expectNum(format == formatRfc1123 ? ' ' : '-'); - month = expectMonth(format == formatRfc1123 ? ' ' : '-'); - year = expectNum(' '); - hours = expectNum(':'); - minutes = expectNum(':'); - seconds = expectNum(' '); - expect('GMT'); - } - expectEnd(); - return DateTime.utc(year, month + 1, day, hours, minutes, seconds, 0); - } -} +class HttpDate { + /// Parse a date string in either of the formats + /// [RFC-1123](http://tools.ietf.org/html/rfc1123 "RFC-1123"), + /// [RFC-850](http://tools.ietf.org/html/rfc850 "RFC-850") or + /// ANSI C's asctime() format. These formats are listed here. + /// + /// Thu, 1 Jan 1970 00:00:00 GMT + /// Thursday, 1-Jan-1970 00:00:00 GMT + /// Thu Jan 1 00:00:00 1970 + /// + /// For more information see [RFC-2616 section + /// 3.1.1](http://tools.ietf.org/html/rfc2616#section-3.3.1 + /// "RFC-2616 section 3.1.1"). + /// + static DateTime parse(String date) { + final sp = 32; + const wkdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; + const weekdays = [ + 'Monday', + 'Tuesday', + 'Wednesday', + 'Thursday', + 'Friday', + 'Saturday', + 'Sunday' + ]; + const months = [ + 'Jan', + 'Feb', + 'Mar', + 'Apr', + 'May', + 'Jun', + 'Jul', + 'Aug', + 'Sep', + 'Oct', + 'Nov', + 'Dec' + ]; + + final formatRfc1123 = 0; + final formatRfc850 = 1; + final formatAsctime = 2; + + var index = 0; + String tmp; + + void expect(String s) { + if (date.length - index < s.length) { + throw Exception('Invalid HTTP date $date'); + } + final tmp = date.substring(index, index + s.length); + if (tmp != s) { + throw Exception('Invalid HTTP date $date'); + } + index += s.length; + } + + int expectWeekday() { + int weekday; + // The formatting of the weekday signals the format of the date string. + var pos = date.indexOf(',', index); + if (pos == -1) { + var pos = date.indexOf(' ', index); + if (pos == -1) throw Exception('Invalid HTTP date $date'); + tmp = date.substring(index, pos); + index = pos + 1; + weekday = wkdays.indexOf(tmp); + if (weekday != -1) { + return formatAsctime; + } + } else { + tmp = date.substring(index, pos); + index = pos + 1; + weekday = wkdays.indexOf(tmp); + if (weekday != -1) { + return formatRfc1123; + } + weekday = weekdays.indexOf(tmp); + if (weekday != -1) { + return formatRfc850; + } + } + throw Exception('Invalid HTTP date $date'); + } + + int expectMonth(String separator) { + var pos = date.indexOf(separator, index); + if (pos - index != 3) throw Exception('Invalid HTTP date $date'); + tmp = date.substring(index, pos); + index = pos + 1; + var month = months.indexOf(tmp); + if (month != -1) return month; + throw Exception('Invalid HTTP date $date'); + } + + int expectNum(String separator) { + int pos; + if (separator.isNotEmpty) { + pos = date.indexOf(separator, index); + } else { + pos = date.length; + } + var tmp = date.substring(index, pos); + index = pos + separator.length; + try { + var value = int.parse(tmp); + return value; + } on FormatException { + throw Exception('Invalid HTTP date $date'); + } + } + + void expectEnd() { + if (index != date.length) { + throw Exception('Invalid HTTP date $date'); + } + } + + var format = expectWeekday(); + int year; + int month; + int day; + int hours; + int minutes; + int seconds; + if (format == formatAsctime) { + month = expectMonth(' '); + if (date.codeUnitAt(index) == sp) index++; + day = expectNum(' '); + hours = expectNum(':'); + minutes = expectNum(':'); + seconds = expectNum(' '); + year = expectNum(''); + } else { + expect(' '); + day = expectNum(format == formatRfc1123 ? ' ' : '-'); + month = expectMonth(format == formatRfc1123 ? ' ' : '-'); + year = expectNum(' '); + hours = expectNum(':'); + minutes = expectNum(':'); + seconds = expectNum(' '); + expect('GMT'); + } + expectEnd(); + return DateTime.utc(year, month + 1, day, hours, minutes, seconds, 0); + } +} diff --git a/lib/src/util/response_extension.dart b/dio_cache_interceptor/lib/src/util/response_extension.dart similarity index 97% rename from lib/src/util/response_extension.dart rename to dio_cache_interceptor/lib/src/util/response_extension.dart index 56192b8..b526566 100644 --- a/lib/src/util/response_extension.dart +++ b/dio_cache_interceptor/lib/src/util/response_extension.dart @@ -1,22 +1,22 @@ -import 'package:dio/dio.dart'; -import 'package:dio_cache_interceptor/src/util/contants.dart'; - -extension ResponseExtension on Response { - /// Update cache headers on 304 - /// - /// https://tools.ietf.org/html/rfc7232#section-4.1 - void updateCacheHeaders(Response response) { - _updateNonNullHeader(cacheControlHeader, response); - _updateNonNullHeader(dateHeader, response); - _updateNonNullHeader(etagHeader, response); - _updateNonNullHeader(lastModifiedHeader, response); - _updateNonNullHeader(expiresHeader, response); - _updateNonNullHeader(contentLocationHeader, response); - _updateNonNullHeader(varyHeader, response); - } - - void _updateNonNullHeader(String headerKey, Response response) { - final values = response.headers[headerKey]; - if (values != null) headers.map[headerKey] = values; - } -} +import 'package:dio/dio.dart'; +import 'package:dio_cache_interceptor/src/util/contants.dart'; + +extension ResponseExtension on Response { + /// Update cache headers on 304 + /// + /// https://tools.ietf.org/html/rfc7232#section-4.1 + void updateCacheHeaders(Response response) { + _updateNonNullHeader(cacheControlHeader, response); + _updateNonNullHeader(dateHeader, response); + _updateNonNullHeader(etagHeader, response); + _updateNonNullHeader(lastModifiedHeader, response); + _updateNonNullHeader(expiresHeader, response); + _updateNonNullHeader(contentLocationHeader, response); + _updateNonNullHeader(varyHeader, response); + } + + void _updateNonNullHeader(String headerKey, Response response) { + final values = response.headers[headerKey]; + if (values != null) headers.map[headerKey] = values; + } +} diff --git a/pubspec.yaml b/dio_cache_interceptor/pubspec.yaml similarity index 66% rename from pubspec.yaml rename to dio_cache_interceptor/pubspec.yaml index 1871398..3332404 100644 --- a/pubspec.yaml +++ b/dio_cache_interceptor/pubspec.yaml @@ -3,7 +3,7 @@ description: Dio HTTP cache interceptor with multiple stores respecting HTTP dir repository: https://github.com/llfbandit/dio_cache_interceptor issue_tracker: https://github.com/llfbandit/dio_cache_interceptor/issues -version: 2.3.1 +version: 3.0.0 environment: sdk: ">=2.12.0 <3.0.0" @@ -11,23 +11,13 @@ environment: dependencies: # https://pub.dev/packages/dio dio: ^4.0.0 - # https://pub.dev/packages/hive - hive: ^2.0.3 - # https://pub.dev/packages/moor - moor: ^4.1.0 # https://pub.dev/packages/path path: ^1.8.0 # https://pub.dev/packages/uuid uuid: ^3.0.1 dev_dependencies: - # https://pub.dev/packages/moor_generator - moor_generator: ^4.2.1 - # https://pub.dev/packages/build_runner - build_runner: ^2.0.1 # https://pub.dev/packages/pedantic pedantic: ^1.11.0 - # https://pub.dev/packages/sqlite3 - sqlite3: ^1.0.0 # https://pub.dev/packages/test test: ^1.16.8 diff --git a/test/backup_store_test.dart b/dio_cache_interceptor/test/backup_store_test.dart similarity index 96% rename from test/backup_store_test.dart rename to dio_cache_interceptor/test/backup_store_test.dart index 1cc6684..e90619b 100644 --- a/test/backup_store_test.dart +++ b/dio_cache_interceptor/test/backup_store_test.dart @@ -1,30 +1,30 @@ -import 'dart:io'; - -import 'package:dio_cache_interceptor/dio_cache_interceptor.dart'; -import 'package:dio_cache_interceptor/src/store/file_cache_store.dart'; -import 'package:test/test.dart'; - -import 'common_store_testing.dart'; - -void main() { - late BackupCacheStore store; - - setUp(() async { - store = BackupCacheStore( - primary: MemCacheStore(), - secondary: FileCacheStore('${Directory.current.path}/test/data'), - ); - await store.clean(); - }); - - tearDown(() async => await store.close()); - - test('Empty by default', () async => await emptyByDefault(store)); - test('Add item', () async => await addItem(store)); - test('Get item', () async => await getItem(store)); - test('Delete item', () async => await deleteItem(store)); - test('Clean', () async => await clean(store)); - test('Expires', () async => await expires(store)); - test('LastModified', () async => await lastModified(store)); - test('Staled', () async => await staled(store)); -} +import 'dart:io'; + +import 'package:dio_cache_interceptor/dio_cache_interceptor.dart'; +import 'package:dio_cache_interceptor/src/store/file_cache_store/file_cache_store_io.dart'; +import 'package:test/test.dart'; + +import 'common_store_testing.dart'; + +void main() { + late BackupCacheStore store; + + setUp(() async { + store = BackupCacheStore( + primary: MemCacheStore(), + secondary: FileCacheStore('${Directory.current.path}/test/data'), + ); + await store.clean(); + }); + + tearDown(() async => await store.close()); + + test('Empty by default', () async => await emptyByDefault(store)); + test('Add item', () async => await addItem(store)); + test('Get item', () async => await getItem(store)); + test('Delete item', () async => await deleteItem(store)); + test('Clean', () async => await clean(store)); + test('Expires', () async => await expires(store)); + test('LastModified', () async => await lastModified(store)); + test('Staled', () async => await staled(store)); +} diff --git a/test/cache_control_test.dart b/dio_cache_interceptor/test/cache_control_test.dart similarity index 96% rename from test/cache_control_test.dart rename to dio_cache_interceptor/test/cache_control_test.dart index 068b831..666ea7a 100644 --- a/test/cache_control_test.dart +++ b/dio_cache_interceptor/test/cache_control_test.dart @@ -1,66 +1,66 @@ -import 'dart:convert'; - -import 'package:dio_cache_interceptor/dio_cache_interceptor.dart'; -import 'package:test/test.dart'; - -void main() { - CacheResponse _buildResponse({ - DateTime? date, - DateTime? expires, - CacheControl? cacheControl, - }) { - return CacheResponse( - cacheControl: cacheControl, - content: utf8.encode('foo'), - date: date, - eTag: 'an etag', - expires: expires, - headers: null, - key: 'foo', - lastModified: null, - maxStale: null, - priority: CachePriority.normal, - responseDate: DateTime.now(), - url: 'https://foo.com', - ); - } - - test('isExpired', () { - var resp = _buildResponse( - date: null, - expires: null, - cacheControl: CacheControl(), - ); - expect(resp.isExpired(), isTrue); - - resp = _buildResponse( - date: DateTime.now().subtract(const Duration(seconds: 12)), - expires: null, - cacheControl: CacheControl(maxAge: 10), - ); - expect(resp.isExpired(), isTrue); - - // max-age takes precedence over expires - resp = _buildResponse( - date: DateTime.now().subtract(const Duration(seconds: 12)), - expires: DateTime.now().add(const Duration(hours: 10)), - cacheControl: CacheControl(maxAge: 10), - ); - expect(resp.isExpired(), isTrue); - - // max-age is invalid check with expires - resp = _buildResponse( - date: DateTime.now().subtract(const Duration(seconds: 12)), - expires: DateTime.now().add(const Duration(hours: 10)), - cacheControl: CacheControl(maxAge: 0), - ); - expect(resp.isExpired(), isFalse); - - resp = _buildResponse( - date: null, - expires: DateTime.now().subtract(const Duration(hours: 10)), - cacheControl: CacheControl(), - ); - expect(resp.isExpired(), isTrue); - }); -} +import 'dart:convert'; + +import 'package:dio_cache_interceptor/dio_cache_interceptor.dart'; +import 'package:test/test.dart'; + +void main() { + CacheResponse _buildResponse({ + DateTime? date, + DateTime? expires, + CacheControl? cacheControl, + }) { + return CacheResponse( + cacheControl: cacheControl, + content: utf8.encode('foo'), + date: date, + eTag: 'an etag', + expires: expires, + headers: null, + key: 'foo', + lastModified: null, + maxStale: null, + priority: CachePriority.normal, + responseDate: DateTime.now(), + url: 'https://foo.com', + ); + } + + test('isExpired', () { + var resp = _buildResponse( + date: null, + expires: null, + cacheControl: CacheControl(), + ); + expect(resp.isExpired(), isTrue); + + resp = _buildResponse( + date: DateTime.now().subtract(const Duration(seconds: 12)), + expires: null, + cacheControl: CacheControl(maxAge: 10), + ); + expect(resp.isExpired(), isTrue); + + // max-age takes precedence over expires + resp = _buildResponse( + date: DateTime.now().subtract(const Duration(seconds: 12)), + expires: DateTime.now().add(const Duration(hours: 10)), + cacheControl: CacheControl(maxAge: 10), + ); + expect(resp.isExpired(), isTrue); + + // max-age is invalid check with expires + resp = _buildResponse( + date: DateTime.now().subtract(const Duration(seconds: 12)), + expires: DateTime.now().add(const Duration(hours: 10)), + cacheControl: CacheControl(maxAge: 0), + ); + expect(resp.isExpired(), isFalse); + + resp = _buildResponse( + date: null, + expires: DateTime.now().subtract(const Duration(hours: 10)), + cacheControl: CacheControl(), + ); + expect(resp.isExpired(), isTrue); + }); +} diff --git a/test/cache_interceptor_test.dart b/dio_cache_interceptor/test/cache_interceptor_test.dart similarity index 96% rename from test/cache_interceptor_test.dart rename to dio_cache_interceptor/test/cache_interceptor_test.dart index faa2b4e..8390cff 100644 --- a/test/cache_interceptor_test.dart +++ b/dio_cache_interceptor/test/cache_interceptor_test.dart @@ -1,304 +1,304 @@ -import 'dart:io'; - -import 'package:dio/dio.dart'; -import 'package:dio_cache_interceptor/dio_cache_interceptor.dart'; -import 'package:dio_cache_interceptor/src/model/cache_cipher.dart'; -import 'package:dio_cache_interceptor/src/store/file_cache_store.dart'; -import 'package:test/test.dart'; - -import 'mock_httpclient_adapter.dart'; - -void main() { - late Dio _dio; - late CacheStore store; - late CacheOptions options; - - setUp(() async { - _dio = Dio()..httpClientAdapter = MockHttpClientAdapter(); - - store = FileCacheStore('${Directory.current.path}/test/data/interceptor'); - await store.clean(); - options = CacheOptions(store: store); - - _dio.interceptors.add(DioCacheInterceptor(options: options)); - }); - - tearDown(() async { - _dio.close(); - }); - - test('Fetch stream 200', () async { - final resp = await _dio.get('${MockHttpClientAdapter.mockBase}/ok-stream'); - expect(await store.exists(resp.extra[CacheResponse.cacheKey]), isTrue); - }); - - test('Fetch canceled', () async { - try { - await _dio.get( - '${MockHttpClientAdapter.mockBase}/ok', - cancelToken: CancelToken()..cancel(), - ); - } catch (err) { - expect(err is DioError, isTrue); - expect((err as DioError).type == DioErrorType.cancel, isTrue); - return; - } - - expect(false, isTrue, reason: 'Should never reach this check'); - }); - - test('Fetch with cipher', () async { - final cipherOptions = options.copyWith( - cipher: CacheCipher( - decrypt: (bytes) => - Future.value(bytes.reversed.toList(growable: false)), - encrypt: (bytes) => - Future.value(bytes.reversed.toList(growable: false)), - ), - ); - - var resp = await _dio.get( - '${MockHttpClientAdapter.mockBase}/ok', - options: cipherOptions.toOptions(), - ); - expect(await store.exists(resp.extra[CacheResponse.cacheKey]), isTrue); - - resp = await _dio.get( - '${MockHttpClientAdapter.mockBase}/ok', - options: - cipherOptions.copyWith(policy: CachePolicy.forceCache).toOptions(), - ); - expect(resp.data['path'], equals('/ok')); - }); - - test('Fetch 200', () async { - final resp = await _dio.get('${MockHttpClientAdapter.mockBase}/ok'); - expect(resp.data['path'], equals('/ok')); - expect(await store.exists(resp.extra[CacheResponse.cacheKey]), isTrue); - }); - - test('Fetch bytes 200', () async { - final resp = await _dio.get('${MockHttpClientAdapter.mockBase}/ok-bytes'); - expect(await store.exists(resp.extra[CacheResponse.cacheKey]), isTrue); - }); - - test('Fetch 304', () async { - final resp = await _dio.get('${MockHttpClientAdapter.mockBase}/ok'); - final cacheKey = resp.extra[CacheResponse.cacheKey]; - expect(await store.exists(cacheKey), isTrue); - - final resp304 = await _dio.get( - '${MockHttpClientAdapter.mockBase}/ok', - options: Options(headers: {'if-none-match': resp.headers['etag']}), - ); - expect(resp304.statusCode, equals(304)); - expect(resp.data['path'], equals('/ok')); - expect(resp304.extra[CacheResponse.cacheKey], equals(cacheKey)); - expect(resp304.extra[CacheResponse.fromNetwork], isTrue); - expect(resp304.headers['etag'], equals(['5678'])); - }); - - test('Fetch cacheStoreNo policy', () async { - final resp = await _dio.get( - '${MockHttpClientAdapter.mockBase}/ok', - options: options.copyWith(policy: CachePolicy.noCache).toOptions(), - ); - expect(resp.statusCode, equals(200)); - expect(resp.extra[CacheResponse.cacheKey], isNull); - }); - - test('Fetch force policy', () async { - // 1st time fetch - var resp = await _dio.get( - '${MockHttpClientAdapter.mockBase}/ok-nodirective', - options: options.copyWith(policy: CachePolicy.forceCache).toOptions(), - ); - expect(resp.statusCode, equals(200)); - expect(resp.extra[CacheResponse.fromNetwork], isTrue); - // 2nd time cache - resp = await _dio.get( - '${MockHttpClientAdapter.mockBase}/ok-nodirective', - options: options.copyWith(policy: CachePolicy.forceCache).toOptions(), - ); - expect(resp.statusCode, equals(304)); - expect(resp.extra[CacheResponse.fromNetwork], isFalse); - // 3rd time fetch - resp = await _dio.get( - '${MockHttpClientAdapter.mockBase}/ok-nodirective', - options: - options.copyWith(policy: CachePolicy.refreshForceCache).toOptions(), - ); - expect(resp.statusCode, equals(200)); - expect(resp.extra[CacheResponse.fromNetwork], isTrue); - }); - - test('Fetch refresh policy', () async { - final resp = await _dio.get('${MockHttpClientAdapter.mockBase}/ok'); - final cacheKey = resp.extra[CacheResponse.cacheKey]; - expect(await store.exists(cacheKey), isTrue); - - final resp200 = await _dio.get( - '${MockHttpClientAdapter.mockBase}/ok', - options: options - .copyWith( - policy: CachePolicy.refresh, - maxStale: Duration(minutes: 10), - ) - .toOptions(), - ); - expect(resp200.statusCode, equals(200)); - expect(resp.data['path'], equals('/ok')); - }); - - test('Fetch post skip request', () async { - final resp = await _dio.post('${MockHttpClientAdapter.mockBase}/post'); - expect(resp.statusCode, equals(200)); - expect(resp.data['path'], equals('/post')); - expect(resp.extra[CacheResponse.cacheKey], isNull); - }); - - test('Fetch post doesn\'t skip request', () async { - final resp = await _dio.post( - '${MockHttpClientAdapter.mockBase}/post', - options: Options( - extra: options.copyWith(allowPostMethod: true).toExtra(), - ), - ); - - expect(resp.statusCode, equals(200)); - expect(resp.data['path'], equals('/post')); - expect(resp.extra[CacheResponse.cacheKey], isNotNull); - }); - - test('Fetch hitCacheOnErrorExcept 500', () async { - final resp = await _dio.get('${MockHttpClientAdapter.mockBase}/ok'); - final cacheKey = resp.extra[CacheResponse.cacheKey]; - expect(await store.exists(cacheKey), isTrue); - - try { - await _dio.get( - '${MockHttpClientAdapter.mockBase}/ok', - options: Options( - extra: options.copyWith( - hitCacheOnErrorExcept: [500], - policy: CachePolicy.refresh).toExtra() - ..addAll({'x-err': '500'}), - ), - ); - } catch (err) { - expect((err as DioError).response?.statusCode, equals(500)); - } - - try { - await _dio.get( - '${MockHttpClientAdapter.mockBase}/ok', - options: Options( - extra: options - .copyWith( - hitCacheOnErrorExcept: null, - policy: CachePolicy.refresh, - ) - .toExtra() - ..addAll({'x-err': '500'}), - ), - ); - } catch (err) { - expect((err as DioError).response?.statusCode, equals(500)); - return; - } - - expect(false, isTrue, reason: 'Should never reach this check'); - }); - - test('Fetch hitCacheOnErrorExcept 500 valid', () async { - final resp = await _dio.get('${MockHttpClientAdapter.mockBase}/ok'); - final cacheKey = resp.extra[CacheResponse.cacheKey]; - expect(await store.exists(cacheKey), isTrue); - - final resp2 = await _dio.get( - '${MockHttpClientAdapter.mockBase}/ok', - options: Options( - extra: options.copyWith( - hitCacheOnErrorExcept: [], - policy: CachePolicy.refresh, - ).toExtra() - ..addAll({'x-err': '500'}), - ), - ); - - expect(resp2.statusCode, equals(304)); - expect(resp2.data['path'], equals('/ok')); - }); - - test('Fetch hitCacheOnErrorExcept socket exception valid', () async { - final resp = await _dio.get('${MockHttpClientAdapter.mockBase}/exception'); - final cacheKey = resp.extra[CacheResponse.cacheKey]; - expect(await store.exists(cacheKey), isTrue); - - final resp2 = await _dio.get( - '${MockHttpClientAdapter.mockBase}/exception', - options: Options( - extra: options.copyWith( - hitCacheOnErrorExcept: [], - ).toExtra() - ..addAll({'x-err': '500'}), - ), - ); - - expect(resp2.statusCode, equals(304)); - expect(resp2.data['path'], equals('/exception')); - }); - - test('Fetch Cache-Control', () async { - final resp = await _dio.get( - '${MockHttpClientAdapter.mockBase}/cache-control', - ); - var cacheKey = resp.extra[CacheResponse.cacheKey]; - expect(await store.exists(cacheKey), isTrue); - - var resp304 = await _dio.get( - '${MockHttpClientAdapter.mockBase}/cache-control', - ); - expect(resp304.statusCode, equals(304)); - expect(resp304.extra[CacheResponse.cacheKey], equals(cacheKey)); - // request is not expired even if max-age is 0 - expect(resp304.extra[CacheResponse.fromNetwork], isFalse); - }); - - test('Fetch Cache-Control expired', () async { - final resp = await _dio.get( - '${MockHttpClientAdapter.mockBase}/cache-control-expired', - ); - var cacheKey = resp.extra[CacheResponse.cacheKey]; - expect(await store.exists(cacheKey), isTrue); - - final resp304 = await _dio.get( - '${MockHttpClientAdapter.mockBase}/cache-control-expired', - ); - expect(resp304.statusCode, equals(304)); - cacheKey = resp304.extra[CacheResponse.cacheKey]; - expect(await store.exists(cacheKey), isTrue); - expect(resp304.extra[CacheResponse.fromNetwork], isTrue); - }); - - test('Fetch Cache-Control no-store', () async { - final resp = await _dio.get( - '${MockHttpClientAdapter.mockBase}/cache-control-no-store', - ); - final cacheKey = resp.extra[CacheResponse.cacheKey]; - expect(cacheKey, isNull); - }); - - test('Fetch max-age', () async { - final resp = await _dio.get('${MockHttpClientAdapter.mockBase}/max-age'); - final cacheKey = resp.extra[CacheResponse.cacheKey]; - final cacheResp = await store.get(cacheKey); - expect(cacheResp, isNotNull); - - // We're before max-age: 1 - expect(cacheResp!.isExpired(), isFalse); - // We're after max-age: 1 - await Future.delayed(const Duration(seconds: 1)); - expect(cacheResp.isExpired(), isTrue); - }); -} +import 'dart:io'; + +import 'package:dio/dio.dart'; +import 'package:dio_cache_interceptor/dio_cache_interceptor.dart'; +import 'package:dio_cache_interceptor/src/model/cache_cipher.dart'; +import 'package:dio_cache_interceptor/src/store/file_cache_store/file_cache_store_io.dart'; +import 'package:test/test.dart'; + +import 'mock_httpclient_adapter.dart'; + +void main() { + late Dio _dio; + late CacheStore store; + late CacheOptions options; + + setUp(() async { + _dio = Dio()..httpClientAdapter = MockHttpClientAdapter(); + + store = FileCacheStore('${Directory.current.path}/test/data/interceptor'); + await store.clean(); + options = CacheOptions(store: store); + + _dio.interceptors.add(DioCacheInterceptor(options: options)); + }); + + tearDown(() async { + _dio.close(); + }); + + test('Fetch stream 200', () async { + final resp = await _dio.get('${MockHttpClientAdapter.mockBase}/ok-stream'); + expect(await store.exists(resp.extra[CacheResponse.cacheKey]), isTrue); + }); + + test('Fetch canceled', () async { + try { + await _dio.get( + '${MockHttpClientAdapter.mockBase}/ok', + cancelToken: CancelToken()..cancel(), + ); + } catch (err) { + expect(err is DioError, isTrue); + expect((err as DioError).type == DioErrorType.cancel, isTrue); + return; + } + + expect(false, isTrue, reason: 'Should never reach this check'); + }); + + test('Fetch with cipher', () async { + final cipherOptions = options.copyWith( + cipher: CacheCipher( + decrypt: (bytes) => + Future.value(bytes.reversed.toList(growable: false)), + encrypt: (bytes) => + Future.value(bytes.reversed.toList(growable: false)), + ), + ); + + var resp = await _dio.get( + '${MockHttpClientAdapter.mockBase}/ok', + options: cipherOptions.toOptions(), + ); + expect(await store.exists(resp.extra[CacheResponse.cacheKey]), isTrue); + + resp = await _dio.get( + '${MockHttpClientAdapter.mockBase}/ok', + options: + cipherOptions.copyWith(policy: CachePolicy.forceCache).toOptions(), + ); + expect(resp.data['path'], equals('/ok')); + }); + + test('Fetch 200', () async { + final resp = await _dio.get('${MockHttpClientAdapter.mockBase}/ok'); + expect(resp.data['path'], equals('/ok')); + expect(await store.exists(resp.extra[CacheResponse.cacheKey]), isTrue); + }); + + test('Fetch bytes 200', () async { + final resp = await _dio.get('${MockHttpClientAdapter.mockBase}/ok-bytes'); + expect(await store.exists(resp.extra[CacheResponse.cacheKey]), isTrue); + }); + + test('Fetch 304', () async { + final resp = await _dio.get('${MockHttpClientAdapter.mockBase}/ok'); + final cacheKey = resp.extra[CacheResponse.cacheKey]; + expect(await store.exists(cacheKey), isTrue); + + final resp304 = await _dio.get( + '${MockHttpClientAdapter.mockBase}/ok', + options: Options(headers: {'if-none-match': resp.headers['etag']}), + ); + expect(resp304.statusCode, equals(304)); + expect(resp.data['path'], equals('/ok')); + expect(resp304.extra[CacheResponse.cacheKey], equals(cacheKey)); + expect(resp304.extra[CacheResponse.fromNetwork], isTrue); + expect(resp304.headers['etag'], equals(['5678'])); + }); + + test('Fetch cacheStoreNo policy', () async { + final resp = await _dio.get( + '${MockHttpClientAdapter.mockBase}/ok', + options: options.copyWith(policy: CachePolicy.noCache).toOptions(), + ); + expect(resp.statusCode, equals(200)); + expect(resp.extra[CacheResponse.cacheKey], isNull); + }); + + test('Fetch force policy', () async { + // 1st time fetch + var resp = await _dio.get( + '${MockHttpClientAdapter.mockBase}/ok-nodirective', + options: options.copyWith(policy: CachePolicy.forceCache).toOptions(), + ); + expect(resp.statusCode, equals(200)); + expect(resp.extra[CacheResponse.fromNetwork], isTrue); + // 2nd time cache + resp = await _dio.get( + '${MockHttpClientAdapter.mockBase}/ok-nodirective', + options: options.copyWith(policy: CachePolicy.forceCache).toOptions(), + ); + expect(resp.statusCode, equals(304)); + expect(resp.extra[CacheResponse.fromNetwork], isFalse); + // 3rd time fetch + resp = await _dio.get( + '${MockHttpClientAdapter.mockBase}/ok-nodirective', + options: + options.copyWith(policy: CachePolicy.refreshForceCache).toOptions(), + ); + expect(resp.statusCode, equals(200)); + expect(resp.extra[CacheResponse.fromNetwork], isTrue); + }); + + test('Fetch refresh policy', () async { + final resp = await _dio.get('${MockHttpClientAdapter.mockBase}/ok'); + final cacheKey = resp.extra[CacheResponse.cacheKey]; + expect(await store.exists(cacheKey), isTrue); + + final resp200 = await _dio.get( + '${MockHttpClientAdapter.mockBase}/ok', + options: options + .copyWith( + policy: CachePolicy.refresh, + maxStale: Duration(minutes: 10), + ) + .toOptions(), + ); + expect(resp200.statusCode, equals(200)); + expect(resp.data['path'], equals('/ok')); + }); + + test('Fetch post skip request', () async { + final resp = await _dio.post('${MockHttpClientAdapter.mockBase}/post'); + expect(resp.statusCode, equals(200)); + expect(resp.data['path'], equals('/post')); + expect(resp.extra[CacheResponse.cacheKey], isNull); + }); + + test('Fetch post doesn\'t skip request', () async { + final resp = await _dio.post( + '${MockHttpClientAdapter.mockBase}/post', + options: Options( + extra: options.copyWith(allowPostMethod: true).toExtra(), + ), + ); + + expect(resp.statusCode, equals(200)); + expect(resp.data['path'], equals('/post')); + expect(resp.extra[CacheResponse.cacheKey], isNotNull); + }); + + test('Fetch hitCacheOnErrorExcept 500', () async { + final resp = await _dio.get('${MockHttpClientAdapter.mockBase}/ok'); + final cacheKey = resp.extra[CacheResponse.cacheKey]; + expect(await store.exists(cacheKey), isTrue); + + try { + await _dio.get( + '${MockHttpClientAdapter.mockBase}/ok', + options: Options( + extra: options.copyWith( + hitCacheOnErrorExcept: [500], + policy: CachePolicy.refresh).toExtra() + ..addAll({'x-err': '500'}), + ), + ); + } catch (err) { + expect((err as DioError).response?.statusCode, equals(500)); + } + + try { + await _dio.get( + '${MockHttpClientAdapter.mockBase}/ok', + options: Options( + extra: options + .copyWith( + hitCacheOnErrorExcept: null, + policy: CachePolicy.refresh, + ) + .toExtra() + ..addAll({'x-err': '500'}), + ), + ); + } catch (err) { + expect((err as DioError).response?.statusCode, equals(500)); + return; + } + + expect(false, isTrue, reason: 'Should never reach this check'); + }); + + test('Fetch hitCacheOnErrorExcept 500 valid', () async { + final resp = await _dio.get('${MockHttpClientAdapter.mockBase}/ok'); + final cacheKey = resp.extra[CacheResponse.cacheKey]; + expect(await store.exists(cacheKey), isTrue); + + final resp2 = await _dio.get( + '${MockHttpClientAdapter.mockBase}/ok', + options: Options( + extra: options.copyWith( + hitCacheOnErrorExcept: [], + policy: CachePolicy.refresh, + ).toExtra() + ..addAll({'x-err': '500'}), + ), + ); + + expect(resp2.statusCode, equals(304)); + expect(resp2.data['path'], equals('/ok')); + }); + + test('Fetch hitCacheOnErrorExcept socket exception valid', () async { + final resp = await _dio.get('${MockHttpClientAdapter.mockBase}/exception'); + final cacheKey = resp.extra[CacheResponse.cacheKey]; + expect(await store.exists(cacheKey), isTrue); + + final resp2 = await _dio.get( + '${MockHttpClientAdapter.mockBase}/exception', + options: Options( + extra: options.copyWith( + hitCacheOnErrorExcept: [], + ).toExtra() + ..addAll({'x-err': '500'}), + ), + ); + + expect(resp2.statusCode, equals(304)); + expect(resp2.data['path'], equals('/exception')); + }); + + test('Fetch Cache-Control', () async { + final resp = await _dio.get( + '${MockHttpClientAdapter.mockBase}/cache-control', + ); + var cacheKey = resp.extra[CacheResponse.cacheKey]; + expect(await store.exists(cacheKey), isTrue); + + var resp304 = await _dio.get( + '${MockHttpClientAdapter.mockBase}/cache-control', + ); + expect(resp304.statusCode, equals(304)); + expect(resp304.extra[CacheResponse.cacheKey], equals(cacheKey)); + // request is not expired even if max-age is 0 + expect(resp304.extra[CacheResponse.fromNetwork], isFalse); + }); + + test('Fetch Cache-Control expired', () async { + final resp = await _dio.get( + '${MockHttpClientAdapter.mockBase}/cache-control-expired', + ); + var cacheKey = resp.extra[CacheResponse.cacheKey]; + expect(await store.exists(cacheKey), isTrue); + + final resp304 = await _dio.get( + '${MockHttpClientAdapter.mockBase}/cache-control-expired', + ); + expect(resp304.statusCode, equals(304)); + cacheKey = resp304.extra[CacheResponse.cacheKey]; + expect(await store.exists(cacheKey), isTrue); + expect(resp304.extra[CacheResponse.fromNetwork], isTrue); + }); + + test('Fetch Cache-Control no-store', () async { + final resp = await _dio.get( + '${MockHttpClientAdapter.mockBase}/cache-control-no-store', + ); + final cacheKey = resp.extra[CacheResponse.cacheKey]; + expect(cacheKey, isNull); + }); + + test('Fetch max-age', () async { + final resp = await _dio.get('${MockHttpClientAdapter.mockBase}/max-age'); + final cacheKey = resp.extra[CacheResponse.cacheKey]; + final cacheResp = await store.get(cacheKey); + expect(cacheResp, isNotNull); + + // We're before max-age: 1 + expect(cacheResp!.isExpired(), isFalse); + // We're after max-age: 1 + await Future.delayed(const Duration(seconds: 1)); + expect(cacheResp.isExpired(), isTrue); + }); +} diff --git a/test/cipher_test.dart b/dio_cache_interceptor/test/cipher_test.dart similarity index 96% rename from test/cipher_test.dart rename to dio_cache_interceptor/test/cipher_test.dart index 1444d3a..52a79aa 100644 --- a/test/cipher_test.dart +++ b/dio_cache_interceptor/test/cipher_test.dart @@ -1,28 +1,28 @@ -import 'dart:convert'; - -import 'package:dio_cache_interceptor/src/model/cache_cipher.dart'; -import 'package:test/test.dart'; - -void main() { - test('Encrypt/decrypt', () async { - // Encrypt => Upside down all content - // Decrypt => do the same to get back our content - // So powerful ! - final cipher = CacheCipher( - decrypt: (bytes) { - return Future.value(bytes.reversed.toList(growable: false)); - }, - encrypt: (bytes) async { - return Future.value(bytes.reversed.toList(growable: false)); - }, - ); - - final data = utf8.encode('Something to keep secret'); - - final encrypted = await cipher.encrypt(data); - expect(encrypted, equals('terces peek ot gnihtemoS'.codeUnits)); - - final decrypted = await cipher.decrypt(encrypted); - expect(decrypted, equals(data)); - }); -} +import 'dart:convert'; + +import 'package:dio_cache_interceptor/src/model/cache_cipher.dart'; +import 'package:test/test.dart'; + +void main() { + test('Encrypt/decrypt', () async { + // Encrypt => Upside down all content + // Decrypt => do the same to get back our content + // So powerful ! + final cipher = CacheCipher( + decrypt: (bytes) { + return Future.value(bytes.reversed.toList(growable: false)); + }, + encrypt: (bytes) async { + return Future.value(bytes.reversed.toList(growable: false)); + }, + ); + + final data = utf8.encode('Something to keep secret'); + + final encrypted = await cipher.encrypt(data); + expect(encrypted, equals('terces peek ot gnihtemoS'.codeUnits)); + + final decrypted = await cipher.decrypt(encrypted); + expect(decrypted, equals(data)); + }); +} diff --git a/test/common_store_testing.dart b/dio_cache_interceptor/test/common_store_testing.dart similarity index 96% rename from test/common_store_testing.dart rename to dio_cache_interceptor/test/common_store_testing.dart index c73688e..e8e3c91 100644 --- a/test/common_store_testing.dart +++ b/dio_cache_interceptor/test/common_store_testing.dart @@ -1,145 +1,145 @@ -import 'dart:convert'; - -import 'package:dio/dio.dart'; -import 'package:dio_cache_interceptor/src/model/cache_control.dart'; -import 'package:dio_cache_interceptor/src/model/cache_priority.dart'; -import 'package:dio_cache_interceptor/src/model/cache_response.dart'; -import 'package:dio_cache_interceptor/src/store/cache_store.dart'; -import 'package:test/test.dart'; - -Future _addFooResponse( - CacheStore store, { - CacheControl? cacheControl, - DateTime? expires, - String? lastModified, - List? headers, - DateTime? maxStale, -}) { - final resp = CacheResponse( - cacheControl: cacheControl, - content: utf8.encode('foo'), - date: DateTime.now(), - eTag: 'an etag', - expires: expires, - headers: headers, - key: 'foo', - lastModified: lastModified, - maxStale: maxStale, - priority: CachePriority.normal, - responseDate: DateTime.now(), - url: 'https://foo.com', - ); - - return store.set(resp); -} - -Future emptyByDefault(CacheStore store) async { - expect(await store.exists('foo'), isFalse); - expect(await store.get('foo'), isNull); -} - -Future addItem(CacheStore store) async { - await _addFooResponse(store); - expect(await store.exists('foo'), isTrue); -} - -Future getItem(CacheStore store) async { - final headers = utf8.encode( - jsonEncode({ - Headers.contentTypeHeader: [Headers.jsonContentType] - }), - ); - final cacheControl = CacheControl(maxAge: 10, privacy: 'public'); - - await _addFooResponse( - store, - maxStale: DateTime.now().add(const Duration(days: 1)), - headers: headers, - cacheControl: cacheControl, - ); - - final resp = await store.get('foo'); - expect(resp, isNotNull); - expect(resp?.key, equals('foo')); - expect(resp?.url, equals('https://foo.com')); - expect(resp?.eTag, equals('an etag')); - expect(resp?.lastModified, isNull); - expect(resp?.maxStale, isNotNull); - expect(resp?.content, equals(utf8.encode('foo'))); - expect(resp?.headers, equals(headers)); - expect(resp?.priority, CachePriority.normal); - expect(resp?.cacheControl?.maxAge, equals(cacheControl.maxAge)); - expect(resp?.cacheControl?.privacy, equals(cacheControl.privacy)); -} - -Future deleteItem(CacheStore store) async { - await _addFooResponse(store); - expect(await store.exists('foo'), isTrue); - - await store.delete('foo'); - expect(await store.exists('foo'), isFalse); - await store.delete('foo'); // check for non exception - - await _addFooResponse( - store, - maxStale: DateTime.now().add(const Duration(days: 1)), - ); - expect(await store.exists('foo'), isTrue); - - await store.delete('foo', staleOnly: true); - expect(await store.exists('foo'), isTrue); -} - -Future clean(CacheStore store) async { - await _addFooResponse( - store, - maxStale: DateTime.now().add(const Duration(days: 1)), - ); - expect(await store.exists('foo'), isTrue); - - await store.clean(staleOnly: true); - expect(await store.exists('foo'), isTrue); - - await store.clean(priorityOrBelow: CachePriority.low); - expect(await store.exists('foo'), isTrue); - - await store.clean(); - expect(await store.exists('foo'), isFalse); -} - -Future staled(CacheStore store) async { - await _addFooResponse( - store, - maxStale: DateTime.now().subtract(const Duration(seconds: 1)), - ); - expect(await store.exists('foo'), isTrue); - - final resp = await store.get('foo'); - expect(resp, isNull); -} - -Future expires(CacheStore store) async { - final now = DateTime.now(); - await _addFooResponse(store, expires: DateTime.now()); - final resp = await store.get('foo'); - expect( - resp!.expires!.subtract( - Duration( - milliseconds: resp.expires!.millisecond, - microseconds: resp.expires!.microsecond), - ), - equals( - now.subtract( - Duration(milliseconds: now.millisecond, microseconds: now.microsecond), - ), - ), - ); -} - -Future lastModified(CacheStore store) async { - final lastModified = 'Wed, 21 Oct 2015 07:28:00 GMT'; - - await _addFooResponse(store, lastModified: lastModified); - final resp = await store.get('foo'); - expect(resp!.lastModified, equals(lastModified)); -} +import 'dart:convert'; + +import 'package:dio/dio.dart'; +import 'package:dio_cache_interceptor/src/model/cache_control.dart'; +import 'package:dio_cache_interceptor/src/model/cache_priority.dart'; +import 'package:dio_cache_interceptor/src/model/cache_response.dart'; +import 'package:dio_cache_interceptor/src/store/cache_store.dart'; +import 'package:test/test.dart'; + +Future _addFooResponse( + CacheStore store, { + CacheControl? cacheControl, + DateTime? expires, + String? lastModified, + List? headers, + DateTime? maxStale, +}) { + final resp = CacheResponse( + cacheControl: cacheControl, + content: utf8.encode('foo'), + date: DateTime.now(), + eTag: 'an etag', + expires: expires, + headers: headers, + key: 'foo', + lastModified: lastModified, + maxStale: maxStale, + priority: CachePriority.normal, + responseDate: DateTime.now(), + url: 'https://foo.com', + ); + + return store.set(resp); +} + +Future emptyByDefault(CacheStore store) async { + expect(await store.exists('foo'), isFalse); + expect(await store.get('foo'), isNull); +} + +Future addItem(CacheStore store) async { + await _addFooResponse(store); + expect(await store.exists('foo'), isTrue); +} + +Future getItem(CacheStore store) async { + final headers = utf8.encode( + jsonEncode({ + Headers.contentTypeHeader: [Headers.jsonContentType] + }), + ); + final cacheControl = CacheControl(maxAge: 10, privacy: 'public'); + + await _addFooResponse( + store, + maxStale: DateTime.now().add(const Duration(days: 1)), + headers: headers, + cacheControl: cacheControl, + ); + + final resp = await store.get('foo'); + expect(resp, isNotNull); + expect(resp?.key, equals('foo')); + expect(resp?.url, equals('https://foo.com')); + expect(resp?.eTag, equals('an etag')); + expect(resp?.lastModified, isNull); + expect(resp?.maxStale, isNotNull); + expect(resp?.content, equals(utf8.encode('foo'))); + expect(resp?.headers, equals(headers)); + expect(resp?.priority, CachePriority.normal); + expect(resp?.cacheControl?.maxAge, equals(cacheControl.maxAge)); + expect(resp?.cacheControl?.privacy, equals(cacheControl.privacy)); +} + +Future deleteItem(CacheStore store) async { + await _addFooResponse(store); + expect(await store.exists('foo'), isTrue); + + await store.delete('foo'); + expect(await store.exists('foo'), isFalse); + await store.delete('foo'); // check for non exception + + await _addFooResponse( + store, + maxStale: DateTime.now().add(const Duration(days: 1)), + ); + expect(await store.exists('foo'), isTrue); + + await store.delete('foo', staleOnly: true); + expect(await store.exists('foo'), isTrue); +} + +Future clean(CacheStore store) async { + await _addFooResponse( + store, + maxStale: DateTime.now().add(const Duration(days: 1)), + ); + expect(await store.exists('foo'), isTrue); + + await store.clean(staleOnly: true); + expect(await store.exists('foo'), isTrue); + + await store.clean(priorityOrBelow: CachePriority.low); + expect(await store.exists('foo'), isTrue); + + await store.clean(); + expect(await store.exists('foo'), isFalse); +} + +Future staled(CacheStore store) async { + await _addFooResponse( + store, + maxStale: DateTime.now().subtract(const Duration(seconds: 1)), + ); + expect(await store.exists('foo'), isTrue); + + final resp = await store.get('foo'); + expect(resp, isNull); +} + +Future expires(CacheStore store) async { + final now = DateTime.now(); + await _addFooResponse(store, expires: DateTime.now()); + final resp = await store.get('foo'); + expect( + resp!.expires!.subtract( + Duration( + milliseconds: resp.expires!.millisecond, + microseconds: resp.expires!.microsecond), + ), + equals( + now.subtract( + Duration(milliseconds: now.millisecond, microseconds: now.microsecond), + ), + ), + ); +} + +Future lastModified(CacheStore store) async { + final lastModified = 'Wed, 21 Oct 2015 07:28:00 GMT'; + + await _addFooResponse(store, lastModified: lastModified); + final resp = await store.get('foo'); + expect(resp!.lastModified, equals(lastModified)); +} diff --git a/test/content_serialization_test.dart b/dio_cache_interceptor/test/content_serialization_test.dart similarity index 96% rename from test/content_serialization_test.dart rename to dio_cache_interceptor/test/content_serialization_test.dart index 0386b57..397e4e4 100644 --- a/test/content_serialization_test.dart +++ b/dio_cache_interceptor/test/content_serialization_test.dart @@ -1,66 +1,66 @@ -import 'package:dio/dio.dart'; -import 'package:dio_cache_interceptor/src/util/content_serialization.dart'; -import 'package:test/test.dart'; - -void main() { - test('Serialize bytes', () async { - final content = 'test'.codeUnits; - - final serializedContent = await serializeContent( - ResponseType.bytes, - content, - ); - final deserializedContent = await deserializeContent( - ResponseType.bytes, - serializedContent, - ); - expect(deserializedContent, equals(content)); - }); - - test('Serialize stream', () async { - Stream> content() async* { - yield 'test'.codeUnits; - } - - final serializedContent = await serializeContent( - ResponseType.stream, - content(), - ); - final deserializedContent = await deserializeContent( - ResponseType.stream, - serializedContent, - ); - expect( - await (deserializedContent as Stream>).first, - equals(await content().first), - ); - }); - - test('Serialize plain', () async { - final content = 'test'; - - final serializedContent = await serializeContent( - ResponseType.plain, - content, - ); - final deserializedContent = await deserializeContent( - ResponseType.plain, - serializedContent, - ); - expect(deserializedContent, equals(content)); - }); - - test('Serialize json', () async { - final content = {'test': 'value'}; - - final serializedContent = await serializeContent( - ResponseType.json, - content, - ); - final deserializedContent = await deserializeContent( - ResponseType.json, - serializedContent, - ); - expect(deserializedContent, equals(content)); - }); -} +import 'package:dio/dio.dart'; +import 'package:dio_cache_interceptor/src/util/content_serialization.dart'; +import 'package:test/test.dart'; + +void main() { + test('Serialize bytes', () async { + final content = 'test'.codeUnits; + + final serializedContent = await serializeContent( + ResponseType.bytes, + content, + ); + final deserializedContent = await deserializeContent( + ResponseType.bytes, + serializedContent, + ); + expect(deserializedContent, equals(content)); + }); + + test('Serialize stream', () async { + Stream> content() async* { + yield 'test'.codeUnits; + } + + final serializedContent = await serializeContent( + ResponseType.stream, + content(), + ); + final deserializedContent = await deserializeContent( + ResponseType.stream, + serializedContent, + ); + expect( + await (deserializedContent as Stream>).first, + equals(await content().first), + ); + }); + + test('Serialize plain', () async { + final content = 'test'; + + final serializedContent = await serializeContent( + ResponseType.plain, + content, + ); + final deserializedContent = await deserializeContent( + ResponseType.plain, + serializedContent, + ); + expect(deserializedContent, equals(content)); + }); + + test('Serialize json', () async { + final content = {'test': 'value'}; + + final serializedContent = await serializeContent( + ResponseType.json, + content, + ); + final deserializedContent = await deserializeContent( + ResponseType.json, + serializedContent, + ); + expect(deserializedContent, equals(content)); + }); +} diff --git a/test/file_store_test.dart b/dio_cache_interceptor/test/file_store_test.dart similarity index 95% rename from test/file_store_test.dart rename to dio_cache_interceptor/test/file_store_test.dart index 67ef11d..1015492 100644 --- a/test/file_store_test.dart +++ b/dio_cache_interceptor/test/file_store_test.dart @@ -1,28 +1,28 @@ -import 'dart:io'; - -import 'package:dio_cache_interceptor/src/store/file_cache_store.dart'; -import 'package:test/test.dart'; - -import 'common_store_testing.dart'; - -void main() { - late FileCacheStore store; - - setUp(() async { - store = FileCacheStore('${Directory.current.path}/test/data/file_store'); - await store.clean(); - }); - - tearDown(() async { - await store.close(); - }); - - test('Empty by default', () async => await emptyByDefault(store)); - test('Add item', () async => await addItem(store)); - test('Get item', () async => await getItem(store)); - test('Delete item', () async => await deleteItem(store)); - test('Clean', () async => await clean(store)); - test('Expires', () async => await expires(store)); - test('LastModified', () async => await lastModified(store)); - test('Staled', () async => await staled(store)); -} +import 'dart:io'; + +import 'package:dio_cache_interceptor/src/store/file_cache_store/file_cache_store_io.dart'; +import 'package:test/test.dart'; + +import 'common_store_testing.dart'; + +void main() { + late FileCacheStore store; + + setUp(() async { + store = FileCacheStore('${Directory.current.path}/test/data/file_store'); + await store.clean(); + }); + + tearDown(() async { + await store.close(); + }); + + test('Empty by default', () async => await emptyByDefault(store)); + test('Add item', () async => await addItem(store)); + test('Get item', () async => await getItem(store)); + test('Delete item', () async => await deleteItem(store)); + test('Clean', () async => await clean(store)); + test('Expires', () async => await expires(store)); + test('LastModified', () async => await lastModified(store)); + test('Staled', () async => await staled(store)); +} diff --git a/test/http_date_test.dart b/dio_cache_interceptor/test/http_date_test.dart similarity index 97% rename from test/http_date_test.dart rename to dio_cache_interceptor/test/http_date_test.dart index 7e6b966..d2ebeac 100644 --- a/test/http_date_test.dart +++ b/dio_cache_interceptor/test/http_date_test.dart @@ -1,63 +1,63 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'package:dio_cache_interceptor/src/util/http_date.dart'; -import 'package:test/test.dart'; - -void testParseHttpDate() { - DateTime date; - date = DateTime.utc(1999, DateTime.june, 11, 18, 46, 53, 0); - expect(date, HttpDate.parse('Fri, 11 Jun 1999 18:46:53 GMT')); - expect(date, HttpDate.parse('Friday, 11-Jun-1999 18:46:53 GMT')); - expect(date, HttpDate.parse('Fri Jun 11 18:46:53 1999')); - - date = DateTime.utc(1970, DateTime.january, 1, 0, 0, 0, 0); - expect(date, HttpDate.parse('Thu, 1 Jan 1970 00:00:00 GMT')); - expect(date, HttpDate.parse('Thursday, 1-Jan-1970 00:00:00 GMT')); - expect(date, HttpDate.parse('Thu Jan 1 00:00:00 1970')); - - date = DateTime.utc(2012, DateTime.march, 5, 23, 59, 59, 0); - expect(date, HttpDate.parse('Mon, 5 Mar 2012 23:59:59 GMT')); - expect(date, HttpDate.parse('Monday, 5-Mar-2012 23:59:59 GMT')); - expect(date, HttpDate.parse('Mon Mar 5 23:59:59 2012')); -} - -void testParseHttpDateFailures() { - // The calls below can throw different exceptions based on the iteration of - // the loop. This matcher catches all exceptions. - final throws = throwsA(TypeMatcher()); - expect(() { - HttpDate.parse(''); - }, throws); - var valid = 'Mon, 5 Mar 2012 23:59:59 GMT'; - for (var i = 1; i < valid.length - 1; i++) { - var tmp = valid.substring(0, i); - expect(() { - HttpDate.parse(tmp); - }, throws); - expect(() { - HttpDate.parse(' $tmp'); - }, throws); - expect(() { - HttpDate.parse(' $tmp '); - }, throws); - expect(() { - HttpDate.parse('$tmp '); - }, throws); - } - expect(() { - HttpDate.parse(' $valid'); - }, throws); - expect(() { - HttpDate.parse(' $valid '); - }, throws); - expect(() { - HttpDate.parse('$valid '); - }, throws); -} - -void main() { - test('parseHttpDate', testParseHttpDate); - test('parseHttpDateFailures', testParseHttpDateFailures); -} +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:dio_cache_interceptor/src/util/http_date.dart'; +import 'package:test/test.dart'; + +void testParseHttpDate() { + DateTime date; + date = DateTime.utc(1999, DateTime.june, 11, 18, 46, 53, 0); + expect(date, HttpDate.parse('Fri, 11 Jun 1999 18:46:53 GMT')); + expect(date, HttpDate.parse('Friday, 11-Jun-1999 18:46:53 GMT')); + expect(date, HttpDate.parse('Fri Jun 11 18:46:53 1999')); + + date = DateTime.utc(1970, DateTime.january, 1, 0, 0, 0, 0); + expect(date, HttpDate.parse('Thu, 1 Jan 1970 00:00:00 GMT')); + expect(date, HttpDate.parse('Thursday, 1-Jan-1970 00:00:00 GMT')); + expect(date, HttpDate.parse('Thu Jan 1 00:00:00 1970')); + + date = DateTime.utc(2012, DateTime.march, 5, 23, 59, 59, 0); + expect(date, HttpDate.parse('Mon, 5 Mar 2012 23:59:59 GMT')); + expect(date, HttpDate.parse('Monday, 5-Mar-2012 23:59:59 GMT')); + expect(date, HttpDate.parse('Mon Mar 5 23:59:59 2012')); +} + +void testParseHttpDateFailures() { + // The calls below can throw different exceptions based on the iteration of + // the loop. This matcher catches all exceptions. + final throws = throwsA(TypeMatcher()); + expect(() { + HttpDate.parse(''); + }, throws); + var valid = 'Mon, 5 Mar 2012 23:59:59 GMT'; + for (var i = 1; i < valid.length - 1; i++) { + var tmp = valid.substring(0, i); + expect(() { + HttpDate.parse(tmp); + }, throws); + expect(() { + HttpDate.parse(' $tmp'); + }, throws); + expect(() { + HttpDate.parse(' $tmp '); + }, throws); + expect(() { + HttpDate.parse('$tmp '); + }, throws); + } + expect(() { + HttpDate.parse(' $valid'); + }, throws); + expect(() { + HttpDate.parse(' $valid '); + }, throws); + expect(() { + HttpDate.parse('$valid '); + }, throws); +} + +void main() { + test('parseHttpDate', testParseHttpDate); + test('parseHttpDateFailures', testParseHttpDateFailures); +} diff --git a/test/mem_store_test.dart b/dio_cache_interceptor/test/mem_store_test.dart similarity index 96% rename from test/mem_store_test.dart rename to dio_cache_interceptor/test/mem_store_test.dart index e650734..aeaf06b 100644 --- a/test/mem_store_test.dart +++ b/dio_cache_interceptor/test/mem_store_test.dart @@ -1,64 +1,64 @@ -import 'dart:io'; - -import 'package:dio_cache_interceptor/dio_cache_interceptor.dart'; -import 'package:dio_cache_interceptor/src/store/mem_cache_store.dart'; -import 'package:test/test.dart'; - -import 'common_store_testing.dart'; - -void main() { - late MemCacheStore store; - - setUp(() async { - store = MemCacheStore(maxEntrySize: 100000, maxSize: 500000); - await store.clean(); - }); - - tearDown(() async { - await store.close(); - }); - - test('Exceeds maxSize', () async { - final now = DateTime.now(); - final content = File('./README.md').readAsBytesSync(); - - for (var i = 0; i < 150; ++i) { - final resp = CacheResponse( - cacheControl: null, - content: content, - date: now, - eTag: 'an etag', - expires: null, - headers: null, - key: 'foo_$i', - lastModified: null, - maxStale: null, - priority: CachePriority.normal, - responseDate: now, - url: 'https://foo.com', - ); - - await store.set(resp); - } - - var validEntries = 0; - var recycledEntries = 0; - for (var i = 0; i < 150; ++i) { - final resp = await store.get('foo_$i'); - validEntries = resp != null ? validEntries + 1 : validEntries; - recycledEntries = resp == null ? recycledEntries + 1 : recycledEntries; - } - - expect(validEntries, greaterThan(0), reason: 'validEntries'); - expect(recycledEntries, greaterThan(0), reason: 'recycledEntries'); - }); - - test('Empty by default', () async => await emptyByDefault(store)); - test('Add item', () async => await addItem(store)); - test('Get item', () async => await getItem(store)); - test('Delete item', () async => await deleteItem(store)); - test('Clean', () async => await clean(store)); - test('Expires', () async => await expires(store)); - test('LastModified', () async => await lastModified(store)); - test('Staled', () async => await staled(store)); -} +import 'dart:io'; + +import 'package:dio_cache_interceptor/dio_cache_interceptor.dart'; +import 'package:dio_cache_interceptor/src/store/mem_cache_store.dart'; +import 'package:test/test.dart'; + +import 'common_store_testing.dart'; + +void main() { + late MemCacheStore store; + + setUp(() async { + store = MemCacheStore(maxEntrySize: 100000, maxSize: 500000); + await store.clean(); + }); + + tearDown(() async { + await store.close(); + }); + + test('Exceeds maxSize', () async { + final now = DateTime.now(); + final content = File('./README.md').readAsBytesSync(); + + for (var i = 0; i < 150; ++i) { + final resp = CacheResponse( + cacheControl: null, + content: content, + date: now, + eTag: 'an etag', + expires: null, + headers: null, + key: 'foo_$i', + lastModified: null, + maxStale: null, + priority: CachePriority.normal, + responseDate: now, + url: 'https://foo.com', + ); + + await store.set(resp); + } + + var validEntries = 0; + var recycledEntries = 0; + for (var i = 0; i < 150; ++i) { + final resp = await store.get('foo_$i'); + validEntries = resp != null ? validEntries + 1 : validEntries; + recycledEntries = resp == null ? recycledEntries + 1 : recycledEntries; + } + + expect(validEntries, greaterThan(0), reason: 'validEntries'); + expect(recycledEntries, greaterThan(0), reason: 'recycledEntries'); + }); + + test('Empty by default', () async => await emptyByDefault(store)); + test('Add item', () async => await addItem(store)); + test('Get item', () async => await getItem(store)); + test('Delete item', () async => await deleteItem(store)); + test('Clean', () async => await clean(store)); + test('Expires', () async => await expires(store)); + test('LastModified', () async => await lastModified(store)); + test('Staled', () async => await staled(store)); +} diff --git a/test/mock_httpclient_adapter.dart b/dio_cache_interceptor/test/mock_httpclient_adapter.dart similarity index 100% rename from test/mock_httpclient_adapter.dart rename to dio_cache_interceptor/test/mock_httpclient_adapter.dart diff --git a/dio_cache_interceptor_db_store/.gitignore b/dio_cache_interceptor_db_store/.gitignore new file mode 100644 index 0000000..1ba9c33 --- /dev/null +++ b/dio_cache_interceptor_db_store/.gitignore @@ -0,0 +1,43 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Web related +lib/generated_plugin_registrant.dart + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Exceptions to above rules. +!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages diff --git a/dio_cache_interceptor_db_store/CHANGELOG.md b/dio_cache_interceptor_db_store/CHANGELOG.md new file mode 100644 index 0000000..83e3556 --- /dev/null +++ b/dio_cache_interceptor_db_store/CHANGELOG.md @@ -0,0 +1,2 @@ +## 3.0.0 +- Initial release. \ No newline at end of file diff --git a/dio_cache_interceptor_db_store/LICENSE b/dio_cache_interceptor_db_store/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/dio_cache_interceptor_db_store/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/dio_cache_interceptor_db_store/README.md b/dio_cache_interceptor_db_store/README.md new file mode 100644 index 0000000..fb26b4d --- /dev/null +++ b/dio_cache_interceptor_db_store/README.md @@ -0,0 +1,8 @@ +# dio_cache_interceptor_db_store + +Moor cache store implementation. + + +- __Android - iOS support__: Add sqlite3_flutter_libs as dependency in your app (version 0.4.0+1 or later). +- __Desktop support__: Follow Moor install [documentation](https://moor.simonbinder.eu/docs/platforms/). +- __Web support__: You must include 'sql.js' library. Follow Moor install [documentation](https://moor.simonbinder.eu/web/) for further info. diff --git a/dio_cache_interceptor_db_store/analysis_options.yaml b/dio_cache_interceptor_db_store/analysis_options.yaml new file mode 100644 index 0000000..29d9c07 --- /dev/null +++ b/dio_cache_interceptor_db_store/analysis_options.yaml @@ -0,0 +1,5 @@ +include: package:pedantic/analysis_options.yaml + +analyzer: + exclude: + - "example/**" \ No newline at end of file diff --git a/build.yaml b/dio_cache_interceptor_db_store/build.yaml similarity index 97% rename from build.yaml rename to dio_cache_interceptor_db_store/build.yaml index 3c57206..97d9f21 100644 --- a/build.yaml +++ b/dio_cache_interceptor_db_store/build.yaml @@ -1,14 +1,14 @@ -# Configuration for moor generator -# https://moor.simonbinder.eu/docs/advanced-features/builder_options/ -targets: - $default: - builders: - moor_generator: - options: - # We don't use companion classes to update partially rows - # Still generated but will be tree-shaked at compile time. - data_class_to_companions: false - apply_converters_on_variables: true - # Less code generated - skip_verification_code: true - override_hash_and_equals_in_result_sets: false +# Configuration for moor generator +# https://moor.simonbinder.eu/docs/advanced-features/builder_options/ +targets: + $default: + builders: + moor_generator: + options: + # We don't use companion classes to update partially rows + # Still generated but will be tree-shaked at compile time. + data_class_to_companions: false + apply_converters_on_variables: true + # Less code generated + skip_verification_code: true + override_hash_and_equals_in_result_sets: false diff --git a/dio_cache_interceptor_db_store/lib/dio_cache_interceptor_db_store.dart b/dio_cache_interceptor_db_store/lib/dio_cache_interceptor_db_store.dart new file mode 100644 index 0000000..c23b022 --- /dev/null +++ b/dio_cache_interceptor_db_store/lib/dio_cache_interceptor_db_store.dart @@ -0,0 +1,3 @@ +library dio_cache_interceptor_db_store; + +export 'src/store/dio_cache_interceptor_db_store.dart'; diff --git a/lib/src/store/db_cache_store/cache_table.moor b/dio_cache_interceptor_db_store/lib/src/store/cache_table.moor similarity index 96% rename from lib/src/store/db_cache_store/cache_table.moor rename to dio_cache_interceptor_db_store/lib/src/store/cache_table.moor index 43365fb..3c9985d 100644 --- a/lib/src/store/db_cache_store/cache_table.moor +++ b/dio_cache_interceptor_db_store/lib/src/store/cache_table.moor @@ -1,14 +1,14 @@ -CREATE TABLE IF NOT EXISTS DioCache ( - cacheKey TEXT NOT NULL PRIMARY KEY, - date DATETIME, - cacheControl TEXT, - content BLOB, - eTag TEXT, - expires DATETIME, - headers BLOB, - lastModified TEXT, - maxStale DATETIME, - priority INT NOT NULL, - responseDate DATETIME NOT NULL, - url TEXT NOT NULL +CREATE TABLE IF NOT EXISTS DioCache ( + cacheKey TEXT NOT NULL PRIMARY KEY, + date DATETIME, + cacheControl TEXT, + content BLOB, + eTag TEXT, + expires DATETIME, + headers BLOB, + lastModified TEXT, + maxStale DATETIME, + priority INT NOT NULL, + responseDate DATETIME NOT NULL, + url TEXT NOT NULL ); \ No newline at end of file diff --git a/lib/src/store/db_cache_store/database.dart b/dio_cache_interceptor_db_store/lib/src/store/database.dart similarity index 96% rename from lib/src/store/db_cache_store/database.dart rename to dio_cache_interceptor_db_store/lib/src/store/database.dart index 7f0f994..bb818b8 100644 --- a/lib/src/store/db_cache_store/database.dart +++ b/dio_cache_interceptor_db_store/lib/src/store/database.dart @@ -1,111 +1,111 @@ -import 'package:dio_cache_interceptor/dio_cache_interceptor.dart'; -import 'package:moor/moor.dart'; - -export 'db_platform/db_platform.dart'; - -part 'database.g.dart'; - -@UseMoor(include: {'cache_table.moor'}, daos: [DioCacheDao]) -class DioCacheDatabase extends _$DioCacheDatabase { - DioCacheDatabase(QueryExecutor e) : super(e); - - @override - int get schemaVersion => 1; -} - -@UseDao(include: {'cache_table.moor'}) -class DioCacheDao extends DatabaseAccessor - with _$DioCacheDaoMixin { - DioCacheDao(DioCacheDatabase db) : super(db); - - Future clean({ - CachePriority priorityOrBelow = CachePriority.high, - bool staleOnly = false, - }) async { - final query = delete(dioCache) - ..where( - (t) { - var expr = t.priority.isSmallerOrEqualValue(priorityOrBelow.index); - if (staleOnly) { - expr = - expr & t.maxStale.isSmallerOrEqualValue(DateTime.now().toUtc()); - } - return expr; - }, - ); - - await query.go(); - } - - Future deleteKey(String key, {bool staleOnly = false}) async { - final query = delete(dioCache) - ..where((t) { - final Expression expr = t.cacheKey.equals(key); - - return staleOnly - ? expr & t.maxStale.isSmallerOrEqualValue(DateTime.now().toUtc()) - : expr; - }); - - await query.go(); - } - - Future exists(String key) async { - final countExp = dioCache.cacheKey.count(); - final query = selectOnly(dioCache)..addColumns([countExp]); - final count = await query.map((row) => row.read(countExp)).getSingle(); - - return count == 1; - } - - Future get(String key) async { - // Get record - final query = select(dioCache) - ..where((t) => t.cacheKey.equals(key)) - ..limit(1); - final result = await query.getSingleOrNull(); - if (result == null) return Future.value(); - - return CacheResponse( - cacheControl: CacheControl.fromHeader(result.cacheControl?.split(', ')), - content: result.content, - date: result.date, - eTag: result.eTag, - expires: result.expires, - headers: result.headers, - key: key, - lastModified: result.lastModified, - maxStale: result.maxStale, - priority: CachePriority.values[result.priority], - responseDate: result.responseDate, - url: result.url, - ); - } - - Future set(CacheResponse response) async { - final checkedContent = response.content; - final checkedHeaders = response.headers; - - await into(dioCache).insert( - DioCacheData( - date: response.date, - cacheControl: response.cacheControl?.toHeader(), - content: (checkedContent != null) - ? Uint8List.fromList(checkedContent) - : null, - eTag: response.eTag, - expires: response.expires, - headers: (checkedHeaders != null) - ? Uint8List.fromList(checkedHeaders) - : null, - cacheKey: response.key, - lastModified: response.lastModified, - maxStale: response.maxStale, - priority: response.priority.index, - responseDate: response.responseDate, - url: response.url, - ), - mode: InsertMode.insertOrReplace, - ); - } -} +import 'package:dio_cache_interceptor/dio_cache_interceptor.dart'; +import 'package:moor/moor.dart'; + +export 'db_platform/db_platform.dart'; + +part 'database.g.dart'; + +@UseMoor(include: {'cache_table.moor'}, daos: [DioCacheDao]) +class DioCacheDatabase extends _$DioCacheDatabase { + DioCacheDatabase(QueryExecutor e) : super(e); + + @override + int get schemaVersion => 1; +} + +@UseDao(include: {'cache_table.moor'}) +class DioCacheDao extends DatabaseAccessor + with _$DioCacheDaoMixin { + DioCacheDao(DioCacheDatabase db) : super(db); + + Future clean({ + CachePriority priorityOrBelow = CachePriority.high, + bool staleOnly = false, + }) async { + final query = delete(dioCache) + ..where( + (t) { + var expr = t.priority.isSmallerOrEqualValue(priorityOrBelow.index); + if (staleOnly) { + expr = + expr & t.maxStale.isSmallerOrEqualValue(DateTime.now().toUtc()); + } + return expr; + }, + ); + + await query.go(); + } + + Future deleteKey(String key, {bool staleOnly = false}) async { + final query = delete(dioCache) + ..where((t) { + final Expression expr = t.cacheKey.equals(key); + + return staleOnly + ? expr & t.maxStale.isSmallerOrEqualValue(DateTime.now().toUtc()) + : expr; + }); + + await query.go(); + } + + Future exists(String key) async { + final countExp = dioCache.cacheKey.count(); + final query = selectOnly(dioCache)..addColumns([countExp]); + final count = await query.map((row) => row.read(countExp)).getSingle(); + + return count == 1; + } + + Future get(String key) async { + // Get record + final query = select(dioCache) + ..where((t) => t.cacheKey.equals(key)) + ..limit(1); + final result = await query.getSingleOrNull(); + if (result == null) return Future.value(); + + return CacheResponse( + cacheControl: CacheControl.fromHeader(result.cacheControl?.split(', ')), + content: result.content, + date: result.date, + eTag: result.eTag, + expires: result.expires, + headers: result.headers, + key: key, + lastModified: result.lastModified, + maxStale: result.maxStale, + priority: CachePriority.values[result.priority], + responseDate: result.responseDate, + url: result.url, + ); + } + + Future set(CacheResponse response) async { + final checkedContent = response.content; + final checkedHeaders = response.headers; + + await into(dioCache).insert( + DioCacheData( + date: response.date, + cacheControl: response.cacheControl?.toHeader(), + content: (checkedContent != null) + ? Uint8List.fromList(checkedContent) + : null, + eTag: response.eTag, + expires: response.expires, + headers: (checkedHeaders != null) + ? Uint8List.fromList(checkedHeaders) + : null, + cacheKey: response.key, + lastModified: response.lastModified, + maxStale: response.maxStale, + priority: response.priority.index, + responseDate: response.responseDate, + url: response.url, + ), + mode: InsertMode.insertOrReplace, + ); + } +} diff --git a/dio_cache_interceptor_db_store/lib/src/store/database.g.dart b/dio_cache_interceptor_db_store/lib/src/store/database.g.dart new file mode 100644 index 0000000..c894672 --- /dev/null +++ b/dio_cache_interceptor_db_store/lib/src/store/database.g.dart @@ -0,0 +1,519 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'database.dart'; + +// ************************************************************************** +// MoorGenerator +// ************************************************************************** + +// ignore_for_file: unnecessary_brace_in_string_interps, unnecessary_this +class DioCacheData extends DataClass implements Insertable { + final String cacheKey; + final DateTime? date; + final String? cacheControl; + final Uint8List? content; + final String? eTag; + final DateTime? expires; + final Uint8List? headers; + final String? lastModified; + final DateTime? maxStale; + final int priority; + final DateTime responseDate; + final String url; + DioCacheData( + {required this.cacheKey, + this.date, + this.cacheControl, + this.content, + this.eTag, + this.expires, + this.headers, + this.lastModified, + this.maxStale, + required this.priority, + required this.responseDate, + required this.url}); + factory DioCacheData.fromData(Map data, GeneratedDatabase db, + {String? prefix}) { + final effectivePrefix = prefix ?? ''; + return DioCacheData( + cacheKey: const StringType() + .mapFromDatabaseResponse(data['${effectivePrefix}cacheKey'])!, + date: const DateTimeType() + .mapFromDatabaseResponse(data['${effectivePrefix}date']), + cacheControl: const StringType() + .mapFromDatabaseResponse(data['${effectivePrefix}cacheControl']), + content: const BlobType() + .mapFromDatabaseResponse(data['${effectivePrefix}content']), + eTag: const StringType() + .mapFromDatabaseResponse(data['${effectivePrefix}eTag']), + expires: const DateTimeType() + .mapFromDatabaseResponse(data['${effectivePrefix}expires']), + headers: const BlobType() + .mapFromDatabaseResponse(data['${effectivePrefix}headers']), + lastModified: const StringType() + .mapFromDatabaseResponse(data['${effectivePrefix}lastModified']), + maxStale: const DateTimeType() + .mapFromDatabaseResponse(data['${effectivePrefix}maxStale']), + priority: const IntType() + .mapFromDatabaseResponse(data['${effectivePrefix}priority'])!, + responseDate: const DateTimeType() + .mapFromDatabaseResponse(data['${effectivePrefix}responseDate'])!, + url: const StringType() + .mapFromDatabaseResponse(data['${effectivePrefix}url'])!, + ); + } + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['cacheKey'] = Variable(cacheKey); + if (!nullToAbsent || date != null) { + map['date'] = Variable(date); + } + if (!nullToAbsent || cacheControl != null) { + map['cacheControl'] = Variable(cacheControl); + } + if (!nullToAbsent || content != null) { + map['content'] = Variable(content); + } + if (!nullToAbsent || eTag != null) { + map['eTag'] = Variable(eTag); + } + if (!nullToAbsent || expires != null) { + map['expires'] = Variable(expires); + } + if (!nullToAbsent || headers != null) { + map['headers'] = Variable(headers); + } + if (!nullToAbsent || lastModified != null) { + map['lastModified'] = Variable(lastModified); + } + if (!nullToAbsent || maxStale != null) { + map['maxStale'] = Variable(maxStale); + } + map['priority'] = Variable(priority); + map['responseDate'] = Variable(responseDate); + map['url'] = Variable(url); + return map; + } + + factory DioCacheData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= moorRuntimeOptions.defaultSerializer; + return DioCacheData( + cacheKey: serializer.fromJson(json['cacheKey']), + date: serializer.fromJson(json['date']), + cacheControl: serializer.fromJson(json['cacheControl']), + content: serializer.fromJson(json['content']), + eTag: serializer.fromJson(json['eTag']), + expires: serializer.fromJson(json['expires']), + headers: serializer.fromJson(json['headers']), + lastModified: serializer.fromJson(json['lastModified']), + maxStale: serializer.fromJson(json['maxStale']), + priority: serializer.fromJson(json['priority']), + responseDate: serializer.fromJson(json['responseDate']), + url: serializer.fromJson(json['url']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= moorRuntimeOptions.defaultSerializer; + return { + 'cacheKey': serializer.toJson(cacheKey), + 'date': serializer.toJson(date), + 'cacheControl': serializer.toJson(cacheControl), + 'content': serializer.toJson(content), + 'eTag': serializer.toJson(eTag), + 'expires': serializer.toJson(expires), + 'headers': serializer.toJson(headers), + 'lastModified': serializer.toJson(lastModified), + 'maxStale': serializer.toJson(maxStale), + 'priority': serializer.toJson(priority), + 'responseDate': serializer.toJson(responseDate), + 'url': serializer.toJson(url), + }; + } + + DioCacheData copyWith( + {String? cacheKey, + DateTime? date, + String? cacheControl, + Uint8List? content, + String? eTag, + DateTime? expires, + Uint8List? headers, + String? lastModified, + DateTime? maxStale, + int? priority, + DateTime? responseDate, + String? url}) => + DioCacheData( + cacheKey: cacheKey ?? this.cacheKey, + date: date ?? this.date, + cacheControl: cacheControl ?? this.cacheControl, + content: content ?? this.content, + eTag: eTag ?? this.eTag, + expires: expires ?? this.expires, + headers: headers ?? this.headers, + lastModified: lastModified ?? this.lastModified, + maxStale: maxStale ?? this.maxStale, + priority: priority ?? this.priority, + responseDate: responseDate ?? this.responseDate, + url: url ?? this.url, + ); + @override + String toString() { + return (StringBuffer('DioCacheData(') + ..write('cacheKey: $cacheKey, ') + ..write('date: $date, ') + ..write('cacheControl: $cacheControl, ') + ..write('content: $content, ') + ..write('eTag: $eTag, ') + ..write('expires: $expires, ') + ..write('headers: $headers, ') + ..write('lastModified: $lastModified, ') + ..write('maxStale: $maxStale, ') + ..write('priority: $priority, ') + ..write('responseDate: $responseDate, ') + ..write('url: $url') + ..write(')')) + .toString(); + } + + @override + int get hashCode => $mrjf($mrjc( + cacheKey.hashCode, + $mrjc( + date.hashCode, + $mrjc( + cacheControl.hashCode, + $mrjc( + content.hashCode, + $mrjc( + eTag.hashCode, + $mrjc( + expires.hashCode, + $mrjc( + headers.hashCode, + $mrjc( + lastModified.hashCode, + $mrjc( + maxStale.hashCode, + $mrjc( + priority.hashCode, + $mrjc(responseDate.hashCode, + url.hashCode)))))))))))); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is DioCacheData && + other.cacheKey == this.cacheKey && + other.date == this.date && + other.cacheControl == this.cacheControl && + other.content == this.content && + other.eTag == this.eTag && + other.expires == this.expires && + other.headers == this.headers && + other.lastModified == this.lastModified && + other.maxStale == this.maxStale && + other.priority == this.priority && + other.responseDate == this.responseDate && + other.url == this.url); +} + +class DioCacheCompanion extends UpdateCompanion { + final Value cacheKey; + final Value date; + final Value cacheControl; + final Value content; + final Value eTag; + final Value expires; + final Value headers; + final Value lastModified; + final Value maxStale; + final Value priority; + final Value responseDate; + final Value url; + const DioCacheCompanion({ + this.cacheKey = const Value.absent(), + this.date = const Value.absent(), + this.cacheControl = const Value.absent(), + this.content = const Value.absent(), + this.eTag = const Value.absent(), + this.expires = const Value.absent(), + this.headers = const Value.absent(), + this.lastModified = const Value.absent(), + this.maxStale = const Value.absent(), + this.priority = const Value.absent(), + this.responseDate = const Value.absent(), + this.url = const Value.absent(), + }); + DioCacheCompanion.insert({ + required String cacheKey, + this.date = const Value.absent(), + this.cacheControl = const Value.absent(), + this.content = const Value.absent(), + this.eTag = const Value.absent(), + this.expires = const Value.absent(), + this.headers = const Value.absent(), + this.lastModified = const Value.absent(), + this.maxStale = const Value.absent(), + required int priority, + required DateTime responseDate, + required String url, + }) : cacheKey = Value(cacheKey), + priority = Value(priority), + responseDate = Value(responseDate), + url = Value(url); + static Insertable custom({ + Expression? cacheKey, + Expression? date, + Expression? cacheControl, + Expression? content, + Expression? eTag, + Expression? expires, + Expression? headers, + Expression? lastModified, + Expression? maxStale, + Expression? priority, + Expression? responseDate, + Expression? url, + }) { + return RawValuesInsertable({ + if (cacheKey != null) 'cacheKey': cacheKey, + if (date != null) 'date': date, + if (cacheControl != null) 'cacheControl': cacheControl, + if (content != null) 'content': content, + if (eTag != null) 'eTag': eTag, + if (expires != null) 'expires': expires, + if (headers != null) 'headers': headers, + if (lastModified != null) 'lastModified': lastModified, + if (maxStale != null) 'maxStale': maxStale, + if (priority != null) 'priority': priority, + if (responseDate != null) 'responseDate': responseDate, + if (url != null) 'url': url, + }); + } + + DioCacheCompanion copyWith( + {Value? cacheKey, + Value? date, + Value? cacheControl, + Value? content, + Value? eTag, + Value? expires, + Value? headers, + Value? lastModified, + Value? maxStale, + Value? priority, + Value? responseDate, + Value? url}) { + return DioCacheCompanion( + cacheKey: cacheKey ?? this.cacheKey, + date: date ?? this.date, + cacheControl: cacheControl ?? this.cacheControl, + content: content ?? this.content, + eTag: eTag ?? this.eTag, + expires: expires ?? this.expires, + headers: headers ?? this.headers, + lastModified: lastModified ?? this.lastModified, + maxStale: maxStale ?? this.maxStale, + priority: priority ?? this.priority, + responseDate: responseDate ?? this.responseDate, + url: url ?? this.url, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (cacheKey.present) { + map['cacheKey'] = Variable(cacheKey.value); + } + if (date.present) { + map['date'] = Variable(date.value); + } + if (cacheControl.present) { + map['cacheControl'] = Variable(cacheControl.value); + } + if (content.present) { + map['content'] = Variable(content.value); + } + if (eTag.present) { + map['eTag'] = Variable(eTag.value); + } + if (expires.present) { + map['expires'] = Variable(expires.value); + } + if (headers.present) { + map['headers'] = Variable(headers.value); + } + if (lastModified.present) { + map['lastModified'] = Variable(lastModified.value); + } + if (maxStale.present) { + map['maxStale'] = Variable(maxStale.value); + } + if (priority.present) { + map['priority'] = Variable(priority.value); + } + if (responseDate.present) { + map['responseDate'] = Variable(responseDate.value); + } + if (url.present) { + map['url'] = Variable(url.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('DioCacheCompanion(') + ..write('cacheKey: $cacheKey, ') + ..write('date: $date, ') + ..write('cacheControl: $cacheControl, ') + ..write('content: $content, ') + ..write('eTag: $eTag, ') + ..write('expires: $expires, ') + ..write('headers: $headers, ') + ..write('lastModified: $lastModified, ') + ..write('maxStale: $maxStale, ') + ..write('priority: $priority, ') + ..write('responseDate: $responseDate, ') + ..write('url: $url') + ..write(')')) + .toString(); + } +} + +class DioCache extends Table with TableInfo { + final GeneratedDatabase _db; + final String? _alias; + DioCache(this._db, [this._alias]); + late final GeneratedTextColumn cacheKey = _constructCacheKey(); + GeneratedTextColumn _constructCacheKey() { + return GeneratedTextColumn('cacheKey', $tableName, false, + $customConstraints: 'NOT NULL PRIMARY KEY'); + } + + late final GeneratedDateTimeColumn date = _constructDate(); + GeneratedDateTimeColumn _constructDate() { + return GeneratedDateTimeColumn('date', $tableName, true, + $customConstraints: ''); + } + + late final GeneratedTextColumn cacheControl = _constructCacheControl(); + GeneratedTextColumn _constructCacheControl() { + return GeneratedTextColumn('cacheControl', $tableName, true, + $customConstraints: ''); + } + + late final GeneratedBlobColumn content = _constructContent(); + GeneratedBlobColumn _constructContent() { + return GeneratedBlobColumn('content', $tableName, true, + $customConstraints: ''); + } + + late final GeneratedTextColumn eTag = _constructETag(); + GeneratedTextColumn _constructETag() { + return GeneratedTextColumn('eTag', $tableName, true, + $customConstraints: ''); + } + + late final GeneratedDateTimeColumn expires = _constructExpires(); + GeneratedDateTimeColumn _constructExpires() { + return GeneratedDateTimeColumn('expires', $tableName, true, + $customConstraints: ''); + } + + late final GeneratedBlobColumn headers = _constructHeaders(); + GeneratedBlobColumn _constructHeaders() { + return GeneratedBlobColumn('headers', $tableName, true, + $customConstraints: ''); + } + + late final GeneratedTextColumn lastModified = _constructLastModified(); + GeneratedTextColumn _constructLastModified() { + return GeneratedTextColumn('lastModified', $tableName, true, + $customConstraints: ''); + } + + late final GeneratedDateTimeColumn maxStale = _constructMaxStale(); + GeneratedDateTimeColumn _constructMaxStale() { + return GeneratedDateTimeColumn('maxStale', $tableName, true, + $customConstraints: ''); + } + + late final GeneratedIntColumn priority = _constructPriority(); + GeneratedIntColumn _constructPriority() { + return GeneratedIntColumn('priority', $tableName, false, + $customConstraints: 'NOT NULL'); + } + + late final GeneratedDateTimeColumn responseDate = _constructResponseDate(); + GeneratedDateTimeColumn _constructResponseDate() { + return GeneratedDateTimeColumn('responseDate', $tableName, false, + $customConstraints: 'NOT NULL'); + } + + late final GeneratedTextColumn url = _constructUrl(); + GeneratedTextColumn _constructUrl() { + return GeneratedTextColumn('url', $tableName, false, + $customConstraints: 'NOT NULL'); + } + + @override + List get $columns => [ + cacheKey, + date, + cacheControl, + content, + eTag, + expires, + headers, + lastModified, + maxStale, + priority, + responseDate, + url + ]; + @override + DioCache get asDslTable => this; + @override + String get $tableName => _alias ?? 'DioCache'; + @override + final String actualTableName = 'DioCache'; + @override + Set get $primaryKey => {cacheKey}; + @override + DioCacheData map(Map data, {String? tablePrefix}) { + return DioCacheData.fromData(data, _db, + prefix: tablePrefix != null ? '$tablePrefix.' : null); + } + + @override + DioCache createAlias(String alias) { + return DioCache(_db, alias); + } + + @override + bool get dontWriteConstraints => true; +} + +abstract class _$DioCacheDatabase extends GeneratedDatabase { + _$DioCacheDatabase(QueryExecutor e) : super(SqlTypeSystem.defaultInstance, e); + late final DioCache dioCache = DioCache(this); + late final DioCacheDao dioCacheDao = DioCacheDao(this as DioCacheDatabase); + @override + Iterable get allTables => allSchemaEntities.whereType(); + @override + List get allSchemaEntities => [dioCache]; +} + +// ************************************************************************** +// DaoGenerator +// ************************************************************************** + +mixin _$DioCacheDaoMixin on DatabaseAccessor { + DioCache get dioCache => attachedDatabase.dioCache; +} diff --git a/lib/src/store/db_cache_store/db_platform/db_none.dart b/dio_cache_interceptor_db_store/lib/src/store/db_platform/db_none.dart similarity index 95% rename from lib/src/store/db_cache_store/db_platform/db_none.dart rename to dio_cache_interceptor_db_store/lib/src/store/db_platform/db_none.dart index 1eb9d6a..5495ff8 100644 --- a/lib/src/store/db_cache_store/db_platform/db_none.dart +++ b/dio_cache_interceptor_db_store/lib/src/store/db_platform/db_none.dart @@ -1,9 +1,9 @@ -import '../database.dart'; - -DioCacheDatabase openDb({ - required String databasePath, - required String databaseName, - bool logStatements = false, -}) { - throw 'Platform not supported'; -} +import '../database.dart'; + +DioCacheDatabase openDb({ + required String databasePath, + required String databaseName, + bool logStatements = false, +}) { + throw 'Platform not supported'; +} diff --git a/lib/src/store/db_cache_store/db_platform/db_os.dart b/dio_cache_interceptor_db_store/lib/src/store/db_platform/db_os.dart similarity index 95% rename from lib/src/store/db_cache_store/db_platform/db_os.dart rename to dio_cache_interceptor_db_store/lib/src/store/db_platform/db_os.dart index a3c8586..b2d4e7d 100644 --- a/lib/src/store/db_cache_store/db_platform/db_os.dart +++ b/dio_cache_interceptor_db_store/lib/src/store/db_platform/db_os.dart @@ -1,19 +1,19 @@ -import 'dart:io'; - -import 'package:moor/ffi.dart'; -import 'package:path/path.dart' as p; - -import '../database.dart'; - -DioCacheDatabase openDb({ - required String databasePath, - required String databaseName, - bool logStatements = false, -}) { - Directory(databasePath).createSync(recursive: true); - final dbFile = File(p.join(databasePath, '$databaseName.db')); - - return DioCacheDatabase( - VmDatabase(dbFile, logStatements: logStatements), - ); -} +import 'dart:io'; + +import 'package:moor/ffi.dart'; +import 'package:path/path.dart' as p; + +import '../database.dart'; + +DioCacheDatabase openDb({ + required String databasePath, + required String databaseName, + bool logStatements = false, +}) { + Directory(databasePath).createSync(recursive: true); + final dbFile = File(p.join(databasePath, '$databaseName.db')); + + return DioCacheDatabase( + VmDatabase(dbFile, logStatements: logStatements), + ); +} diff --git a/lib/src/store/db_cache_store/db_platform/db_platform.dart b/dio_cache_interceptor_db_store/lib/src/store/db_platform/db_platform.dart similarity index 97% rename from lib/src/store/db_cache_store/db_platform/db_platform.dart rename to dio_cache_interceptor_db_store/lib/src/store/db_platform/db_platform.dart index ff9922c..4be9061 100644 --- a/lib/src/store/db_cache_store/db_platform/db_platform.dart +++ b/dio_cache_interceptor_db_store/lib/src/store/db_platform/db_platform.dart @@ -1,3 +1,3 @@ -export 'db_none.dart' - if (dart.library.html) 'db_web.dart' - if (dart.library.io) 'db_os.dart'; +export 'db_none.dart' + if (dart.library.html) 'db_web.dart' + if (dart.library.io) 'db_os.dart'; diff --git a/lib/src/store/db_cache_store/db_platform/db_web.dart b/dio_cache_interceptor_db_store/lib/src/store/db_platform/db_web.dart similarity index 95% rename from lib/src/store/db_cache_store/db_platform/db_web.dart rename to dio_cache_interceptor_db_store/lib/src/store/db_platform/db_web.dart index 3e3bdfd..6ab4c0b 100644 --- a/lib/src/store/db_cache_store/db_platform/db_web.dart +++ b/dio_cache_interceptor_db_store/lib/src/store/db_platform/db_web.dart @@ -1,13 +1,13 @@ -import 'package:moor/moor_web.dart'; - -import '../database.dart'; - -DioCacheDatabase openDb({ - required String databasePath, - required String databaseName, - bool logStatements = false, -}) { - return DioCacheDatabase( - WebDatabase(databaseName, logStatements: logStatements), - ); -} +import 'package:moor/moor_web.dart'; + +import '../database.dart'; + +DioCacheDatabase openDb({ + required String databasePath, + required String databaseName, + bool logStatements = false, +}) { + return DioCacheDatabase( + WebDatabase(databaseName, logStatements: logStatements), + ); +} diff --git a/lib/src/store/db_cache_store.dart b/dio_cache_interceptor_db_store/lib/src/store/dio_cache_interceptor_db_store.dart similarity index 100% rename from lib/src/store/db_cache_store.dart rename to dio_cache_interceptor_db_store/lib/src/store/dio_cache_interceptor_db_store.dart diff --git a/dio_cache_interceptor_db_store/pubspec.lock b/dio_cache_interceptor_db_store/pubspec.lock new file mode 100644 index 0000000..5d7bdfb --- /dev/null +++ b/dio_cache_interceptor_db_store/pubspec.lock @@ -0,0 +1,544 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + url: "https://pub.dartlang.org" + source: hosted + version: "22.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + url: "https://pub.dartlang.org" + source: hosted + version: "1.7.0" + analyzer_plugin_fork: + dependency: transitive + description: + name: analyzer_plugin_fork + url: "https://pub.dartlang.org" + source: hosted + version: "0.5.1" + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + async: + dependency: transitive + description: + name: async + url: "https://pub.dartlang.org" + source: hosted + version: "2.7.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + build: + dependency: transitive + description: + name: build + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" + build_config: + dependency: transitive + description: + name: build_config + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + build_daemon: + dependency: transitive + description: + name: build_daemon + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.3" + build_runner: + dependency: "direct dev" + description: + name: build_runner + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.4" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + url: "https://pub.dartlang.org" + source: hosted + version: "7.0.0" + built_collection: + dependency: transitive + description: + name: built_collection + url: "https://pub.dartlang.org" + source: hosted + version: "5.1.0" + built_value: + dependency: transitive + description: + name: built_value + url: "https://pub.dartlang.org" + source: hosted + version: "8.1.0" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.1" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + cli_util: + dependency: transitive + description: + name: cli_util + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.0" + code_builder: + dependency: transitive + description: + name: code_builder + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.0" + collection: + dependency: transitive + description: + name: collection + url: "https://pub.dartlang.org" + source: hosted + version: "1.15.0" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + coverage: + dependency: transitive + description: + name: coverage + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" + dart_style: + dependency: transitive + description: + name: dart_style + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + dio: + dependency: transitive + description: + name: dio + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.0" + dio_cache_interceptor: + dependency: "direct main" + description: + name: dio_cache_interceptor + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.1" + ffi: + dependency: transitive + description: + name: ffi + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.2" + file: + dependency: transitive + description: + name: file + url: "https://pub.dartlang.org" + source: hosted + version: "6.1.2" + fixnum: + dependency: transitive + description: + name: fixnum + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + glob: + dependency: transitive + description: + name: glob + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + graphs: + dependency: transitive + description: + name: graphs + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + hive: + dependency: transitive + description: + name: hive + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.4" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" + http_parser: + dependency: transitive + description: + name: http_parser + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.0" + io: + dependency: transitive + description: + name: io + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + js: + dependency: transitive + description: + name: js + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.3" + json_annotation: + dependency: transitive + description: + name: json_annotation + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.1" + logging: + dependency: transitive + description: + name: logging + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + matcher: + dependency: transitive + description: + name: matcher + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.10" + meta: + dependency: transitive + description: + name: meta + url: "https://pub.dartlang.org" + source: hosted + version: "1.4.0" + mime: + dependency: transitive + description: + name: mime + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + moor: + dependency: "direct main" + description: + name: moor + url: "https://pub.dartlang.org" + source: hosted + version: "4.3.2" + moor_generator: + dependency: "direct dev" + description: + name: moor_generator + url: "https://pub.dartlang.org" + source: hosted + version: "4.3.1" + node_preamble: + dependency: transitive + description: + name: node_preamble + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + package_config: + dependency: transitive + description: + name: package_config + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + path: + dependency: transitive + description: + name: path + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.0" + pedantic: + dependency: "direct dev" + description: + name: pedantic + url: "https://pub.dartlang.org" + source: hosted + version: "1.11.1" + pool: + dependency: transitive + description: + name: pool + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.0" + pub_semver: + dependency: transitive + description: + name: pub_semver + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + recase: + dependency: transitive + description: + name: recase + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.0" + shelf: + dependency: transitive + description: + name: shelf + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.4" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + shelf_static: + dependency: transitive + description: + name: shelf_static + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + source_gen: + dependency: transitive + description: + name: source_gen + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + source_maps: + dependency: transitive + description: + name: source_maps + url: "https://pub.dartlang.org" + source: hosted + version: "0.10.10" + source_span: + dependency: transitive + description: + name: source_span + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.1" + sqlite3: + dependency: "direct dev" + description: + name: sqlite3 + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.2" + sqlparser: + dependency: transitive + description: + name: sqlparser + url: "https://pub.dartlang.org" + source: hosted + version: "0.16.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "1.10.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + stream_transform: + dependency: transitive + description: + name: stream_transform + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + test: + dependency: "direct dev" + description: + name: test + url: "https://pub.dartlang.org" + source: hosted + version: "1.17.8" + test_api: + dependency: transitive + description: + name: test_api + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.1" + test_core: + dependency: transitive + description: + name: test_core + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.28" + timing: + dependency: transitive + description: + name: timing + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + uuid: + dependency: transitive + description: + name: uuid + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.4" + vm_service: + dependency: transitive + description: + name: vm_service + url: "https://pub.dartlang.org" + source: hosted + version: "7.1.0" + watcher: + dependency: transitive + description: + name: watcher + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + yaml: + dependency: transitive + description: + name: yaml + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" +sdks: + dart: ">=2.12.0 <3.0.0" diff --git a/dio_cache_interceptor_db_store/pubspec.yaml b/dio_cache_interceptor_db_store/pubspec.yaml new file mode 100644 index 0000000..107d974 --- /dev/null +++ b/dio_cache_interceptor_db_store/pubspec.yaml @@ -0,0 +1,27 @@ +name: dio_cache_interceptor_db_store +description: A DB cache store implementation with Moor for dio_cache_interceptor package. +homepage: https://github.com/llfbandit/dio_cache_interceptor/dio_cache_interceptor_db_store +version: 3.0.0 + +environment: + sdk: ">=2.12.0 <3.0.0" + +dependencies: + dio_cache_interceptor: ^3.0.0 + + # https://pub.dev/packages/moor + moor: ^4.1.0 + # https://pub.dev/packages/path + path: ^1.8.0 + +dev_dependencies: + # https://pub.dev/packages/moor_generator + moor_generator: ^4.2.1 + # https://pub.dev/packages/build_runner + build_runner: ^2.0.1 + # https://pub.dev/packages/pedantic + pedantic: ^1.11.0 + # https://pub.dev/packages/sqlite3 + sqlite3: ^1.0.0 + # https://pub.dev/packages/test + test: ^1.16.8 diff --git a/dio_cache_interceptor_db_store/test/data/dio_cache.db b/dio_cache_interceptor_db_store/test/data/dio_cache.db new file mode 100644 index 0000000..1a784e1 Binary files /dev/null and b/dio_cache_interceptor_db_store/test/data/dio_cache.db differ diff --git a/test/db_store_test.dart b/dio_cache_interceptor_db_store/test/db_store_test.dart similarity index 94% rename from test/db_store_test.dart rename to dio_cache_interceptor_db_store/test/db_store_test.dart index cade868..e50bf4c 100644 --- a/test/db_store_test.dart +++ b/dio_cache_interceptor_db_store/test/db_store_test.dart @@ -1,56 +1,56 @@ -import 'dart:ffi'; -import 'dart:io'; - -import 'package:dio_cache_interceptor/dio_cache_interceptor.dart'; -import 'package:dio_cache_interceptor/src/store/db_cache_store/database.dart'; -import 'package:sqlite3/open.dart'; -import 'package:test/test.dart'; - -import 'common_store_testing.dart'; - -void main() { - late DbCacheStore store; - - DynamicLibrary _openOnWindows() { - final libFile = File('${Directory.current.path}/test/lib/sqlite3.dll'); - return DynamicLibrary.open(libFile.path); - } - - setUp(() async { - open.overrideFor(OperatingSystem.windows, _openOnWindows); - store = DbCacheStore(databasePath: '${Directory.current.path}/test/data'); - await store.clean(); - }); - - tearDown(() async { - await store.close(); - }); - - test('DioCacheData toJson', () { - // toJson is not used, force using it to virtually boost coverage - final now = DateTime.now(); - - final cacheData = DioCacheData( - cacheKey: 'foo', - priority: CachePriority.normal.index, - responseDate: now, - url: 'https://foo.com', - ); - - final map = cacheData.toJson(); - - expect(map['cacheKey'], equals('foo')); - expect(map['priority'], equals(CachePriority.normal.index)); - expect(map['responseDate'], equals(now.millisecondsSinceEpoch)); - expect(map['url'], equals('https://foo.com')); - }); - - test('Empty by default', () async => await emptyByDefault(store)); - test('Add item', () async => await addItem(store)); - test('Get item', () async => await getItem(store)); - test('Delete item', () async => await deleteItem(store)); - test('Clean', () async => await clean(store)); - test('Expires', () async => await expires(store)); - test('LastModified', () async => await lastModified(store)); - test('Staled', () async => await staled(store)); -} +import 'dart:ffi'; +import 'dart:io'; + +import 'package:dio_cache_interceptor/dio_cache_interceptor.dart'; +import 'package:dio_cache_interceptor/src/store/db_cache_store/database.dart'; +import 'package:sqlite3/open.dart'; +import 'package:test/test.dart'; + +import '../../dio_cache_interceptor/test/common_store_testing.dart'; + +void main() { + late DbCacheStore store; + + DynamicLibrary _openOnWindows() { + final libFile = File('${Directory.current.path}/test/lib/sqlite3.dll'); + return DynamicLibrary.open(libFile.path); + } + + setUp(() async { + open.overrideFor(OperatingSystem.windows, _openOnWindows); + store = DbCacheStore(databasePath: '${Directory.current.path}/test/data'); + await store.clean(); + }); + + tearDown(() async { + await store.close(); + }); + + test('DioCacheData toJson', () { + // toJson is not used, force using it to virtually boost coverage + final now = DateTime.now(); + + final cacheData = DioCacheData( + cacheKey: 'foo', + priority: CachePriority.normal.index, + responseDate: now, + url: 'https://foo.com', + ); + + final map = cacheData.toJson(); + + expect(map['cacheKey'], equals('foo')); + expect(map['priority'], equals(CachePriority.normal.index)); + expect(map['responseDate'], equals(now.millisecondsSinceEpoch)); + expect(map['url'], equals('https://foo.com')); + }); + + test('Empty by default', () async => await emptyByDefault(store)); + test('Add item', () async => await addItem(store)); + test('Get item', () async => await getItem(store)); + test('Delete item', () async => await deleteItem(store)); + test('Clean', () async => await clean(store)); + test('Expires', () async => await expires(store)); + test('LastModified', () async => await lastModified(store)); + test('Staled', () async => await staled(store)); +} diff --git a/test/lib/libsqlite3.so b/dio_cache_interceptor_db_store/test/lib/libsqlite3.so similarity index 100% rename from test/lib/libsqlite3.so rename to dio_cache_interceptor_db_store/test/lib/libsqlite3.so diff --git a/test/lib/sqlite3.dll b/dio_cache_interceptor_db_store/test/lib/sqlite3.dll similarity index 100% rename from test/lib/sqlite3.dll rename to dio_cache_interceptor_db_store/test/lib/sqlite3.dll diff --git a/dio_cache_interceptor_hive_store/.gitignore b/dio_cache_interceptor_hive_store/.gitignore new file mode 100644 index 0000000..1ba9c33 --- /dev/null +++ b/dio_cache_interceptor_hive_store/.gitignore @@ -0,0 +1,43 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Web related +lib/generated_plugin_registrant.dart + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Exceptions to above rules. +!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages diff --git a/dio_cache_interceptor_hive_store/CHANGELOG.md b/dio_cache_interceptor_hive_store/CHANGELOG.md new file mode 100644 index 0000000..83e3556 --- /dev/null +++ b/dio_cache_interceptor_hive_store/CHANGELOG.md @@ -0,0 +1,2 @@ +## 3.0.0 +- Initial release. \ No newline at end of file diff --git a/dio_cache_interceptor_hive_store/LICENSE b/dio_cache_interceptor_hive_store/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/dio_cache_interceptor_hive_store/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/dio_cache_interceptor_hive_store/README.md b/dio_cache_interceptor_hive_store/README.md new file mode 100644 index 0000000..36b70cb --- /dev/null +++ b/dio_cache_interceptor_hive_store/README.md @@ -0,0 +1,3 @@ +# dio_cache_interceptor_hive_store + +Hive cache store implementation. diff --git a/dio_cache_interceptor_hive_store/analysis_options.yaml b/dio_cache_interceptor_hive_store/analysis_options.yaml new file mode 100644 index 0000000..29d9c07 --- /dev/null +++ b/dio_cache_interceptor_hive_store/analysis_options.yaml @@ -0,0 +1,5 @@ +include: package:pedantic/analysis_options.yaml + +analyzer: + exclude: + - "example/**" \ No newline at end of file diff --git a/dio_cache_interceptor_hive_store/build.yaml b/dio_cache_interceptor_hive_store/build.yaml new file mode 100644 index 0000000..97d9f21 --- /dev/null +++ b/dio_cache_interceptor_hive_store/build.yaml @@ -0,0 +1,14 @@ +# Configuration for moor generator +# https://moor.simonbinder.eu/docs/advanced-features/builder_options/ +targets: + $default: + builders: + moor_generator: + options: + # We don't use companion classes to update partially rows + # Still generated but will be tree-shaked at compile time. + data_class_to_companions: false + apply_converters_on_variables: true + # Less code generated + skip_verification_code: true + override_hash_and_equals_in_result_sets: false diff --git a/dio_cache_interceptor_hive_store/lib/dio_cache_interceptor_hive_store.dart b/dio_cache_interceptor_hive_store/lib/dio_cache_interceptor_hive_store.dart new file mode 100644 index 0000000..b67c88d --- /dev/null +++ b/dio_cache_interceptor_hive_store/lib/dio_cache_interceptor_hive_store.dart @@ -0,0 +1,3 @@ +library dio_cache_interceptor_hive_store; + +export 'src/store/dio_cache_interceptor_hive_store.dart'; diff --git a/lib/src/store/hive_cache_store.dart b/dio_cache_interceptor_hive_store/lib/src/store/dio_cache_interceptor_hive_store.dart similarity index 99% rename from lib/src/store/hive_cache_store.dart rename to dio_cache_interceptor_hive_store/lib/src/store/dio_cache_interceptor_hive_store.dart index 1c732cd..27575a3 100644 --- a/lib/src/store/hive_cache_store.dart +++ b/dio_cache_interceptor_hive_store/lib/src/store/dio_cache_interceptor_hive_store.dart @@ -1,7 +1,6 @@ +import 'package:dio_cache_interceptor/dio_cache_interceptor.dart'; import 'package:hive/hive.dart'; -import '../../dio_cache_interceptor.dart'; - /// A store saving responses using hive. /// class HiveCacheStore implements CacheStore { diff --git a/dio_cache_interceptor_hive_store/pubspec.lock b/dio_cache_interceptor_hive_store/pubspec.lock new file mode 100644 index 0000000..0433902 --- /dev/null +++ b/dio_cache_interceptor_hive_store/pubspec.lock @@ -0,0 +1,390 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + url: "https://pub.dartlang.org" + source: hosted + version: "22.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + url: "https://pub.dartlang.org" + source: hosted + version: "1.7.0" + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + async: + dependency: transitive + description: + name: async + url: "https://pub.dartlang.org" + source: hosted + version: "2.7.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.1" + cli_util: + dependency: transitive + description: + name: cli_util + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.0" + collection: + dependency: transitive + description: + name: collection + url: "https://pub.dartlang.org" + source: hosted + version: "1.15.0" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + coverage: + dependency: transitive + description: + name: coverage + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" + dio: + dependency: transitive + description: + name: dio + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.0" + dio_cache_interceptor: + dependency: "direct main" + description: + name: dio_cache_interceptor + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.1" + ffi: + dependency: transitive + description: + name: ffi + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.2" + file: + dependency: transitive + description: + name: file + url: "https://pub.dartlang.org" + source: hosted + version: "6.1.2" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + glob: + dependency: transitive + description: + name: glob + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + hive: + dependency: "direct main" + description: + name: hive + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.4" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" + http_parser: + dependency: transitive + description: + name: http_parser + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.0" + io: + dependency: transitive + description: + name: io + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + js: + dependency: transitive + description: + name: js + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.3" + logging: + dependency: transitive + description: + name: logging + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + matcher: + dependency: transitive + description: + name: matcher + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.10" + meta: + dependency: transitive + description: + name: meta + url: "https://pub.dartlang.org" + source: hosted + version: "1.4.0" + mime: + dependency: transitive + description: + name: mime + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + moor: + dependency: transitive + description: + name: moor + url: "https://pub.dartlang.org" + source: hosted + version: "4.3.2" + node_preamble: + dependency: transitive + description: + name: node_preamble + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + package_config: + dependency: transitive + description: + name: package_config + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + path: + dependency: transitive + description: + name: path + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.0" + pedantic: + dependency: "direct dev" + description: + name: pedantic + url: "https://pub.dartlang.org" + source: hosted + version: "1.11.1" + pool: + dependency: transitive + description: + name: pool + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.0" + pub_semver: + dependency: transitive + description: + name: pub_semver + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + shelf: + dependency: transitive + description: + name: shelf + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.4" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + shelf_static: + dependency: transitive + description: + name: shelf_static + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + source_maps: + dependency: transitive + description: + name: source_maps + url: "https://pub.dartlang.org" + source: hosted + version: "0.10.10" + source_span: + dependency: transitive + description: + name: source_span + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.1" + sqlite3: + dependency: transitive + description: + name: sqlite3 + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.2" + stack_trace: + dependency: transitive + description: + name: stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "1.10.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + test: + dependency: "direct dev" + description: + name: test + url: "https://pub.dartlang.org" + source: hosted + version: "1.17.8" + test_api: + dependency: transitive + description: + name: test_api + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.1" + test_core: + dependency: transitive + description: + name: test_core + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.28" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + uuid: + dependency: transitive + description: + name: uuid + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.4" + vm_service: + dependency: transitive + description: + name: vm_service + url: "https://pub.dartlang.org" + source: hosted + version: "7.1.0" + watcher: + dependency: transitive + description: + name: watcher + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + yaml: + dependency: transitive + description: + name: yaml + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" +sdks: + dart: ">=2.12.0 <3.0.0" diff --git a/dio_cache_interceptor_hive_store/pubspec.yaml b/dio_cache_interceptor_hive_store/pubspec.yaml new file mode 100644 index 0000000..0bbdcd5 --- /dev/null +++ b/dio_cache_interceptor_hive_store/pubspec.yaml @@ -0,0 +1,19 @@ +name: dio_cache_interceptor_hive_store +description: A DB cache store implementation with Hive for dio_cache_interceptor package. +homepage: https://github.com/llfbandit/dio_cache_interceptor/dio_cache_interceptor_hive_store +version: 3.0.0 + +environment: + sdk: ">=2.12.0 <3.0.0" + +dependencies: + dio_cache_interceptor: ^3.0.0 + + # https://pub.dev/packages/hive + hive: ^2.0.3 + +dev_dependencies: + # https://pub.dev/packages/pedantic + pedantic: ^1.11.0 + # https://pub.dev/packages/test + test: ^1.16.8 diff --git a/dio_cache_interceptor_hive_store/test/data/file_store/dio_cache.hive b/dio_cache_interceptor_hive_store/test/data/file_store/dio_cache.hive new file mode 100644 index 0000000..e6499e7 Binary files /dev/null and b/dio_cache_interceptor_hive_store/test/data/file_store/dio_cache.hive differ diff --git a/test/hive_store_test.dart b/dio_cache_interceptor_hive_store/test/hive_store_test.dart similarity index 92% rename from test/hive_store_test.dart rename to dio_cache_interceptor_hive_store/test/hive_store_test.dart index 56ba4c7..bbb69a0 100644 --- a/test/hive_store_test.dart +++ b/dio_cache_interceptor_hive_store/test/hive_store_test.dart @@ -3,7 +3,7 @@ import 'dart:io'; import 'package:dio_cache_interceptor/src/store/hive_cache_store.dart'; import 'package:test/test.dart'; -import 'common_store_testing.dart'; +import '../../dio_cache_interceptor/test/common_store_testing.dart'; void main() { late HiveCacheStore store; diff --git a/lib/src/store/db_cache_store/database.g.dart b/lib/src/store/db_cache_store/database.g.dart deleted file mode 100644 index ffa7282..0000000 --- a/lib/src/store/db_cache_store/database.g.dart +++ /dev/null @@ -1,252 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'database.dart'; - -// ************************************************************************** -// MoorGenerator -// ************************************************************************** - -// ignore_for_file: unnecessary_brace_in_string_interps, unnecessary_this -class DioCacheData extends DataClass implements Insertable { - final String cacheKey; - final DateTime? date; - final String? cacheControl; - final Uint8List? content; - final String? eTag; - final DateTime? expires; - final Uint8List? headers; - final String? lastModified; - final DateTime? maxStale; - final int priority; - final DateTime responseDate; - final String url; - DioCacheData( - {required this.cacheKey, - this.date, - this.cacheControl, - this.content, - this.eTag, - this.expires, - this.headers, - this.lastModified, - this.maxStale, - required this.priority, - required this.responseDate, - required this.url}); - factory DioCacheData.fromData(Map data, GeneratedDatabase db, - {String? prefix}) { - final effectivePrefix = prefix ?? ''; - final stringType = db.typeSystem.forDartType(); - final dateTimeType = db.typeSystem.forDartType(); - final uint8ListType = db.typeSystem.forDartType(); - final intType = db.typeSystem.forDartType(); - return DioCacheData( - cacheKey: stringType - .mapFromDatabaseResponse(data['${effectivePrefix}cacheKey'])!, - date: - dateTimeType.mapFromDatabaseResponse(data['${effectivePrefix}date']), - cacheControl: stringType - .mapFromDatabaseResponse(data['${effectivePrefix}cacheControl']), - content: uint8ListType - .mapFromDatabaseResponse(data['${effectivePrefix}content']), - eTag: stringType.mapFromDatabaseResponse(data['${effectivePrefix}eTag']), - expires: dateTimeType - .mapFromDatabaseResponse(data['${effectivePrefix}expires']), - headers: uint8ListType - .mapFromDatabaseResponse(data['${effectivePrefix}headers']), - lastModified: stringType - .mapFromDatabaseResponse(data['${effectivePrefix}lastModified']), - maxStale: dateTimeType - .mapFromDatabaseResponse(data['${effectivePrefix}maxStale']), - priority: - intType.mapFromDatabaseResponse(data['${effectivePrefix}priority'])!, - responseDate: dateTimeType - .mapFromDatabaseResponse(data['${effectivePrefix}responseDate'])!, - url: stringType.mapFromDatabaseResponse(data['${effectivePrefix}url'])!, - ); - } - @override - Map toColumns(bool nullToAbsent) { - final map = {}; - map['cacheKey'] = Variable(cacheKey); - if (!nullToAbsent || date != null) { - map['date'] = Variable(date); - } - if (!nullToAbsent || cacheControl != null) { - map['cacheControl'] = Variable(cacheControl); - } - if (!nullToAbsent || content != null) { - map['content'] = Variable(content); - } - if (!nullToAbsent || eTag != null) { - map['eTag'] = Variable(eTag); - } - if (!nullToAbsent || expires != null) { - map['expires'] = Variable(expires); - } - if (!nullToAbsent || headers != null) { - map['headers'] = Variable(headers); - } - if (!nullToAbsent || lastModified != null) { - map['lastModified'] = Variable(lastModified); - } - if (!nullToAbsent || maxStale != null) { - map['maxStale'] = Variable(maxStale); - } - map['priority'] = Variable(priority); - map['responseDate'] = Variable(responseDate); - map['url'] = Variable(url); - return map; - } - - @override - Map toJson({ValueSerializer? serializer}) { - serializer ??= moorRuntimeOptions.defaultSerializer; - return { - 'cacheKey': serializer.toJson(cacheKey), - 'date': serializer.toJson(date), - 'cacheControl': serializer.toJson(cacheControl), - 'content': serializer.toJson(content), - 'eTag': serializer.toJson(eTag), - 'expires': serializer.toJson(expires), - 'headers': serializer.toJson(headers), - 'lastModified': serializer.toJson(lastModified), - 'maxStale': serializer.toJson(maxStale), - 'priority': serializer.toJson(priority), - 'responseDate': serializer.toJson(responseDate), - 'url': serializer.toJson(url), - }; - } -} - -class DioCache extends Table with TableInfo { - final GeneratedDatabase _db; - final String? _alias; - DioCache(this._db, [this._alias]); - late final GeneratedTextColumn cacheKey = _constructCacheKey(); - GeneratedTextColumn _constructCacheKey() { - return GeneratedTextColumn('cacheKey', $tableName, false, - $customConstraints: 'NOT NULL PRIMARY KEY'); - } - - late final GeneratedDateTimeColumn date = _constructDate(); - GeneratedDateTimeColumn _constructDate() { - return GeneratedDateTimeColumn('date', $tableName, true, - $customConstraints: ''); - } - - late final GeneratedTextColumn cacheControl = _constructCacheControl(); - GeneratedTextColumn _constructCacheControl() { - return GeneratedTextColumn('cacheControl', $tableName, true, - $customConstraints: ''); - } - - late final GeneratedBlobColumn content = _constructContent(); - GeneratedBlobColumn _constructContent() { - return GeneratedBlobColumn('content', $tableName, true, - $customConstraints: ''); - } - - late final GeneratedTextColumn eTag = _constructETag(); - GeneratedTextColumn _constructETag() { - return GeneratedTextColumn('eTag', $tableName, true, - $customConstraints: ''); - } - - late final GeneratedDateTimeColumn expires = _constructExpires(); - GeneratedDateTimeColumn _constructExpires() { - return GeneratedDateTimeColumn('expires', $tableName, true, - $customConstraints: ''); - } - - late final GeneratedBlobColumn headers = _constructHeaders(); - GeneratedBlobColumn _constructHeaders() { - return GeneratedBlobColumn('headers', $tableName, true, - $customConstraints: ''); - } - - late final GeneratedTextColumn lastModified = _constructLastModified(); - GeneratedTextColumn _constructLastModified() { - return GeneratedTextColumn('lastModified', $tableName, true, - $customConstraints: ''); - } - - late final GeneratedDateTimeColumn maxStale = _constructMaxStale(); - GeneratedDateTimeColumn _constructMaxStale() { - return GeneratedDateTimeColumn('maxStale', $tableName, true, - $customConstraints: ''); - } - - late final GeneratedIntColumn priority = _constructPriority(); - GeneratedIntColumn _constructPriority() { - return GeneratedIntColumn('priority', $tableName, false, - $customConstraints: 'NOT NULL'); - } - - late final GeneratedDateTimeColumn responseDate = _constructResponseDate(); - GeneratedDateTimeColumn _constructResponseDate() { - return GeneratedDateTimeColumn('responseDate', $tableName, false, - $customConstraints: 'NOT NULL'); - } - - late final GeneratedTextColumn url = _constructUrl(); - GeneratedTextColumn _constructUrl() { - return GeneratedTextColumn('url', $tableName, false, - $customConstraints: 'NOT NULL'); - } - - @override - List get $columns => [ - cacheKey, - date, - cacheControl, - content, - eTag, - expires, - headers, - lastModified, - maxStale, - priority, - responseDate, - url - ]; - @override - DioCache get asDslTable => this; - @override - String get $tableName => _alias ?? 'DioCache'; - @override - final String actualTableName = 'DioCache'; - @override - Set get $primaryKey => {cacheKey}; - @override - DioCacheData map(Map data, {String? tablePrefix}) { - final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null; - return DioCacheData.fromData(data, _db, prefix: effectivePrefix); - } - - @override - DioCache createAlias(String alias) { - return DioCache(_db, alias); - } - - @override - bool get dontWriteConstraints => true; -} - -abstract class _$DioCacheDatabase extends GeneratedDatabase { - _$DioCacheDatabase(QueryExecutor e) : super(SqlTypeSystem.defaultInstance, e); - late final DioCache dioCache = DioCache(this); - late final DioCacheDao dioCacheDao = DioCacheDao(this as DioCacheDatabase); - @override - Iterable get allTables => allSchemaEntities.whereType(); - @override - List get allSchemaEntities => [dioCache]; -} - -// ************************************************************************** -// DaoGenerator -// ************************************************************************** - -mixin _$DioCacheDaoMixin on DatabaseAccessor { - DioCache get dioCache => attachedDatabase.dioCache; -}